Goal
blur():均值滤波GaussianBlur():高斯滤波
medianBlur():中值滤波
bilateralFilter():双边滤波
Theory
理论来源于:《计算机视觉:算法与应用》
均值滤波,高斯滤波以及中值滤波都比较简单,这里不再介绍。
双边滤波用的较少,详细介绍下。
双边介绍的权重有两个部分,其中第一部分的权重与高斯滤波使用的权重相同,第二部分的权重则是用于评估像素之间强度的差异。高斯滤波的思想:在大部分情况下,离中心像素的距离越近,则其权重越大;一般情况下,的确是这个样子,由于图像像素的缓慢变换,然而在图像的额边缘处,由于像素信息较为丰富,并不是这样子;继续使用空域高斯滤波则可能导致图像边缘模糊,因而这里应该根据像素的差异进行评估权重,若是像素颜色,纹理较为相似,则权重赢较大。因而双边滤波添加了另外的一个权重。具体公式如下(毛星云 《OpenCV3编程入门》):
不是俺不放公式,一放公式就待审查。公式上面提高书上的177-178页。
Code
/*** file Smoothing.cpp
* brief Sample code for simple filters
* author OpenCV team
*/
#include <iostream>
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.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( int argc, char ** argv )
{
namedWindow( window_name, WINDOW_AUTOSIZE );
// Load the source image
const char* filename = argc >=2 ? argv[1] : "./lena.jpg";
src = imread( filename, IMREAD_COLOR );
if(src.empty()){
printf(" Error opening image\n");
printf(" Usage: ./Smoothing [image_name -- default ./lena.jpg] \n");
return -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; }
//![blur]
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; } }
//![blur]
// Applying Gaussian blur
if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; }
//![gaussianblur]
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; } }
//![gaussianblur]
// Applying Median blur
if( display_caption( "Median Blur" ) != 0 ) { return 0; }
//![medianblur]
for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
{ medianBlur ( src, dst, i );//原图想,目标图像,相当于size(i,i)
if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
//![medianblur]
// Applying Bilateral Filter
if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; }
//![bilateralfilter]
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; } }
//![bilateralfilter]
// Done
display_caption( "Done!" );
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) );
return display_dst(DELAY_CAPTION);
}
/**
* @function display_dst
*/
int display_dst( int delay )
{
imshow( window_name, dst );
int c = waitKey ( delay );
if( c >= 0 ) { return -1; }
return 0;
}
添加了更详细的注释,这里不再解释。
CMakeLists.txt文件同上一篇,不用修改。
测试结果是一个渐变的过程。放一个中间过程的截图。