【OpenCV入门教程之九】 非线性滤波专场:中值滤波、双边滤波

双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点。

双边滤波器的好处是可以做边缘保存(edge preserving),一般过去用的维纳滤波或者高斯滤波去降噪,都会较明显地模糊边缘,对于高频细节的保护效果并不明显。双边滤波器顾名思义比高斯滤波多了一个高斯方差sigma-d,它是基于空间分布的高斯滤波函数,所以在边缘附近,离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。但是由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净的滤掉,只能够对于低频信息进行较好的滤波。

在双边滤波器中,输出像素的值依赖于邻域像素值的加权值组合:

而加权系数w(i,j,k,l)取决于定义域核和值域核的乘积。

其中定义域核表示如下(如图):

定义域滤波对应图示:

值域核表示为:

值域滤波:

两者相乘后,就会产生依赖于数据的双边滤波权重函数:

二、深入——OpenCV源码分析溯源

首先让我们一起领略medianBlur()函数的源码,其于…\opencv\sources\modules\imgproc\src\smooth.cpp的第1653行开始。

//———————————–【medianBlur()函数中文注释版源代码】————————-// 代码作用:进行中值滤波操作的函数 // 说明:以下代码为来自于计算机开源视觉库OpenCV的官方源代码 // OpenCV源代码版本:2.4.8 // 源码路径:…\opencv\sources\modules\imgproc\src\smooth.cpp // 源文件中如下代码的起始行数:1653行// 中文注释by浅墨 //——————————————————————————————————–void cv::medianBlur( InputArray _src0,OutputArray _dst, int ksize ){//拷贝形参Mat数据到临时变量,用于稍后的操作 Mat src0 = _src0.getMat(); _dst.create( src0.size(), src0.type() ); Mat dst = _dst.getMat();//处理特定的ksize值的不同情况 if( ksize <= 1 ){src0.copyTo(dst);return;} CV_Assert( ksize% 2 == 1 ); //若之前有过HAVE_TEGRA_OPTIMIZATION优化选项的定义,则执行宏体中的tegra优化版函数并返回#ifdef HAVE_TEGRA_OPTIMIZATION if (tegra::medianBlur(src0, dst, ksize))return;#endifbool useSortNet = ksize == 3 || (ksize == 5#if !CV_SSE2//若CV_SSE2为假,则执行宏体中语句&& src0.depth() > CV_8U#endif);//开始正式进行滤波操作 Mat src; if( useSortNet ){if( dst.data != src0.data )src = src0;elsesrc0.copyTo(src);//根据不同的位深,给medianBlur_SortNet函数取不同的模板类型值if( src.depth() == CV_8U )medianBlur_SortNet<MinMax8u, MinMaxVec8u>( src, dst, ksize );else if( src.depth() == CV_16U )medianBlur_SortNet<MinMax16u, MinMaxVec16u>( src, dst, ksize );else if( src.depth() == CV_16S )medianBlur_SortNet<MinMax16s, MinMaxVec16s>( src, dst, ksize );else if( src.depth() == CV_32F )medianBlur_SortNet<MinMax32f, MinMaxVec32f>( src, dst, ksize );elseCV_Error(CV_StsUnsupportedFormat, "");return;} else{cv::copyMakeBorder( src0, src, 0, 0, ksize/2, ksize/2, BORDER_REPLICATE);int cn = src0.channels();CV_Assert( src.depth() == CV_8U && (cn == 1 || cn == 3 || cn ==4) );double img_size_mp = (double)(src0.total())/(1 << 20);if( ksize <= 3 + (img_size_mp < 1 ? 12 : img_size_mp < 4 ? 6 :2)*(MEDIAN_HAVE_SIMD && checkHardwareSupport(CV_CPU_SSE2) ? 1 : 3))medianBlur_8u_Om( src, dst, ksize );elsemedianBlur_8u_O1( src, dst, ksize );}}

仔细阅读源码我们可以发现,正式进入滤波操作时,根据图像不同的位深,我们会给medianBlur_SortNet函数模板取不同的模板类型值,或者调用medianBlur_8u_Om或medianBlur_8u_O1来进行操作。

真正的停下来,享受自我的体验时刻,也许浮光掠影,

【OpenCV入门教程之九】 非线性滤波专场:中值滤波、双边滤波

相关文章:

你感兴趣的文章:

标签云: