上一篇博文讨论了OpenCV中高斯滤波函数的效率,发现自己编写的滤波代码与OpenCV原代码效率差好多倍,应该是代码出了问题。经过一些调研,发现访问像素值的方法不同,导致操作的效率也存在差异。
这里主要讨论访问像素值的两种方法:at方法和指针方法
1. 使用at方法
如果是灰度图像:img.at<uchar>(row, col) = 128;
如果是彩色图像:
img.at<Vec3b>(row, col)[0] = 128; // B通道
img.at<Vec3b>(row, col)[1] = 128; // G通道
img.at<Vec3b>(row, col)[2] = 128; // R通道
2. 使用ptr 方法:把图像看作是一维数组,利用指针来对这个数组中的像素进行操作
img.ptr<uchar>(row) 得到图像第row行数据的第一个像素值
如果是灰度图像:该行长度为m.cols
如果是彩色图像:该行长度为m.cols*3
编写代码进行比较:
int main()
{
Mat img;
int i, j;
double t;
uchar* data;
int imgSize;
img = imread("lena_gray.jpg", 0);
t = getTickCount();
for (j = 0; j < img.rows; j++){
for (i = 0; i < img.cols; i++){
img.at<uchar>(j, i) = 255;
}
}
t = (getTickCount()-t)/getTickFrequency()*1000;
cout << "at operation cost : " << t << endl;
data = img.ptr<uchar>(0);
imgSize = img.rows*img.cols*img.channels();
t = getTickCount();
for (j = 0; j < imgSize; j++){
data[j] = 255;
}
t = (getTickCount()-t)/getTickFrequency()*1000;
cout << "ptr operation cost : " << t << endl;
return 0;
}
经过计算,对512*512的图像进行编历,
at操作耗时为0.424076ms
ptr操作耗时为0.0346413ms
结合网友的讨论,有如下结论:
(1) at操作比指针操作要慢很多,所以对连续的大量数据操作,使用指针效率高;
(2) 连续扫描图像的做法可以把图像看作一维数组,这种方法可以明显提高速度。换句话说:单循环比双循环更高效,即使它们的操作数是相同的。