OpenCV(三) 之 基本数据结构 CvMat和 IplImage

CvMat
IplImage

OpenCv中基本的数据类型

类型 参数 表示
CvPoint int x,y 像素点
CvPoint2D32f float x,y 平面点
CvPoint3D32f float x,y,z 空间点
CvSize int width,height 图像大小
CvSize2D32f float x, y 区域大小
CvSize3D32f float x,y,z 立方体大小
CvRect int x,y,width,height 矩形区域
CvScalar double val[4] RGBA 值

类型的构造函数仅是类型名首字母小写,比如cvPoint(int x,int y),除了CvScalar

CvScalar类型是可以用来存放4个double类型的数组,最多四个不一定要四个

  1. typedef struct CvScalar 



  2. double val[4]; 

  3. }; 

其赋值函数有四种

  1. 1. CvScalar cvScalar(double v0,double v1,double v2, double v3); 

  2. 2. CvScalar cvRealScalar(double v0); 

  3. //第一个数值赋值,剩余三个为0 

  4. 3. CvScalar cvScalarAll(double v); 

  5. //所有的四个值都相同 

  6. 4. CV_RGB 

  7. #define CV_RGB(r,g,b) cvScalar(b,r,g,0); 

CvMat类型

  1. typedef struct CvMat { 

  2. int type; 

  3. int step; 

  4. int* refcount; // for internal use only 

  5. union { 

  6. uchar* ptr; 

  7. short* s; 

  8. int* i; 

  9. float* fl; 

  10. double* db; 

  11. } data; 

  12. union { 

  13. int rows; 

  14. int height; 

  15. }; 

  16. union { 

  17. int cols; 

  18. int width; 

  19. }; 

  20. } CvMat; 

其构造函数

  1. CvMat* cvCreateMat(int rows,int cols,int type); 

  2. CvMat* cvCreateMatHeader(int rows,int cols,int type); 

  3. CvMat* cvInitMatHeader(CvMat *mat,int rows,int cols,int type, void* data=NULL, int step = CV_AUTOSTEP) 

  4. CvMat* cvCloneMat(CvMat*) 


  5. //内存释放 

  6. void cvReleaseMat(CvMat** mat) 

使用数组创建CvMat

  1. float vals[4]=[1,2,3,4]; 

  2. CvMat* mat; 

  3. cvInitMatHeader(mat,2,2,CV_32FC1,vals); 

CvMat属性值的获取

  1. cvGetElemType(const CvArr* arr);//返回数据类型 

  2. cvGetDims(const CvArr* arr,int* sizes=NULL);//返回CvMat的维数,相当于张量的阶数, int* 可以用来存储每一维对应的长度 

  3. cvGetDimSize(const CvArr* arr,int index);//返回第index维度上的长度 

CvMat数据值的读取

  1. float sum( const CvMat* mat )  



  2. float s = 0.0f; 

  3. for(int row=0; row<mat->rows; row++ )  



  4. const float* ptr = (const float*)(mat->data.ptr + row * mat->step); 

  5. for( col=0; col<mat->cols; col++ ) 



  6. s += *ptr++; 





  7. return( s ); 



这里要注意的是

  1. 要强制指定数据类型,因为CvMat定义中数据类型是union。

  2. 使用step参数是每一行所占的字节数,并不等于cols*sizeof(bytes),因为含有优化的地址对齐问题。

CvMat矩阵数据存储顺序是先行再列,3D数据存储顺序是每个位置的channels,然后按行、列排列。

下图时一组空间点存到不同的CvMat的存储结果

1477837579893.jpg

IplImage

  1. typedef struct _IplImage{ 

  2. int nSize; 

  3. int ID; 

  4. int nChannels; //**type 

  5. int alphaChannel; 

  6. int depth; //**type 

  7. int dataOrder; //数组存储结构,是按照像素存IPL_DATA_ORDER_PIXEL,还是先按照通道存IPL_DATA_ORDER_PLANE 

  8. int origin; //图像坐标原点位于左上角 IPL_ORIGIN_TL,还是左下角IPL_ORIGIN_BL 

  9. int align; 

  10. int width; //**columns 

  11. int height; //**rows 

  12. char colorModel[4]; 

  13. char channelSeq[4]; 

  14. struct _IplROI* roi; //region of interest 

  15. struct _IplImage* maskROI; 

  16. void* imageId; 

  17. struct _IplTileInfo* tileInfo; 

  18. int imageSize; 

  19. char* imageData; //** data 

  20. int widthStep; //** step 

  21. int BorderMode[4]; 

  22. int BorderConst[4]; 

  23. char* imageDataOrigin; 



其中注释**部分对应着CvMat的成员变量,CvMat的type成员被拆分成了两个属性:depth, nChannels表示像素值深度和图像的通道数

depth的取值有

  1. IPL_DEPTH_8U; IPL_DEPTH_8S; IPL_DEPTH_16S; IPL_DEPTH_32S; IPL_DEPTH_32F; IPL_DEPTH_64F; 

看字面就知道什么意思了。

IplROI包含的属性:

  1. int xOffset, yOffset; //x,y 方向的偏置 

  2. int height, width; //感兴趣区域的大小 

  3. int COI; //Channel of Interest,感兴趣的通道 

一旦ROI设置了,那么对图像的操作将尽在ROI内操作。

IplImage数据的访问示例

对于HSV图像,希望将S,V通道值设置为255:

  1. void saturate_sv(IplImage* img) 



  2. for(int y=0;y<img->height;y++) 



  3. uchar* ptr=(uchar*)(img->imageData+y*img->widthStep); 

  4. for(int x=0;x<img->width;i++) 



  5. ptr[3*x+1]=255; 

  6. ptr[3*x+2]=255; 







这里奇怪为什么默认img->dataOrder=IPL_DATA_ORDER_PIXEL。这是因为

We say that dataOrder may be either IPL_DATA_ORDER_PIXEL of IPL_DATA_ORDER_PLANE, but in fact only IPL_DATA_ORDER_PIXEL is supported by OpenCV. Both values are generally supported by IPL/IPP, but OpenCV always uses interleaved images.

Note: 比较CvMat和IplImage数据区的操作,发现IplImage->imageData并没有进行类型转换,全部都是byte字节,而CvMat则需要转换成所存储数据的类型,在指针运算时需要特别注意,尤其是IplImage和CvMat进行计算时。

ROI的使用:

  1. void cvSetImageROI(IplImage* image, CvRect rect); //设置rect区域为感兴趣区域 

  2. void cvResetImageROI(IplImage* image); //取消图像的感兴趣区域 

  1. #include "highgui.h" 

  2. #include "cv.h" 

  3. int main(int argc, char** argv) 



  4. // 图像路径、ROI的x,y偏移量, 长和宽、像素值增加量 

  5. IplImage* src; 

  6. if (argc == 7 && ((src = cvLoadImage(argv[1])) != 0)) 



  7. int xOffset = atoi(argv[2]); //x偏移 

  8. int yOffset = atoi(argv[3]); //y偏移 

  9. int width = atoi(argv[4]); //ROI宽 

  10. int height = atoi(argv[5]); //ROI高 

  11. int add = atoi(argv[6]); //每个像素值增加量 


  12. cvSetImageROI(src, cvRect(xOffset, yOffset, width, height)); 

  13. cvAddS(src, cvScalarAll(add), src); 

  14. cvResetImageROI(src); 

  15. cvNamedWindow("src"); 

  16. cvShowImage("src", src); 

  17. cvWaitKey(0); 

  18. cvReleaseImage(&src); 

  19. cvDestroyWindow("src"); 







1478005187960.jpg

上述过程还存在另一种直接地址操作的方法

  1. #include "highgui.h" 

  2. #include "cv.h" 

  3. int main(int argc, char** argv) 



  4. // 图像路径、ROI的x,y偏移量, 长和宽、像素值增加量 

  5. IplImage* src; 

  6. if (argc == 7 && ((src = cvLoadImage(argv[1])) != 0)) 



  7. int xOffset = atoi(argv[2]); //x偏移 

  8. int yOffset = atoi(argv[3]); //y偏移 

  9. int width = atoi(argv[4]); //ROI宽 

  10. int height = atoi(argv[5]); //ROI高 

  11. int add = atoi(argv[6]); //每个像素值增加量 


  12. IplImage * sub_img = cvCreateImageHeader(cvSize(width, height), src->depth, src->nChannels); 

  13. sub_img->widthStep = src->widthStep; 

  14. sub_img->imageData = src->imageData + yOffset*src->widthStep + xOffset*src->nChannels; 


  15. cvAddS(sub_img, cvScalarAll(add), sub_img); 

  16. cvReleaseImageHeader(&sub_img); 


  17. cvResetImageROI(src); 

  18. cvNamedWindow("src"); 

  19. cvShowImage("src", src); 

  20. cvWaitKey(0); 

  21. cvReleaseImage(&src); 

  22. cvDestroyWindow("src"); 







这里很容易理解,就是将ROI截取出来作为一个新的图像,需要注意的时sub_img并没有新分配地址,数据区指向的仍然是src的数据区,此时图像sub_img的数据区并不是连续的,所以将src->widthStep赋值给sub_img-》widthStep保证读取正确的地址数据。

OpenCV(三) 之 基本数据结构 CvMat和 IplImage的更多相关文章

  1. OpenCV数据结构:CvMat,IplImage,CvArr的应用

    最近看HS算法时,发现在新的OpenCV3.0已经移除了该算法,于是不得不看老版的.这其中涉及到了CvMat,CvArr,IplImage的使用.关于这三个结构与Mat的转换关系,总结如下: (1)派 ...

  2. OpenCV——Mat、CvMat、IplImage类型浅析【转】

    OpenCV中常见的与图像操作有关的数据容器有Mat,cvMat和IplImage. 一.Mat类型:矩阵类型,Matrix. 在openCV中,Mat是一个多维的密集数据数组.可以用来处理向量和矩阵 ...

  3. Opencv中将CvMat转为IplImage

    Opencv中将CvMat转为IplImage,并在内存获得起头指针,而不用cvSaveImage(),贴上代码 IplImage * imgg = NULL; imgg = cvCreateImag ...

  4. OpenCV学习(2)--基本数据结构

    OpenCV的基本数据结构 CvPoint:表示图像中的点 CvPoint2D32f:二维空间中的点 CvPoint3D32f:三维空间中的点 这些都是结构体,并不是C++语言中的类,所以他们的构造函 ...

  5. CvArr、Mat、CvMat、IplImage、BYTE转换

    一.Mat类型:矩阵类型,Matrix.     在openCV中.Mat是一个多维的密集数据数组. 能够用来处理向量和矩阵.图像.直方图等等常见的多维数据.     Mat有3个重要的方法:     ...

  6. 图像处理之opencv---mat、cvmat、IplImage之间的转换

    一.Mat类型:矩阵类型,Matrix.  在openCV中,Mat是一个多维的密集数据数组.可以用来处理向量和矩阵.图像.直方图等等常见的多维数据. Mat有3个重要的方法: 1.Mat mat = ...

  7. 【转】Cvmat与IplImage的相互转换

    seyvlei 原文地址 1.IplImage转Cvmat IplImage* src = cvLoadImage(); CvMat* mat=cvCreateMat(src->height,s ...

  8. 《学习opencv》笔记——基本数据结构,CvMat,矩阵訪问

        老板让让做一个东东.输入端要用到opencv顺便就来学习一下.买了本书<学习opencv>翻来一看,opencv1.0,去官网上一看.opencv2.49,瞬间有种蛋碎的赶脚.看着 ...

  9. opencv常用数据结构之:IplImage

    typedef struct_IplImage{      int nSize; //IplImage大小      int ID; //版本(=0)      int nChannels; //大多 ...

随机推荐

  1. jvm--2.类加载机制

    3.JVM类加载机制 (1)类加载机制 虚拟机把描述类的数据从Class文件,用ClassLoader ,加载到内存,并对数据进行校验.转换解析和初始化,最终形成虚拟机直接使用的java类型, 这就是 ...

  2. 轻松搞定laravel的curd操作搞定简易留言版(四)

    一:目的开发laravel简易留言板 二:路由操作routes.php <?php //GET /msg/index 展示留言列表 //GET /msg/add 展示表单 //POST /msg ...

  3. secureCRT The remote system refused the connection.

    转 http://blog.csdn.net/lifengxun20121019/article/details/13627757 我在实践远程登录工具SecureCRT的时候遇到了这个问题 Ubun ...

  4. 耿丹CS16-2班第五次作业汇总

    Deadline: 2016-10-26 23:59 作业内容 实验4-1 求1到20的阶乘的和,其中求阶乘用函数完成. 实验4-2 写一个判素数的函数,在主函数输入一个整数,输出其是否是素数的信息. ...

  5. 我的LaTeX中文文档模板

    中文LaTeX处理模板 环境MiTex内核 编辑环境WinEdit 源码如下: \documentclass[a4paper,12pt]{article} \usepackage{CJK} %设定字号 ...

  6. idea 分支主干管理

    1.创建分支 2.切换主干/分支 3.合并主干.分支

  7. 【Tomcat】解决Eclipse无法添加Tomcat Service问题

    直接上图:今天因为弄Maven的时候,不小心把Tomcat7 Service 给弄没了,没法直接添加. 可以参照上图的结构进行 Download and Install...点击之后等待一会儿. 其实 ...

  8. Total Hamming Distance

    The Hamming distance between two integers is the number of positions at which the corresponding bits ...

  9. WPF直接用Window.Close直接关闭窗口导致不能完全退出的问题

    前几天我在CSDN扔了一个问题,基本描述一下:写了一段这样的代码,来实现获取Control的template,却发现一个这样的问题,就是当我打开了一个window以后,手动调用Close(),窗口的确 ...

  10. 别老嫌Mac系统难用 这些快捷键你都用过吗

    苹果今年10月发布的全新带把儿(bar)的MacBook,轻薄炫酷的外观大受欢迎,其中当然不乏很多从Windows转到Mac阵营的用户.不少习惯了Windows操作习惯的用户在上手Mac时都会觉得非常 ...