當前位置: 妍妍網 > 碼農

OpenCV中C++11 lambda方式像素遍歷

2024-03-20碼農

點選上方 藍字 關註我們

微信公眾號: 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 = 3840x2560cv::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方式遍歷的確比較靠譜。

系統化學習直接掃碼檢視

推薦閱讀