目录
一、前言
二、OpenCV基础结构
0、引入
1、基础结构都有啥
2、类型简述
0.介绍
1.Complex
2.Point_
3.Point3_
4.Size_
5.Rect_
6.RotatedRect
7.Range
8.Scalar_
9.KeyPoint
10.DMatch
11.TermCriteria
三、Point_
1、定义
1.构造函数
2.基本操作
3.成员变量
4.使用时的数据类型
2、常用方法
1.构造函数
2.常用基本操作
四、Size_
1、定义
1.构造函数
2.基本操作
3.成员变量
4.使用时的数据类型
2、常用方法
1.构造函数
2.常用基本操作
重要!说在后面的话
一、前言
上一篇文章,我们讲了Mat类,Mat类是最重要的基础结构,没有之一,因为所有的操作,都是基于你先定义了一个Mat类,然后再做深入操作。但是在OpenCV中,不仅仅有Mat类一个基础结构。
除了Mat类之外,还有哪些基础结构,他们有哪些基本用法呢?接下来就跟我一起走进这节课,来了解更多的基础结构吧!
给大家的小建议:
这一部分其实在后面的使用中并不是特别的重要,但是作为讲解,必须要放在这里讲解,如果你是初学者,你可以跳过这一部分的内容。
所以,对这一部分的内容,推荐这几种方式阅读:
1.兴趣了解,看一下,了解一下;
2.学到后面,用到一个没有见过的类型,过来看一下,理解一下;
3.已经对OpenCV有一定认知基础,过来巩固一下知识;
4.比较深入了解OpenCV,通过阅读基本类型,能够通过阅读本文构建一个更为完整的框架;
5.OpenCV大牛,对本文内容批评指正。
二、OpenCV基础结构
0、引入
在上一节内容中,我们讲到了OpenCV最基本的结构,也是最常用的结构Mat,在使用Mat的过程中,我们还涉及到了如下几个结构:
const Rect& roi;
const Range* ranges;
const Point_<_Tp>& pt;
const Point3_<_Tp>& pt;
const Scalar& s;
啥?
你敢说我没讲?
回去好好看看上一篇博客去!
1、基础结构都有啥
当然结构不只有这些,那基础结构都有啥呢?
让我们打开OpenCV,找到types.hpp文件,看一下描述:
好吧,其实这个并不是很重要,重要的是下面,让我们一起走进这些基础结构,首先我们看一下这些基础结构的描述。
#include <climits>
#include <cfloat>
#include <vector>
#include <limits>
#include "opencv2/core/cvdef.h"
#include "opencv2/core/cvstd.hpp"
#include "opencv2/core/matx.hpp"
namespace cv
{
//! @addtogroup core_basic
//! @{
//////////////////////////////// Complex //////////////////////////////
//////////////////////////////// Point_ ////////////////////////////////
//////////////////////////////// Point3_ ////////////////////////////////
//////////////////////////////// Size_ ////////////////////////////////
//////////////////////////////// Rect_ ////////////////////////////////
///////////////////////////// RotatedRect /////////////////////////////
//////////////////////////////// Range /////////////////////////////////
//////////////////////////////// Scalar_ ///////////////////////////////
/////////////////////////////// KeyPoint ////////////////////////////////
//////////////////////////////// DMatch /////////////////////////////////
///////////////////////////// TermCriteria //////////////////////////////
//! @} core_basic
///////////////////////// raster image moments //////////////////////////
//! @addtogroup imgproc_shape
//! @{
2、类型简述
0.介绍
在这里给大家简单介绍一下这里的一些类,了解一下他们是做什么的。
1.Complex
第一个是一个复数类,这个比较简单,学过高中数学的,对其基本内容也比较清楚,没有什么太多要说明的,不常用。
2.Point_
这个算是OpenCV中比较基础的类了,表示的是二维点,既然是二维点,我们就一般使用两个坐标x和y来表示。我们能想到的有关于二维点集的操作,基本上在这里都有实现,在后面,我们还会详细说明。
3.Point3_
这个表示的也是点,表示的是三维点它的常用类型有:
typedef Point3_<int> Point3i;
typedef Point3_<float> Point3f;
typedef Point3_<double> Point3d;
在后面,我们详细讲解二维点的时候,我们发现它的定义是:
typedef Point_<int> Point2i;
typedef Point_<int64> Point2l;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
typedef Point2i Point;
通过这个对比,我们就能知道这里面的2表示的是二维,3表示的是三维。
4.Size_
这个是用于指定图像或矩形大小的简短模板类。这个也是我们经常会使用到的,这个类包括两个成员变量:width和height,表示图像或者矩阵的大小。在后面我们也会详细讲解。
5.Rect_
这个用于描述二维矩形,主要有两个部分的参数:
1.图像矩阵的左上角坐标。
2.图像矩阵的宽度和高度。
这个类型相比较上面的类型多了定位功能。
6.RotatedRect
上面表示的矩形是横平竖直的矩形,但是我们生活中遇到的矩形可能是歪着的,这个类表示的就是带有旋转角度的矩形。既然如此,那它的参数也就增加了。
因为是带有旋转角度,所以它的定位点,不再是左上角点,而是中心点,然后有四条边的长度(Size2f类型),还有最重要的旋转角度。
RotatedRect(const Point2f& center, const Size2f& size, float angle);
我们也知道,如果一个矩形,我们给定了三个顶点,另外一个顶点的坐标也就知道了,所以在具体使用中,还有一种构造方式:
RotatedRect(const Point2f& point1, const Point2f& point2, const Point2f& point3);
7.Range
这个是用于指定序列的连续子序列(切片)的模板类。重点在于,这个指定序列是什么?其实就是我们上一部分讲的Mat,虽然它是一个二维矩阵,但是它在存储的过程中是以一维数组的方式存储的。如果你学过python的话,这个跟python的range是类似的。只不过python中的可以设置步长,这个是连续的,也就是步长固定为1。
它最常用的构造函数如下:
Range::Range(int _start, int _end)
8.Scalar_
这个也算是OpenCV中比较基础的类了,简单一点来说,我们一般用这个类来定义像素值,比如:
Scalar(0, 0, 255); //红色
Scalar(0, 255, 0); //绿色
Scalar(255, 0, 0); //蓝色
在后面我们还会详细讲到,所以在这里就不过多说明啦!
9.KeyPoint
首先我们翻译一下这个名字,叫:关键点。这个是角点检测器的结构。由许多可用的关键点检测器之一找到的点特征,例如Harris角检测器等等。
在后面实战中,还会给大家介绍到。
10.DMatch
这个和上面的KeyPoint算是一个类型的,他们都是用作特征匹配的。这个类别用于查询描述符索引、列车描述符索引、列车图像索引和描述符之间的距离。
11.TermCriteria
这个是定义迭代算法终止条件的类。我们可以使用默认构造函数初始化它,然后重写任何参数,或者可以使用构造函数的高级变量完全初始化结构。
上面那个是整体介绍,主要是让大家能够简单了解都有哪些东西,确实太多啦,所以在这里,给大家讲解一下常用的成员及方法。其他没有讲到的,在后面使用中,我们还会逐步详细说明。
三、Point_
首先我们必须要讲的是Point_,这个是二维图像中非常基本的类了,就包括小学生也知道:
点构成线,线构成面,面构成体。
让我们从定义出发,一步一步来了解它吧!
1、定义
首先,我们要先看一下它的定义,定义如下:
template<typename _Tp> class Point_
{
public:
typedef _Tp value_type;
//! default constructor
Point_();
Point_(_Tp _x, _Tp _y);
Point_(const Point_& pt);
Point_(Point_&& pt) CV_NOEXCEPT;
Point_(const Size_<_Tp>& sz);
Point_(const Vec<_Tp, 2>& v);
Point_& operator = (const Point_& pt);
Point_& operator = (Point_&& pt) CV_NOEXCEPT;
//! conversion to another data type
template<typename _Tp2> operator Point_<_Tp2>() const;
//! conversion to the old-style C structures
operator Vec<_Tp, 2>() const;
//! dot product
_Tp dot(const Point_& pt) const;
//! dot product computed in double-precision arithmetics
double ddot(const Point_& pt) const;
//! cross-product
double cross(const Point_& pt) const;
//! checks whether the point is inside the specified rectangle
bool inside(const Rect_<_Tp>& r) const;
_Tp x; //!< x coordinate of the point
_Tp y; //!< y coordinate of the point
};
typedef Point_<int> Point2i;
typedef Point_<int64> Point2l;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
typedef Point2i Point;
template<typename _Tp> class DataType< Point_<_Tp> >
{
public:
typedef Point_<_Tp> value_type;
typedef Point_<typename DataType<_Tp>::work_type> work_type;
typedef _Tp channel_type;
enum { generic_type = 0,
channels = 2,
fmt = traits::SafeFmt<channel_type>::fmt + ((channels - 1) << 8)
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
,depth = DataType<channel_type>::depth
,type = CV_MAKETYPE(depth, channels)
#endif
};
typedef Vec<channel_type, channels> vec_type;
};
namespace traits {
template<typename _Tp>
struct Depth< Point_<_Tp> > { enum { value = Depth<_Tp>::value }; };
template<typename _Tp>
struct Type< Point_<_Tp> > { enum { value = CV_MAKETYPE(Depth<_Tp>::value, 2) }; };
} // namespace
这里面最基本的定义主要包括如下三部分:
1.构造函数
几个构造函数,用于生成Point对象:
//! default constructor
Point_();
Point_(_Tp _x, _Tp _y);
Point_(const Point_& pt);
Point_(Point_&& pt) CV_NOEXCEPT;
Point_(const Size_<_Tp>& sz);
Point_(const Vec<_Tp, 2>& v);
2.基本操作
几个基本操作,具体含义及其定义方式如下:
//! 两个赋值运算符
Point_& operator = (const Point_& pt);
Point_& operator = (Point_&& pt) CV_NOEXCEPT;
//! 点积
_Tp dot(const Point_& pt) const;
//! 双精度算法计算点积
double ddot(const Point_& pt) const;
//! 交叉积
double cross(const Point_& pt) const;
//! 检查点是否在指定的矩形内
bool inside(const Rect_<_Tp>& r) const;
3.成员变量
两个类体成员变量,大家肯定也能知道,就是两个坐标值:
_Tp x; //!< x coordinate of the point
_Tp y; //!< y coordinate of the point
4.使用时的数据类型
当我们定义了Point_类之后,我们要根据点的数据定义其具体使用时候的数据类型:
typedef Point_<int> Point2i;
typedef Point_<int64> Point2l;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
typedef Point2i Point;
其中,前四个指定 了Point_类的数据,分别是int,int64,float,double,在一般情况下,我们都会使用int类型的Point_,所以我们默认Point2i为Point。
2、常用方法
接下来我们要说的就是常用成员,它的全部成员函数还是很多的,我们只讲最常用的几个,为了方便大家快速理解,我们分类说明。
1.构造函数
构造函数如下:
template<typename _Tp> inline
Point_<_Tp>::Point_()
: x(0), y(0) {}
template<typename _Tp> inline
Point_<_Tp>::Point_(_Tp _x, _Tp _y)
: x(_x), y(_y) {}
template<typename _Tp> inline
Point_<_Tp>::Point_(const Point_& pt)
: x(pt.x), y(pt.y) {}
template<typename _Tp> inline
Point_<_Tp>::Point_(Point_&& pt) CV_NOEXCEPT
: x(std::move(pt.x)), y(std::move(pt.y)) {}
template<typename _Tp> inline
Point_<_Tp>::Point_(const Size_<_Tp>& sz)
: x(sz.width), y(sz.height) {}
template<typename _Tp> inline
Point_<_Tp>::Point_(const Vec<_Tp,2>& v)
: x(v[0]), y(v[1]) {}
最基本的构造函数,就是构造一个空的点,然后将坐标置为(0,0)。
Point p1 = Point();
然后我们最常用的一个是使用两个点的坐标来创建一个点。
Point p2 = Point(1, 2);
最基本的构造函数,就是构造一个空的点,然后将坐标置为(0,0)。
Point p3 = Point(p2);
我们可以将上面的点输出,也可以访问点的两个坐标,代码和结果如下:
cout << "p1 = " << p1 << endl;
cout << "p1 = " << p2 << endl;
cout << "p3 = " << p3 << endl;
cout << "p3.x = " << p3.x << " , p3.y = " << p3.y << endl;
2.常用基本操作
常用基本操作主要包括两个点的运算(包括以点表示的向量的运算,比如点(1,2)表示向量(1,2)),点的数乘运算等等,具体如下:
template<typename _Tp> inline
Point_<_Tp>& Point_<_Tp>::operator = (Point_&& pt) CV_NOEXCEPT
{
x = std::move(pt.x); y = std::move(pt.y);
return *this;
}
template<typename _Tp> template<typename _Tp2> inline
Point_<_Tp>::operator Point_<_Tp2>() const
{
return Point_<_Tp2>(saturate_cast<_Tp2>(x), saturate_cast<_Tp2>(y));
}
template<typename _Tp> inline
Point_<_Tp>::operator Vec<_Tp, 2>() const
{
return Vec<_Tp, 2>(x, y);
}
template<typename _Tp> inline
_Tp Point_<_Tp>::dot(const Point_& pt) const
{
return saturate_cast<_Tp>(x*pt.x + y*pt.y);
}
template<typename _Tp> inline
double Point_<_Tp>::ddot(const Point_& pt) const
{
return (double)x*(double)(pt.x) + (double)y*(double)(pt.y);
}
template<typename _Tp> inline
double Point_<_Tp>::cross(const Point_& pt) const
{
return (double)x*pt.y - (double)y*pt.x;
}
template<typename _Tp> inline bool
Point_<_Tp>::inside( const Rect_<_Tp>& r ) const
{
return r.contains(*this);
}
template<typename _Tp> static inline
Point_<_Tp>& operator += (Point_<_Tp>& a, const Point_<_Tp>& b)
{
a.x += b.x;
a.y += b.y;
return a;
}
template<typename _Tp> static inline
Point_<_Tp>& operator -= (Point_<_Tp>& a, const Point_<_Tp>& b)
{
a.x -= b.x;
a.y -= b.y;
return a;
}
template<typename _Tp> static inline
Point_<_Tp>& operator *= (Point_<_Tp>& a, int b)
{
a.x = saturate_cast<_Tp>(a.x * b);
a.y = saturate_cast<_Tp>(a.y * b);
return a;
}
template<typename _Tp> static inline
Point_<_Tp>& operator *= (Point_<_Tp>& a, float b)
{
a.x = saturate_cast<_Tp>(a.x * b);
a.y = saturate_cast<_Tp>(a.y * b);
return a;
}
template<typename _Tp> static inline
Point_<_Tp>& operator *= (Point_<_Tp>& a, double b)
{
a.x = saturate_cast<_Tp>(a.x * b);
a.y = saturate_cast<_Tp>(a.y * b);
return a;
}
template<typename _Tp> static inline
Point_<_Tp>& operator /= (Point_<_Tp>& a, int b)
{
a.x = saturate_cast<_Tp>(a.x / b);
a.y = saturate_cast<_Tp>(a.y / b);
return a;
}
template<typename _Tp> static inline
Point_<_Tp>& operator /= (Point_<_Tp>& a, float b)
{
a.x = saturate_cast<_Tp>(a.x / b);
a.y = saturate_cast<_Tp>(a.y / b);
return a;
}
template<typename _Tp> static inline
Point_<_Tp>& operator /= (Point_<_Tp>& a, double b)
{
a.x = saturate_cast<_Tp>(a.x / b);
a.y = saturate_cast<_Tp>(a.y / b);
return a;
}
template<typename _Tp> static inline
double norm(const Point_<_Tp>& pt)
{
return std::sqrt((double)pt.x*pt.x + (double)pt.y*pt.y);
}
template<typename _Tp> static inline
bool operator == (const Point_<_Tp>& a, const Point_<_Tp>& b)
{
return a.x == b.x && a.y == b.y;
}
template<typename _Tp> static inline
bool operator != (const Point_<_Tp>& a, const Point_<_Tp>& b)
{
return a.x != b.x || a.y != b.y;
}
template<typename _Tp> static inline
Point_<_Tp> operator + (const Point_<_Tp>& a, const Point_<_Tp>& b)
{
return Point_<_Tp>( saturate_cast<_Tp>(a.x + b.x), saturate_cast<_Tp>(a.y + b.y) );
}
template<typename _Tp> static inline
Point_<_Tp> operator - (const Point_<_Tp>& a, const Point_<_Tp>& b)
{
return Point_<_Tp>( saturate_cast<_Tp>(a.x - b.x), saturate_cast<_Tp>(a.y - b.y) );
}
template<typename _Tp> static inline
Point_<_Tp> operator - (const Point_<_Tp>& a)
{
return Point_<_Tp>( saturate_cast<_Tp>(-a.x), saturate_cast<_Tp>(-a.y) );
}
template<typename _Tp> static inline
Point_<_Tp> operator * (const Point_<_Tp>& a, int b)
{
return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) );
}
template<typename _Tp> static inline
Point_<_Tp> operator * (int a, const Point_<_Tp>& b)
{
return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) );
}
template<typename _Tp> static inline
Point_<_Tp> operator * (const Point_<_Tp>& a, float b)
{
return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) );
}
template<typename _Tp> static inline
Point_<_Tp> operator * (float a, const Point_<_Tp>& b)
{
return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) );
}
template<typename _Tp> static inline
Point_<_Tp> operator * (const Point_<_Tp>& a, double b)
{
return Point_<_Tp>( saturate_cast<_Tp>(a.x*b), saturate_cast<_Tp>(a.y*b) );
}
template<typename _Tp> static inline
Point_<_Tp> operator * (double a, const Point_<_Tp>& b)
{
return Point_<_Tp>( saturate_cast<_Tp>(b.x*a), saturate_cast<_Tp>(b.y*a) );
}
template<typename _Tp> static inline
Point_<_Tp> operator * (const Matx<_Tp, 2, 2>& a, const Point_<_Tp>& b)
{
Matx<_Tp, 2, 1> tmp = a * Vec<_Tp,2>(b.x, b.y);
return Point_<_Tp>(tmp.val[0], tmp.val[1]);
}
template<typename _Tp> static inline
Point3_<_Tp> operator * (const Matx<_Tp, 3, 3>& a, const Point_<_Tp>& b)
{
Matx<_Tp, 3, 1> tmp = a * Vec<_Tp,3>(b.x, b.y, 1);
return Point3_<_Tp>(tmp.val[0], tmp.val[1], tmp.val[2]);
}
template<typename _Tp> static inline
Point_<_Tp> operator / (const Point_<_Tp>& a, int b)
{
Point_<_Tp> tmp(a);
tmp /= b;
return tmp;
}
template<typename _Tp> static inline
Point_<_Tp> operator / (const Point_<_Tp>& a, float b)
{
Point_<_Tp> tmp(a);
tmp /= b;
return tmp;
}
template<typename _Tp> static inline
Point_<_Tp> operator / (const Point_<_Tp>& a, double b)
{
Point_<_Tp> tmp(a);
tmp /= b;
return tmp;
}
为什么这里有很多重载函数?
这里面有很多,因为涉及到具体类型,所以需要写很多重载函数,这也是函数多的原因,但是真正的没有几类。
比如实现乘法,乘法运算符的左右两边可能是点和数,也可能是数和点,数的类型可能是整型int,可能是单精度浮点型float,可能是双精度浮点型double。这些在具体实现都是要写清楚的。
下面我们举几个例子来讲解一下常用的几个方法:
比如上面我们说到了点的基本操作,在这里也有实现,我们先把这几个实现一下:
Point p2 = Point(1, 2);
Point p4 = Point(7, 8);
cout << "dot: " << p2.dot(p4) << endl;
cout << "ddot: " << p2.ddot(p4) << endl;
cout << "cross: " << p2.cross(p4) << endl;
cout << "inside: " << p2.inside(Rect(0, 0, 5, 5)) << endl;
结果如下:
然后还有几个我们很熟悉的运算符,我们举几个例子:
Point p2 = Point(1, 2);
Point p3 = Point(p2);
if (p2 == p3) cout << "p2 == p3" << endl;
else cout << "p2 != p3" << endl;
cout << "norm(p2) = " << norm(p2) << endl;
cout << "p2 + p3 = " << p2 + p3 << endl;
cout << "p2 - p3 = " << p2 - p3 << endl;
cout << "p2 * 2 = " << p2 * 2 << endl;
cout << "p2 / 2 = " << p2 / 2 << endl;
四、Size_
接下来我们要讲的是Size_,这个表达的就是尺寸,在二维图像中,尺寸当然就是图像的长和宽啦!接下来让我们走进它吧!
1、定义
首先,我们要先看一下它的定义,定义如下:
template<typename _Tp> class Size_
{
public:
typedef _Tp value_type;
//! default constructor
Size_();
Size_(_Tp _width, _Tp _height);
Size_(const Size_& sz);
Size_(Size_&& sz) CV_NOEXCEPT;
Size_(const Point_<_Tp>& pt);
Size_& operator = (const Size_& sz);
Size_& operator = (Size_&& sz) CV_NOEXCEPT;
//! the area (width*height)
_Tp area() const;
//! aspect ratio (width/height)
double aspectRatio() const;
//! true if empty
bool empty() const;
//! conversion of another data type.
template<typename _Tp2> operator Size_<_Tp2>() const;
_Tp width; //!< the width
_Tp height; //!< the height
};
typedef Size_<int> Size2i;
typedef Size_<int64> Size2l;
typedef Size_<float> Size2f;
typedef Size_<double> Size2d;
typedef Size2i Size;
template<typename _Tp> class DataType< Size_<_Tp> >
{
public:
typedef Size_<_Tp> value_type;
typedef Size_<typename DataType<_Tp>::work_type> work_type;
typedef _Tp channel_type;
enum { generic_type = 0,
channels = 2,
fmt = DataType<channel_type>::fmt + ((channels - 1) << 8)
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
,depth = DataType<channel_type>::depth
,type = CV_MAKETYPE(depth, channels)
#endif
};
typedef Vec<channel_type, channels> vec_type;
};
namespace traits {
template<typename _Tp>
struct Depth< Size_<_Tp> > { enum { value = Depth<_Tp>::value }; };
template<typename _Tp>
struct Type< Size_<_Tp> > { enum { value = CV_MAKETYPE(Depth<_Tp>::value, 2) }; };
} // namespace
这里面最基本的定义主要包括如下三部分:
1.构造函数
几个构造函数,用于生成size对象:
//! default constructor
Size_();
Size_(_Tp _width, _Tp _height);
Size_(const Size_& sz);
Size_(Size_&& sz) CV_NOEXCEPT;
Size_(const Point_<_Tp>& pt);
2.基本操作
几个基本操作,具体含义及其定义方式如下:
//! 两个赋值运算符
Size_& operator = (const Size_& sz);
Size_& operator = (Size_&& sz) CV_NOEXCEPT;
//! 面积 (width*height)
_Tp area() const;
//! 宽高比 (width/height)
double aspectRatio() const;
//! 判断是否为空
bool empty() const;
3.成员变量
两个类体成员变量,大家肯定也能知道,就是宽高:
_Tp width; //!< the width
_Tp height; //!< the height
4.使用时的数据类型
当我们定义了Size_类之后,我们要根据点的数据定义其具体使用时候的数据类型:
typedef Size_<int> Size2i;
typedef Size_<int64> Size2l;
typedef Size_<float> Size2f;
typedef Size_<double> Size2d;
typedef Size2i Size;
其中,前四个指定 了Size_类的数据,分别是int,int64,float,double,在一般情况下,我们都会使用int类型的Size_,所以我们默认Size2i为Size。
2、常用方法
接下来我们要说的就是常用成员,它的全部成员函数还是很多的,我们只讲最常用的几个,为了方便大家快速理解,我们分类说明。
注:
大家会发现这个跟我们上面讲到Point类似,所以我们就不占字数进行代码举例啦,大家可以参考Point类的内容,如果有问题,可以随时跟我交流。
1.构造函数
构造函数如下:
template<typename _Tp> inline
Size_<_Tp>::Size_()
: width(0), height(0) {}
template<typename _Tp> inline
Size_<_Tp>::Size_(_Tp _width, _Tp _height)
: width(_width), height(_height) {}
template<typename _Tp> inline
Size_<_Tp>::Size_(const Size_& sz)
: width(sz.width), height(sz.height) {}
template<typename _Tp> inline
Size_<_Tp>::Size_(Size_&& sz) CV_NOEXCEPT
: width(std::move(sz.width)), height(std::move(sz.height)) {}
template<typename _Tp> inline
Size_<_Tp>::Size_(const Point_<_Tp>& pt)
: width(pt.x), height(pt.y) {}
template<typename _Tp> template<typename _Tp2> inline
Size_<_Tp>::operator Size_<_Tp2>() const
{
return Size_<_Tp2>(saturate_cast<_Tp2>(width), saturate_cast<_Tp2>(height));
}
2.常用基本操作
常用基本操作主要包括基本赋值操作:
template<typename _Tp> inline
Size_<_Tp>& Size_<_Tp>::operator = (const Size_<_Tp>& sz)
{
width = sz.width; height = sz.height;
return *this;
}
template<typename _Tp> inline
Size_<_Tp>& Size_<_Tp>::operator = (Size_<_Tp>&& sz) CV_NOEXCEPT
{
width = std::move(sz.width); height = std::move(sz.height);
return *this;
}
类体内基本操作:
template<typename _Tp> inline
_Tp Size_<_Tp>::area() const
{
const _Tp result = width * height;
CV_DbgAssert(!std::numeric_limits<_Tp>::is_integer
|| width == 0 || result / width == height); // make sure the result fits in the return value
return result;
}
template<typename _Tp> inline
double Size_<_Tp>::aspectRatio() const
{
return width / static_cast<double>(height);
}
template<typename _Tp> inline
bool Size_<_Tp>::empty() const
{
return width <= 0 || height <= 0;
}
运算符,包括赋值运算符(*=,/=,+=,-= ),四则运算符(+,-,*,/),等于不等于(==,!=)
template<typename _Tp> static inline
Size_<_Tp>& operator *= (Size_<_Tp>& a, _Tp b)
{
a.width *= b;
a.height *= b;
return a;
}
template<typename _Tp> static inline
Size_<_Tp> operator * (const Size_<_Tp>& a, _Tp b)
{
Size_<_Tp> tmp(a);
tmp *= b;
return tmp;
}
template<typename _Tp> static inline
Size_<_Tp>& operator /= (Size_<_Tp>& a, _Tp b)
{
a.width /= b;
a.height /= b;
return a;
}
template<typename _Tp> static inline
Size_<_Tp> operator / (const Size_<_Tp>& a, _Tp b)
{
Size_<_Tp> tmp(a);
tmp /= b;
return tmp;
}
template<typename _Tp> static inline
Size_<_Tp>& operator += (Size_<_Tp>& a, const Size_<_Tp>& b)
{
a.width += b.width;
a.height += b.height;
return a;
}
template<typename _Tp> static inline
Size_<_Tp> operator + (const Size_<_Tp>& a, const Size_<_Tp>& b)
{
Size_<_Tp> tmp(a);
tmp += b;
return tmp;
}
template<typename _Tp> static inline
Size_<_Tp>& operator -= (Size_<_Tp>& a, const Size_<_Tp>& b)
{
a.width -= b.width;
a.height -= b.height;
return a;
}
template<typename _Tp> static inline
Size_<_Tp> operator - (const Size_<_Tp>& a, const Size_<_Tp>& b)
{
Size_<_Tp> tmp(a);
tmp -= b;
return tmp;
}
template<typename _Tp> static inline
bool operator == (const Size_<_Tp>& a, const Size_<_Tp>& b)
{
return a.width == b.width && a.height == b.height;
}
template<typename _Tp> static inline
bool operator != (const Size_<_Tp>& a, const Size_<_Tp>& b)
{
return !(a == b);
}
重要!说在后面的话
哈,就先写到这里吧!因为确实是太多了,以至于博客温馨提醒,说读完可能需要一个小时让我删减内容。因为是讲基础,所以我得详细说一下,可能确实说的内容太多啦。
其实我纠结了一上午到底要不要写这一部分内容。
不写呢?这个东西是基础,在以后会经常用到,如果讲到了,就会很感觉很突兀。
写呢?确实不知道该怎么把握这个度。是要写成一本词典类型的吗?大可不必这样,这样既没有主次之分,又让整片博客太过于臃肿。还是讲几个重要的,把常用的说一下就好。但是这样讲的太简单了,觉得还是不太好。
所以我想了一下,要写,而且,要在上面两种写的方式取个折中。
从源码角度带领大家,整体看一下都有啥,了解了之后,将每种类型简单说明,让大家能够有个整体认识,能够知道都有哪几种类型,类型的含义是啥,表示的是什么数据。然后我们从中挑选出最常用的,详细讲解!从定义,方法,实战角度,全面了解。
学习之路,道阻且长!这个疫情,放慢了每个人的脚步,也让我想了很多,我研究生的方向,已经有所改变,跟计算机视觉可能没有直接关系了,但是,我喜欢,我还是想花一定的时间,放在这上面。
人,真的,要想想自己想要什么,愿不愿意为了喜欢的东西,去付出自己的时间和经历。曾经的我太年轻,没有坚持好好学数学,但这世上没有卖后悔药的,现在,我有了一个比较喜欢的东西,再难,我也要坚持下去!
我也希望大家能够借助疫情这次机会,静下心来,想想自己到底该做点什么,该怎么做?理想有时候很丰满,既然这么丰满,那我们为什么不努力去追寻一下呢?
正如开题的话!
我想:骨干的现实,会在追逐理想的我们面前屈服!