OpenCv2 学习笔记(4) OpenCv基本的数据类型

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文件夹下。

上面讲解的数据结构也都是从参考手册引用而来,目的是要了解彼此之间的关系和其用途是使用方法,在不同对象之间要灵活运用。

猜你喜欢

转载自blog.csdn.net/wanggao_1990/article/details/53229428
今日推荐