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

学习《OpenCV应用开发:入门、进阶与工程化实践》一书

做真正的OpenCV开发者,从入门到入职,一步到位!

C++11 lambda语法

C++11中引入了lambda表达式,它支持定义一个内联(inline)的函数,作为一个本地的对象或者一个参数。有了lambda表达式,就可以很方便的使用stl标准库,它的标准语法如下:

cpp 复制代码
[...](...) mutable throwSpec -> returnType {...}

参数解释:

[...]里面包含的是可以引用的本地变量

(...)里面包含的是函数的变量参数

returnType是返回类型

一个简单的例子如下:

cpp 复制代码
auto sum_xy = [](int x, int y) -> int {
  return x + y;
};
std::cout <<" sum_xy = "<< sum_xy(11, 12) << std::endl;

引入本地变量

cpp 复制代码
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对象快速像素遍历。语法如下:

cpp 复制代码
void cv::Mat::forEach(const Functor & operation)

其中operation是一个C++11 lambda表达式,同时也是一个匿名的C++函数。基于Mat的for Each实现的像素遍历代码如下:

cpp 复制代码
// 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指针方式的像素遍历访问代码如下:

cpp 复制代码
// 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 - 点击这里

相关推荐
极客小张几秒前
基于正点原子Linux开发板的智能监控与家电控制系统设计:深度解析Video4Linux和TCP/IP技术栈
linux·运维·c++·物联网·网络协议·tcp/ip·算法
o(╯□╰)o亚比囧囧囧1 小时前
李沐 过拟合和欠拟合【动手学深度学习v2】
人工智能·深度学习
钡铼技术1 小时前
通过MCGS在ARMxy边缘计算网关上实现物流自动化
人工智能·自动化·边缘计算·钡铼技术·armxy边缘计算网关
周哈里窗的编程2 小时前
CSP-CCF★201912-2回收站选址★
c++·算法·图论
OpenTiny社区2 小时前
茶思屋直播|TinyEngine+AI:聚焦主航道,在实践中探索低代码技术黑土地
人工智能·低代码
chenkangck503 小时前
AI大模型之旅--milvus向量库安装
人工智能·aigc·milvus
学习前端的小z3 小时前
【AI视频】Runway:Gen-2 图文生视频与运动模式详解
人工智能·aigc·音视频
SpikeKing4 小时前
LLM - 理解 多模态大语言模型(MLLM) 的 指令微调(Instruction-Tuning) 与相关技术 (四)
人工智能·语言模型·指令微调·数据调整·自指令·数据混合·instruction
未来可期LJ4 小时前
【C++ 设计模式】单例模式的两种懒汉式和饿汉式
c++·单例模式·设计模式
Trouvaille ~5 小时前
【C++篇】C++类与对象深度解析(六):全面剖析拷贝省略、RVO、NRVO优化策略
c++·c++20·编译原理·编译器·类和对象·rvo·nrvo