OpenCV基本数据类型

Point_

[cpp]  view plain copy
  1. typedef Point_<int> Point2i;  
  2. typedef Point2i Point;  
  3. typedef Point_<float> Point2f;  
  4. typedef Point_<double> Point2d;  

Point3_

[cpp]  view plain copy
  1. typedef Point3_<int> Point3i;  
  2. typedef Point3_<float> Point3f;  
  3. typedef Point3_<double> Point3d;  

Size_

[html]  view plain copy
  1. typedef Size_<int> Size2i;  
  2. typedef Size2i Size;  
  3. typedef Size_<float> Size2f;  

Rect_

[cpp]  view plain copy
  1. typedef Rect_<int> Rect;  

Matx

[cpp]  view plain copy
  1. typedef Matx<float,1,2> Matx12f;  
  2. typedef Matx<double,1,2> Matx12d;  
  3. ...  

Vec

[cpp]  view plain copy
  1. typedef Vec<uchar, 2> Vec2b;  
  2. typedef Vec<short,3> Vec3s;  
  3. typedef Vec<int, 4> Vec4i;  
  4. typddef Vec<float,6> Vec6i;  
  5. ...  

Scalar_

[cpp]  view plain copy
  1. typedef Scalar_<double> Scalar;  

Range

[cpp]  view plain copy
  1. class Range  
  2. {  
  3. public:  
  4. ...  
  5. int start, end;  
  6. };  

ex:取A的全部行,和 1到179列
[cpp]  view plain copy
  1. Mat A = imread("b.jpg", CV_LOAD_IMAGE_COLOR);  
  2. Mat B = A(Range::all(), Range(1, 180));  

Mat

创建复杂的矩阵

[cpp]  view plain copy
  1. // make a 7x7 complex matrix filled with 1+3j.  
  2. Mat M(7,7,CV_32FC2,Scalar(1,3));  
  3. // and now turn M to a 100x60 15-channel 8-bit matrix.  
  4. // The old content will be deallocated  
  5. M.create(100,60,CV_8UC(15));  
多维数组

[cpp]  view plain copy
  1. // create a 100x100x100 8-bit array  
  2. int sz[] = {100, 100, 100};  
  3. Mat bigCube(3, sz, CV_8U, Scalar::all(0));  
矩阵行操作

[cpp]  view plain copy
  1. // add the 5-th row, multiplied by 3 to the 3rd row  
  2. M.row(3) = M.row(3) + M.row(5)*3;  

矩阵列操作

[cpp]  view plain copy
  1. // now copy the 7-th column to the 1-st column  
  2. // M.col(1) = M.col(7); // this will not work  
  3. Mat M1 = M.col(1);  
  4. M.col(7).copyTo(M1);  

locateROI使用

[cpp]  view plain copy
  1. Mat A = Mat::eye(10, 10, CV_32S);  
  2. // extracts A columns, 1 (inclusive) to 3 (exclusive).  
  3. Mat B = A(Range::all(), Range(1, 3));  
  4. // extracts B rows, 5 (inclusive) to 9 (exclusive).  
  5. // that is, C ~ A(Range(5, 9), Range(1, 3))  
  6. Mat C = B(Range(5, 9), Range::all());  
  7. Size size; Point ofs;  
  8. C.locateROI(size, ofs);  
  9. // size will be (width=10,height=10) and the ofs will be (x=1, y=5)  




矩阵元素访问:

指针加[ ] 

[cpp]  view plain copy
  1. int sum = 0;  
  2.     Mat M = Mat::eye(20, 20, CV_8UC1);  
  3.     for (int i=0; i < M.rows; i++)  
  4.     {  
  5.         const uchar* mi = M.ptr<uchar>(i);  
  6.         for (int j=0; j < M.cols; j++)  
  7.         {  
  8.             sum += mi[j];  
  9.         }  
  10.     }  

迭代

[cpp]  view plain copy
  1. MatConstIterator_<uchar> it = M.begin<uchar>(), it_end = M.end<uchar>();  
  2. for (; it != it_end; ++it)  
  3.     sum += *it;                                                                                         




首先介绍2维点对Point_,它的是一个模板类。我们可以直接访问数据成员x,y。它不仅定了+、-、==、!=这4个基本的操作,还定义了点乘、叉乘等操作。特别的这个类还提供了inside函数来判断一个点是否在矩形区域内。此外,还定义了一些其他的类型转化函数,比如转化为1.X版本的CvPoint。
为了方便使用,opencv又对常用的类型进行了定义:
typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;
typedef Point_<double> Point2d;


同理还有Point3_,只不过它是一个3维点(x,y,z)而已。它的常用类型是:
typedef Point3_<int> Point3i;
typedef Point3_<float> Point3f;
typedef Point3_<double> Point3d;


介绍完点,就可以介绍Size_了。它也是模板类。
typedef Size_<int> Size2i;
typedef Size2i Size;
typedef Size_<float> Size2f
Size能够访问的成员变量是height和width。还定义了area函数来求面积。其他的操作基本都是类型转化函数。


下来介绍Rect_模版类。它是由左上角点和长度、宽度定义的。在opecv中,一般定义为左开右闭区间。有意思的是,这个类竟然也提供了一个Rect+Point的函数,作用是对矩形的偏移,还有一个Rect + Size的函数,在左上角不变的情况下,重新调整矩形的大小。其他的操作还有与&和|,是求两个矩形的交集和并集。


除了基本的矩形之外,opecv还提供了一个可以旋转的矩形RotatedRect,它是由中心、变长、旋转角度决定的。你可以访问它的这三个成员,也可以使用points函数返回它的4个顶点,使用boundingRect求出它的外接矩形(非旋转),下面是一个例子:

[cpp]  view plain copy
  1. int main(void)  
  2. {  
  3.     Mat bg(200,200,CV_8UC3,Scalar(0));  
  4.     imshow("",bg);  
  5.     RotatedRect rRect(Point2f(100,100),Size(100,100),40);   
  6.     Point2f vertices[4];  
  7.     rRect.points(vertices);  
  8.     for(int i = 0; i < 4;++i)  
  9.         line(bg,vertices[i],vertices[(i+1)%4],Scalar(0,255,0));  
  10.     Rect brect = rRect.boundingRect();  
  11.     rectangle(bg,brect,Scalar(255,0,0));  
  12.     imshow("",bg);  
  13.     waitKey();  
  14.     return 0;  
  15. }  




下面介绍Matx类,这也是一个模板类,用来记录一些小的矩形。这些矩形在编译前大小就固定了:
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;


如果要使用灵活的矩形,还是用Mat吧。


下面介绍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<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;
它支持加、减、数乘、相等、不等、求范数等运算。




Scalar_类其实是用Vec<tp,4>派生下来的,也就是说,它是一个4元组:typedef Scalar_<double> Scalar;
他通常用来传递像素。


Range类用来指定连续的子序列。比如矩阵的一部分,比较简单,我们直接看定义:

[cpp]  view plain copy
  1. class CV_EXPORTS Range  
  2. {  
  3. public:  
  4.     Range();  
  5.     Range(int _start, int _end);  
  6.     Range(const CvSlice& slice);  
  7.     int size() const;  
  8.     bool empty() const;  
  9.     static Range all();  
  10.     operator CvSlice() const;  
  11.   
  12.     int start, end;  
  13. };  

讲完这些简单的类型之后,我们看一个非常重要的类型;Mat。Mat是opencv中的一种非常重要的数据结构,当刚开始使用时,我仅仅把它当做一个储存图像的数据结构,后来才慢慢理解,它不仅可以储存二维矩阵,也可以储存高维矩阵,这在模式识别、机器学习中是非常常用的。对于这类问题,我们就没有必要自己手动分配内存了,直接使用它们就可以了。这个类的内容很多,但opencv的帮助手册,很好的帮我们理清的其中的内容。
其中的核心数据成员data的储存方式在前一篇博客《我的OpenCV学习笔记(23):Mat中实际数据是如何保存的》中已经讨论过了,这里只做一个补充,就是多维情况:

[cpp]  view plain copy
  1. int main(void)  
  2. {  
  3.     int sz[]={4,5,6};  
  4.     Mat img(3,sz,CV_8U);//3维数组  
  5.     cout<<img.dims<<endl;  
  6.     cout<<img.size[0]<<endl;  
  7.     cout<<img.size[1]<<endl;  
  8.     cout<<img.size[2]<<endl;  
  9.   
  10.     cout<<img.step[0]<<endl;  
  11.     cout<<img.step[1]<<endl;  
  12.     cout<<img.step[2]<<endl;  
  13.     //遍历每个元素  
  14.     for(int i = 0; i < 4;++i)  
  15.     {  
  16.         for(int j = 0; j < 5;++j)  
  17.         {  
  18.             for(int k = 0; k < 6;++k)  
  19.             {  
  20.                 cout<<(int)*(B.data + B.step[0]*i + B.step[1]*j + B.step[2]*k)<<endl;  
  21.             }  
  22.         }  
  23.     }  
  24.     return 0;  
  25. }  
我们建立了一个3维数组,数组的每一维长度分别为4,5,6。这可以通过size来获得。由于每个第一维向量中包含5个第二维的数组,而每个第二维数组中又包含了6个第三维数组,所以第一维每增加一步,相当于整个地址移动了5*6.所以step[0],等于30.
下面我们主要是看看Mat提供的函数。
首先是构造函数,光构造函数就有很多种,这里介绍几种常用的方式:
1.使用(nrows, ncols, type),初始化2维矩阵
// 创建一个7*7的2通道浮点矩阵,通常这样的矩阵用来表示复矩阵
Mat M(7,7,CV_32FC2,Scalar(1,3));
//改变为100*60的15通道uchar矩阵,原先的数据将会被释放
M.create(100,60,CV_8UC(15));
创建高维矩阵
//创建100*100*100的3维矩阵
int sz[] = {100, 100, 100};
Mat bigCube(3, sz, CV_8U, Scalar::all(0));


下面是一些简单的对整行、整列的操作
// 第5行*3 + 第3行,这样的操作在线性代数中很常见
M.row(3) = M.row(3) + M.row(5)*3;


// 把第7列拷贝到第1列
// M.col(1) = M.col(7); // 不能这样写
Mat M1 = M.col(1);
M.col(7).copyTo(M1);


用源图像的一部分创建新图像
// 创建一个320*240的图像
Mat img(Size(320,240),CV_8UC3);
// 选择感兴趣区域
Mat roi(img, Rect(10,10,100,100));
// 将区域改为绿色,原图像也会发生修改
roi = Scalar(0,255,0);


B是A的[1,3)列,对B的修改会影响A

[cpp]  view plain copy
  1. int main(void)  
  2. {  
  3.     Mat A = Mat::eye(5,5,CV_8U);  
  4.   
  5.     Mat B = A(Range::all(),Range(1,3));  
  6.     B.setTo(100);  
  7.     for(int i = 0; i < 5;++i)  
  8.     {  
  9.         for(int j = 0; j < 5;++j)  
  10.         {  
  11.             cout<<(int)A.at<uchar>(i,j)<<endl;  
  12.         }  
  13.     }  
  14.     return 0;  
  15. }  

如果需要深拷贝,则使用clone方法。


对于初始化Mat,还有其他的一些方法:
比如Matlab风格的 zeros(), ones(), eye():
M += Mat::eye(M.rows, M.cols, CV_64F);


Mat M = (Mat_<double>(3,3) << 1, 0, 0, 0, 1, 0, 0, 0, 1);


如果是处理“外来”的数据,那么则在构造函数中加上data则会非常方便的将外来数据转化为Mat结构:

[cpp]  view plain copy
  1. void process_video_frame(const unsigned char* pixels,int width, int height, int step)  
  2. {  
  3.     Mat img(height, width, CV_8UC3, pixels, step);  
  4.     GaussianBlur(img, img, Size(7,7), 1.5, 1.5);  
  5. }  
  6.   
  7. double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}};  
  8. Mat M = Mat(3, 3, CV_64F, m).inv();  

特别的,对于与opencv1.X中的IplImage结构的交互:

[cpp]  view plain copy
  1. IplImage* img = cvLoadImage("greatwave.jpg", 1);  
  2. Mat mtx(img); // convert IplImage* -> Mat  
  3. CvMat oldmat = mtx; // convert Mat -> CvMat 




矩阵元素访问:

指针加[ ] 

[cpp]  view plain copy
  1. int sum = 0;  
  2.     Mat M = Mat::eye(20, 20, CV_8UC1);  
  3.     for (int i=0; i < M.rows; i++)  
  4.     {  
  5.         const uchar* mi = M.ptr<uchar>(i);  
  6.         for (int j=0; j < M.cols; j++)  
  7.         {  
  8.             sum += mi[j];  
  9.         }  
  10.     }  

迭代

[cpp]  view plain copy
  1. MatConstIterator_<uchar> it = M.begin<uchar>(), it_end = M.end<uchar>();  
  2. for (; it != it_end; ++it)  
  3.     sum += *it;                                                                                         
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值