OpenCV 第二课 认识图像的存储结构

Mat

Mat 类包含两部分,矩阵头和矩阵体。矩阵头包含矩阵的大小,存储方式和矩阵体存储空间的指针。因此,Mat中矩阵头的大小是固定的,矩阵体大小是不定的。

为了减少矩阵拷贝产生的计算消耗,opencv中一般使用引用计数方式处理矩阵,比如下面三种创建Mat的形式

  1. Mat A,C; //这里仅仅创建了矩阵头,具体矩阵体还没创建 

  2. A=imread(argv[1],CV_LOAD_IMAGE_COLOR); //给矩阵分配空间,并将首地址给了A 

  3. Mat B(A); //拷贝构造函数,B是A的拷贝,只是矩阵头不同 

  4. C=A; //赋值操作仍然指向的是同一块矩阵体地址。 

这时候使用任何一个Mat对象修改数据,其他的对象也会跟着变化。

如果想拷贝矩阵体,那么可以使用clone()和copyTo()函数。

  1. Mat F=A.clone(); 

  2. Mat G; 

  3. A.copyTo(G) 

为什么称为reference counting system呢,因为每次拷贝矩阵拷贝次数都加1,当一个拷贝结束时,拷贝次数减一,最后一个引用决定了这块地址什么时候释放。

需要注意的点:

  • Output image allocation for OpenCV functions is automatic (unless specified otherwise).

  • You do not need to think about memory management with OpenCVs C++ interface.

  • The assignment operator and the copy constructor only copies the header.

  • The underlying matrix of an image may be copied using the clone() and copyTo() functions


Mat的结构

  1. class CV_EXPORTS Mat 



  2. public: 

  3. int flags;//标志位 

  4. int dims;//维度>=2 

  5. int rows,cols;//行和列或者(-1,-1),此时数组超过了2维 

  6. uchar * data;//矩阵数据块的指针 

  7. int *refcount;//指针引用计数器 



Mat的构造函数

  1. #include "opencv2/imgproc/imgproc.hpp" 

  2. #include "opencv2/highgui/highgui.hpp" 

  3. #include <iostream> 

  4. #include<stdlib.h> 

  5. using namespace cv; 

  6. using namespace std; 


  7. int main() 



  8. Mat image1; //创建无初始化的矩阵 

  9. Mat image2(6, 6, CV_8UC1);//创建大小为6*6,8位unsigned单通道矩阵 

  10. Mat image3(Size(7, 7), CV_8UC3);//创建7*7的size,8位无符号3通道矩阵 

  11. Mat image4(8, 8, CV_32FC2, Scalar(1, 3));//创建8*8,32位浮点型2通道矩阵,赋值1+3j 

  12. Mat image5(Size(9, 9), CV_8UC3, Scalar(1, 2, 3));//创建9*9大小的矩阵,3通道,8位无符号型,每一个位置三个通道初始化值为(1,2,3) 

  13. Mat image6(image2);//使用已经创建的矩阵创建矩阵,这时候仅拷贝矩阵头,矩阵值指针是相同的 

  14. cout << image1 << endl; 

  15. cout << image2 << endl; 

  16. cout << image3 << endl;  

  17. cout << image4 << endl; 

  18. system("PAUSE"); 




1474894045162.jpg

看输出结果可以看出,Mat数据在存储时首先向同一个位置的多个通道值存储了再存储别的位置元素。


Mat的基本操作

  1. #include "opencv2/imgproc/imgproc.hpp" 

  2. #include "opencv2/highgui/highgui.hpp" 

  3. #include <iostream> 

  4. #include<stdlib.h> 

  5. using namespace cv; 

  6. using namespace std; 


  7. int main() 




  8. Mat image1(10, 8, CV_8UC1, Scalar(5)); 

  9. cout << "Image1 rows:" << image1.rows << endl; //行数 

  10. cout << "Image1 col:" << image1.cols << endl;//列数 

  11. cout << "Image channel:" << image1.channels ()<< endl;//通道,方法 


  12. cout << image1.rowRange(1, 3) << endl; //取1,2两行 

  13. cout << image1.colRange(1, 4) << endl;//取1,2,3列 


  14. Mat image2(8, 8, CV_32FC2, Scalar(1, 5)); 

  15. image2.create(10, 10, CV_8UC3);//create重建举着数据 


  16. //cout << image2 << endl; 

  17. image2.convertTo(image2, CV_32F);//类型转换 

  18. cout << "Image2 depth:" << image2.depth() << endl;//深度,方法 


  19. Mat image3 = Mat::zeros(image1.rows, image1.cols, CV_8UC1);//全零矩阵 

  20. Mat image4 = Mat::ones(image2.rows, image2.cols, CV_8UC1);//全一矩阵 

  21. image4.row(1) = image4.row(2) * 5; //矩阵行操作,列操作可以使用row(),col()函数直接操作 

  22. cout << image4 << endl; 


  23. Mat image5 = image2.row(2); 

  24. image1.row(1).copyTo(image5);//第一行拷贝到image5 

  25. cout << image5 << endl; 


  26. system("PAUSE"); 





OpenCV 第二课 认识图像的存储结构的更多相关文章

  1. 跟我一起学opencv 第二课之图像的掩膜操作

    1.掩膜(mask)概念 用选定的图像,图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程.用于覆盖的特定图像或物体称为掩模或模板.光学图像处理中,掩模可以足胶片,滤光片等 ...

  2. 跟我一起学opencv 第一课之图像加载,修改,保存

    使用opencv前记得引入库和头文件: #include<opencv2\opencv.hpp> 1.加载图像(cv::imread)(OPENCV 支持 JPG,PNG,TIFF等常见格 ...

  3. opencv第二课 进行缩放图片~

    #include<stdio.h> #include<iostream> #include<opencv2\opencv.hpp> using namespace ...

  4. opencv第二课,使用cmake编译OpenCV,并添加opencv_contrib模块

    一.下载安装cmake 想要在Windows平台下生成OpenCV的解决方案,我们需要一个名为cmake的开源软件,可以在camke的官网:http://www.cmake.org/上下载到 或者点击 ...

  5. 【ios开发学习 - 第二课】iOS项目文件夹结构

    文件夹结构 AppDelegate Models Macro General Helpers Vendors Sections Resources   一个合理的文件夹结构首先应该是清晰的.让人一眼看 ...

  6. OpenCV第二课,嵌入MFC

    单纯显示图片,只需链接 opencv_core2411d.libopencv_highgui2411d.lib 1.首先创建一个MFC的dlg,添加Picture Control控件 void CCO ...

  7. NeHe OpenGL教程 第十三课:图像字体

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  8. grails2.3.11第二课

    第二课主要介绍grails相关插件的使用,这是敏捷开发所必需的途径. 可以把grails的插件看作是grails正常项目的迷你型,因为看插件的源码,它的目录结构和正常项目相差无几. 官方开源插件地址 ...

  9. (续)一个demo弄清楚位图在内存中的存储结构

    本来续---数字图像处理之位图在计算机中的存储结构一文,通过参考别人的代码,进行修改和测试终于成功运行. 该实例未使用任何API和相关类,相信如果对此实例能够完全理解那么将有进一步进行数字图像处理的能 ...

随机推荐

  1. 方法重载的小demo

    方法的重载(overload)要求:1,同一个类中2,方法名必须相同3,方法的参数列表不同(1,参数的个数不同2,参数类型不同,但是参数名相同) 注:方法的重载与方法的返回值类型没有关系 packag ...

  2. String[] a = new String[]{"1","2"},我如果想增加一个"3"到a中,如何增加?

    在java中数组是定长的,当你声明了数组的大小后数组的长度就不能改变在你的程序中,数组的初始化大小为2,a[0]="1";a[1]="2",所以无法产生元素a[ ...

  3. Ubuntu离线更新flashplugin

    当网络太烂时,Ubuntu更新可能会卡在下载flashplugin上面,继而出错.在U论坛上找到一篇帖子,寻到成功安装flashplugin-installer的方法: 1.首先使用sudo apt- ...

  4. IT人学习方法论(二):学习误区

    之前我们讨论了“学什么”的问题,今天我们来谈一谈“怎么学”的问题.磨刀不误砍柴工,我们要提高学习效率,首先需要找到自己学习方法上的误区. 一些常见的学习方法误区 1)资料导向型 现在就停止阅读这篇文章 ...

  5. 浅谈我的编程之路——感谢引领我的leader

    在开发的道路上,就始终无法避开版本控制,哪怕你是独自一人进行开发,版本控制也是有必要的,从最早开始使用CVS,到后来使用SVN,再到git,最后又回到了SVN,但是不知道为什么真的对SVN很无爱. 现 ...

  6. SQL Server占用内存的认识

    SQL Server占用的内存主要由三部分组成:数据缓存(Data Buffer).执行缓存(Procedure Cache).以及SQL Server引擎程序.SQL Server引擎程序所占用缓存 ...

  7. Android Programming: Pushing the Limits -- Chapter 6: Services and Background Tasks

    什么时候使用Service 服务类型 开启服务 后台运行 服务通信 附加资源 什么时候使用Service: @.任何与用户界面无关的操作,可移到后台线程,然后由一个Service来控制这个线程. 服务 ...

  8. MVC缓存03,扩展方法实现视图缓存

    关于缓存,先前尝试了: ● 在"MVC缓存01,使用控制器缓存或数据层缓存"中,分别在控制器和Data Access Layer实现了缓存 ● 在"MVC缓存02,使用数 ...

  9. 设计模式学习之模板方法模式(TemplateMethod,行为型模式)(9)

    一.什么是模板方法模式 Template Method模式也叫模板方法模式,是行为模式之一,它把具有特定步骤算法中的某些必要的处理委让给抽象方法,通过子类继承对抽象方法的不同实现改变整个算法的行为. ...

  10. Extjs ComboBox 动态选中第一项

    有时候我们希望通过Store加载过来的数据,ComboBoxItem能够选择第一条数据作为默认数据,我们可以这么操作: var storeinfo = Ext.create('Ext.data.Sto ...