OpenCV中double和float类型图像数据的访问

首先,必须知道OpenCV用imread或者cvLoadImage得到的图像数据都是char类型的,至少2.x.x都是的,以后的不知道。

下面了解下结构体IplImage和类Mat中Widthstep和step的意义:

对于32位OS(64位是不是我不太清楚),内存读取图片数据是要满足每行数据4字节对齐的,也就是说如果图像是单通道char或者uchar的,每行数据的大小就是sizeof(uchar)*width=width字节,这个大小由width决定,如果width是4的倍数,那么widthstep就是width,如果不是4的倍数,需要补齐4个字节。比如width=16,widthstep=16;width=18,widthstep=(width+3)/4*4=20字节。对于3通道float类型的图像,其widthstep=(width*3*sizeof(float)*3+3)/4*4;因此这个widthstep只和宽度和数据类型有关。不管是IplImage和Mat两者读同样的图像,其widthstep都是一样的,但是两者存储的图像数据类型都是uchar,不管你创建的图像是什么类型的,一般读取的图像数据类型都是char,然而在处理的过程中,可能会创建一幅大小相同,数据类型不同(如float、double)的图像(准确讲这不是图像了,算做数组),比如积分图像,每个像素的值不可能仅限于0-255或者-127-128,用char类型的图像来存储显然是不够的。下面来解释如何访问float或者double类型的图像数据。

比如,现在我们创建一幅宽*高为111*113大小的3通道double类型的图像image=cvCreateImage(cvSize(111,113),IPL_DEPTH_64F,3);

这里的widthstep=(111*3*sizeof(double)+3)/4*4=2664;因为111*3*sizeof(double)=2664已经正好是4的倍数了,因此无需补充字节。现在用指针访问第31行、55列的图像数据,这个数据应该是double类型的。image->imageData的类型是char的,因此可以转换成double,通过double指针来访问:

double *data=(double*)image->imageData;
double val=*(data+31*width+51);

或者可以通过uchar指针找到(31,51)处的地址,然后转换成double指针进行访问:

char* data=image->imageData;
double val=*(double*)(data+31*image->widthStep+51*sizeof(double));
对于IplImage,指针访问可以参考以上两种方式,其实这本质就是数据类型的转换而已,计算机专业的同学很容易理解,这里主要面对类似咱这种非计算机专业而言的。

对于Mat,指针访问就更简单了,有一种方法很方便:double ptr=(double*)m.ptr(y);这里就能访问第y行的数据了,然后用ptr[x]就可以访问第y行、x列的数据了。

以上均为本人理解所写,如有错误,欢迎留言指教!



你可能感兴趣的:(图像处理,Visual,C++,OpenCV)