10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列


本文作者:小嗷

微信号:aoxiaoji

链接:https://www.jianshu.com/u/45da1fbce7d0

关键词:颜色空间缩减和计时函数【两个简便的计时函数—getTickCount()和getTickFrequency()】


1.前言.png
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第1张图片
2.前言.png
2. 简介及用途
  1. 计时函数用途:计算耗时工作

  2. 颜色空间缩减用途:颜色空间缩减。(公式如下)

10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第2张图片
3.颜色缩减法公式
  1. 如何遍历图像中的每一个像素点? 请看第8篇代码【更正曝光不足的图像(图像的对比度和亮度及轨迹条)】
  2. OpenCv的矩阵值是如何存储的? 请看第9篇恶心的内容【基本的图像容器(Mat详解)】
  3. 如何测试我们所实现算法的性能?通过算法耗时和效果的对比【计时函数】
  4. 查找表是什么?为什么要用它?等一下,会说到。

图像矩阵的大小取决于我们使用的颜色模型,确切的说,取决于所用通道数。如果是灰度图像,矩阵就会像这样:

10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第3张图片
4.灰度图像矩阵

而对于多通道图像来说,矩阵中的列会包含多个子列,其子列个数与通道数相等,例如,RGB颜色模型的矩阵:

10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第4张图片
5.RGB颜色矩阵

在这里,我们需要注意的是:子列的通道顺序是反过来的,是BGR,而不是我们数字图像书中常说的RGB.很多情况下,因为内存够大,可以实现连续存储。连续存储可以提高图像的扫描速度。我们可以使用isContinuous来判断矩阵是否连续矩阵。

6.颜色空间缩减和计时函数.png

3.1 颜色空间的缩减

如果矩阵元素存储的是单通道像素,使用C或C++的无符号字符类型,那么像素可能有256个不同的值.但若是三通道图像,这种存储格式的颜色数就太多了(确切的说,有一千六百多万种).用如此之多的颜色 可能会对我们算法的性能造成严重的影响。其实,有时候,我们仅适用这些颜色的一小部分,就足以达到同样的效果。

这种情况下,常用的一种方法就是【颜色空间缩减】.其做法是:将现有颜色值除以某个输入值,以获得较少的颜色数。例如:0到9可取新值0;10到19取值1,以此类推。

uchar(无符号字符,即0到255之间取值的数)类型除以int值,结果仍为char。因为结果是char类型的, 所以,求出来小数也要向下取整。利用这一点,刚才提到在uchar定义域中进行颜色缩减运算就可以表达为下列形式:

Inew=Iold/10*10;

这样的话,简单的颜色缩减算法就可以由以下两步组成:

1--遍历图像矩阵中的每一个像素 (第8篇用过)

2--对像素应用上述公式

值得注意的是,我们这里用到了除法和乘法运算,而这种运算又特别费时,所以,我们应尽可能用代价较低的加减,赋值等运算替换他们。

3.2 计时函数

  1. OpenCv为我们提供了两个简单的计时函数---getTickCount()和getTickFrequency()
  2. getTickCount()函数---返回CPU自某个事件以来走过的----时钟周期数
  3. getTickFrequency()函数返回CUP一秒钟所走的时钟周期数。这样,我们就可以轻松的以秒为单位对某运算计时

这两个函数组合起来的使用如下所示:

//【5】记录其实时间  
double timeStartPtr=static_cast(getTickCount());  
//【6】调用颜色空间缩减函数  
colorReducePtr(srcImg,dstImgPtr,32);  
//【7】计算运行时间,并输出  
double timeExpensePtr=((double)getTickCount()-timeStartPtr)/getTickFrequency();  
cout<<"【1】ptr指针操作像素,此方法运行时间为---------->"<

我一般都是复制粘贴计时函数,哈哈哈

3.3 访问图像中像素的三类方法

任何图像处理算法。都是从操作每个像素开始的。即使我们不会使用OpenCv提供的各种图像处理函数,只要我们了解图像处理算法的基本原理,也可以写出具有相同功能的程序.在OpenCv中,提供了三种访问每个像素的方法:

1--指针访问----------ptr<>()函数  
2--动态地址计算------at<>()函数  
3--迭代器iterator  
这三种方法,在访问速度上略有差异,指针比较快。 
11.相关代码
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第5张图片
image.png
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第6张图片
7.2代码图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第7张图片
7.3代码图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第8张图片
7.4代码图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第9张图片
7.5代码图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第10张图片
7.6代码图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第11张图片
image.png
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第12张图片
7.8代码图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第13张图片
7.9代码图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第14张图片
7.10代码图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第15张图片
7.11代码图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第16张图片
7.12代码图.PNG
//      程序描述:来自一本国外OpenCV2书籍的示例-遍历图像像素的14种方法
//------------------------------------------------------------------------------------------------

/*------------------------------------------------------------------------------------------*\
This file contains material supporting chapter 2 of the cookbook:
Computer Vision Programming using the OpenCV Library.
by Robert Laganiere, Packt Publishing, 2011.

This program is free software; permission is hereby granted to use, copy, modify,
and distribute this source code, or portions thereof, for any purpose, without fee,
subject to the restriction that the copyright notice may not be removed
or altered from any source or altered source distribution.
The software is released on an as-is basis and without any warranties of any kind.
In particular, the software is not guaranteed to be fault-tolerant or free from failure.
The author disclaims all warranties with regard to this software, any use,
and any consequent failure, is purely the responsibility of the user.

Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name
\*------------------------------------------------------------------------------------------*/

//---------------------------------【头文件、命名空间包含部分】-----------------------------
//      描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------------------
#include 
#include 
#include 
using namespace cv;
using namespace std;

//---------------------------------【宏定义部分】---------------------------------------------
//      描述:包含程序所使用宏定义
//-------------------------------------------------------------------------------------------------
#define NTESTS 14
#define NITERATIONS 20

//----------------------------------------- 【方法一】-------------------------------------------
//      说明:利用.ptr 和 []
//-------------------------------------------------------------------------------------------------
void colorReduce0(Mat &image, int div = 64) {

   int nl = image.rows; //行数
   int nc = image.cols * image.channels(); //每行元素的总元素数量

   for (int j = 0; j(j);

       for (int i = 0; i(j);

       for (int i = 0; i(j);

       for (int i = 0; i(log(static_cast(div)) / log(2.0));
   //掩码值
   uchar mask = 0xFF << n; // e.g. 对于 div=16, mask= 0xF0

   for (int j = 0; j(j);

       for (int i = 0; i(log(static_cast(div)) / log(2.0));
   int step = image.step; //有效宽度
                          //掩码值
   uchar mask = 0xFF << n; // e.g. 对于 div=16, mask= 0xF0

                           //获取指向图像缓冲区的指针
   uchar *data = image.data;

   for (int j = 0; j(log(static_cast(div)) / log(2.0));
   //掩码值
   uchar mask = 0xFF << n; // e.g. 例如div=16, mask= 0xF0

   for (int j = 0; j(j);

       for (int i = 0; i(log(static_cast(div)) / log(2.0));
   //掩码值
   uchar mask = 0xFF << n; // e.g. 比如div=16, mask= 0xF0

   for (int j = 0; j(j);

       for (int i = 0; i(log(static_cast(div)) / log(2.0));
   //掩码值
   uchar mask = 0xFF << n; // e.g. 比如div=16, mask= 0xF0

   for (int j = 0; j(j);

       for (int i = 0; i::iterator it = image.begin();
   Mat_::iterator itend = image.end();

   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;

       //-------------结束像素处理------------------------
   }//单行处理结束  
}

//-------------------------------------【方法十】-----------------------------------------------
//      说明:利用Mat_ iterator以及位运算
//-------------------------------------------------------------------------------------------------
void colorReduce9(Mat &image, int div = 64) {

   // div必须是2的幂
   int n = static_cast(log(static_cast(div)) / log(2.0));
   //掩码值
   uchar mask = 0xFF << n; // e.g. 比如 div=16, mask= 0xF0

                           // 获取迭代器
   Mat_::iterator it = image.begin();
   Mat_::iterator itend = image.end();

   //扫描所有元素
   for (; it != itend; ++it)
   {

       //-------------开始处理每个像素-------------------

       (*it)[0] = (*it)[0] & mask + div / 2;
       (*it)[1] = (*it)[1] & mask + div / 2;
       (*it)[2] = (*it)[2] & mask + div / 2;

       //-------------结束像素处理------------------------
   }//单行处理结束  
}

//------------------------------------【方法十一】---------------------------------------------
//      说明:利用Mat Iterator_
//-------------------------------------------------------------------------------------------------
void colorReduce10(Mat &image, int div = 64) {

   //获取迭代器
   Mat_ cimage = image;
   Mat_::iterator it = cimage.begin();
   Mat_::iterator itend = cimage.end();

   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;

       //-------------结束像素处理------------------------
   }
}

//--------------------------------------【方法十二】--------------------------------------------
//      说明:利用动态地址计算配合at
//-------------------------------------------------------------------------------------------------
void colorReduce11(Mat &image, int div = 64) {

   int nl = image.rows; //行数
   int nc = image.cols; //列数

   for (int j = 0; j(j, i)[0] = image.at(j, i)[0] / div*div + div / 2;
           image.at(j, i)[1] = image.at(j, i)[1] / div*div + div / 2;
           image.at(j, i)[2] = image.at(j, i)[2] / div*div + div / 2;

           //-------------结束像素处理------------------------

       } //单行处理结束                 
   }
}

//----------------------------------【方法十三】----------------------------------------------- 
//      说明:利用图像的输入与输出
//-------------------------------------------------------------------------------------------------
void colorReduce12(const Mat &image, //输入图像
   Mat &result,      // 输出图像
   int div = 64) {

   int nl = image.rows; //行数
   int nc = image.cols; //列数

                        //准备好初始化后的Mat给输出图像
   result.create(image.rows, image.cols, image.type());

   //创建无像素填充的图像
   nc = nc*nl;
   nl = 1;  //单维数组

   int n = static_cast(log(static_cast(div)) / log(2.0));
   //掩码值
   uchar mask = 0xFF << n; // e.g.比如div=16, mask= 0xF0

   for (int j = 0; j(j);
       const uchar* idata = image.ptr(j);

       for (int i = 0; i(log(static_cast(div)) / log(2.0));
   //掩码值
   uchar mask = 0xFF << n; // e.g. 比如div=16, mask= 0xF0

                           //进行色彩还原
   image = (image&Scalar(mask, mask, mask)) + Scalar(div / 2, div / 2, div / 2);
}

//-----------------------------------【main( )函数】--------------------------------------------
//      描述:控制台应用程序的入口函数,我们的程序从这里开始
//-------------------------------------------------------------------------------------------------
int main()
{
   int64 t[NTESTS], tinit;
   Mat image0;
   Mat image1;
   Mat image2;

   system("color 4F");

   image0 = imread("D://1.png");
   if (!image0.data) {
       cout <<  " could not image " << endl;
   getchar();
   return -1;
}

   //时间值设为0
   for (int i = 0; i

效果图

10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第17张图片
8.1 效果图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第18张图片
8.2 效果图.PNG
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第19张图片
8.3 效果图.PNG

注意:第八种方法最快,利用 .ptr 和 * ++ 以及位运算 (continuous+channels)的方法所用时间为1.08502ms(以后就用第八种【以后复制粘贴第八种】,哈哈哈)

image.png
  1. 本人是抱着玩一玩的心态,学习opencv(其实深度学习没有外界说的这么高深,小嗷是白板,而且有工作在身并且于代码无关)
  2. 大家可以把我的数学水平想象成初中水平,毕竟小嗷既不是代码靠吃饭又不是靠数学吃饭,毕业N年
  3. 写文章主要是为了后人少走点弯路,多交点朋友,一起学习
  4. 如果有好的图像识别群拉我进去QQ:631821577
  5. 就我一个白板,最后还是成的,你们别怕,慢慢来把
10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第20张图片
7.二维码

分享可以无数次,转载成自己文章QQ邮箱通知一下,未经授权请勿转载。

  • 邮箱:[email protected]
  • QQ群:736854977
  • 有什么疑问公众号提问,下班或者周六日回答,ths

你可能感兴趣的:(10.马赛克原理之简单提高图像算法性能(颜色空间缩减和计时函数) --- OpenCV从零开始到图像(人脸 + 物体)识别系列)