如何遍历一副图像?最简单的方法就是写个双层循环,增量分别为行和列,但是如何高效遍历一副图像?
核心思想就两点:①减少双重循环中外层循环的次数②对图像处理过程中,| & 比普通运算效率高。
在一副彩色图像中,计算机是以二维数组的形式来存储,数组中每个元素是一个包含三个元素的向量,通常是BGR(或者RGB)。所以一个宽度为W,高度为H的图像需要一个大小为W*H*3的uchar构成的内存块。但是出于性能的考虑,每行会填补一些额外的像素,这是因为,如果行的长度是4或者8的倍数,一些多媒体处理芯片可以更高效的处理图像,这些额外的像素不会被显示或者保存,填补的值将被忽略。
1 void colorReduce(cv::Mat& image, int div=64) 2 { 3 int nl = image.rows(); // 行数 4 int nc = image.cols(); // 列数 5 if (image.isContinuous()) 6 { 7 // 没有对像素进行填补 8 nc *= nl; 9 nl = 1; 10 } 11 int n = static_cast<int>(log(static_cast<double>(div))/log(2.0)); 12 // 用来对像素值进行取整的二进制掩码 13 uchar mask = 0xff << n; 14 // for all pixels 15 for (int i = 0; i < nl; ++i) 16 { 17 uchar* data = image.ptr<uchar>(i); 18 for (int j = 0; j < nc; ++j) 19 { 20 // 处理每个像素 21 *data++ = *data&mask + div/2; 22 *data++ = *data&mask + div/2; 23 *data++ = *data&mask + div/2; 24 } 25 } 26 27 }