OpenCV遍历图像像素是很常见的事情,比较下面的三种遍历方式哪个是最高效的。

前言

在OpenCV C++中Mat对象的内存管理由OpenCV框架自动负责内存分配与回收,基于智能指针实现内存管理。Mat对象的数据组织形式与像素块数据的存储方式,Mat对象由两个部分组成,元数据头部加像素数据块部分,图示如下:

三种图像遍历方式

方法一

基于Mat对象的随机像素访问API实现,通过行列索引方式遍历每个像素值

void method_1(Mat &image) {double t1 = getTickCount();int w = image.cols;int h = image.rows;for (int row = 0; row < h; row++) {for (int col = 0; col < w; col++) {Vec3b bgr = image.at<Vec3b>(row, col);bgr[0] = 255 - bgr[0];bgr[1] = 255 - bgr[1];bgr[2] = 255 - bgr[2];image.at<Vec3b>(row, col) = bgr;}}double t2 = getTickCount();double t = ((t2 - t1) / getTickFrequency()) * 1000;ostringstream ss;ss << "Execute time : " << std::fixed << std::setprecision(2) << t << " ms ";putText(image, ss.str(), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);imshow("result", image);
}

方法二

基于Mat对象的行随机访问指针方式实现对每个像素的遍历

 void method_2(Mat &image) {double t1 = getTickCount();int w = image.cols;int h = image.rows;for (int row = 0; row < h; row++) {Vec3b* curr = image.ptr<Vec3b>(row);for (int col = 0; col < w; col++) {Vec3b bgr = curr[col];bgr[0] = 255 - bgr[0];bgr[1] = 255 - bgr[1];bgr[2] = 255 - bgr[2];}}double t2 = getTickCount();double t = ((t2 - t1) / getTickFrequency()) * 1000;ostringstream ss;ss << "Execute time : " << std::fixed << std::setprecision(2) << t << " ms ";putText(image, ss.str(), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);imshow("result", image);
}

除了上述的行指针遍历方式,常见的行指针还有如下:

CV_8UC1: 灰度图像
uchar* ptr = image.ptr<uchar>(row_index);CV_8UC3: 彩色图像
Vec3b* ptr = image.ptr<cv::Vec3b>(row_index);CV_32FC1: 单通道浮点数图像
float* ptr = image.ptr<float>(row_index);CV_32FC3: 三通道浮点数图像
Vec3f* ptr = image.ptr<cv::Vec3f>(row_index);

方法三

直接获取Mat对象的像素块的数据指针,基于指针操作,实现快速像素方法

 void method_3(Mat &image) {double t1 = getTickCount();int w = image.cols;int h = image.rows;for (int row = 0; row < h; row++) {uchar* uc_pixel = image.data + row*image.step;for (int col = 0; col < w; col++) {uc_pixel[0] = 255 - uc_pixel[0];uc_pixel[1] = 255 - uc_pixel[1];uc_pixel[2] = 255 - uc_pixel[2];uc_pixel += 3;}}double t2 = getTickCount();double t = ((t2 - t1) / getTickFrequency()) * 1000;ostringstream ss;ss << "Execute time : " << std::fixed << std::setprecision(2) << t << " ms ";putText(image, ss.str(), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);imshow("result", image);
}

实践证明,唯一正确的选择是直接方法三使用data指针直接访问,但是这个在OpenCV官方的教程都没有明确说明,官方教程代码都是基于第一种方式,是为了理解与入门,这个也导致一些人在做开发的时候直接使用第一种方式做遍历,然后就是代码运行太慢,以后请用正确方式打开Mat对象遍历。

OpenCV——高效遍历图像(C++版本)相关推荐

  1. opencv高效遍历图像

    初次接触OpenCV的开发者,必须过的第一道坎就是学会如何遍历访问Mat对象中每个像素,实现像素级别的图像操作,这个是最级别的编程技能,但是不同的像素遍历方法效率有云泥之别,相差特别大,甚至可能成为算 ...

  2. OpenCV 【十二】OpenCV如何扫描图像、利用查找表和计时

    目录 OpenCV如何扫描图像.利用查找表和计时 1.函数计算时间测试case 2. Mat图像的存储机理 3. 像素遍历的3--4种方式 4. 实例 OpenCV如何扫描图像.利用查找表和计时 如何 ...

  3. OpenCV遍历图像性能比较、利用查找表

    原文:http://blog.csdn.net/chenjiazhou12/article/details/21052849 对于如何扫描图像的方法实在是太多了,在浏览一些资料的时候也找到了一些好的方 ...

  4. OpenCV优化:图像的遍历4种方式

    小知识:反色 反色原理很简单,在一个rgb色彩空间中,可将任何一种颜色看成笛卡尔坐标中的一个点,对于任意点,反色就是计算以(128, 128,128)为中心时该点的对称点,比如rgb(100, 150 ...

  5. opencv 几种不同遍历图像像素的方法详解

    简述 我们在图像处理时经常会用到遍历图像像素点的方式,同样是遍历图像像素点,共有很多中方法可以做到:在这些方法中,有相对高效的,也有低效的:不是说低效的方法就不好,不同场景使用不同方法. 方法 下面将 ...

  6. OpenCV GPU 简单遍历图像

    OpenCV GPU  简单遍历图像 [cpp] view plaincopy print? #include "cuda_runtime.h" #include "de ...

  7. c++ opencv数字图像处理:访问图像像素,遍历图像像素

    文章目录 前言 一.访问图像像素 1.访问(j,i)处像素 2.例子:在图像中加入白色椒盐噪声 二.遍历图像像素 1.指针扫描 2.opencv自带的卷积运算:filter2D 前言 数字图像处理c+ ...

  8. OpenCV之core 模块. 核心功能(1)Mat - 基本图像容器 OpenCV如何扫描图像、利用查找表和计时 矩阵的掩码操作 使用OpenCV对两幅图像求和(求混合(blending))

    Mat - 基本图像容器 目的 从真实世界中获取数字图像有很多方法,比如数码相机.扫描仪.CT或者磁共振成像.无论哪种方法,我们(人类)看到的是图像,而让数字设备来"看"的时候,则 ...

  9. BEBLID:增强的高效局部图像特征描述符

    (本文转载自:当SLAM遇见小王同学) 在前不久发布的OpenCV4.5中更新了很多新特性: 从4.5版本开始,OpenCV将正式使用Apache2协议,从而避免专利算法带来的潜在纠纷 SIFT专利到 ...

最新文章

  1. 解密中国研发团队如何开发VS2010新特性
  2. LeetCode 406 Queue Reconstruction by Height
  3. java+log日志服务器_Logserver日志服务器结构
  4. python3视频教学_Python3入门基础视频课程(下)
  5. VS Code:4个中文乱码问题及解决方法
  6. MapGIS格式转ArcGIS方法
  7. 简笔画花边边框超简单_好看的花边边框简笔画
  8. CQF笔记M1L2二叉树模型
  9. 英国内政部(Home Office)间谍机构(spy powers)假装它是Ofcom咨询中的一名私人公民1525445610411...
  10. 错误使用empty()函数
  11. Python # 扫描端口功能 # 获取网卡的Mac地址 # 局域网扫描器IP地址和MAC地址,获取网卡名称和其ip地址
  12. idea工具和激活码获取
  13. 数据分析大数据分析如何应用于电商行业?
  14. git配置姓名和邮箱
  15. 目前html邮件都支持手机屏幕,Html电子邮件不能在手机上阅读媒体查询
  16. python转盘抽奖_python实现转盘效果 python实现轮盘抽奖游戏
  17. 计算机科学导论知识体系,《计算机科学导论》 数据库基础知识
  18. android okhttp 断点续传,OkHttp实现断点续传
  19. 9. Qt5文件及磁盘处理
  20. Analog Devices AD1983 @ 英特尔 82801H(ICH8) 高保真音频

热门文章

  1. VSCode使用VIM复制内容到系统剪切板
  2. html 音频格式,html5中audio支持音频格式
  3. 服务器系统咋关机呀,各种服务器系统的关机
  4. 代码下移快捷键_收藏细看!最全面的通达信快捷键一览
  5. as 运算符 与 where T : class
  6. 在Linux下安装和使用MySQL
  7. 2010年度十大杰出IT博客大赛奖品展示
  8. 30个超实用Python代码片段
  9. pandas中size方法_eplot,在pandas中流畅的使用pyecharts!
  10. 2022-04-11 查询PostGIS和pgRouting的版本号