When you write an image-processing function, efficiency is often a concern(涉及). When you design your function, you will frequently need to check the computational efficiency of your code in order to detect(發現) any bottleneck(瓶頸) in your processing that might slow down(變慢) your program.
1.1 實現方法
爲了衡量函數或代碼段的運行時間,OpenCV有一個非常實用的函數,即cv::getTickCount(),該函數返回從最近一次電腦開機到當前的時鐘週期數。如希望得到以秒爲單位的代碼運行時間,要使用另一個方法,即cv::getTickFrequency(),返回每秒的時鐘週期數。
const int64 start = cv::getTickCount();
colorReduce(image);
// elapsed (經過的時間) time in seconds
double duration = (cv::getTickCount() - start) /
cv::getTickFrequency();
1.2 四種存取像素方式效率對比
查看.at、pointers、reshape及iterators四種遍歷圖像方式所消耗時間
//Test running time,edited by yunfung #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <iostream> using namespace cv; using namespace std; void colorReduce1(Mat& image, int div = 64) { for (int i = 0; i < image.rows; i++) { for (int j = 0; j < image.cols; j++) { image.at<Vec3b>(i, j)[0] = image.at<Vec3b>(i, j)[0] / div*div + div / 2; image.at<Vec3b>(i, j)[1] = image.at<Vec3b>(i, j)[1] / div*div + div / 2; image.at<Vec3b>(i, j)[2] = image.at<Vec3b>(i, j)[2] / div*div + div / 2; } } } void colorReduce2(cv::Mat image, int div = 64) { int nl = image.rows; int nc = image.cols * image.channels(); for (int j = 0; j < nl; j++) { uchar* data = image.ptr<uchar>(j); for (int i = 0; i < nc; i++) { data[i] = data[i] / div*div + div / 2; } } } void colorReduce3(cv::Mat &image, int div = 64) { if (image.isContinuous()){ image.reshape(1, 1); } int nl = image.rows; int nc = image.cols * image.channels(); for (int j = 0; j < nl; j++) { uchar* data = image.ptr<uchar>(j); for (int i = 0; i < nc; i++) { data[i] = data[i] / div*div + div / 2; } } } void colorReduce4(cv::Mat &image, int div = 64) { cv::Mat_<cv::Vec3b>::iterator it = image.begin<cv::Vec3b>(); cv::Mat_<cv::Vec3b>::iterator itend = image.end<cv::Vec3b>(); for (; it != itend; ++it) { (*it)[0] = (*it)[0] / div * div + div / 2; (*it)[1] = (*it)[1] / div * div + div / 2; (*it)[2] = (*it)[2] / div * div + div / 2; } } void calrunTime(int v, Mat&image) { double duration; duration = static_cast<double>(getTickCount()); //強制轉化爲double for (int i = 0; i < 10; i++) { switch (v) { case 1: colorReduce1(image); //at break; case 2: colorReduce2(image); //pointers break; case 3: colorReduce3(image); //reshape(continuous) break; case 4: colorReduce4(image); //iterators break; default: break; } } duration = static_cast<double>(getTickCount()) - duration; duration /= getTickFrequency(); duration *= (1000/10); //average cout << "duration" << v << " : " << duration << "mS"<< endl; } int main() { Mat image = imread("test.jpg"); Mat imageClone = image.clone(); cout << "yunfung_opencv_learn_test:" <<"\n\n"; calrunTime(1, image); image = imread("test.jpg"); imageClone = image.clone(); calrunTime(2, image); image = imread("test.jpg"); imageClone = image.clone(); calrunTime(3, image); image = imread("test.jpg"); imageClone = image.clone(); calrunTime(4, image); namedWindow("Image Result"); imshow("Image Result", imageClone); waitKey(); return 0; }
可見用at的方式讀取像素效率最低,用迭代器速度也比較慢,效率最高的方式還是使用指針讀取。