您的位置首页生活百科

IplImage数据结构:访问图像像素

IplImage数据结构:访问图像像素

的有关信息介绍如下:

IplImage数据结构:访问图像像素

绪:

在机器视觉领域,图像处理是基础;

OpenCV作为一个视觉图像处理开源库,熟悉理解其访问图像像素方法必要基础;

IplImage是OpenCV中的图像数据结构。

经验目录:

...IplImage数据结构;

...图像数据存储;

...访问图像像素的方法;

...注意事项;

IplImage数据结构:来自于 Intel Image Processing Library。

OpenCV 只支持其中的一个子集:

IplImage图像头:

typedef struct _IplImage

....{

int nSize; /* IplImage大小,=sizeof(IplImage)*/

int ID; /* 版本 (=0)*/

int nChannels;/* 大多数OPENCV函数支持1,2,3 或 4 个通道 */

int alphaChannel;/* 被OpenCV忽略 */

.........int depth; /* 像素的位深度: IPL_DEPTH_8U, IPL_DEPTH_8S,

................................/*IPL_DEPTH_16U,IPL_DEPTH_16S, IPL_DEPTH_32S,

................................/*IPL_DEPTH_32F and IPL_DEPTH_64F 可支持 */

char colorModel; /* 被OpenCV忽略 */

char channelSeq; /* 被OpenCV忽略 */

int dataOrder; /* 0 - 交叉存取颜色通道,对三通道RGB图像,像素存

......................................../*储顺序为BGR BGR BGR ... BGR;

......................................../*1 - 分开的颜色通道,对三通道RGB图像,像素存储顺

......................................../*序为RRR...R GGG...G BBB...B。

......................................./*cvCreateImage只能创建交叉存取图像 */

int origin; /* 0 - 顶—左结构,

1 - 底—左结构 (Windows bitmaps 风格) */

int align; /* 图像行排列 (4 or 8). OpenCV 忽略它,使用 widthStep 代替 */

int width; /* 图像宽像素数 */

int height; /* 图像高像素数*/

struct _IplROI *roi;/* 图像感兴趣区域. 当该值非空只对该区域进行处理 */

struct _IplImage *maskROI; /* 在 OpenCV中必须置NULL */

void *imageId; /* 同上*/

struct _IplTileInfo *tileInfo; /*同上*/

int imageSize; /* 图像数据大小(在交叉存取格式下imageSize=image->height*image->widthStep),单位字节*/

char *imageData; /* 指向排列的图像数据 */

int widthStep; /* 排列的图像行大小,以字节为单位 */

int BorderMode; /* 边际结束模式, 被OpenCV忽略 */

int BorderConst; /* 同上 */

char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的 */

}

IplImage;

在IplImage数据类型中,访问图像像素最重要的元素:

....char *imageData; /* 指向排列的图像数据 */

....int widthStep;/*排列的图像行大小,以字节为单位*/

....int width;/*图像宽像素数*/

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

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

访问图像像素方法:

(1)根据上述数据排列,定义指针访问:

语句:

..........pData=(unsigned char*)(pImg->imageData+i*pImg->widthStep)[j];

//像素点的地址

其中,

pImg->imageData:指向图像pImg第一行首地址;

widthStep:图像的行宽,单位字节;

unsigned char*:由于pImg->imageData默认为char类型,图像像素值中有可能出现负数,所以需要强制类型转换为unsigned char;

对于单通道图像;

【注】:先遍历行和先遍历列的区分;

如下图:

(2)对于多通道图像;

IplImage*img=cvCreateImage(cvGetSize (_pImg),IPL_DEPTH_8U,3);

unsigned char*data=(unsigned char*)img->imageData;

intstep=img->widthStep/sizeof(uchar);

intchannels=img->nChannels;

uchar*b,*g,*r;

for(inti=0;iheight;i++)

....for(intj=0;jwidth;j++)

..{

....*b=data[i*step+j*chanels+0];

....*g=data[i*step+j*chanels+1];

....*r=data[i*step+j*chanels+2];

..}

其数据访问格式如下:

与数据类型相关,宽度相关;

注意事项:

①OpenCV中使用imread()、cvLoadImage()得到的图像,其数据类型都是char类型;

②对于32为操作系统,内存存储图像数据满足每行数据4字节对齐;

即:

当图像为单通道char/uchar,每行数据大小为sizeof(uchar)*width=widthStep字节;

如果width为4的倍数,那么widthStep=width;

如果width不为4的倍数,则需补齐4个字节。

eg. width=16àwidthStep=16字节;

.......width=18àwidthStep=(width+2)/4*4=20字节;

当图像为3通道float型,widthStep=(width*3*sizeof(float)+3)/4*4;

widthStep只和宽度与数据类型有关。

③示例:

创建一副宽*高为111*113大小的3通道float类型图像,访问第31行、51列的图像数据。

IplImage *image=cvCreateImage(cvSize(111,113),IPL_DEPTH_32F,3);

//则widthStep=(111*3*sizeof(float)+3)/4*4=2664字节;

float *data_1=(float*)image->imageData;

float val_1=*(data_1+31*width+51);

//或

char *data_2=image->imageData;

float val_2=*(float*)(data_2+31*image->widthStep+51*sizeof(float));

④【注】:

对于char、uchar图像数据类型,用widthStep;

对于float、double图像数据类型,用width;否则会出错。

【特别注意】:

在IplImage头中,imageData默认为char*类型;

当 .IplImage* img=cvCreateImage(cvGetSize(_Img),IPL_DEPTH_8U,1)

......unsigned char *data_1;

......for(int i=0;iheight;i++)

.........{

..........for(int j=0;jwidth;j++)

....{

...............//①对

...............data_1=(unsigned char*)img->imageData + i*img->widthStep;

...............//②对

...............//data_1=(unsigned char*)(img->imageData + i*img->widthStep);

}

}

当 .IplImage* img=cvCreateImage(cvGetSize(_Img),IPL_DEPTH_32F,1)

......float *data_2;

......for(int i=0;iheight;i++)

.........{

..........for(int j=0;jwidth;j++)

..........{

..................//①对

..................data_2=(float*)img->imageData + i*img->width;

.................//②错

.................//data_2=(float*)(img->imageData + i*img->width);

.................//③错

................//data_2=(float*)img->imageData + i*img->widthStep;

................//data_2=(float*)img->imageData + i*img->widthStep/sizeof(float);//④对

}

}