我们在实际应用中对图像进行的操作,往往并不是将图像作为一个整体进行操作,而是对图像中的所有点或特殊点进行运算,所以遍历图像就显得很重要,如何高效的遍历图像是一个很值得探讨的问题。下面介绍几种图像遍历的几种方式。

一、主函数

#include <opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void colorReduce(Mat& inputImage, Mat& outputImage, int div);int main()
{Mat srcImage = imread("D:\\vvoo\\lena.jpg");imshow("原始图像", srcImage);Mat dstImage;dstImage.create(srcImage.rows, srcImage.cols, srcImage.type());//效果图的大小、类型与原图片相同 //记录起始时间double time0 = static_cast<double>(getTickCount());//调用颜色空间缩减函数colorReduce(srcImage, dstImage, 128);//计算运行时间并输出time0 = ((double)getTickCount() - time0) / getTickFrequency();cout << "此方法运行时间为: " << time0 << "秒" << endl;  //输出运行时间//显示效果图imshow("效果图", dstImage);waitKey(0);return 0;
}

二、.at<Vec3b>(i, j)[k]访问像素

Mat类提供了一个at的方法用于取得图像上的点,它是一个模板函数,可以取到任何类型的图像上的点。下面我们通过一个图像处理中的实际来说明它的用法。

在实际应用中,我们很多时候需要对图像降色彩,因为256*256*256实在太多了,在图像颜色聚类或彩色直方图时,我们需要用一些代表性的颜色代替丰富的色彩空间,我们的思路是将每个通道的256种颜色用64种代替,即将原来256种颜色划分64个颜色段,每个颜色段取中间的颜色值作为代表色。

通过上面的例子我们可以看出,at方法取图像中的点的用法:

outputImage.at<uchar>(i,j):取出灰度图像中i行j列的点。

outputImage.at<Vec3b>(i,j)[k]:取出彩色图像中i行j列第k通道的颜色点。其中uchar,Vec3b都是图像像素值的类型,不要对Vec3b这种类型感觉害怕,其实在core里它是通过typedef Vec<T,N>来定义的,N代表元素的个数,T代表类型。

更简单一些的方法:OpenCV定义了一个Mat的模板子类为Mat_,它重载了operator()让我们可以更方便的取图像上的点。

Mat_<uchar> im=outputImage;

im(i,j)=im(i,j)/div*div+div/2;

void colorReduce(Mat&inputImage, Mat&outputImage, int div)
{outputImage = inputImage.clone();int rows = outputImage.rows;int cols = outputImage.cols;for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){outputImage.at<Vec3b>(i, j)[0] = outputImage.at<Vec3b>(i, j)[0] / div*div + div / 2;outputImage.at<Vec3b>(i, j)[1] = outputImage.at<Vec3b>(i, j)[1] / div*div + div / 2;outputImage.at<Vec3b>(i, j)[2] = outputImage.at<Vec3b>(i, j)[2] / div*div + div / 2;}}}

结果:

二、指针法

void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{outputImage = inputImage.clone();int rows = outputImage.rows;int cols = outputImage.cols*outputImage.channels();for (int i = 0; i < rows; i++){/*uchar* data = inputImage.ptr<uchar>(i);*/uchar* dataout = outputImage.ptr<uchar>(i);for (int j = 0; j < cols; j++){dataout[j] = dataout[j] / div*div + div / 2;}}}

从上面的例子看出,取出图像第i行的数据指针:outputImage.ptr<uchar>(i);
 值得说明的是:程序中将三通道的数据转换为1通道,在建立在每一行数据元素之间在内存里是连续存储的,每个像素三通道像素按顺序存储。也就是一幅图像数据最开始的三个值,是最左上角的那像素的三个通道的值。

三、迭代器法

下面的方法可以让我们来为图像中的像素声明一个迭代器:

MatIterator_<Vec3b> it;

Mat_<Vec3b>::iterator it;

如果迭代器指向一个const图像,则可以用下面的声明:

MatConstIterator<Vec3b> it; 或者

Mat_<Vec3b>::const_iterator it;

下面我们用迭代器来简化上面的colorReduce程序:

void colorReduce(Mat& inputImage, Mat& outputImage, int div)
{outputImage = inputImage.clone();//模板必须指明数据类型  Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>();Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>();//也可以通过指明cimage类型的方法不写begin和end的类型  /*Mat_<Vec3b> cimage = outputImage;Mat_<Vec3b>::iterator itout =outputImage.begin<Vec3b>();Mat_<Vec3b>::iterator itoutend = cimage.end();*/for (; it != itend; it++/*, it++*/){(*it)[0] = (*it)[0] / div*div + div / 2;(*it)[1] = (*it)[1] / div*div + div / 2;(*it)[2] = (*it)[2] / div*div + div / 2;}
}

结果:


参考资料:

图像遍历的几种方法

Opencv访问图像像素的三种方法相关推荐

  1. Opencv3编程入门学习笔记(三)之访问图像像素的三种方法

    访问图像像素的三种方法:指针访问,迭代器访问,动态地址访问.访问最快的为指针访问,以下算法在几毫秒,但指针访问容易造成内存泄漏:其次为迭代器访问:最后为动态地址访问. 以下程序是根据<OpenC ...

  2. OpenCV精进之路(零):访问图像中像素的三种方法

    访问像素的三种方法 指针访问:最快 迭代器iterator:较慢,非常安全,指针访问可能出现越界问题 动态地址计算:更慢,通过at()实现.适用于访问具体某个第i行,j列的像素,而不适用遍历像素 这里 ...

  3. Action访问Servlet API的三种方法

    一.为什么要访问Servlet API ? Struts2的Action并未与Servlet API进行耦合,这是Struts2 的一个改良,从而方便了单独对Action进行测试.但是对于Web控制器 ...

  4. OpenCV访问像素的三种方法

    三种方法分别问: 指针访问:void colorReduce_ptr(cv::Mat &inputImage, cv::Mat &outputImage, int div); 迭代器访 ...

  5. 使用OpenCV进行人脸识别的三种方法

    1 简介 OpenCV从版本2.4开始,加入了一个类FaceRecognizer,使用它可以方便的地进行人脸识别(源代码,在OpenCV的opencv\modules\contrib\doc\face ...

  6. 比较图像相似的三种方法

    转载自:https://blog.csdn.net/Alieon/article/details/97924522 前言 本来想自己写一篇总结图像相似hash算法,无意之中看到一篇博客真的是总结地很精 ...

  7. 图像的边缘检测-三种方法

    图像的边缘检测: 比较拉普拉斯算子,LOG算子,Canny算子三种边缘检测算法. 编程思路: 图像边缘就是图像灰度值突变的地方,也就是图像在该部分的像素值变化速度非常之快,就比如在坐标轴上一条曲线有刚 ...

  8. OpenCV(图像处理)—访问像素的三种方法

    方法一:用指针访问像素 1 #include <opencv2/opencv.hpp> 2 #include <opencv2/core/core.hpp> 3 #includ ...

  9. 遍历图片像素的三种方法

    1.指针访问像素 void colorReduce(Mat& inputImage, Mat& outputImage, int div) {outputImage = inputIm ...

  10. Struts2中Action访问Servlet API的三种方法

    Struts2的Action并未直接与任何Servlet API耦合,这是Struts2的一个改良之处,因为Action类不再与Servlet API耦合,能更轻松的测试该Action.但如何访问? ...

最新文章

  1. nginx lua调用redis和mongo
  2. android onclick fragment,Android Fragment onClick按钮方法
  3. SMO写的查看数据库信息的代码
  4. (转)GDB 使用方法
  5. php里面的 n算是,用PHP中的bcmath计算第N个根
  6. c语言指针章总结,c语言指针的学习心得
  7. python中访问lmdb
  8. Wincc使用.net控件将锐浪报表Grid++Report6嵌入
  9. 火狐浏览器50Linux32位,火狐浏览器32位完整离线安装包下载
  10. php dingo和jwt,Laravel5.5+dingo+JWT 开发后台 API
  11. C语言常见英文词汇表
  12. 跨境电商独立站模式分析
  13. 关于DebugView无法打印出KdPrint信息
  14. Nagios之配置介绍
  15. Restful风格的URL请求
  16. mysql 计算gps坐标距离_mysql实现经纬度计算两个坐标之间的距离
  17. 中国山苍子油行业销售动态与营销趋势预测报告2022-2027年
  18. vue Pc端微信支付和支付宝支付
  19. 【解决方案】视频结构化智能畜禽养殖场养猪场视频监控的实现,智慧养殖模式为养殖业加成
  20. SAP ALV右击电子表格不显示问题

热门文章

  1. 什么是敏捷项目管理?
  2. 强化学习 原理与Python实现(四)
  3. keil编译错误:Error:Flash DownLoad failed - “Cortex-M4“
  4. HNOI2015 亚瑟王
  5. 不可不看:管理定理一网打尽
  6. VSCode插件之Beautify
  7. Spring 事务源码(6)—createTransactionIfNecessary处理事务属性并尝试创建事务【两万字】
  8. Drupal采集,Drupal文章采集爬虫采集插件(附图文)
  9. 文件夹病毒或1K病毒解决
  10. 多目标优化 MOP (三):遗传算法 SPEA2+SDE 2014