Opencv访问图像像素的三种方法
我们在实际应用中对图像进行的操作,往往并不是将图像作为一个整体进行操作,而是对图像中的所有点或特殊点进行运算,所以遍历图像就显得很重要,如何高效的遍历图像是一个很值得探讨的问题。下面介绍几种图像遍历的几种方式。
一、主函数
#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访问图像像素的三种方法相关推荐
- Opencv3编程入门学习笔记(三)之访问图像像素的三种方法
访问图像像素的三种方法:指针访问,迭代器访问,动态地址访问.访问最快的为指针访问,以下算法在几毫秒,但指针访问容易造成内存泄漏:其次为迭代器访问:最后为动态地址访问. 以下程序是根据<OpenC ...
- OpenCV精进之路(零):访问图像中像素的三种方法
访问像素的三种方法 指针访问:最快 迭代器iterator:较慢,非常安全,指针访问可能出现越界问题 动态地址计算:更慢,通过at()实现.适用于访问具体某个第i行,j列的像素,而不适用遍历像素 这里 ...
- Action访问Servlet API的三种方法
一.为什么要访问Servlet API ? Struts2的Action并未与Servlet API进行耦合,这是Struts2 的一个改良,从而方便了单独对Action进行测试.但是对于Web控制器 ...
- OpenCV访问像素的三种方法
三种方法分别问: 指针访问:void colorReduce_ptr(cv::Mat &inputImage, cv::Mat &outputImage, int div); 迭代器访 ...
- 使用OpenCV进行人脸识别的三种方法
1 简介 OpenCV从版本2.4开始,加入了一个类FaceRecognizer,使用它可以方便的地进行人脸识别(源代码,在OpenCV的opencv\modules\contrib\doc\face ...
- 比较图像相似的三种方法
转载自:https://blog.csdn.net/Alieon/article/details/97924522 前言 本来想自己写一篇总结图像相似hash算法,无意之中看到一篇博客真的是总结地很精 ...
- 图像的边缘检测-三种方法
图像的边缘检测: 比较拉普拉斯算子,LOG算子,Canny算子三种边缘检测算法. 编程思路: 图像边缘就是图像灰度值突变的地方,也就是图像在该部分的像素值变化速度非常之快,就比如在坐标轴上一条曲线有刚 ...
- OpenCV(图像处理)—访问像素的三种方法
方法一:用指针访问像素 1 #include <opencv2/opencv.hpp> 2 #include <opencv2/core/core.hpp> 3 #includ ...
- 遍历图片像素的三种方法
1.指针访问像素 void colorReduce(Mat& inputImage, Mat& outputImage, int div) {outputImage = inputIm ...
- Struts2中Action访问Servlet API的三种方法
Struts2的Action并未直接与任何Servlet API耦合,这是Struts2的一个改良之处,因为Action类不再与Servlet API耦合,能更轻松的测试该Action.但如何访问? ...
最新文章
- nginx lua调用redis和mongo
- android onclick fragment,Android Fragment onClick按钮方法
- SMO写的查看数据库信息的代码
- (转)GDB 使用方法
- php里面的 n算是,用PHP中的bcmath计算第N个根
- c语言指针章总结,c语言指针的学习心得
- python中访问lmdb
- Wincc使用.net控件将锐浪报表Grid++Report6嵌入
- 火狐浏览器50Linux32位,火狐浏览器32位完整离线安装包下载
- php dingo和jwt,Laravel5.5+dingo+JWT 开发后台 API
- C语言常见英文词汇表
- 跨境电商独立站模式分析
- 关于DebugView无法打印出KdPrint信息
- Nagios之配置介绍
- Restful风格的URL请求
- mysql 计算gps坐标距离_mysql实现经纬度计算两个坐标之间的距离
- 中国山苍子油行业销售动态与营销趋势预测报告2022-2027年
- vue Pc端微信支付和支付宝支付
- 【解决方案】视频结构化智能畜禽养殖场养猪场视频监控的实现,智慧养殖模式为养殖业加成
- SAP ALV右击电子表格不显示问题
热门文章
- 什么是敏捷项目管理?
- 强化学习 原理与Python实现(四)
- keil编译错误:Error:Flash DownLoad failed - “Cortex-M4“
- HNOI2015 亚瑟王
- 不可不看:管理定理一网打尽
- VSCode插件之Beautify
- Spring 事务源码(6)—createTransactionIfNecessary处理事务属性并尝试创建事务【两万字】
- Drupal采集,Drupal文章采集爬虫采集插件(附图文)
- 文件夹病毒或1K病毒解决
- 多目标优化 MOP (三):遗传算法 SPEA2+SDE 2014