aihot  2017-05-08 16:04:23  OpenCV |   查看评论   
;k<nr;k++) 9 { 10 // 每一行图像的指针 11 const uchar* inData=image.ptr<uchar>(k); 12 uchar* outData=outImage.ptr<uchar>(k); 13 for(int i=0;i<nl;i++) 14 { 15 outData[i]=inData[i]/div*div+div/2; 16 } 17 } 18 }

从上面的例子中可以看出,取出图像中第i行数据的指针:image.ptr<uchar>(i)。

值得说明的是:中将三通道的数据转换为1通道,在建立在每一行数据元素之间在内存里是连续存储的,每个像素三通道像素按顺序存储。也就是一幅图像数据最开始的三个值,是最左上角的那像素的三个通道的值。

但是这种用法不能用在行与行之间,因为图像在OpenCV里的存储机制问题,行与行之间可能有空白单元。这些空白单元对图像来说是没有意思的,只是为了在某些架构上能够更有效率,比如intel MMX可以更有效的处理那种个数是4或8倍数的行。但是我们可以申明一个连续的空间来存储图像,这个话题引入下面最为高效的遍历图像的机制。

三、更高效的方法

上面已经提到过了,一般来说图像行与行之间往往存储是不连续的,但是有些图像可以是连续的,Mat提供了一个检测图像是否连续的函数isContinuous()。当图像连通时,我们就可以把图像完全展开,看成是一行。

 1 void colorReduce(const Mat& image,Mat& outImage,int div)  2 {  3     int nr=image.rows;  4     int nc=image.cols;  5     outImage.create(image.size(),image.type());  6     if(image.isContinuous()&&outImage.isContinuous())  7     {  8         nr=1;  9         nc=nc*image.rows*image.channels(); 10     } 11     for(int i=0;i<nr;i++) 12     { 13         const uchar* inData=image.ptr<uchar>(i); 14         uchar* outData=outImage.ptr<uchar>(i); 15         for(int j=0;j<nc;j++) 16         { 17             *outData++=*inData++/div*div+div/2; 18         } 19     } 20 }

用指针除了用上面的方法外,还可以用指针来索引固定位置的像素:

image.step返回图像一行像素元素的个数(包括空白元素),image.elemSize()返回一个图像像素的大小。

&image.at<uchar>(i,j)=image.data+i*image.step+j*image.elemSize();

四、还有吗?用迭代器来遍历。

下面的方法可以让我们来为图像中的像素声明一个迭代器:

MatIterator_<Vec3b> it;

 

除特别注明外,本站所有文章均为 赢咖4注册 原创,转载请注明出处来自OpenCV成长之路(2):图像的遍历

留言与评论(共有 0 条评论)
   
验证码:
[lianlun]1[/lianlun]