首先介绍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 plaincopy
  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 plaincopy
  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. int start, end;
  12. };

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

[cpp] view plaincopy
  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. cout<<img.step[0]<<endl;
  10. cout<<img.step[1]<<endl;
  11. cout<<img.step[2]<<endl;
  12. //遍历每个元素
  13. for(int i = 0; i < 4;++i)
  14. {
  15. for(int j = 0; j < 5;++j)
  16. {
  17. for(int k = 0; k < 6;++k)
  18. {
  19. cout<<(int)*(B.data + B.step[0]*i + B.step[1]*j + B.step[2]*k)<<endl;
  20. }
  21. }
  22. }
  23. return 0;
  24. }

我们建立了一个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 plaincopy
  1. int main(void)
  2. {
  3. Mat A = Mat::eye(5,5,CV_8U);
  4. Mat B = A(Range::all(),Range(1,3));
  5. B.setTo(100);
  6. for(int i = 0; i < 5;++i)
  7. {
  8. for(int j = 0; j < 5;++j)
  9. {
  10. cout<<(int)A.at<uchar>(i,j)<<endl;
  11. }
  12. }
  13. return 0;
  14. }

如果需要深拷贝,则使用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 plaincopy
  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. double m[3][3] = {{a, b, c}, {d, e, f}, {g, h, i}};
  7. Mat M = Mat(3, 3, CV_64F, m).inv();

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

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

说完了,构造、初始化,应该讨论元素访问的方法,这个在之前的博客中也有提过《我的OpenCV学习笔记(二):操作每个像素》这里就不再重复了。

OpenCV中的数据结构相关推荐

  1. OPENCV中图像数据结构及其转化

    OPENCV中图像数据结构及其转化 1. IplImage 它是openCV库中表示图像的结构体. 初始化: cvLoadImage(),cvCreateImage() 访问元素:[行指针] b = ...

  2. OPENCV中的数据结构总结

    最近在写自己的算法,其实就是对一些传统算法的改进.传统算法可以参考opecv的源代码.在阅读源代码的过程中,我慢慢领会到了opencv的强大之处,并不是因为它实现了各种算法,而是在于它对于基本数据结构 ...

  3. OpenCV中基本数据结构(4)_Rect

    Rect数据结构经常是在OpenCV中被用来表示为一个矩形尺寸,其成员包括x,y, width,height,其中x和y分别表示矩形框的左上角的起始点坐标,width和height分别表示宽和高. R ...

  4. OpenCV中基本数据结构(1)_Point

    为了便于对一些常见的数据进行操作,OpenCV定义了一些常见的数据结构(Point ,Scalar等),以方便后续对数据算法的实现,主要分为basic data type.helper objects ...

  5. OpenCV中基本数据结构(8)_Complex

    Complex为OpenCV中的复数表示类,与STL 中的complex类似但是不一样,两者可以互换,与STL的complex最大的不同是,STL中获取到实部和虚部的值 分别使用real()和imag ...

  6. OpenCV中基本数据结构(6)_Matx

    Matx为OpenCV轻量级的矩阵,被称为fixed matrix classes,意思是每个矩阵的大小都是固定的,主要是应对矩阵数据比较小的场景,最新的版本4.0不超过6*6大小的矩阵,旧版本一般不 ...

  7. OpenCV中基本数据结构(7)_Vec

    Vec系列数据结构是Matx的一个派生类,其矩阵的行的大小永远固定为一行,列大小从1到6不等,可以认为类似与C++ vector,但与C++ 的vector又有很大不同,,以下不同来自于一段技术博客, ...

  8. OpenCV中基本数据结构(5)_RotatedRect

    RotatedRect也是表示一个矩形框,但是与Rect不同的是,RotatedRect可以带倾斜角的矩形,如下图所示: RotatedRect结构中包括三个变量: Point2f center:为矩 ...

  9. OpenCV中Mat数据结构使用举例

    #include "stdafx.h" #include <string> #include <iostream> #include <opencv2 ...

最新文章

  1. Android 人脸识别
  2. 开源 java CMS - FreeCMS2.8 数据对象 applyopen
  3. 授权服务框架Spring Authorization Server的过滤器链
  4. 【Web安全】中国蚁剑+DVWA(本地文件上传漏洞Upload)
  5. 区块链系列教程之:比特币中的挖矿
  6. 机器学习对价格预测做模型与应用
  7. BZOJ_1629_[Usaco2007_Demo]_Cow_Acrobats_(贪心)
  8. 如何让机器像人一样多角度思考?
  9. VB快速查找大型文件中包含的字符串
  10. 数学概念的提出(一) —— 熵的定义式 H(x)=-log2(p(x))
  11. MODBUS ASCII协议和RTU协议的比较 -----和利时PLC采用Modbus RTU
  12. [转]人像识别是个伪命题
  13. valgrind 报告 ecpg内存泄露 (二)
  14. g4600黑苹果efi_Hackintosh黑苹果长期维护机型EFI列表及安装教程整理
  15. C# IE环境 - 重置IE( 注册表)
  16. 客户说发货慢怎么回复_物流走件慢回复话术
  17. Windows+Nvdia显卡配置Tensorflow
  18. MATLAB安装 C盘空间不足问题解决
  19. 百度地图 大头针设置本地图片与网络图片
  20. uniapp如何点击高亮,文字相对于整个页面左右居中显示?

热门文章

  1. 开发健壮的企业级应用的研究
  2. 用javah 导出类的头文件, 常见的错误及正确的使用方法
  3. 微软宣布推出Windows Embedded Compact 2013正式版
  4. 【Unity】Protobuf的使用与常见问题
  5. lustre1.6.5+drbd主备切换
  6. Rider首个发布候选版加入了性能提升特性
  7. CentOS系统搭建OpenERP
  8. 【web安全】Xss Exploits and Defense翻译2
  9. 中缀表达式转换成后缀表达式
  10. 【Python学习系列十八】基于scikit-learn库逻辑回归训练模型(delta比赛代码3)