OpenCV数据类型

 Max.C     2020-04-17   23657 words    & views

一、基本类型

可以在 opencv-4.0.0\modules\core\include\opencv2\core\base.hppopencv-4.0.0\modules\core\include\opencv2\core\types.hpp找到基本数据类型的定义和声明,下面简单介绍常见的数据类型:

//base.hpp中的声明
template<typename _Tp, int cn> class Vec;
template<typename _Tp, int m, int n> class Matx;

template<typename _Tp> class Complex;
template<typename _Tp> class Point_;
template<typename _Tp> class Point3_;
template<typename _Tp> class Size_;
template<typename _Tp> class Rect_;
template<typename _Tp> class Scalar_;

class CV_EXPORTS Mat;

template<typename _Tp> class Mat_;

1、Point类

二维点类,作为一个模板类使用,模板实例宏定义如下:

typedef Point_<int> Point2i;
typedef Point_<int64> Point2l;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;
typedef Point2i Point;

接下来我们找到模板类Point_的定义:

template<typename _Tp> class Point_
{
public:
    typedef _Tp value_type;

    //构造函数
    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;
    //转换为另一种数据类型的Point_
    template<typename _Tp2> operator Point_<_Tp2>() const;

    //转化为旧类型
    operator Vec<_Tp, 2>() const;

    //点乘操作
    _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;
  
    _Tp x; //成员变量x
    _Tp y; //成员变量y
};

除了二维点,OpenCV还有三维点的模板类Point3_,包含变量x、y、z,其定义如下:

typedef Point3_<int> Point3i;
typedef Point3_<float> Point3f;
typedef Point3_<double> Pointd;
template<typename _Tp> class Point3_
{
public:
    typedef _Tp value_type;

    //! default constructor
    Point3_();
    Point3_(_Tp _x, _Tp _y, _Tp _z);
    Point3_(const Point3_& pt);
    Point3_(Point3_&& pt) CV_NOEXCEPT;
    explicit Point3_(const Point_<_Tp>& pt);
    Point3_(const Vec<_Tp, 3>& v);

    Point3_& operator = (const Point3_& pt);
    Point3_& operator = (Point3_&& pt) CV_NOEXCEPT;
    //! conversion to another data type
    template<typename _Tp2> operator Point3_<_Tp2>() 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; //!< x coordinate of the 3D point
    _Tp y; //!< y coordinate of the 3D point
    _Tp z; //!< z coordinate of the 3D point
};

2、Scaler类

cv::Scalar类是四维点类,继承自Vec模板类,模板类的定义如下:

template<typename _Tp> class Scalar_ : public Vec<_Tp, 4>
{
public:
    //构造函数
    Scalar_();
    Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);
    Scalar_(_Tp v0);

    Scalar_(const Scalar_& s);
    Scalar_(Scalar_&& s) CV_NOEXCEPT;

    //运算符重载
  	Scalar_& operator=(const Scalar_& s);
    Scalar_& operator=(Scalar_&& s) CV_NOEXCEPT;

    template<typename _Tp2, int cn>
    Scalar_(const Vec<_Tp2, cn>& v);

    //将所有数值设为v0
    static Scalar_<_Tp> all(_Tp v0);

    //数据类型转换
    template<typename T2> operator Scalar_<T2>() const;

    //乘
    Scalar_<_Tp> mul(const Scalar_<_Tp>& a, double scale=1 ) const;

    //共轭,returns (v0, -v1, -v2, -v3)
    Scalar_<_Tp> conj() const;

    //实数,returns true iff v1 == v2 == v3 == 0
    bool isReal() const;
};

Scaler类型默认为双精度类型:

typedef Scalar_<double> Scalar;

Scalar可以用以下方法初始化:

Scalar col(255,255,255);

Scalar col[7];
col[0] = {255, 255,255};
col[1] = {0, 255,255};
col[2] = {255, 0,255};
col[3] = {255, 255,0};
col[4] = {0, 0,255};
col[5] = {255, 0,0};
col[6] = {0, 255,0};

3、Size类

Size类与Point类类似,而且可以与Point类互相转换,两者的主要区别在于Point类的数据成员是x和y,而size类中对应的成员是width和height

Size类型的宏定义如下:

typedef Size_<int> Size2i;
typedef Size_<int64> Size2l;
typedef Size_<float> Size2f;
typedef Size_<double> Size2d;
typedef Size2i Size;

其中包含Size_模板类,Size_的模板类的定义如下:

template<typename _Tp> class Size_
{
public:
    typedef _Tp value_type;

    //构造函数
    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;
    //求面积
    _Tp area() const;
    //求长宽比
    double aspectRatio() const;
    //true if empty
    bool empty() const;

    //类型转换
    template<typename _Tp2> operator Size_<_Tp2>() const;

    _Tp width; //!< the width
    _Tp height; //!< the height
};

4、Rect类

Rect类表示矩形,包含Point类的成员x和y(矩形左上角)和Size类的成员width和height(代表矩形的大小),有以下几种数据类型表示:

typedef Rect_<int> Rect2i;
typedef Rect_<float> Rect2f;
typedef Rect_<double> Rect2d;
typedef Rect2i Rect;

Rect_类的定义如下:

template<typename _Tp> class Rect_
{
public:
    typedef _Tp value_type;

    //! default constructor
    Rect_();
    Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);
    Rect_(const Rect_& r);
    Rect_(Rect_&& r) CV_NOEXCEPT;
    Rect_(const Point_<_Tp>& org, const Size_<_Tp>& sz);
    Rect_(const Point_<_Tp>& pt1, const Point_<_Tp>& pt2);

    Rect_& operator = ( const Rect_& r );
    Rect_& operator = ( Rect_&& r ) CV_NOEXCEPT;
    //! 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;
    //! true if empty
    bool empty() const;

    //数据类型转换
    template<typename _Tp2> operator Rect_<_Tp2>() const;

    //检查点是否位于矩形内
    bool contains(const Point_<_Tp>& pt) const;

    //成员函数
  	_Tp x; //!< x coordinate of the top-left corner
    _Tp y; //!< y coordinate of the top-left corner
    _Tp width; //!< width of the rectangle
    _Tp height; //!< height of the rectangle
};

5、RotatedRect类

RotatedRect类表示一个矩形,包含成员变量为中心点坐标、长宽和旋转角度,代表矩形饶中心点旋转的角度。

class CV_EXPORTS RotatedRect
{
public:
    //! default constructor
    RotatedRect();
    /** full constructor
    @param center The rectangle mass center.
    @param size Width and height of the rectangle.
    @param angle The rotation angle in a clockwise direction. When the angle is 0, 90, 180, 270 etc.,
    the rectangle becomes an up-right rectangle.
    */
    RotatedRect(const Point2f& center, const Size2f& size, float angle);
    /**
    Any 3 end points of the RotatedRect. They must be given in order (either clockwise or
    anticlockwise).
     */
    RotatedRect(const Point2f& point1, const Point2f& point2, const Point2f& point3);

    /** returns 4 vertices of the rectangle
    @param pts The points array for storing rectangle vertices. The order is bottomLeft, topLeft, topRight, bottomRight.
    */
    void points(Point2f pts[]) const;
    //! returns the minimal up-right integer rectangle containing the rotated rectangle
    Rect boundingRect() const;
    //! returns the minimal (exact) floating point rectangle containing the rotated rectangle, not intended for use with images
    Rect_<float> boundingRect2f() const;
    //! returns the rectangle mass center
    Point2f center;
    //! returns width and height of the rectangle
    Size2f size;
    //! returns the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle.
    float angle;
};

6、复数类

复数类包含re和im两个成员变量,其模板类和宏定义如下:

typedef Complex<float> Complexf;
typedef Complex<double> Complexd;
template<typename _Tp> class Complex
{
public:

    //! default constructor
    Complex();
    Complex( _Tp _re, _Tp _im = 0 );

    //! conversion to another data type
    template<typename T2> operator Complex<T2>() const;
    //! 共轭
    Complex conj() const;

    _Tp re, im; //< the real and the imaginary parts
};

typedef Complex<float> Complexf;
typedef Complex<double> Complexd;

7、range类

range类是一个普通的类,表示一个区间范围start和end,数据类型为int:

class CV_EXPORTS Range
{
public:
    Range();
    Range(int _start, int _end);
    int size() const;
    bool empty() const;
    static Range all();

    int start, end;
};

8、固定矩阵类

固定矩阵类是OpenCV中比较核心的部分,为模板类Matx,创建时需要已知行列数和数据类型。

要表示一个用来处理矩阵代数的矩阵的时候,就会用到矩阵类,如果是图像或者大型点列表这样的大数组,应该使用cv::Mat。

template<typename _Tp, int m, int n> class Matx;

//实例类型有以下类型
typedef Matx<float, 1, 2> Matx12f;
typedef Matx<double, 1, 2> Matx12d;
typedef Matx<float, 1, 3> Matx13f;
typedef Matx<double, 1, 3> Matx13d;
typedef Matx<float, 1, 4> Matx14f;
typedef Matx<double, 1, 4> Matx14d;
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, 3, 1> Matx31f;
typedef Matx<double, 3, 1> Matx31d;
typedef Matx<float, 4, 1> Matx41f;
typedef Matx<double, 4, 1> Matx41d;
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, 2, 3> Matx23f;
typedef Matx<double, 2, 3> Matx23d;
typedef Matx<float, 3, 2> Matx32f;
typedef Matx<double, 3, 2> Matx32d;

typedef Matx<float, 3, 3> Matx33f;
typedef Matx<double, 3, 3> Matx33d;

typedef Matx<float, 3, 4> Matx34f;
typedef Matx<double, 3, 4> Matx34d;
typedef Matx<float, 4, 3> Matx43f;
typedef Matx<double, 4, 3> Matx43d;

typedef Matx<float, 4, 4> Matx44f;
typedef Matx<double, 4, 4> Matx44d;
typedef Matx<float, 6, 6> Matx66f;
typedef Matx<double, 6, 6> Matx66d;
template<typename _Tp, int m, int n> class Matx
{
public:
    enum {
           rows     = m,
           cols     = n,
           channels = rows*cols,
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
           depth    = traits::Type<_Tp>::value,
           type     = CV_MAKETYPE(depth, channels),
#endif
           shortdim = (m < n ? m : n)
         };

    typedef _Tp                           value_type;
    typedef Matx<_Tp, m, n>               mat_type;
    typedef Matx<_Tp, shortdim, 1> diag_type;

    //下面是构造函数,对应各种行列数
    Matx();

    explicit Matx(_Tp v0); //!< 1x1 matrix
    Matx(_Tp v0, _Tp v1); //!< 1x2 or 2x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2); //!< 1x3 or 3x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 1x4, 2x2 or 4x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 1x5 or 5x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 1x6, 2x3, 3x2 or 6x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 1x7 or 7x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 1x8, 2x4, 4x2 or 8x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 1x9, 3x3 or 9x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 1x10, 2x5 or 5x2 or 10x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
         _Tp v4, _Tp v5, _Tp v6, _Tp v7,
         _Tp v8, _Tp v9, _Tp v10, _Tp v11); //!< 1x12, 2x6, 3x4, 4x3, 6x2 or 12x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
         _Tp v4, _Tp v5, _Tp v6, _Tp v7,
         _Tp v8, _Tp v9, _Tp v10, _Tp v11,
         _Tp v12, _Tp v13); //!< 1x14, 2x7, 7x2 or 14x1 matrix
    Matx(_Tp v0, _Tp v1, _Tp v2, _Tp v3,
         _Tp v4, _Tp v5, _Tp v6, _Tp v7,
         _Tp v8, _Tp v9, _Tp v10, _Tp v11,
         _Tp v12, _Tp v13, _Tp v14, _Tp v15); //!< 1x16, 4x4 or 16x1 matrix
    explicit Matx(const _Tp* vals); //!< initialize from a plain array

    Matx(std::initializer_list<_Tp>); //!< initialize from an initializer list

    static Matx all(_Tp alpha); //统一元素矩阵
    static Matx zeros(); //零矩阵
    static Matx ones();  //全一矩阵
    static Matx eye();  //单位矩阵
    static Matx diag(const diag_type& d); //对角阵
    static Matx randu(_Tp a, _Tp b); //均匀分布矩阵
    static Matx randn(_Tp a, _Tp b); //正态分布矩阵

    //点乘
    _Tp dot(const Matx<_Tp, m, n>& v) const;

    //双精度点乘
    double ddot(const Matx<_Tp, m, n>& v) const;

    //!数据类型转换
    template<typename T2> operator Matx<T2, m, n>() const;

    //改变矩阵形状
    template<int m1, int n1> Matx<_Tp, m1, n1> reshape() const;

    //提取子矩阵
    template<int m1, int n1> Matx<_Tp, m1, n1> get_minor(int i, int j) const;

    //提取行
    Matx<_Tp, 1, n> row(int i) const;

    //提取列
    Matx<_Tp, m, 1> col(int i) const;

    //提取对角阵
    diag_type diag() const;

    //转置
    Matx<_Tp, n, m> t() const;

    //求逆
    Matx<_Tp, n, m> inv(int method=DECOMP_LU, bool *p_is_ok = NULL) const;

    //解线性方程
    template<int l> Matx<_Tp, n, l> solve(const Matx<_Tp, m, l>& rhs, int flags=DECOMP_LU) const;
    Vec<_Tp, n> solve(const Vec<_Tp, m>& rhs, int method) const;

    //元素级乘法
    Matx<_Tp, m, n> mul(const Matx<_Tp, m, n>& a) const;

    //元素级除法
    Matx<_Tp, m, n> div(const Matx<_Tp, m, n>& a) const;

    //! element access
    const _Tp& operator ()(int i, int j) const;
    _Tp& operator ()(int i, int j);

    //! 1D element access
    const _Tp& operator ()(int i) const;
    _Tp& operator ()(int i);

    Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_AddOp);
    Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_SubOp);
    template<typename _T2> Matx(const Matx<_Tp, m, n>& a, _T2 alpha, Matx_ScaleOp);
    Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_MulOp);
    Matx(const Matx<_Tp, m, n>& a, const Matx<_Tp, m, n>& b, Matx_DivOp);
    template<int l> Matx(const Matx<_Tp, m, l>& a, const Matx<_Tp, l, n>& b, Matx_MatMulOp);
    Matx(const Matx<_Tp, n, m>& a, Matx_TOp);

    _Tp val[m*n]; //< matrix elements
};

调用方法:

m23d = cv::Matx23d::zeros();

m(i, j), m(i); //成员访问

m91f = m33f.reshape<9,1>();

m44f = (Matx44f) m44d;
	
m31f = m33f.solve(rhs31f, method);

9、固定向量类

固定向量类Vec由固定矩阵类派生得到,为列向量,创建时需要已知元素个数和数据类型。

template<typename _Tp, int cn> class Vec;

//实例如下
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<ushort, 2> Vec2w;
typedef Vec<ushort, 3> Vec3w;
typedef Vec<ushort, 4> Vec4w;

typedef Vec<int, 2> Vec2i;
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<int, 6> Vec6i;
typedef Vec<int, 8> Vec8i;

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;
template<typename _Tp, int cn> class Vec : public Matx<_Tp, cn, 1>
{
public:
    typedef _Tp value_type;
    enum {
           channels = cn,
#ifdef OPENCV_TRAITS_ENABLE_DEPRECATED
           depth    = Matx<_Tp, cn, 1>::depth,
           type     = CV_MAKETYPE(depth, channels),
#endif
           _dummy_enum_finalizer = 0
         };

    //构造函数
    Vec();

    Vec(_Tp v0); //!< 1-element vector constructor
    Vec(_Tp v0, _Tp v1); //!< 2-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2); //!< 3-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3); //!< 4-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4); //!< 5-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5); //!< 6-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6); //!< 7-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7); //!< 8-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8); //!< 9-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9); //!< 10-element vector constructor
    Vec(_Tp v0, _Tp v1, _Tp v2, _Tp v3, _Tp v4, _Tp v5, _Tp v6, _Tp v7, _Tp v8, _Tp v9, _Tp v10, _Tp v11, _Tp v12, _Tp v13); //!< 14-element vector constructor
    explicit Vec(const _Tp* values);

    Vec(std::initializer_list<_Tp>);

    Vec(const Vec<_Tp, cn>& v);

    static Vec all(_Tp alpha); //统一元素向量

    //元素级相乘
    Vec mul(const Vec<_Tp, cn>& v) const;

    //! conjugation (makes sense for complex numbers and quaternions)
    Vec conj() const;

    /*!
      cross product of the two 3D vectors.

      For other dimensionalities the exception is raised
    */
    Vec cross(const Vec& v) const;
    //数据类型
    template<typename T2> operator Vec<T2, cn>() const;

    /*! element access */
    const _Tp& operator [](int i) const;
    _Tp& operator[](int i);
    const _Tp& operator ()(int i) const;
    _Tp& operator ()(int i);

    Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_AddOp);
    Vec(const Matx<_Tp, cn, 1>& a, const Matx<_Tp, cn, 1>& b, Matx_SubOp);
    template<typename _T2> Vec(const Matx<_Tp, cn, 1>& a, _T2 alpha, Matx_ScaleOp);
};

调用:

v4f[i]; v3w(j); //元素访问,可以通过单个数索引各项

二、矩阵类型

1、CvMat

OpenCV中常用的矩阵类型有MatCvMatIplImage,其中CvMatIplImage为结构体,CvMat的定义如下:

struct CvMat
{
    int type; //元素类型
    int step; //以字节为单位的行数据长度

    /* for internal use only */
    int* refcount;
    int hdr_refcount;

    union
    {
        uchar* ptr;
        short* s;
        int* i;
        float* fl;
        double* db;
    } data; //数据指针

#ifdef __cplusplus
    union
    {
        int rows;
        int height;
    };

    union
    {
        int cols;
        int width;
    };
#else
    int rows;
    int cols;
#endif

#if defined(CV__ENABLE_C_API_CTORS) && defined(__cplusplus)
    CvMat() {}
    CvMat(const cv::Mat& m) { *this = cvMat(m); }
#endif
}
CvMat;

CvMat中的type成员用于标示元素类型和标记,OpenCV中用一系列的宏定义了可取的元素值,其中数据类型有8U、8S、16U、16S、32S、32F、64F

#define CV_8UC1 CV_MAKETYPE(CV_8U,1)

#define CV_8UC2 CV_MAKETYPE(CV_8U,2)

#define CV_8UC3 CV_MAKETYPE(CV_8U,3)

#define CV_8UC4 CV_MAKETYPE(CV_8U,4)

#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n))

对CvMat的初始化有以下几种方式:

CvMat* mat = cvCreateMat( 2, 2, CV_64FC1 ); //初始化

cvZero( mat );  //元素置为0

cvmSet( mat, 0, 0, 1 );  //(0,0) = 1,以下以此类推

cvmSet( mat, 0, 1, 2 );

cvmSet( mat, 1, 0, 3 );

cvmSet( mat, 2, 2, 4 );

cvReleaseMat( &mat ); //释放

//---------------------------------------------------

double a[12] = { 1, 2, 3, 4,
  5, 6, 7, 8,
  9, 10, 11, 12 };

CvMat mat = cvMat( 3, 4, CV_64FC1, a ); //使用指针初始化

2、ImlImage

可以说IplImage类型继承自CvMat类型,较之CvMat多了很多参数,当然还包括其他的变量将之解析成图像数据。其定义如下

typedef struct _IplImage IplImage;

struct
_IplImage
{
    int  nSize;             /**< sizeof(IplImage) */
    int  ID;                /**< version (=0)*/
    int  nChannels;         /**< Most of OpenCV functions support 1,2,3 or 4 channels */
    int  alphaChannel;      /**< Ignored by OpenCV */
    int  depth;             /**< Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S,
                               IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported.  */
    char colorModel[4];     /**< Ignored by OpenCV */
    char channelSeq[4];     /**< ditto */
    int  dataOrder;         /**< 0 - interleaved color channels, 1 - separate color channels.
                               cvCreateImage can only create interleaved images */
    int  origin;            /**< 0 - top-left origin,
                               1 - bottom-left origin (Windows bitmaps style).  */
    int  align;             /**< Alignment of image rows (4 or 8).
                               OpenCV ignores it and uses widthStep instead.    */
    int  width;             /**< Image width in pixels.                           */
    int  height;            /**< Image height in pixels.                          */
    struct _IplROI *roi;    /**< Image ROI. If NULL, the whole image is selected. */
    struct _IplImage *maskROI;      /**< Must be NULL. */
    void  *imageId;                 /**< "           " */
    struct _IplTileInfo *tileInfo;  /**< "           " */
    int  imageSize;         /**< Image data size in bytes
                               (==image->height*image->widthStep
                               in case of interleaved data)*/
    char *imageData;        /**< Pointer to aligned image data.         */
    int  widthStep;         /**< Size of aligned image row in bytes.    */
    int  BorderMode[4];     /**< Ignored by OpenCV.                     */
    int  BorderConst[4];    /**< Ditto.                                 */
    char *imageDataOrigin;  /**< Pointer to very origin of image data
                               (not necessarily aligned) -
                               needed for correct deallocation */

#if defined(CV__ENABLE_C_API_CTORS) && defined(__cplusplus)
    _IplImage() {}
    _IplImage(const cv::Mat& m) { *this = cvIplImage(m); }
#endif
}
IplImage;

可以直接将IplImage文件保存为图片:

IplImage img1;
//code
cvSaveImage("res.jpg",img1); //保存结果

3、Mat

Mat类可以被看做是OpenCV中C++版本的矩阵类,替代原来C版本的矩阵结构体CvMat和图像结构体IplImage;

Mat是一种高效的数据类型,它对内存进行动态的管理,不需要之前用户手动的管理内存。

Mat类定义于core.hpp中,成员变量主要包含有两部分数据:一部分是矩阵头(matrix header),这部分的大小是固定的,包含矩阵的大小,存储的方式,矩阵存储的地址等等;另一个部分是一个指向矩阵包含像素值的指针(data)。

Mat类的定义如下:

class CV_EXPORTS Mat
{
public:
    // ... a lot of methods ...
    ...
    
    /*! includes several bit-fields:
         - the magic signature
         - continuity flag
         - depth
         - number of channels
     */
    int flags;
    //! the matrix dimensionality, >= 2
    int dims;
    //! the number of rows and columns or (-1, -1) when the matrix has more than 2 dimensions
    int rows, cols;
    //! pointer to the data
    uchar* data;

    //! helper fields used in locateROI and adjustROI
    const uchar* datastart;
    const uchar* dataend;
    const uchar* datalimit;

    //! custom allocator
    MatAllocator* allocator;
    //! and the standard allocator
    static MatAllocator* getStdAllocator();
    static MatAllocator* getDefaultAllocator();
    static void setDefaultAllocator(MatAllocator* allocator);

    //! internal use method: updates the continuity flag
    void updateContinuityFlag();

    //! interaction with UMat
    UMatData* u;

    MatSize size;
    MatStep step;
};

数据类型:

Mat的存储是逐行存储的,矩阵中的数据类型包括:Mat_对应的是CV_8U,Mat_对应的是CV_8U,Mat_对应的是CV_8S,Mat_对应的是CV_32S,Mat_对应的是CV_32F,Mat_对应的是CV_64F,对应的数据深度如下:

• CV_8U - 8-bit unsigned integers ( 0..255 )

• CV_8S - 8-bit signed integers ( -128..127 )

• CV_16U - 16-bit unsigned integers ( 0..65535 )

• CV_16S - 16-bit signed integers ( -32768..32767 )

• CV_32S - 32-bit signed integers ( -2147483648..2147483647 )

• CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )

• CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )

初始化


数据类型转换

因为OpenCV包含多种矩阵类,通常需要在各种矩阵类之间进行数据转换,下面是几种转换方式:

1、IplImage -> cvMat

IplImage *img = cvLoadImage("pic.jpg");

CvMat mathdr,*mat1 = cvGetMat( img, &mathdr );

CvMat *mat2 = cvCreateMat( img->height, img->width, CV_64FC3 );
cvConvert( img, mat2 );

2、cvMat -> IplImage

IplImage* img1 = cvCreateImage(cvGetSize(mat1),8,1); //初始化大小
cvGetImage(mat1,img1); //转换
cvSaveImage("res.jpg",img1); //保存结果

参考资料

OpenCV中的数据类型

OpenCV中矩阵类详解之一:Mat

OpenCV学习之CvMat的用法详解及实例

OPenCV的几种数据转换方式