[cookbook笔记三] colorReduce函数运行效率测试方法

原创 2014年05月15日 16:15:02
一个很有用的测试图像处理运行耗时的方法为
double duration;
duration = static_cast<double>(cv::getTickCount());
colorReduce(image); // the function to be tested
duration = static_cast<double>(cv::getTickCount())-duration;
duration /= cv::getTickFrequency(); // the elapsed time in s

其中duration结果可以是多次调用函数colorReduce后的平均值,注意到函数getTickFrequency()是将tick转换成秒,而不是毫秒!

那么接下来就测试一下几种函数实现同意功能的不同运行耗时:

测试函数:

double duration = static_cast<double>(getTickCount());
	for (int i=0 ; i<10 ; i++){
		colorReduce2(img,64);
	}
	duration = static_cast<double>(getTickCount())-duration ;
	duration *=1000;//转换成ms
	duration /=(getTickFrequency()*10);
	cout<<"共耗时 : "<<duration<<" ms"<<endl;

函数一:

void colorReduce1(Mat &image , int factor)//行指针扫描方式,据官方文档说是最快的方式
{
	int colLength = image.cols*image.channels();
	for(int i=0; i<image.rows ; i++){
		uchar *data = image.ptr<uchar>(i);//得到每一行的起始地址
		for(int j=0; j< colLength; j++){
			data[j] = data[j]/factor * factor + factor/2;
		}
	}
}

实际运行效果(取10次的平均值):



函数二:

void colorReduce2(Mat &image ,int factor)//连续时直接扫描
{
	int nCols,nRows;
	if(image.isContinuous()){
		nCols = image.total() * image.elemSize();
		nRows = 1;
		uchar *data = image.ptr<uchar>(0);//第一行指针
		for(int i=0 ; i<nCols ; i++){
			data[i] = 255;
		}
	}
}

实际运行效果(取10次的平均值):



函数三:

void colorReduce3(Mat &image , int factor)//迭代器方式
{
	Mat_<Vec3b> cImage = image;
	Mat_<Vec3b>::iterator it = cImage.begin();
	Mat_<Vec3b>::iterator itEnd = cImage.end();
	for(; it!=itEnd ; it++){
		(*it)[0] = (*it)[0]/factor *factor + factor/2;
		(*it)[1] = (*it)[1]/factor *factor + factor/2;
		(*it)[2] = (*it)[2]/factor *factor + factor/2;
	}
}
实际运行效果(取10次的平均值):


函数四:

void colorReduce4(Mat &image , int factor)//at方式---注意内外层循环的嵌套方式 ,由于图片是按行存储,因此下面的方式应该会很慢---真的么?
{
	for(int ncols=0 ; ncols <image.cols ; ncols++){
		for(int nrows=0 ; nrows<image.rows ; nrows++){
			image.at<Vec3b>(nrows , ncols)[0] = image.at<Vec3b>(nrows , ncols)[0]/factor * factor + factor/2;
			image.at<Vec3b>(nrows , ncols)[1] = image.at<Vec3b>(nrows , ncols)[1]/factor * factor + factor/2;
			image.at<Vec3b>(nrows , ncols)[2] = image.at<Vec3b>(nrows , ncols)[2]/factor * factor + factor/2;
		}
	}
}

实际运行效果(取10次的平均值):



函数五:

void colorReduce5(Mat &image , int factor)
{
	for(int nrows=0 ; nrows <image.rows ; nrows++){//at方式---注意内外层循环的嵌套方式 ,由于图片是按行存储,因此下面的方式应该会比上面的快一些--真的么?
		for(int ncols=0 ; ncols<image.cols ; ncols++){
			image.at<Vec3b>(nrows , ncols)[0] = image.at<Vec3b>(nrows , ncols)[0]/factor * factor + factor/2;
			image.at<Vec3b>(nrows , ncols)[1] = image.at<Vec3b>(nrows , ncols)[1]/factor * factor + factor/2;
			image.at<Vec3b>(nrows , ncols)[2] = image.at<Vec3b>(nrows , ncols)[2]/factor * factor + factor/2;
		}
	}
}

实际运行效果(取10次的平均值):



函数六:

void colorReduce6(Mat &image , int factor)
{
	if(image.isContinuous()){
		image.reshape(1,image.cols*image.rows);//并不改变存储方式
	}
	int nrow = image.rows;
	int ncol = image.cols * image.channels();
	for(int i=0; i<nrow; i++){
		uchar* data = image.ptr<uchar>(i);
		for(int j=0; j<ncol; j++){
			data[j] = data[j]/factor*factor +factor/2;
		}
	}
}
实际运行效果(取10次的平均值):



注意:注意到许多运行效率的问题都有能来自于程序编写所致,

例如:

将int nc= image.cols * image.channels(); 

for (int i=0; i<nc; i++) {}

换成for (int i=0; i<image.cols * image.channels(); i++) {}

这样你需要多次重复计算一行的元素个数,会带来巨大的运行消耗,而这个消耗是可以避免的!


结论:1.关于迭代器访问方式:迭代器访问方式的主要作用是简化访问步骤---smart enough to skip the gaps,且可以与STL兼容(可以用到如sort等算法中去),所以运行效率稍低是可以接受的。

           2.关于at访问方式效率最低,这种方式往往用于随机访问某一位置像素点的值,一般不用于扫描整个图像!

   3.注意函数4和5,很显然其实没有这回事儿,因为在内存中,不存在磁头移动的问题,因此上一次随机存取的位置对这一次没有影响!都是要计算起始地址加偏移量。因此俩函数效率差不多!

   4.关于for循环:循环次数少但循环内语句多点  >  一个长循环

   这样我们可以得到最快的改进版函数:

void colorReduce7(Mat &image , int factor)
{
	int nCols,nRows;
	if(image.isContinuous()){
		nRows = 1;
		uchar *data = image.ptr<uchar>(0);//第一行指针
		for(int i=0 ; i<image.cols ; i++){
			data[i] = data[i]/factor * factor + factor/2;
			data[i++] = data[i++]/factor * factor + factor/2;
			data[i++] = data[i++]/factor * factor + factor/2;
		}
	}
}
注意到这里总是假定image是连续的,一个更完善的方案是如下方案:

void colorReduce8(Mat &image , int factor)
{
	int nRows=image.rows;
	int nCols=image.cols;

	if(image.isContinuous()){
		nCols = image.cols * image.rows;
		nRows = 1;
	}
	for(int i=0 ; i<nRows ; i++){
		uchar *data = image.ptr<uchar>(i);//第一行指针
		for(int j=0 ; j<nCols ; j++)
		{
			*data++ = *data/factor * factor + factor/2;
			*data++ = *data/factor * factor + factor/2;
			*data++ = *data/factor * factor + factor/2;
		}
	}
}

扩展:使用多线程技术也是一个加快嵌套的for循环运行效率的方法!在此可以参考目前比较常用的OpenMP和Intel Threading Building Blocks (TBB)这俩API。OpenMp直接在VS中开启的方法就是打开工程属性页面,找到 C++/语言 这一栏,其中有一个OpenMP支持,打开就能使用了!


一起学opencv2 (三) 扫描图像 COLOR REDUCE

说明: 彩色图像像素形式为3通道像素,每个通道数据格式为8-bit unsigned char ,因此数据总量为256x256x256 ,这些彩色数据对于计算机来讲处理将占用大量内存和CPU为此,...
  • keetsky
  • keetsky
  • 2016年10月26日 14:25
  • 780

OpenCV, color reduction method

转载请注明出处!!!http://blog.csdn.net/zhonghuan1992 OpenCV, colorreduction method 目标:          这次学...
  • u013035103
  • u013035103
  • 2014年08月06日 23:43
  • 5532

我的OpenCV学习笔记(二):操作每个像素

首先推荐一本书:《OpenCV 2 Computer Vision Application Programming Cookbook》网上可以下载到这本书的英文版,貌似没有翻译的。这本书的特点是里面的...
  • thefutureisour
  • thefutureisour
  • 2012年04月21日 23:30
  • 19094

最快的颜色缩减函数

#include #include #include #include using namespace std; using namespace cv; //颜色缩减函数 /*void colorRe...
  • fanpengfei0
  • fanpengfei0
  • 2014年04月14日 15:48
  • 828

colorReduce cpp

/*------------------------------------------------------------------------------------------*\    T...
  • autumn20080101
  • autumn20080101
  • 2016年06月30日 19:12
  • 224

[cookbook笔记三] colorReduce函数运行效率测试方法

一个很有用的测试图像处理运行耗时的方法为double duration; duration = static_cast(cv::getTickCount()); colorReduce(image);...
  • u010013164
  • u010013164
  • 2014年05月15日 16:15
  • 1569

opencv图像处理总结

opencv图像处理基本操作 1. 矩阵数据类型 通用矩阵数据类型: CV_(S|U|F)C 其中,S表示带符号整数; U表示无符号整数; F表示浮点数; 例如:CV_8UC1 ...
  • sjtudou
  • sjtudou
  • 2017年09月26日 22:45
  • 282

python-cookbook学习笔记七

Python中表示时间的模块是datetime,引入下面的模块 from datetime import datetime,timedelta print datetime.today()  #打...
  • zhfcmx1
  • zhfcmx1
  • 2017年04月26日 23:05
  • 214

《MFC游戏开发》笔记三 游戏贴图与透明特效的实现

本系列文章由七十一雾央编写,转载请注明出处。 http://blog.csdn.net/u011371356/article/details/9313239 作者:七十一雾央 新浪微博:h...
  • lsybryant
  • lsybryant
  • 2014年09月08日 13:46
  • 1257

opencv:访问图像中像素的三类方法

见代码分析:#include #include #include using namespace std; using namespace cv;//全局函数声明 void colorReduc...
  • qq_31935691
  • qq_31935691
  • 2017年05月11日 23:37
  • 95
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[cookbook笔记三] colorReduce函数运行效率测试方法
举报原因:
原因补充:

(最多只允许输入30个字)