Mat的详细讲述安排在下一节,本节将简要介绍其他最常用的几个数据类型,包括Point_、Point3_、Size_、Rect_、Matx、Vec、Scalar_等,分别为二维点、三维点、尺寸、矩形、小矩阵、小向量、标量等模板类。
1、Point_
可以理解为二维点,包括下面的int、float和double3三种类型的二维点。
typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
类定义如下:
class Point_
template<typename _Tp> class CV_EXPORTS Point_
{
public:
typedef _Tp value_type;
// various constructors
Point_();
Point_(_Tp _x, _Tp _y);
Point_(const Point_& pt);
Point_(const CvPoint& pt);
Point_(const CvPoint2D32f& pt);
Point_(const Size_<_Tp>& sz);
Point_(const Vec<_Tp, 2>& v);
Point_& operator = (const Point_& pt);
//! conversion to another data type
template<typename _Tp2> operator Point_<_Tp2>() const;
//! conversion to the old-style C structures
operator CvPoint() const;
operator CvPoint2D32f() const;
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, y; //< the point coordinates
}
可以有其他的的二维数据结构构造,如老版本中的CvPoint、CvPoint2D32f,以及后续的Size和Vec<_Tp,2>,另外还有成员函数,点乘dot()、叉乘cross(),检查点是否在矩形内部inside()。
点与点、点与数值可以进行直接运算,如下:
pt1 = pt2 + pt3;
pt1 = pt2 - pt3;
pt1 = pt2 * a;
pt1 = a * pt2;
pt1 += pt2;
pt1 -= pt2;
pt1 *= a;
double value = norm(pt); // L2 norm
pt1 == pt2;
pt1 != pt2;
Point2f a(0.3f, 0.f), b(0.f, 0.4f);
Point pt = (a + b)*10.f;
cout << pt.x << ", " << pt.y << endl; // 3,4
2、Point3_
Point3_和Point2_类似,是三维点,同样有三种数据类型,
typedef Point3_<int> Point3i;
typedef Point3_<float> Point3f;
typedef Point3_<double> Point3d;
详细定义如下:
class Point3_
template<typename _Tp> class CV_EXPORTS Point3_
{
public:
typedef _Tp value_type;
// various constructors
Point3_();
Point3_(_Tp _x, _Tp _y, _Tp _z);
Point3_(const Point3_& pt);
explicit Point3_(const Point_<_Tp>& pt);
Point3_(const CvPoint3D32f& pt);
Point3_(const Vec<_Tp, 3>& v);
Point3_& operator = (const Point3_& pt);
//! conversion to another data type
template<typename _Tp2> operator Point3_<_Tp2>() const;
//! conversion to the old-style CvPoint...
operator CvPoint3D32f() const;
//! conversion to cv::Vec<>
operator Vec<_Tp, 3>() const;
//! dot product
_Tp dot(const Point3_& pt) const;
//! dot product computed in double-precision arithmetics
double ddot(const Point3_& pt) const;
//! cross product of the 2 3D points
Point3_ cross(const Point3_& pt) const;
_Tp x, y, z; //< the point coordinates
};
3、Size_
二维尺寸,用来描述矩阵大小、矩形区域大小、宽高等。类型有,
typedef Size_<int> Size2i;
typedef Size2i Size;
typedef Size_<float> Size2f;
具体定义如下
class Size_
template<typename _Tp> class CV_EXPORTS Size_
{
public:
typedef _Tp value_type;
//! various constructors
Size_();
Size_(_Tp _width, _Tp _height);
Size_(const Size_& sz);
Size_(const CvSize& sz);
Size_(const CvSize2D32f& sz);
Size_(const Point_<_Tp>& pt);
Size_& operator = (const Size_& sz);
//! the area (width*height)
_Tp area() const;
//! conversion of another data type.
template<typename _Tp2> operator Size_<_Tp2>() const;
//! conversion to the old-style OpenCV types
operator CvSize() const;
operator CvSize2D32f() const;
_Tp width, height; // the width and the height
};
同Point2_一样,可以通过二维数据类型CvSize、CvSize2D32f等构造,成员变量有 width和height;还能计算面积area()=height*width;
4、Rect_
二维矩形,有效类型为 typedef Rect_<int> Rect; 该数据类型由顶点x,y和尺寸width、height定义。
template<typename _Tp> class CV_EXPORTS Rect_
{
public:
typedef _Tp value_type;
//! various constructors
Rect_();
Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
Rect_(const Rect_& r);
Rect_(const CvRect& r);
Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);
Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);
Rect_& operator = ( const Rect_& r );
//! the top-left corner
Point_<_Tp> tl() const;
//! the bottom-right corner
Point_<_Tp> br() const;
//! size (width, height) of the rectangle
Size_<_Tp> size() const;
//! area (width*height) of the rectangle
_Tp area() const;
//! conversion to another data type
template<typename _Tp2> operator Rect_<_Tp2>() const;
//! conversion to the old-style CvRect
operator CvRect() const;
//! checks whether the rectangle contains the point
bool contains(const Point_<_Tp>& pt) const;
_Tp x, y, width, height; //< the top-left corner, as well as width and height of the rectangle
};
构造函数比较多,Rect(x,y,width,height)和Rect_( Rect )、Rect_( CvRect )结构上是一样的,4个参数;还可以用2个参数构造,顶点x,y这两个可以用Point表示,height和width可以用Point或Szie表示。
成员函数可以返回左上角tl()和右下角br()的二维点坐标,还有面积area(); 和Point对应,能够检查矩形内是是否有点contains(); 基本的运算有如下:
Rect r1(0, 0, 100, 100), r2(20, 20, 120, 120),r3;
Point p(30, 30);
Size size(50, 50);
r3 = r1 + p; // Rect(30,30,100,100)
r3 = r1 + size; // Rect(0,0,150,150)
r3 = r1 & r2; // Rect(20,20,80,80) // 可以用于从Mat中截取roi区域,而roi区域越界时的处理
r3 = r1 | r2; // Rect(0,0,140,140)
5、Matx
小矩阵,是一个模板类,便于构造。
template<typename _Tp, int m, int n> class Matx {...}; //m行n列的矩阵,(m,n通常较小)
typedef Matx<float, 1, 2> Matx12f;
typedef Matx<double, 1, 2> Matx12d;
...
typedef Matx<float, 1, 6> Matx16f;
typedef Matx<double, 1, 6> Matx16d;
typedef Matx<float, 2, 1> Matx21f;
typedef Matx<double, 2, 1> Matx21d;
...
typedef Matx<float, 6, 1> Matx61f;
typedef Matx<double, 6, 1> Matx61d;
typedef Matx<float, 2, 2> Matx22f;
typedef Matx<double, 2, 2> Matx22d;
...
typedef Matx<float, 6, 6> Matx66f;
typedef Matx<double, 6, 6> Matx66d;
小矩阵的好处在于,便于构造,如下:
Matx33f m(1, 2, 3,
4, 5, 6,
7, 8, 9);
cout << sum(Mat(m*m.t())) << endl; // 返回值为Scalar(693,0,0,0)
m.t()为矩阵m的转置,sum是所有矩阵元素之和,返回类型为Scalar。
6、Vec
小向量,派生于Matx<_Tp, n, 1>,即 列向量。
template<typename _Tp, int n> class Vec : public Matx<_Tp, n, 1> {...};
typedef Vec<uchar, 2> Vec2b;
typedef Vec<uchar, 3> Vec3b;
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s;
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<float, 2> Vec2f;
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;
typedef Vec<double, 2> Vec2d;
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;
Vec对象可以和其它结构互相转化,如 Vec<T, 2> <=> Point_ ,Vec<T, 3> <=> Point3_ ,Vec<T, 4> <=> CvScalar / Scalar_。 可以用“[ ]”操作符获取Vec的元素。另外,Vec经常用于描述多通道矩阵的一个像素,如 Mat m(10,10, CV_32FC3,Scalar(0,0,0) ),取(4,5)这个元素m.at<Vec2f>(4,5) ,这个像素各通道的值可以通过m.at<Vec2f>(4,5)[ i ]得到 。
Vec的运算有: v1 = v2 + v3、v1 = v2 - v3、v1 = v2 * scale、v1 = scale * v2、v1 = -v2、v1 += v2 ,v1 == v2、v1 != v2, norm(v1) (欧式距离)等。
7、Scalar_
标量,由Vec<_Tp, 4>模板类派生。在矩阵运算中,特别是图像矩阵涉及到多通道的运算中,对某个像素素的取值和赋值都是多个通道同时进行,因此Vec和Scalar的优势体现明显,被广泛用于图像像素赋值。
template<typename _Tp> class CV_EXPORTS Scalar_ : public Vec<_Tp, 4>
{
public:
//! various constructors
Scalar_();
Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);
Scalar_(const CvScalar& s);
Scalar_(_Tp v0);
//! returns a scalar with all elements set to v0
static Scalar_<_Tp> all(_Tp v0);
//! conversion to the old-style CvScalar
operator CvScalar() const;
//! conversion to another data type
template<typename T2> operator Scalar_<T2>() const;
//! per-element product
Scalar_<_Tp> mul(const Scalar_<_Tp>& t, double scale=1 ) const;
// returns (v0, -v1, -v2, -v3)
Scalar_<_Tp> conj() const;
// returns true iff v1 == v2 == v3 == 0
bool isReal() const;
};
typedef Scalar_<double> Scalar;
既然Scalr_是从Vec派生,那么其元素的取值也是通过“[ ]”运算符操作的,例如,在 s = sum(Mat(m*m.t())) 运算中,sum返回值s是Scalar(693,0,0,0),是包含4个元素的向量,那么结果的取值方法为 double res= s[0]。
图像像素赋值,如 Mat(10, 10, CV_32FC2, Scalar(1,2) ),由于是2个通道,因此Scalar只需要2个数值;由于Scalar是一个4行1列的列向量,因此最多只能给4个通道的图像矩阵像素赋值。
还有一些其他的数据结构类,需要的可以通过参考手册refman.pdf查询,位于opencv安装目录的docs或者doc文件夹下。
上面讲解的数据结构也都是从参考手册引用而来,目的是要了解彼此之间的关系和其用途是使用方法,在不同对象之间要灵活运用。