简介

  本章主要介绍opencv上常用的4种线性滤波器来平滑图片。之所以要平滑图片,是因为在图片中通常会有一些各类噪音,常见的噪音有:
(1)椒盐噪音:噪声的幅值基本相同,但是噪声出现的位置是随机的。
(2)高斯\瑞利噪声:在每一点上都存在噪声,但是它们的幅值随机。
  为了处理这类噪声,opencv使用了若干滤波器。

blur

使用原理

  首先看下blur,它是使用的均值滤波方法。也就是选择一个模板,该模板为临近的若干像素组成(比如3x3矩阵),然后用这个模板中,所有像素的均值,
来替换掉当前的原像素值。
  
  如上所示,最后f(x,y)像素就是这9个点像素的平均值。整个图像中,将所有像素都用这样算法来替换到原像素,达到平滑效果。

代码函数

   opencv提供的blur功能函数如下:
 
void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
  其中:src为原图像,dst为输出图像,ksize为模板矩阵大小,anchor为定位点位置,(-1,-1)表示是在模板矩阵中心。

Gaussian Filter

使用原理

   讲高斯滤波器,首先看一副图片:
   如图,是一个典型的正态分布图,高斯滤波来平滑图片的原理也是基于此,首先高斯滤波也是需要一个平滑模板矩阵,然后矩阵中心就是目标像素。同时可以理解为
该点像素的计算就是:正态分布图就是以目标像素为原点,然后根据模板矩阵中离中心的位置距离越远,权重降低,来算出新的像素值,替换到原来像素。总结来书,就是
离目标像素越近的像素对新像素的影响也就越高。

代码函数

   在opencv中,提供的高斯滤波器功能函数如下:
 
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, int borderType=BORDER_DEFAULT )
   同理,src,dst,ksize分别也都是原图像、输出图像和模板矩阵的size。额,,sigmaX、sigmaY没理解好。。。

Median Filter

使用原理

   该滤波器使用原理,也是使用了一个模板矩阵,比如一个3x3的矩阵,然后在矩阵的9个数据中,找到它们的中间值,举个例子:(2,3,5;5,6,7;7,8,8),
这组矩阵的中间值就是6,然后用这个中间值来取代掉目标像素,目标像素一般也就是模板矩阵的中心点像素。

功能函数

   opencv提供的功能函数如下:
 
   void medianBlur(InputArray src, OutputArray dst, int ksize)
   该函数参数也是一样,最后就是在ksize大小的模板矩阵中找到中间值,取代掉目标像素原来的数据。

Bilateral Filter

使用原理

   在之前的三个滤波器中,都只是考虑到了消除噪声,但是没有考虑到这样的做法,同样会导致图像的边缘模糊掉。所以为了避免这种情况,而引入了双边滤波器。
双边滤波器和高斯滤波一样采用的是考虑权重的办法,不过双边滤波器权重考虑了两个方面。首先一方面和高斯滤波器一模一样,考虑的是模板矩阵距离的权重,另一方面,
双边滤波器还考虑到了周围像素点的强度和目标像素点强度的差异变化,而使用不同的加权,从而避免边缘被平滑掉。

功能函数

   opencv中使用双边滤波函数如下:
 
void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)
     参数含义中,src、dst、d和之前的滤波器中参数含义一致,sigmaColor、sigmaSpace分别影响像素强度变化和距离位置变化的权重。

范例代码

     最后来看下opencv官方提供的这四种滤波器的范例代码:
 
/**
* file Smoothing.cpp
* brief Sample code for simple filters
* author OpenCV team
*/
#include <iostream>
#include <vector>

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/features2d/features2d.hpp"

using namespace std;
using namespace cv;

/// Global Variables
int DELAY_CAPTION = 1500;
int DELAY_BLUR = 100;
int MAX_KERNEL_LENGTH = 31;

Mat src; Mat dst;
char window_name[] = "Smoothing Demo";

/// Function headers
int display_caption( const char* caption );
int display_dst( int delay );


/**
* function main
*/
int main( void )
{
namedWindow( window_name, WINDOW_AUTOSIZE );

/// Load the source image
src = imread( "../data/lena.jpg", 1 );

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

dst = src.clone();
if( display_dst( DELAY_CAPTION ) != 0 ) { return 0; }


/// Applying Homogeneous blur
if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; }

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; } }


/// Applying Gaussian blur
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; } }


/// Applying Median blur
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; } }


/// Applying Bilateral Filter
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; } }

/// Wait until user press a key
display_caption( "End: Press a key!" );

waitKey(0);

return 0;
}

/**
* @function display_caption
*/
int display_caption( const char* caption )
{
dst = Mat::zeros( src.size(), src.type() );
putText( dst, caption,
Point( src.cols/4, src.rows/2),
FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );

imshow( window_name, dst );
int c = waitKey( DELAY_CAPTION );
if( c >= 0 ) { return -1; }
return 0;
}

/**
* @function display_dst
*/
int display_dst( int delay )
{
imshow( window_name, dst );
int c = waitKey ( delay );
if( c >= 0 ) { return -1; }
return 0;
}
12-13 06:26