//-----------------------------------【全局函数声明部分】-----------------------------------
// 描述:全局函数声明
//-----------------------------------------------------------------------------------------------
void colorReduce(Mat& inputImage, Mat& outputImage, int div);
void ShowHelpText();
//--------------------------------------【main( )函数】--------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main( )
{
//【1】创建原始图并显示
Mat srcImage = imread("1.jpg");
imshow("原始图像",srcImage);
//【2】按原始图的参数规格来创建创建效果图
Mat dstImage;
dstImage.create(srcImage.rows,srcImage.cols,srcImage.type());//效果图的大小、类型与原图片相同
ShowHelpText();
//【3】记录起始时间
double time0 = static_cast<double>(getTickCount());
//【4】调用颜色空间缩减函数
colorReduce(srcImage,dstImage,32);
//【5】计算运行时间并输出
time0 = ((double)getTickCount() - time0)/getTickFrequency();
cout<<"此方法运行时间为: "<<time0<<"秒"<<endl; //输出运行时间
//【6】显示效果图
imshow("效果图",dstImage);
waitKey(0);
}
//-------------------------------------【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>(); //终止位置的迭代器
//存取彩色图像像素
for(;it != itend;++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;
// ------------------------【处理结束】----------------------------
}
}
//-----------------------------------【ShowHelpText( )函数】----------------------------------
// 描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
//输出欢迎信息和OpenCV版本
printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");
printf("\n\n\t\t\t此为本书OpenCV2版的第22个配套示例程序\n");
printf("\n\n\t\t\t 当前使用的OpenCV版本为:" CV_VERSION );
printf("\n\n ----------------------------------------------------------------------------\n");
}
程序分析,先来看一下计算时间的函数。
(1)CV_EXPORTS_W int64 getTickCount()
The function returns the number of ticks since the certain event (e.g. when the machine was turned on).
It can be used to initialize cv::RNG or to measure a function execution time by reading the tick count
before and after the function call. The granularity of ticks depends on the hardware and OS used. Use
cv::getTickFrequency() to convert ticks to seconds
该英文翻译为:该函数返回的是某个触发事件所经历的tick次数(当计算机开始计算)。通过计算tick次数,可以用于初始化RNG或者检测一个被调用的应用程序的运行时间。具体的tick次数视硬件和os平台而定。使用getTickFrenquency来把tick转换成秒。
CV_EXPORTS_W double getTickFrequency()//每一秒经历的tick次数
经典用法:
double exec_time = (double)getTickCount();
exec_time = ((double)getTickCount() - exec_time)*1000./getTickFrequency();
再来区分一下这个函数GetTickCount()
实际上,该getTickCount()函数为opencv中的函数,该函数返回的值为自从某一时刻(比如计算机启动)开始,计算机总共经过的tick的次数,其需要结合getTickFrequency()函数使用,getTickFrequency()返回的是CPU在一秒钟内会发出的tick的次数,总体来说,该函数的精度较高,能够精确到1ms左右,获得时间的一个例子如:
double t = (double)getTickCount();
//do sth.
t = ((double)getTickCount() - t)/getTickFrequency(); //获得时间,单位是秒
使用时应注意加上 using namespace cv;
GetTickCount(),首字母大写后,该函数即为windows编程自带的API函数了,也是统计时间用的,但是用起来的时候,返回的值直接就是ms.根据参考文献,其精度大概只有18ms左右。
使用时,应注意:
库文件:kernel32.dll
C/C++头文件:winbase.h
windows程序设计中可以使用头文件windows.h
(2)迭代器iterator
来看这几句:
Mat_<Vec3b>::iterator it = outputImage.begin<Vec3b>(); //初始位置的迭代器
Mat_<Vec3b>::iterator itend = outputImage.end<Vec3b>(); //终止位置的迭代器
for(;it != itend;++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;
// ------------------------【处理结束】----------------------------
}
意思是定义一个迭代器来实现访问像素的过程。首先定义iterator it,是图像的开始指针。然后定义iterator itend,是图像结束像素的指针。然后通过遍历迭代器来访问图像的全部像素。
template<typename _Tp> class CV_EXPORTS Mat_ : public Mat,从矩阵Mat派生出来的类Mat_,是一个_Tp类型的模板类,是个可以存储相关类型对象的集合。
而typedef Vec<uchar, 3> Vec3b;是uchar类型的3通道数据。
迭代器iterator的原型是:
typedef MatIterator_<_Tp> iterator;
而MatIterator_<_Tp>的原型又是:
template<typename _Tp> class CV_EXPORTS MatIterator_;
(完)