opencv学习(五)之像素遍历三种方式耗时分析
来源:互联网 发布:照片变成手绘软件 编辑:程序博客网 时间:2024/06/07 23:29
前面用两篇介绍了像素的颜色空间缩减、查找表、遍历像素的三种方式、程序计时等,也说了一下每种方法的优缺点,现在用一个综合型的程序进行对比。方式是用三种方式对lena图像(220x220)进行处理,使其颜色种类从256中变成64种。在颜色空间缩减方法中讲过这种方式,即每个像素值除以4向下取整然后再乘以4即可将其颜色种类缩减到64种。
#include <iostream>#include <opencv2/core.hpp>#include <opencv2/highgui.hpp>using namespace std;using namespace cv;void colorReduceAt(Mat& srcImage, Mat& dstImageAt, int div);void colorReduceIterator(Mat& srcImage, Mat& dstImageIterator, int div);void colorReducePtr(Mat& srcImage, Mat& dstImagePtr, int div);int main(){ //加载lena图像 Mat srcImage = imread("lena.jpg"); //判断图像是否加载成功 if(srcImage.empty()) { cout << "图像加载失败!" << endl << endl; return -1; } else cout << "图像加载成功!" << endl << endl; imshow("srcImage",srcImage); //声明处理后图像变量 Mat dstImageAt, dstImageIterator, dstImagePtr; dstImageAt = srcImage.clone(); dstImageIterator = srcImage.clone(); dstImagePtr = srcImage.clone(); int div = 4; //声明时间变量 double timeAt, timeIterator, timePtr; timeAt = static_cast<double>(getTickCount()); colorReduceAt(srcImage, dstImageAt, div); timeAt = ((double)getTickCount() - timeAt) / getTickFrequency(); imshow("dstImageAt",dstImageAt); cout << "使用at()动态地址计算耗时:" << timeAt << endl << endl; timeIterator = static_cast<double>(getTickCount()); colorReduceIterator(srcImage, dstImageIterator, div); timeIterator = ((double)getTickCount() - timeIterator) / getTickFrequency(); imshow("dstImageIterator",dstImageIterator); cout << "使用iterator迭代器耗时:" << timeIterator << endl << endl; timePtr = static_cast<double>(getTickCount()); colorReducePtr(srcImage, dstImagePtr, div); timePtr = ((double)getTickCount() - timePtr) / getTickFrequency(); imshow("dstImagePtr",dstImagePtr); cout << "使用ptr指针耗时:" << timePtr << endl; waitKey(0); return 0;}//使用at动态地址计算方式void colorReduceAt(Mat& srcImage, Mat& dstImageAt, int div){ int rowNumber = dstImageAt.rows; //获取图像行数 int colNumber = dstImageAt.cols; //获取图像列数 //对每个像素进行处理 for(int i = 0; i < rowNumber; i++) { for(int j = 0; j < colNumber; j++) { dstImageAt.at<Vec3b>(i,j)[0] = dstImageAt.at<Vec3b>(i,j)[0]/div*div; //Blue dstImageAt.at<Vec3b>(i,j)[1] = dstImageAt.at<Vec3b>(i,j)[1]/div*div; //Green dstImageAt.at<Vec3b>(i,j)[2] = dstImageAt.at<Vec3b>(i,j)[2]/div*div; //Red } }}//使用iterator迭代器方式void colorReduceIterator(Mat& srcImage, Mat& dstImageIterator, int div){ MatIterator_<Vec3b> imageIt = dstImageIterator.begin<Vec3b>(); //获取迭代器初始位置 MatIterator_<Vec3b> imageEnd = dstImageIterator.end<Vec3b>(); //获取迭代器结束位置 //对每个像素进行处理 for(;imageIt != imageEnd; imageIt++) { (*imageIt)[0] = (*imageIt)[0]/div*div; //Blue (*imageIt)[1] = (*imageIt)[1]/div*div; //Green (*imageIt)[2] = (*imageIt)[2]/div*div; //Red }}//使用ptr指针void colorReducePtr(Mat& srcImage, Mat& dstImagePtr, int div){ int rowNumber = dstImagePtr.rows; //获取图像矩阵行数 int colNumber = dstImagePtr.cols*dstImagePtr.channels(); //三通道图像每行元素个数为列数x通道数 for(int i = 0; i < rowNumber; i++) { uchar* pixelPtr = dstImagePtr.ptr<uchar>(i); //获取矩阵每行首地址指针 for(int j = 0; j < colNumber; j++) pixelPtr[j] = pixelPtr[j] / div * div; }}
运行结果如下:
三种方式在本程序中的耗时情况如下,值得注意的是程序耗时和电脑硬件和编译器等都有关系,在此我用的是cmake 3.5.1
从上述耗时分析来看使用指针方式是最快的处理方式,而迭代器的方式相对最慢。但是使用迭代器是较为安全的访问方式。
从上面程序中仔细分析指针式访问和at()动态地址分配访问方式的不同。可以找更大的图像对三种像素遍历方式进行分析,其耗时会由明显差别。
除了上面三种方式,其官方文档还提到了使用LUT()函数。在进行图像处理时将所给的所有图像值替换成其他的值,opencv中提供的LUT()函数可以批量实现这种功能。其用法如下:
Mat lookUpTable(1, 256, CV_8U);uchar* p = lookUpTable.data;for(int i = 0; i < 256; ++i) p[i] = table[i];//然后调用函数(I是输入图像,J是输出图像)LUT(I, lookUpTable, J);
官方文档中通过对一幅(2560x1600)图像进行上百次的处理得出如下结论:
1. 如果可能的话尽可能使用opencv中提供的参数
2. 最快的方式是LUT()函数,因为opencv库通过Intel Threaded Building Blocks实现其多线程。
3. 如果写一个简单图像的遍历程序推荐使用指针方式。
4. 迭代器是相对来讲比较安全的访问方式,但其速度也相对较慢。
5. 在Debug模式下,动态地址计算方法是最慢的访问方式,但是在Release模式下它有可能比iterator访问方式快
- opencv学习(五)之像素遍历三种方式耗时分析
- opencv学习(四)之像素遍历三种方式
- opencv学习(三)之图像像素遍历(颜色空间缩减、查找表)
- opencv 学习记录(2) 像素遍历
- OpenCV学习遍历图像像素
- opencv 遍历图片像素并生成新图片(两种方式对比)
- opencv开发笔记(七):三种方法遍历图像操作像素
- opencv学习(5) 使用迭代器遍历图像的像素
- openCV学习笔记(四):图像遍历和像素操作
- JAVA API 学习笔记(迭代器)和集合的三种遍历方式以及优缺点分析
- opencv学习三种常用方法访问操作图像像素
- openCV学习笔记-三种访问像素的方法
- opencv之访问图像像素的 三种方法
- OpenCV学习篇之五 使用指针遍历图像
- 【OpenCV学习笔记】三、操作像素
- openCV遍历图片像素方式的时间效率对比
- OpenCV入门三:OpenCV创建新图像以及遍历图片像素值和设置像素值
- OpenCV学习之三:使用迭代器遍历图像
- UISegmentedControl去掉边框-姬云鹏
- 最近看到的spark资料整理
- leetcode:Remove Duplicates from Sorted Array
- CSAPP第六章-存储器的层次结构
- 用变量a给出下面的定义
- opencv学习(五)之像素遍历三种方式耗时分析
- Fragment你应该知道的那些事
- JVM常用工具
- Appserv安装之后mysql服务无法启动
- 蓝牙共享网络BluetoothPan
- Faster rcnn 安装、训练、测试、调试
- 学习面向对象的六大原则
- 【信号】用matlab实现一维信号的高斯滤波
- linux 下的vi 使用方法