【见微知著】OpenCV中C++11 lambda方式急速像素遍历

简介: 【见微知著】OpenCV中C++11 lambda方式急速像素遍历

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, const int * 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方式遍历的确比较靠谱。

系统化学习OpenCV4 - 点击这里

相关文章
|
1天前
|
算法 搜索推荐 C++
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
C++之STL常用算法(遍历、查找、排序、拷贝、替换、算数生成、集合)
9 0
|
1天前
|
算法 C++ 容器
C++之vector容器操作(构造、赋值、扩容、插入、删除、交换、预留空间、遍历)
C++之vector容器操作(构造、赋值、扩容、插入、删除、交换、预留空间、遍历)
4 0
|
1天前
|
C++
C++数组(定义、遍历、长度、地址、最大值、逆置、冒泡排序)
C++数组(定义、遍历、长度、地址、最大值、逆置、冒泡排序)
6 0
|
3天前
|
C++
C++语言的lambda表达式
C++从函数对象到lambda表达式以及操作参数化
|
5天前
|
算法 编译器 C++
C++一分钟之—Lambda表达式初探
【6月更文挑战第22天】C++的Lambda表达式是匿名函数的快捷方式,增强函数式编程能力。基本语法:`[capture](params) -&gt; ret_type { body }`。例如,简单的加法lambda:`[](int a, int b) { return a + b; }`。Lambda可用于捕获外部变量(值/引用),作为函数参数,如在`std::sort`中定制比较。注意点包括正确使用捕获列表、`mutable`关键字和返回类型推导。通过实践和理解这些概念,可以写出更简洁高效的C++代码。
29 13
|
19天前
|
算法 开发工具 计算机视觉
【零代码研发】OpenCV实验大师工作流引擎C++ SDK演示
【零代码研发】OpenCV实验大师工作流引擎C++ SDK演示
20 1
|
19天前
|
存储 计算机视觉
OpenCV3.1中读写图像与读写像素
OpenCV3.1中读写图像与读写像素
11 0
|
19天前
|
算法 Java API
在VC++中使用CxImage库读写图像实现像素操作
在VC++中使用CxImage库读写图像实现像素操作
18 0
|
20天前
|
计算机视觉
OpenCV图像像素值统计
OpenCV图像像素值统计
|
7天前
|
算法 计算机视觉
【Qt&OpenCV 图像的感兴趣区域ROI】
【Qt&OpenCV 图像的感兴趣区域ROI】
12 1