zoukankan      html  css  js  c++  java
  • OpenCV(三) 之 基本数据结构 CvMat和 IplImage

    OpenCV(三) 之 基本数据结构 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. //内存释放 
    7. 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的存储结果

    enter description here

    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.  
    13. cvSetImageROI(src, cvRect(xOffset, yOffset, width, height)); 
    14. cvAddS(src, cvScalarAll(add), src); 
    15. cvResetImageROI(src); 
    16. cvNamedWindow("src"); 
    17. cvShowImage("src", src); 
    18. cvWaitKey(0); 
    19. cvReleaseImage(&src); 
    20. cvDestroyWindow("src"); 
    21.  

    22.  

    enter description here

    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.  
    13. IplImage * sub_img = cvCreateImageHeader(cvSize(width, height), src->depth, src->nChannels); 
    14. sub_img->widthStep = src->widthStep; 
    15. sub_img->imageData = src->imageData + yOffset*src->widthStep + xOffset*src->nChannels; 
    16.  
    17. cvAddS(sub_img, cvScalarAll(add), sub_img); 
    18. cvReleaseImageHeader(&sub_img); 
    19.  
    20. cvResetImageROI(src); 
    21. cvNamedWindow("src"); 
    22. cvShowImage("src", src); 
    23. cvWaitKey(0); 
    24. cvReleaseImage(&src); 
    25. cvDestroyWindow("src"); 
    26.  

    27.  

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

  • 相关阅读:
    Hard 随机洗牌函数 @CareerCup
    Hard 随机选择subset @CareerCup
    Hard 计算0到n之间2的个数 @CareerCup
    Django admin进阶
    hdu 5630 Rikka with Chess
    PHP 表单验证
    PHP 表单验证
    PHP 表单验证
    PHP 表单验证
    PHP 表单处理
  • 原文地址:https://www.cnblogs.com/YiXiaoZhou/p/6021067.html
Copyright © 2011-2022 走看看