计算机视觉
图像处理

opencv源码解析之(1):滤波前言

对图像的滤波和平滑是出来数字图像处理和计算机视觉非常重要的一个步骤,那么什么是滤波呢?滤波用编程语言到底是怎么实现的呢?效果怎么样?本人打算学习Opencv有关滤波的源码,进一步加强图像处理的实践能力。

首先我们利用opencv中常见的4种滤波算法函数来实现滤波功能,让大家有个感性的认识。这4中滤波分别是均值滤波,高斯滤波,中值滤波,双边滤波。利 用opencv2.3.1的参考手册中关于opencv中滤波的介绍,我这里采用的是VS2010+opencv2.3.1,新建了一个 filter_test控制台工程。

其源码和注释如下:

//包含图像处理和界面处理的头文件

#include "stdafx.h"

#include "opencv2/imgproc/imgproc.hpp"

#include "opencv2/highgui/highgui.hpp"

 

//采用cv命名空间和标准命名空间

using namespace std;

using namespace cv;

 

//定义全局变量

int DELAY_CAPTION=1500; //显示标题时延时至少1.5s

int DELAY_BLUR=100; //显示每次滤波时延时0.1s

int MAX_KERNEL_LENGTH=31;//最大的滤波核长度为31

 

Mat src,dst;

char window_name[]="Filter Demo 1:";

 

//函数说明

int display_caption(char *caption);

int display_dst(int delay);

 

//主函数

int main(int argc, _TCHAR* argv[])

{

       namedWindow(window_name,CV_WINDOW_AUTOSIZE);//建立一个窗口

 

       //将lena图片读写到矩阵src

       src=imread("../images/lena.jpg",1);

//将Origin Image单词显示在dst图片中,并在窗口中显示1.5s

       if(display_caption("Origin Image")!=0){return 0;}

 

       dst=src.clone();//将lena图片复制到dst矩阵中,并显示出来,1.5s

       if(display_dst(DELAY_CAPTION)!=0){return 0;}

 

       /*利用均值滤波

其中矩阵滤波的函数原型为void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT)

其中src为滤波前图像矩阵,dst为滤波后图像矩阵,ksize为滤波矩形核,anchor为定标点,如果采用的是Point(-1,-1)则默认为核的中心点,borderType为边缘模式的展开

其滤波公式为:




也就是利用ksize个像素求平均值而已,很容易理解*/

 

       if(display_caption("Homogeneous Blur")!=0){return 0;}//显示Homogeneous Blur单词1.5s

 

       for(int i=1;i<MAX_KERNEL_LENGTH;i=i+2)

       {

              blur(src,dst,Size(i,i),Point(-1,-1));//采用均值滤波函数

              if(display_dst(DELAY_BLUR)!=0){return 0;}

       }

 

         //高斯滤波,和上面类似

       if(display_caption("Gaussian Blur")!=0){return 0;}

 

       for(int i=1;i<MAX_KERNEL_LENGTH;i=i+2)

       {

              GaussianBlur(src,dst,Size(i,i),0,0);

              if(display_dst(DELAY_BLUR)!=0){return 0;}

       }

 

         //中值滤波,和上面类似

       if(display_caption("Median Blur")!=0){return 0;}

 

       for(int i=1;i<MAX_KERNEL_LENGTH;i=i+2)

       {

              medianBlur(src,dst,i);

              if(display_dst(DELAY_BLUR)!=0){return 0;}

       }

 

         //双边滤波,和上面类似

       if(display_caption("Bilateral Blur")!=0){return 0;}

 

       for(int i=1;i<MAX_KERNEL_LENGTH;i=i+2)

       {

              bilateralFilter(src,dst,i,i*2,i/2);

              if(display_dst(DELAY_BLUR)!=0){return 0;}

       }

 

       //按任意键停止

       display_caption("End:Press a key!");

 

       waitKey(0);

       return 0;

}

//中间显示标题,没有按键触发时返回0

int display_caption(char *caption)

{

         dst=Mat::zeros(src.size(),src.type());

//opencv2.3.1中往图片上加字用putText函数,大家一看就应该知道参数是什么意思了

    putText(dst,caption,Point(src.cols/4,src.rows/2),CV_FONT_HERSHEY_COMPLEX,1, Scalar(255,255,255));

 

         imshow(window_name,dst);

 

//延时1.5s,注意在c++中是waitKey,该函数参数如果是非正数的话就直接停止在该位

//置等待按键触发,否则延时至少参数时长ms

         int c=waitKey(DELAY_CAPTION);

         if(c>=0){return -1;}

         return 0;

}

 

//显示滤波后的图片,没有按键触发时返回0

int display_dst(int delay)

{

         imshow(window_name,dst);

         int c=waitKey(delay);

         if(c>=0){return -1;}

         else return 0;

}

对于具体的这4种滤波的具体算法,大家可以自己查看源代码,有时间我也会去具体学习的,今天这个其实没什么内在的东西,主要是让大家对滤波有个宏观的认识,已经对开发环境熟悉一下而已。

在看源代码过程中有看不懂的函数可以在一下2个网站上查看,其中第一个网站非常全

Opencv2.3后的版本英文帮助文件网页:http://opencv.itseez.com/index.html

中文网页:http://www.opencv.org.cn/index.php/Template:Doc

原图像:

滤波后图像:

按照opencv_tutorials.pdf中的滤波部分试了下常用的4种滤波 器的使用方法。在opencv的C++中,这4个函数分别 为:blur,GaussianBlur,meidaBlur,bilateralFilter.下面就这几个函数在opencv中的功能,以及参数做个 介绍:

  1. 均值滤波:其函数声明为:void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )。

这个函数在上一节中介绍过了,这里简单些一下。

功能:对输入的图像src进行均值滤波后用dst输出。

参数:src和dst当然分别是输入图像和输出图像。size为均值滤波器模板大小。Anchor为锚点(具体什么没看源码不懂),如果为Point(-1,-1),则锚点是滤波器的中心点。borderType为边缘点插值类型。

理解:以原图对应像素为中心的与模板中心重叠,将模板覆盖领域内全部像素求均值就是滤波后像素的值了。

  1. 高斯滤波:其函数声明 为: void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT ) ;

功能:对输入的图像src进行高斯滤波后用dst输出。

参数:src和dst当然分别是输入图像和输出图像。Ksize为高斯滤波器模板大小,sigmaX和sigmaY分别为高斯滤波在横线和竖向的滤波系数(有点晦涩,等下解释)。borderType为边缘点插值类型。

理解:数字图像的滤波可以简单的这么理解,就是对原图像的每一个像素滤波,那么对应这个像素滤波后的值是根据其相邻像素(包括自己那个点)与一个滤波模板进行相乘即可。所以具体到高斯滤波,我们只要知道这个高斯滤波的模板即可。

那怎么确定这个模板呢?首先这个模板的大小为ksize,其每个数字的计算是这样的:

 

其中 是归一化系数,因为其和要为1.

为了简化,一般在二维图像处理中,ui和uj取0,sigma1和sigma2取相等。所以公式就简化为 :

因此很容易就计算出模板每个位置的数字了,简单吧!

但是要注意2点,第一点就是ksize的宽和高必须是奇数;第二点就是如果参数sigmaX=sigmaY=0,则实际用的是公式sigma = 0.3*((ksize-1)*0.5 – 1) + 0.8 .

  1. 中值滤波:其函数声明为void medianBlur(InputArray src, OutputArray dst, int ksize)。

功能:对输入的图像src进行中值滤波后用dst输出。

参数:src和dst当然分别是输入图像和输出图像。ksize为均值滤波器模板大小,因为模板为正方形,所以只有一个参数。

理解:以原图对应像素为中心的与模板中心重叠,将模板覆盖领域内全部像素排序后的中间值就是滤波后像素的值了,所以模板长度必须为奇数。

  1. 双向滤波:其 函数声明为:void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT )

功能:对输入的图像src进行双向滤波后用dst输出。

参数:src和dst当然分别是输入图像和输出图像。d为每个像素领域的直径,sigmaColor为颜色空间的标准偏差,sigmaSpace为坐标空间的标准偏差。borderType为边缘点插值类型。

理解:暂时不明白双向滤波的工作原理,以后有时间弄懂再补上吧,也欢迎大家补上。

转载注明来源:CV视觉网 » opencv源码解析之(1):滤波前言

分享到:更多 ()
扫描二维码,给作者 打赏
pay_weixinpay_weixin

请选择你看完该文章的感受:

0不错 0超赞 0无聊 0扯淡 0不解 0路过

评论 3

评论前必须登录!