opencv2.0 DataType
2016-03-05 14:56
477 查看
从2.0开始,opencv采用c++来重写代码,既然是c++,自然少不了模板类,所以DataType是模板类的集合。
官方的描述:
DataType
是opencv最基础的数据类型了,它是一些c++基础数据类型的组合。
Point_ 类(在core.hpp里)
注:类名后面带下划线,这个是指模板类,以后不再重申。
可以看到,这是2维点的原型,成员边量就两个x,y. _Tp是模板类的参数,又被重命名为value_type了。
所以我们可以取_Tp为很多c++的基本数据类型,如int,float,double...
因此,就有一堆实际类了,
比如:Point_<int>,Point_<float>,Point_<double>
为了方便用户使用,opencv都给这些取了别名
其中,还为最最常用的Point_<int>取了别名
从上面可以看出opencv定义基本数据类型的套路...接下来的其他数据结构都是这样...所以后面部分可能不再这么详细解释...
Point3_(在core.hpp里)
3维的点的定义,多了一个z成员变量.
注意:此处没有再为Point3_<int>取别名了,可见Point3_<int>不及Point_<int>通用...
Size_(在core.hpp里)
这个类可以用来表示矩形或者图像的尺寸...它的两个属性是width和height,而不是rows和cols
常用的是int和float
Rect_(在core.hpp里)
这是个矩形类,他有4个成员,分别是矩形的左上角顶点坐标(x,y),宽度width和高度height
显然可以通过宽度和高度计算得到矩形的右下角坐标(x+width,y+height)...
注意:opencv规定了矩形的左边界和上边界属于这个矩形,下边界和右边界不属于这个矩形
常用的是int
RotatedRect(在core.hpp里)
这个不是模板类了,只支持float
旋转矩形,center是矩形的两条对角线的交点,size.width和size.height分别是矩形的宽和高,angle是旋转角度,所以这个矩形是可以倾斜的,于是我们可以发现up-right retangle其实就是矩形的边平行x轴和y轴的的情况。
关于angle这个参数在我的另一篇博客里细讲
opencv2.0 DataType 实现 ,在1.0版本中对应了Cvbox2D这个结构体...
Range(在core.hpp里)
这个也不是模板类
Range类可以理解为区间,可以用于提取矩阵的一行或者一列,成员变量就start和end,分别表示区间的起点和终点
注意:这是一个左闭右开的区间,相信熟悉STL的童鞋,对左闭右开这种写法很习惯了...
Matx(在core.hpp里)
这个类表示小矩阵,主要是在编译前你可以确定矩阵大小并且矩阵规模较小的情况,仔细看源码的定义,我们发现写库的人直接开了一个静态数组,这个写法感觉略粗糙啊,再吐槽一句吧,c++语法是不建议使用变量来作为数组大小的,可是源码里也直接开m*n了,这样感觉不符合写库的水平啊...
这个类常用的类就多了...可以发现主要是float和double...
Vec(在core.hpp里)
这个类继承自Matx,表示了一个cn行1列的矩阵了,注意一个比较蛋疼的问题是,这个分配的空间是在栈区,因为它继承自Matx,而这个写库的人很单纯的开了静态数组,而我们知道静态数组是占用栈空间的,当然如果定义成全局变量就另当别论了,于是又引出一个问题,写库人的本意是这个Vec也是规模很小的,所以千万注意不要开太大,ACMer一般都有经验,普通PC机栈区一般就几M,开个20000以上的就非常危险了。
注意:防止爆栈!!! 如果希望使用大的Vec,那就考虑使用std::vector,然而ACMer知道这玩意的效率是极低的...自己权衡吧
这个常用的也一大堆,可以看到出现了uchar和ushort,这个是opencv定义的宏,就是unsigned char 和 unsigned short ...
Scalar_(在core.hpp里)
这个继承自Vec,是一个4行1列的矩阵...
Mat(在core.hpp里)
这个类才是图像处理的神器,当然结构就复杂多了...这是一个表示2维的矩阵,如何表示2维,其实原理很简单,它使用的是1维数组来模拟2维数组...
这里我先介绍一下我知道的一些成员,剩余的以后遇见了再来补充。
先推荐我之前写的一篇博客
OpenCV CvMat 初窥 ,在这里你可以找到关于DEPTH和CN的解释...
在opencv1.0的CvMat里有1个type属性,这个到了2.0就对应了flags属性,经本人观察,这两个属性是一模一样,在前一篇博文里,我介绍了type是怎么编码的...
主要由4部分构成,DEPTH,CN,MAGIC,CONT,其中源码里也有注释...
DEPTH:矩阵数据的类型,目前就7类,参考前一篇博文
CN:通道数,常用的是1,2,3,n
CONT: 图像的连续性,这个是Intel为了利用他们的CPU加速,在存储图像时,往往会往矩阵里添加一些元素来使矩阵元素格式变成4或者8的倍数,便于CPU快速处理
MAGIC:暂时还不知道
其中flags里包含了这4部分信息,编码方式见前一篇博文
dims:这个表示矩阵的维数
rows,cols:矩阵的行数和列数
data:指向数据区域的指针
refcount:这个在opencv1.0的CvMat里也有,供内部使用,其实主要目的是表示这个矩阵实例被引用了多少次,主要方便操作系统来管理内存,当矩阵的引用次数为0时,这个空间会被自动析构,一般来说很多库都会来这样高效的管理内存,这是一种值得我们学习方法
datastart,dataend,datalimit:这个3个指针主要是同来管理ROI(感兴趣区域)的,以后再说.
allocator:这个是个迭代器,具体实现还不清楚,但可以猜测矩阵的有一种类似STL迭代器的遍历方式,大概与这个有关系,以后再说吧
size:是一个内部类,和维度有关系,size的*p在分配空间时,多分配了一个int*的空间,这个是用来存维数的,也就是size[-1]=dims,而对于size[i],i>=0表示第i维的长度
注意:我在书上发现一个误区,书本上说调用Mat的size()方法返回一个Size对象,这是错误的理解,因为Mat根本没有size()方法,实际上是Mat的成员size调用了()运算符,返回了Size对象,这里只能说写书的作者水平有限,没有仔细看Mat的结构
step: 这个类是方便用来寻址的,假设我们要找mat.data[i][j][k],当然不能这样写,因为data是一维数组,所以我们需要将高维地址转换为一维地址,而这个地址就是i*step[0]+j*step[1]+k*step[2],于是可以发现step[i]=step[i+1]*size[i+1] ,然而官方文档告诉我们step[i]>=step[i+1]*size[i+1]...为什么会大于呢?因为矩阵可能不连续存储,因此会在某些维后面补充些空白字节,也就是CONT标记的意义,所以导致了大于号的出现,后面我们会发现我们可以通过这个不等式来做很多事...
到此为止!
以后再补充...
官方的描述:
DataType
class DataType Template “trait” class for OpenCV primitive data types. A primitive OpenCV data type is one of unsigned char, bool, signed char, unsigned short, signed short, int, float, double, or a tuple of values of one of these types, where all the values in the tuple have the same type.
是opencv最基础的数据类型了,它是一些c++基础数据类型的组合。
Point_ 类(在core.hpp里)
注:类名后面带下划线,这个是指模板类,以后不再重申。
/*! template 2D point class. The class defines a point in 2D space. Data type of the point coordinates is specified as a template parameter. There are a few shorter aliases available for user convenience. See cv::Point, cv::Point2i, cv::Point2f and cv::Point2d. */ template<typename _Tp> class CV_EXPORTS Point_ { public: typedef _Tp value_type; // ... 略去所有函数 _Tp x, y; //< the point coordinates };
可以看到,这是2维点的原型,成员边量就两个x,y. _Tp是模板类的参数,又被重命名为value_type了。
所以我们可以取_Tp为很多c++的基本数据类型,如int,float,double...
因此,就有一堆实际类了,
比如:Point_<int>,Point_<float>,Point_<double>
为了方便用户使用,opencv都给这些取了别名
/*! \typedef shorter aliases for the most popular cv::Point_<> specializations */ typedef Point_<int> Point2i; typedef Point_<float> Point2f; typedef Point_<double> Point2d;
其中,还为最最常用的Point_<int>取了别名
typedef Point2i Point;
从上面可以看出opencv定义基本数据类型的套路...接下来的其他数据结构都是这样...所以后面部分可能不再这么详细解释...
Point3_(在core.hpp里)
/*! template 3D point class. The class defines a point in 3D space. Data type of the point coordinates is specified as a template parameter. \see cv::Point3i, cv::Point3f and cv::Point3d */ template<typename _Tp> class CV_EXPORTS Point3_ { public: typedef _Tp value_type; // ... 略去所有函数 _Tp x, y, z; //< the point coordinates };
3维的点的定义,多了一个z成员变量.
/*! \typedef shorter aliases for the most popular cv::Point3_<> specializations */ typedef Point3_<int> Point3i; typedef Point3_<float> Point3f; typedef Point3_<double> Point3d;
注意:此处没有再为Point3_<int>取别名了,可见Point3_<int>不及Point_<int>通用...
Size_(在core.hpp里)
/*! The 2D size class The class represents the size of a 2D rectangle, image size, matrix size etc. Normally, cv::Size ~ cv::Size_<int> is used. */ template<typename _Tp> class CV_EXPORTS Size_ { public: typedef _Tp value_type; // ...略去所有函数 _Tp width, height; // the width and the height };
这个类可以用来表示矩形或者图像的尺寸...它的两个属性是width和height,而不是rows和cols
typedef Size_<int> Size2i; typedef Size_<float> Size2f;
常用的是int和float
typedef Size2i Size;
Rect_(在core.hpp里)
/*! The 2D up-right rectangle class The class represents a 2D rectangle with coordinates of the specified data type. Normally, cv::Rect ~ cv::Rect_<int> is used. */ template<typename _Tp> class CV_EXPORTS Rect_ { public: typedef _Tp value_type; // 略去所有函数 _Tp x, y, width, height; //< the top-left corner, as well as width and height of the rectangle };
这是个矩形类,他有4个成员,分别是矩形的左上角顶点坐标(x,y),宽度width和高度height
显然可以通过宽度和高度计算得到矩形的右下角坐标(x+width,y+height)...
注意:opencv规定了矩形的左边界和上边界属于这个矩形,下边界和右边界不属于这个矩形
typedef Rect_<int> Rect;
常用的是int
RotatedRect(在core.hpp里)
/*! The rotated 2D rectangle. The class represents rotated (i.e. not up-right) rectangles on a plane. Each rectangle is described by the center point (mass center), length of each side (represented by cv::Size2f structure) and the rotation angle in degrees. */ class CV_EXPORTS RotatedRect { public: // ...略去所有函数 Point2f center; //< the rectangle mass center Size2f size; //< width and height of the rectangle float angle; //< the rotation angle. When the angle is 0, 90, 180, 270 etc., the rectangle becomes an up-right rectangle. };
这个不是模板类了,只支持float
旋转矩形,center是矩形的两条对角线的交点,size.width和size.height分别是矩形的宽和高,angle是旋转角度,所以这个矩形是可以倾斜的,于是我们可以发现up-right retangle其实就是矩形的边平行x轴和y轴的的情况。
关于angle这个参数在我的另一篇博客里细讲
opencv2.0 DataType 实现 ,在1.0版本中对应了Cvbox2D这个结构体...
Range(在core.hpp里)
/*! The 2D range class This is the class used to specify a continuous subsequence, i.e. part of a contour, or a column span in a matrix. */ class CV_EXPORTS Range { public: // ...略去所有函数 int start, end; };
这个也不是模板类
Range类可以理解为区间,可以用于提取矩阵的一行或者一列,成员变量就start和end,分别表示区间的起点和终点
注意:这是一个左闭右开的区间,相信熟悉STL的童鞋,对左闭右开这种写法很习惯了...
Matx(在core.hpp里)
////////////////////////////// Small Matrix /////////////////////////// template<typename _Tp, int m, int n> class CV_EXPORTS Matx { public: typedef _Tp value_type; typedef Matx<_Tp, MIN(m, n), 1> diag_type; typedef Matx<_Tp, m, n> mat_type; enum { depth = DataDepth<_Tp>::value, rows = m, cols = n, channels = rows*cols, type = CV_MAKETYPE(depth, channels) }; // ... _Tp val[m*n]; //< matrix elements };
这个类表示小矩阵,主要是在编译前你可以确定矩阵大小并且矩阵规模较小的情况,仔细看源码的定义,我们发现写库的人直接开了一个静态数组,这个写法感觉略粗糙啊,再吐槽一句吧,c++语法是不建议使用变量来作为数组大小的,可是源码里也直接开m*n了,这样感觉不符合写库的水平啊...
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;
这个类常用的类就多了...可以发现主要是float和double...
Vec(在core.hpp里)
/*! A short numerical vector. This template class represents short numerical vectors (of 1, 2, 3, 4 ... elements) on which you can perform basic arithmetical operations, access individual elements using [] operator etc. The vectors are allocated on stack, as opposite to std::valarray, std::vector, cv::Mat etc., which elements are dynamically allocated in the heap. The template takes 2 parameters: -# _Tp element type -# cn the number of elements In addition to the universal notation like Vec<float, 3>, you can use shorter aliases for the most popular specialized variants of Vec, e.g. Vec3f ~ Vec<float, 3>. */ template<typename _Tp, int cn> class CV_EXPORTS Vec : public Matx<_Tp, cn, 1> { public: typedef _Tp value_type; enum { depth = DataDepth<_Tp>::value, channels = cn, type = CV_MAKETYPE(depth, channels) }; // ... };
这个类继承自Matx,表示了一个cn行1列的矩阵了,注意一个比较蛋疼的问题是,这个分配的空间是在栈区,因为它继承自Matx,而这个写库的人很单纯的开了静态数组,而我们知道静态数组是占用栈空间的,当然如果定义成全局变量就另当别论了,于是又引出一个问题,写库人的本意是这个Vec也是规模很小的,所以千万注意不要开太大,ACMer一般都有经验,普通PC机栈区一般就几M,开个20000以上的就非常危险了。
注意:防止爆栈!!! 如果希望使用大的Vec,那就考虑使用std::vector,然而ACMer知道这玩意的效率是极低的...自己权衡吧
/* \typedef Shorter aliases for the most popular specializations of Vec<T,n> */ 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;
这个常用的也一大堆,可以看到出现了uchar和ushort,这个是opencv定义的宏,就是unsigned char 和 unsigned short ...
Scalar_(在core.hpp里)
//////////////////////////////// Scalar_ /////////////////////////////// /*! The template scalar class. This is partially specialized cv::Vec class with the number of elements = 4, i.e. a short vector of four elements. Normally, cv::Scalar ~ cv::Scalar_<double> is used. */ template<typename _Tp> class CV_EXPORTS Scalar_ : public Vec<_Tp, 4> { public: // ... };
这个继承自Vec,是一个4行1列的矩阵...
typedef Scalar_<double> Scalar;
Mat(在core.hpp里)
/*! The n-dimensional matrix class. The class represents an n-dimensional dense numerical array that can act as a matrix, image, optical flow map, 3-focal tensor etc. It is very similar to CvMat and CvMatND types from earlier versions of OpenCV, and similarly to those types, the matrix can be multi-channel. It also fully supports ROI mechanism. */ class CV_EXPORTS Mat { public: enum { MAGIC_VAL=0x42FF0000, AUTO_STEP=0, CONTINUOUS_FLAG=CV_MAT_CONT_FLAG, SUBMATRIX_FLAG=CV_SUBMAT_FLAG }; /*! 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; //! pointer to the reference counter; // when matrix points to user-allocated data, the pointer is NULL int* refcount; //! helper fields used in locateROI and adjustROI uchar* datastart; uchar* dataend; uchar* datalimit; //! custom allocator MatAllocator* allocator; struct CV_EXPORTS MSize { MSize(int* _p); Size operator()() const; const int& operator[](int i) const; int& operator[](int i); operator const int*() const; bool operator == (const MSize& sz) const; bool operator != (const MSize& sz) const; int* p; }; struct CV_EXPORTS MStep { MStep(); MStep(size_t s); const size_t& operator[](int i) const; size_t& operator[](int i); operator size_t() const; MStep& operator = (size_t s); size_t* p; size_t buf[2]; protected: MStep& operator = (const MStep&); }; MSize size; MStep step; };
这个类才是图像处理的神器,当然结构就复杂多了...这是一个表示2维的矩阵,如何表示2维,其实原理很简单,它使用的是1维数组来模拟2维数组...
这里我先介绍一下我知道的一些成员,剩余的以后遇见了再来补充。
先推荐我之前写的一篇博客
OpenCV CvMat 初窥 ,在这里你可以找到关于DEPTH和CN的解释...
在opencv1.0的CvMat里有1个type属性,这个到了2.0就对应了flags属性,经本人观察,这两个属性是一模一样,在前一篇博文里,我介绍了type是怎么编码的...
主要由4部分构成,DEPTH,CN,MAGIC,CONT,其中源码里也有注释...
DEPTH:矩阵数据的类型,目前就7类,参考前一篇博文
CN:通道数,常用的是1,2,3,n
CONT: 图像的连续性,这个是Intel为了利用他们的CPU加速,在存储图像时,往往会往矩阵里添加一些元素来使矩阵元素格式变成4或者8的倍数,便于CPU快速处理
MAGIC:暂时还不知道
其中flags里包含了这4部分信息,编码方式见前一篇博文
dims:这个表示矩阵的维数
rows,cols:矩阵的行数和列数
data:指向数据区域的指针
refcount:这个在opencv1.0的CvMat里也有,供内部使用,其实主要目的是表示这个矩阵实例被引用了多少次,主要方便操作系统来管理内存,当矩阵的引用次数为0时,这个空间会被自动析构,一般来说很多库都会来这样高效的管理内存,这是一种值得我们学习方法
datastart,dataend,datalimit:这个3个指针主要是同来管理ROI(感兴趣区域)的,以后再说.
allocator:这个是个迭代器,具体实现还不清楚,但可以猜测矩阵的有一种类似STL迭代器的遍历方式,大概与这个有关系,以后再说吧
size:是一个内部类,和维度有关系,size的*p在分配空间时,多分配了一个int*的空间,这个是用来存维数的,也就是size[-1]=dims,而对于size[i],i>=0表示第i维的长度
inline Mat::MSize::MSize(int* _p) : p(_p) {} inline Size Mat::MSize::operator()() const { CV_DbgAssert(p[-1] <= 2); return Size(p[1], p[0]); } inline const int& Mat::MSize::operator[](int i) const { return p[i]; } inline int& Mat::MSize::operator[](int i) { return p[i]; } inline Mat::MSize::operator const int*() const { return p; } inline bool Mat::MSize::operator == (const MSize& sz) const { int d = p[-1], dsz = sz.p[-1]; if( d != dsz ) return false; if( d == 2 ) return p[0] == sz.p[0] && p[1] == sz.p[1]; for( int i = 0; i < d; i++ ) if( p[i] != sz.p[i] ) return false; return true; } inline bool Mat::MSize::operator != (const MSize& sz) const { return !(*this == sz); }注意:size没有默认构造函数,因此Mat的构造函数必须调用size(int*)的构造方法来初始化size,size重载了[]运算符,返回的是引用,所以size[i]完全等价于size.p[i],注意当dims=2时,size[0]和rows的地址是相同的,size[1]和cols的地址也是相同的...
注意:我在书上发现一个误区,书本上说调用Mat的size()方法返回一个Size对象,这是错误的理解,因为Mat根本没有size()方法,实际上是Mat的成员size调用了()运算符,返回了Size对象,这里只能说写书的作者水平有限,没有仔细看Mat的结构
step: 这个类是方便用来寻址的,假设我们要找mat.data[i][j][k],当然不能这样写,因为data是一维数组,所以我们需要将高维地址转换为一维地址,而这个地址就是i*step[0]+j*step[1]+k*step[2],于是可以发现step[i]=step[i+1]*size[i+1] ,然而官方文档告诉我们step[i]>=step[i+1]*size[i+1]...为什么会大于呢?因为矩阵可能不连续存储,因此会在某些维后面补充些空白字节,也就是CONT标记的意义,所以导致了大于号的出现,后面我们会发现我们可以通过这个不等式来做很多事...
inline Mat::MStep::MStep() { p = buf; p[0] = p[1] = 0; } inline Mat::MStep::MStep(size_t s) { p = buf; p[0] = s; p[1] = 0; } inline const size_t& Mat::MStep::operator[](int i) const { return p[i]; } inline size_t& Mat::MStep::operator[](int i) { return p[i]; } inline Mat::MStep::operator size_t() const { CV_DbgAssert( p == buf ); return buf[0]; } inline Mat::MStep& Mat::MStep::operator = (size_t s) { CV_DbgAssert( p == buf ); buf[0] = s; return *this; }我们发现里面还有个buf数组,这个是干什么的呢?这个buf只有当dims<=2的时候发挥作用,此时p=buf了...后面会发现opencv中的Mat的dims是不会等于1的...所以只剩dims=0和dims=2的情况了...同理重载了[]运算符,step()返回的是buf[0]...
到此为止!
以后再补充...
相关文章推荐
- Apache高级篇------页面重定向!!!
- Apache高级篇------页面重定向!!!
- linux文件系统
- Linux内核分析——操作系统是如何工作的
- Apache Felix Event Admin在ServiceMix容器下使用
- truncate 和 drop table 的区别
- 如何在linux上定时执行程序
- linux内核移植、配置及nfs文件系统挂载
- linux下定时运行打开网页url链接
- shell脚本编写汇集
- 【安装虚拟机和linux系统ubuntu14.04遇到的问题】
- 三层架构中bll层把datatable转换为实体model的理解
- apache的三种虚拟主机应用场景!!!
- 什么是Linux 什么又是web服务器
- Linux内核分析作业第二周
- 在新的主机上部署网站遇到的问题
- 学习linux决心书
- PHP识别电脑还是手机访问网站
- linux下面自动打包备份并且删除5 天前的文件
- linux分页机制