《访问Mat图像中每个像素的值》)

来源:互联网 发布:网络彩票何时开售 编辑:程序博客网 时间:2024/06/15 15:43

目录(?)[+]

转载请注明出处:http://blog.csdn.net/xiaowei_cqu/article/details/7557063

!!此篇是基于IplImage* (C接口或者说2.1之前版本的接口,新的Mat的访问方式请参考博文:
《访问Mat图像中每个像素的值》)

IplImage是OpenCV中CxCore部分基础的数据结构,用来表示图像,其中Ipl是Intel Image Processing Library的简写。以下是IplImage的结构分析(来自OpenCV中文网站:http://www.opencv.org.cn/index.php/Cxcore%E5%9F%BA%E7%A1%80%E7%BB%93%E6%9E%84#IplImage)

[cpp] view plaincopy
  1. typedef struct _IplImage  
  2.     {  
  3.         int  nSize;         /* IplImage大小 */  
  4.         int  ID;            /* 版本 (=0)*/  
  5.         int  nChannels;     /* 大多数OPENCV函数支持1,2,3 或 4 个通道 */  
  6.         int  alphaChannel;  /* 被OpenCV忽略 */  
  7.         int  depth;         /* 像素的位深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U, 
  8.                                IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F 可支持 */  
  9.         char colorModel[4]; /* 被OpenCV忽略 */  
  10.         char channelSeq[4]; /* 同上 */  
  11.         int  dataOrder;     /* 0 - 交叉存取颜色通道, 1 - 分开的颜色通道. 
  12.                                cvCreateImage只能创建交叉存取图像 */  
  13.         int  origin;        /* 0 - 顶—左结构, 
  14.                                1 - 底—左结构 (Windows bitmaps 风格) */  
  15.         int  align;         /* 图像行排列 (4 or 8). OpenCV 忽略它,使用 widthStep 代替 */  
  16.         int  width;         /* 图像宽像素数 */  
  17.         int  height;        /* 图像高像素数*/  
  18.         struct _IplROI *roi;/* 图像感兴趣区域. 当该值非空只对该区域进行处理 */  
  19.         struct _IplImage *maskROI; /* 在 OpenCV中必须置NULL */  
  20.         void  *imageId;     /* 同上*/  
  21.         struct _IplTileInfo *tileInfo; /*同上*/  
  22.         int  imageSize;     /* 图像数据大小(在交叉存取格式下imageSize=image->height*image->widthStep),单位字节*/  
  23.         char *imageData;  /* 指向排列的图像数据 */  
  24.         int  widthStep;   /* 排列的图像行大小,以字节为单位 */  
  25.         int  BorderMode[4]; /* 边际结束模式, 被OpenCV忽略 */  
  26.         int  BorderConst[4]; /* 同上 */  
  27.         char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的 */  
  28.     }  
  29.     IplImage;  

直接访问:

对我们来说比较重要的两个元素是:char *imageData以及widthStep。imageData存放图像像素数据,而widStep类似CvMat中的step,表示以字节为单位的行数据长度。

一个m*n的单通道字节型图像,其imageData排列如下:


如果我们要遍历图像中的元素,只需:

[cpp] view plaincopy
  1. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);  
  2. uchar* tmp;  
  3. for(int i=0;i<img->height;i++)  
  4.     for(int j=0;j<img->width;j++)  
  5.         *tmp=((uchar *)(img->imageData + i*img->widthStep))[j];  

这种直接访问的方法速度快,但容易出错,我们可以通过定义指针来访问。即:

[cpp] view plaincopy
  1. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);  
  2. ucha* data=(uchar *)img->imageData;  
  3. int step = img->widthStep/sizeof(uchar);  
  4. uchar* tmp;  
  5. for(int i=0;i<img->height;i++)  
  6.     for(int j=0;j<img->width;j++)  
  7.         *tmp=data[i*step+j];  

而多通道(三通道)字节图像中,imageData排列如下:

其中(Bi,Bj)(Gi,Gj)(Ri,Rj)表示图像(i,j)处BGR分量的值。使用指针的遍历方法如下:

[cpp] view plaincopy
  1. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);  
  2. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);  
  3. uchar* data=(uchar *)img->imageData;  
  4. int step = img->widthStep/sizeof(uchar);  
  5. int channels = img->nChannels;  
  6. uchar *b,*g,*r;  
  7. for(int i=0;i<img->height;i++)  
  8.      for(int j=0;j<img->width;j++){  
  9.            *b=data[i*step+j*chanels+0];  
  10.            *g=data[i*step+j*chanels+1];  
  11.            *r=data[i*step+j*chanels+2];  
  12.       }  

*如果要修改某像素值,则直接赋值。

使用cvGet2D()函数访问:

cvGet*D系列函数可以用来返回特定位置的数组元素(一般使用cvGet2D),原型如下:
[cpp] view plaincopy
  1. CvScalar cvGet1D( const CvArr* arr, int idx0 );  
  2. CvScalar cvGet2D( const CvArr* arr, int idx0, int idx1 );  
  3. CvScalar cvGet3D( const CvArr* arr, int idx0, int idx1, int idx2 );  
  4. CvScalar cvGetND( const CvArr* arr, int* idx );  
idx0,idx1,idx2分别用来指示元素数组下标,即cvGet2D返回(idx0,idx1)处元素的值。
因此,单通道图像像素访问方式如下:
[cpp] view plaincopy
  1. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);  
  2. double tmp;  
  3. for(int i=0;i<img->height;i++)  
  4.     for(int j=0;j<img->width;j++)  
  5.         tmp=cvGet2D(img,i,j).val[0];  
多通道字节型/浮点型图像:
[cpp] view plaincopy
  1. IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);  
  2. double tmpb,tmpg,bmpr;  
  3. for(int i=0;i<img->height;i++)  
  4.     for(int j=0;j<img->width;j++){  
  5.         tmpb=cvGet2D(img,i,j).val[0];  
  6.         tmpg=cvGet2D(img,i,j).val[1];  
  7.         tmpr=cvGet2D(img,i,j).val[2];  
  8.     }  
如果是修改元素的值,可用cvSet*D(一般是cvSet2D)函数:
[cpp] view plaincopy
  1. void cvSet1D( CvArr* arr, int idx0, CvScalar value );  
  2. void cvSet2D( CvArr* arr, int idx0, int idx1, CvScalar value );  
  3. void cvSet3D( CvArr* arr, int idx0, int idx1, int idx2, CvScalar value );  
  4. void cvSetND( CvArr* arr, int* idx, CvScalar value );  
这种方法对于任何图像的访问方式是一样的,比较简单,但效率较低,不推荐使用。
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 赌博拘留15天不交罚款怎么办 给人打了不赔钱怎么办 打了人对方讹钱怎么办 换车了原来的etc怎么办 换异地车牌了etc怎么办 被执行人拘留15天后不还钱怎么办 被执行人拘留后还是不还钱怎么办 摩托车套牌被交警扣了怎么办 套牌摩托车遇到交警怎么办 不知情收到小偷东西了怎么办 盗窃罪法院判定农民赔钱没钱怎么办 公安局通知家属取刑拘通知书怎么办 老公诈骗坐牢家人该怎么办 家人被拘留我该怎么办 车牌被偷了一个怎么办 车牌给人家偷了怎么办 收购了偷来的铝怎么办 员工自动离职后档案怎么办 辞职了老板不发工资怎么办 上班老板不发工资怎么办 逮捕后延长羁押期限怎么办手续 员工提出辞职公司不同意怎么办 员工提出辞职后即不来上班怎么办 打架把对方打成轻伤害怎么办 被刑拘了家人该怎么办 看守所在押人员检查出乙肝怎么办 孩子不写作业老师该怎么办 孩子老师向我表白该怎么办 幼儿园老师打孩子家长该怎么办 老师对孩子太苛刻该怎么办 孩子不敢上学怕老师该怎么办 学生上课迟到老师该怎么办 看守所转监狱不收怎么办 己判实刑有病看守所不收怎么办 判决书生效前看守所不收怎么办 法院判实刑看守所不收怎么办 派出所立案后送拘留所了怎么办 打架斗殴被关在看守所了怎么办 在看守所羁押期间患癌症怎么办 无法偿还借款拘留15天后怎么办 离婚起诉被告人被羁押怎么办