当前位置: 代码迷 >> Android >> Android OpenCV中的几种根本数据结构
  详细解决方案

Android OpenCV中的几种根本数据结构

热度:113   发布时间:2016-04-27 22:22:55.0
Android OpenCV中的几种基本数据结构

本文的代码基于OpenCV for Android 3.0

矩阵的类型结构

在opencv中,矩阵的类型结构被定义在opencv2/core/cvdef.h中,如下

#define CV_CN_MAX     512#define CV_CN_SHIFT   3#define CV_DEPTH_MAX  (1 << CV_CN_SHIFT)#define CV_8U   0#define CV_8S   1#define CV_16U  2#define CV_16S  3#define CV_32S  4#define CV_32F  5#define CV_64F  6#define CV_USRTYPE1 7#define CV_MAT_DEPTH_MASK       (CV_DEPTH_MAX - 1)#define CV_MAT_DEPTH(flags)     ((flags) & CV_MAT_DEPTH_MASK)#define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT))#define CV_MAKE_TYPE CV_MAKETYPE#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))#define CV_8SC1 CV_MAKETYPE(CV_8S,1)#define CV_8SC2 CV_MAKETYPE(CV_8S,2)#define CV_8SC3 CV_MAKETYPE(CV_8S,3)#define CV_8SC4 CV_MAKETYPE(CV_8S,4)#define CV_8SC(n) CV_MAKETYPE(CV_8S,(n))#define CV_16UC1 CV_MAKETYPE(CV_16U,1)#define CV_16UC2 CV_MAKETYPE(CV_16U,2)#define CV_16UC3 CV_MAKETYPE(CV_16U,3)#define CV_16UC4 CV_MAKETYPE(CV_16U,4)#define CV_16UC(n) CV_MAKETYPE(CV_16U,(n))#define CV_16SC1 CV_MAKETYPE(CV_16S,1)#define CV_16SC2 CV_MAKETYPE(CV_16S,2)#define CV_16SC3 CV_MAKETYPE(CV_16S,3)#define CV_16SC4 CV_MAKETYPE(CV_16S,4)#define CV_16SC(n) CV_MAKETYPE(CV_16S,(n))#define CV_32SC1 CV_MAKETYPE(CV_32S,1)#define CV_32SC2 CV_MAKETYPE(CV_32S,2)#define CV_32SC3 CV_MAKETYPE(CV_32S,3)#define CV_32SC4 CV_MAKETYPE(CV_32S,4)#define CV_32SC(n) CV_MAKETYPE(CV_32S,(n))#define CV_32FC1 CV_MAKETYPE(CV_32F,1)#define CV_32FC2 CV_MAKETYPE(CV_32F,2)#define CV_32FC3 CV_MAKETYPE(CV_32F,3)#define CV_32FC4 CV_MAKETYPE(CV_32F,4)#define CV_32FC(n) CV_MAKETYPE(CV_32F,(n))#define CV_64FC1 CV_MAKETYPE(CV_64F,1)#define CV_64FC2 CV_MAKETYPE(CV_64F,2)#define CV_64FC3 CV_MAKETYPE(CV_64F,3)#define CV_64FC4 CV_MAKETYPE(CV_64F,4)#define CV_64FC(n) CV_MAKETYPE(CV_64F,(n))

可以看出都是通过一个CV_MAKETYPE宏定义的,该宏有两个参数,第一个参数是数据位深度,不同数据结构的位深度的值在前面的宏中定义过了,比如

CV_8U   8位无符号整型(0-255)CV_8S   8位有符号整型(-128-127)CV_16U  16位无符号整型(0-65535)CV_16S  16位有符号整型(-32768-32767)CV_32S  32位有符号整型(-2147483648-2147483647)CV_32F  32为浮点型CV_64F  64位浮点型

Depth的最大值为8,一般0到7,即CV_8U到CV_USRTYPE1,这个可以从宏

#define CV_CN_SHIFT   3#define CV_DEPTH_MAX  (1 << CV_CN_SHIFT)

看出CV_DEPTH_MAX 的值,1左移3就是8,这个值需要占3位

第二个参数指明每个元素的通道数,每个元素至少需要有一个通道数,直接使用CV_8U这样的类型表示的是一个通道

从宏

#define CV_CN_MAX     512

可以看出通道数最大是512,这个值需要占9位

CV_MAKETYPE这个宏就是将位深度depth作为低3位,通道数作为高9位,总共需要12位,形成一个type值,即矩阵类型。具体的计算过程见上面定义的几个宏CV_MAKETYPECV_MAT_DEPTHCV_MAT_DEPTH_MASK

你会发现这个过程和Android中的MeasureSpec类是如此相似

DataType模板类

DataType定义在opencv2/core/traits.hpp中,该类的作用主要是将一些基本数据类型转换为opencv中的矩阵类型。这个类涉及到一个c++的模板的特性,有兴趣搜索c++ traits,这里给出两篇参考文章

  • 【C++模版之旅】神奇的Traits
  • Step By Step(C++模板Trait)
template<typename _Tp> class DataType{public:    typedef _Tp         value_type;    typedef value_type  work_type;    typedef value_type  channel_type;    typedef value_type  vec_type;    enum { generic_type = 1,           depth        = -1,           channels     = 1,           fmt          = 0,           type = CV_MAKETYPE(depth, channels)         };};

我们可以调用DataType::type、DataType::type类似的结构去获得一个矩阵类型

Point_等模板类

内部有几个c++模板类,定义在opencv2/core/types.hpp

Point_是一个可以认为是一个点的封装,内部具有x,y属性,代表这个点的坐标,并重载了一些运算符

template<typename _Tp> class Point_{public:    typedef _Tp value_type;    // various constructors    Point_();    Point_(_Tp _x, _Tp _y);    Point_(const Point_& 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 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};

同时用typedef重新定义了float,int,double类型的点,默认情况下我们使用的Point是整型的

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

当然为了兼容c,定义了对应的结构体,结构体中也有x,y两个属性,如果是c++,则在对应的宏中增加构造函数等定义

typedef struct CvPoint{    int x;    int y;#ifdef __cplusplus    CvPoint(int _x = 0, int _y = 0): x(_x), y(_y) {}    template<typename _Tp>    CvPoint(const cv::Point_<_Tp>& pt): x((int)pt.x), y((int)pt.y) {}    template<typename _Tp>    operator cv::Point_<_Tp>() const { return cv::Point_<_Tp>(cv::saturate_cast<_Tp>(x), cv::saturate_cast<_Tp>(y)); }#endif}CvPoint;

浮点型的对应定义

typedef struct CvPoint2D32f{    float x;    float y;#ifdef __cplusplus    CvPoint2D32f(float _x = 0, float _y = 0): x(_x), y(_y) {}    template<typename _Tp>    CvPoint2D32f(const cv::Point_<_Tp>& pt): x((float)pt.x), y((float)pt.y) {}    template<typename _Tp>    operator cv::Point_<_Tp>() const { return cv::Point_<_Tp>(cv::saturate_cast<_Tp>(x), cv::saturate_cast<_Tp>(y)); }#endif}CvPoint2D32f;typedef struct CvPoint2D64f{    double x;    double y;}CvPoint2D64f;

立体空间的坐标系,也就是具有z坐标的定义

typedef struct CvPoint3D32f{    float x;    float y;    float z;#ifdef __cplusplus    CvPoint3D32f(float _x = 0, float _y = 0, float _z = 0): x(_x), y(_y), z(_z) {}    template<typename _Tp>    CvPoint3D32f(const cv::Point3_<_Tp>& pt): x((float)pt.x), y((float)pt.y), z((float)pt.z) {}    template<typename _Tp>    operator cv::Point3_<_Tp>() const { return cv::Point3_<_Tp>(cv::saturate_cast<_Tp>(x), cv::saturate_cast<_Tp>(y), cv::saturate_cast<_Tp>(z)); }#endif}CvPoint3D32f;typedef struct CvPoint3D64f{    double x;    double y;    double z;}CvPoint3D64f;

当然对应的c++中肯定是有这个类的

template<typename _Tp> class 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 Vec<_Tp, 3>& v);    Point3_& operator = (const Point3_& pt);    //! 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, y, z; //< the point coordinates};

同样用typedef定义了int,float,double类型

typedef Point3_<int> Point3i;typedef Point3_<float> Point3f;typedef Point3_<double> Point3d;

除了点,还有一个Size,里面有两个属性,width和height属性,内部结构和Point类的定义十分相似,还有对应的结构体CvSize

template<typename _Tp> class Size_{public:    typedef _Tp value_type;    //! various constructors    Size_();    Size_(_Tp _width, _Tp _height);    Size_(const Size_& 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;    _Tp width, height; // the width and the height};
typedef Size_<int> Size2i;typedef Size_<float> Size2f;typedef Size_<double> Size2d;typedef Size2i Size;
typedef struct CvSize{    int width;    int height;#ifdef __cplusplus    CvSize(int w = 0, int h = 0): width(w), height(h) {}    template<typename _Tp>    CvSize(const cv::Size_<_Tp>& sz): width(cv::saturate_cast<int>(sz.width)), height(cv::saturate_cast<int>(sz.height)) {}    template<typename _Tp>    operator cv::Size_<_Tp>() const { return cv::Size_<_Tp>(cv::saturate_cast<_Tp>(width), cv::saturate_cast<_Tp>(height)); }#endif}CvSize;typedef struct CvSize2D32f{    float width;    float height;#ifdef __cplusplus    CvSize2D32f(float w = 0, float h = 0): width(w), height(h) {}    template<typename _Tp>    CvSize2D32f(const cv::Size_<_Tp>& sz): width(cv::saturate_cast<float>(sz.width)), height(cv::saturate_cast<float>(sz.height)) {}    template<typename _Tp>    operator cv::Size_<_Tp>() const { return cv::Size_<_Tp>(cv::saturate_cast<_Tp>(width), cv::saturate_cast<_Tp>(height)); }#endif}CvSize2D32f;

下面这个类基本上算具备了Point和Size的所有属性,可以认为它是一个矩形,一旦有矩形左上角的坐标,以及宽度和高度,就可以表示这个矩形了。

template<typename _Tp> class Rect_{public:    typedef _Tp value_type;    //! various constructors    Rect_();    Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height);    Rect_(const Rect_& 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;    //! 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};
typedef Rect_<int> Rect2i;typedef Rect_<float> Rect2f;typedef Rect_<double> Rect2d;typedef Rect2i Rect;
typedef struct CvRect{    int x;    int y;    int width;    int height;#ifdef __cplusplus    CvRect(int _x = 0, int _y = 0, int w = 0, int h = 0): x(_x), y(_y), width(w), height(h) {}    template<typename _Tp>    CvRect(const cv::Rect_<_Tp>& r): x(cv::saturate_cast<int>(r.x)), y(cv::saturate_cast<int>(r.y)), width(cv::saturate_cast<int>(r.width)), height(cv::saturate_cast<int>(r.height)) {}    template<typename _Tp>    operator cv::Rect_<_Tp>() const { return cv::Rect_<_Tp>((_Tp)x, (_Tp)y, (_Tp)width, (_Tp)height); }#endif}CvRect;

Scalar_ 是一个四维向量,暂时你可以认为在使用颜色时,一个argb表示的颜色具有a,r,g,b四个值,刚好可以由Scalar_ 内部的四个属性表示

template<typename _Tp> class Scalar_ : public Vec<_Tp, 4>{public:    //! various constructors    Scalar_();    Scalar_(_Tp v0, _Tp v1, _Tp v2=0, _Tp v3=0);    Scalar_(_Tp v0);    template<typename _Tp2, int cn>    Scalar_(const Vec<_Tp2, cn>& v);    //! returns a scalar with all elements set to v0    static Scalar_<_Tp> all(_Tp v0);    //! conversion to another data type    template<typename T2> operator Scalar_<T2>() const;    //! per-element product    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;};

用typedef定义了Scalar

typedef Scalar_<double> Scalar;

对应的结构体数据结构

typedef struct CvScalar{    double val[4];#ifdef __cplusplus    CvScalar() {}    CvScalar(double d0, double d1 = 0, double d2 = 0, double d3 = 0) { val[0] = d0; val[1] = d1; val[2] = d2; val[3] = d3; }    template<typename _Tp>    CvScalar(const cv::Scalar_<_Tp>& s) { val[0] = s.val[0]; val[1] = s.val[1]; val[2] = s.val[2]; val[3] = s.val[3]; }    template<typename _Tp>    operator cv::Scalar_<_Tp>() const { return cv::Scalar_<_Tp>(cv::saturate_cast<_Tp>(val[0]), cv::saturate_cast<_Tp>(val[1]), cv::saturate_cast<_Tp>(val[2]), cv::saturate_cast<_Tp>(val[3])); }    template<typename _Tp, int cn>    CvScalar(const cv::Vec<_Tp, cn>& v)    {        int i;        for( i = 0; i < (cn < 4 ? cn : 4); i++ ) val[i] = v.val[i];        for( ; i < 4; i++ ) val[i] = 0;    }#endif}CvScalar;

Scalar类继承了Vec类,Vec被定义在opencv2/core/matx.hpp中,它表示向量

template<typename _Tp, int cn> class Vec : public Matx<_Tp, cn, 1>{public:    typedef _Tp value_type;    enum { depth    = Matx<_Tp, cn, 1>::depth,           channels = cn,           type     = CV_MAKETYPE(depth, channels)         };    //! default constructor    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    explicit Vec(const _Tp* values);    Vec(const Vec<_Tp, cn>& v);    static Vec all(_Tp alpha);    //! per-element multiplication    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;    //! conversion to another data type    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);};

用typedef定义了很多类型。。。

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;

除了这些类之外,这几个头文件中还定义了很多其他的基本数据类型,有兴趣自行查看

版权声明:本文为博主原创文章,未经博主允许不得转载。

  相关解决方案