多语言展示
当前在线:1166今日阅读:176今日分享:34

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

绪:在机器视觉领域,图像处理是基础;OpenCV作为一个视觉图像处理开源库,熟悉理解其访问图像像素方法必要基础;IplImage是OpenCV中的图像数据结构。经验目录:...IplImage数据结构;...图像数据存储;...访问图像像素的方法;...注意事项;
工具/原料
1

OpenCV视觉库

2

VS2010编译器

方法/步骤
1

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[4]; /* 被OpenCV忽略 */        char channelSeq[4]; /* 被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[4]; /* 边际结束模式, 被OpenCV忽略 */        int  BorderConst[4]; /* 同上 */        char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的 */    }    IplImage;

2

在IplImage数据类型中,访问图像像素最重要的元素:....char *imageData;  /* 指向排列的图像数据 */....int widthStep;/*排列的图像行大小,以字节为单位*/或....int width;/*图像宽像素数*/一个m*n的单通道字节型图像,其imageData排列如作图:多通道(三通道)字节图像中,imageData排列如右图:

3

访问图像像素方法:(1)根据上述数据排列,定义指针访问:语句:..........pData=(unsigned char*)(pImg->imageData+i*pImg->widthStep)[j];//像素点的地址其中,pImg->imageData:指向图像pImg第一行首地址;widthStep:图像的行宽,单位字节;unsigned char*:由于pImg->imageData默认为char类型,图像像素值中有可能出现负数,所以需要强制类型转换为unsigned char;对于单通道图像;【注】:先遍历行和先遍历列的区分;如下图:

4

(2)对于多通道图像;IplImage* img=cvCreateImage(cvGetSize (_pImg),IPL_DEPTH_8U,3);  unsigned char* data=(unsigned char *)img->imageData;  int step = img->widthStep/sizeof(uchar);  int channels = img->nChannels;  uchar *b,*g,*r;  for(int i=0;iheight;i++)  ....for(int j=0;jwidth;j++)..{  ....*b=data[i*step+j*chanels+0];  .... *g=data[i*step+j*chanels+1];  ....*r=data[i*step+j*chanels+2];  ..}  其数据访问格式如下:与数据类型相关,宽度相关;

5

注意事项:①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;否则会出错。

6

【特别注意】:在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);//④对    }}

注意事项
1

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

2

对于float、double图像数据类型,用width;

3

widthStep=(width*3*sizeof(float)+3)/4*4;

推荐信息