點選上方 藍字 關註我們
微信公眾號: OpenCV學堂
關註獲取更多電腦視覺與深度學習知識
C++11 lambda語法
C++11中引入了lambda運算式,它支持定義一個行內(inline)的函式,作為一個原生的物件或者一個參數。有了lambda運算式,就可以很方便的使用stl標準庫,它的標準語法如下:
[...](...) mutable throwSpec -> returnType {...}
參數解釋:
[…]裏麵包含的是可以參照的本地變量
(…)裏麵包含的是函式的變量參數
returnType是返回型別
一個簡單的例子如下:
auto sum_xy = [](int x, int y) -> int {
return x + y;
};
std::cout <<" sum_xy = "<< sum_xy(11, 12) << std::endl;
引入本地變量
int a = 25, b = 9;
auto sum_xy = [&a, &b](int x, int y) -> int {
return x + y + a + b;
};
std::cout <<" sum_xy = "<< sum_xy(11, 12) << std::endl;
註意: 如果直接使用,沒有把本地變量放到變量列表中去,就會出現一個常見的 語法錯誤 :
封閉函式局部變量不能在lambda體中參照,除非位於捕獲列表中
Mat的for Each遍歷
說實話我也沒有註意過,OpenCV4從哪個版本開始支持,反正已經支持了,透過Mat的forEach方式結合C++11 lambda運算式,實作對Mat物件快速像素遍歷。語法如下:
void cv::Mat::forEach(const Functor & operation)
其中operation是一個C++11 lambda運算式,同時也是一個匿名的C++函式。基於Mat的for Each實作的像素遍歷程式碼如下:
// wxh = 3840x2560
cv::Mat image = cv::imread("D:/test_pixs.jpg");
typedef cv::Point3_<uint8_t> Pixel;
// forEach方式的像素遍歷
double start = (double)cv::getTickCount();
image.forEach<Pixel>([](Pixel &p, constint * position) -> void {
p.x = 255 - p.x;
p.y = 255 - p.y;
p.z = 255 - p.z;
});
double time = (((double)cv::getTickCount() - start)) / cv::getTickFrequency();
printf(" forEach time : %.4f seconds\n", time);
傳統高效的OpenCV指標方式的像素遍歷存取程式碼如下 :
// raw pointer access.
start = (double)cv::getTickCount();
for (int r = 0; r < image.rows; ++r) {
Pixel* ptr = image.ptr<Pixel>(r, 0);
const Pixel* ptr_end = ptr + image.cols;
for (; ptr != ptr_end; ++ptr) {
ptr->x = 255 - ptr->x;
ptr->y = 255 - ptr->y;
ptr->z = 255 - ptr->z;
}
}
time = (((double)cv::getTickCount() - start)) / cv::getTickFrequency();
printf(" raw pointer access time : %.4f seconds\n", time);
執行結果對比如下:
從執行的時間可以看出,針對一張3840x2560大小的影像、forEach方式遍歷的確比較靠譜。
系統化學習直接掃碼檢視
推薦閱讀