上一篇文章我们介绍了双边滤波,它的公式为:
(1)
其中,,,,f(ξ)表示原图。
c(ξ,x)表示的是高斯距离的权值,σd值大则滤波结果会受到更远的像素影响;s(ξ,x)表示的是高斯相似度的权值,σr值大则意味着更无关的像素强度值(或颜色值)会影响滤波器结果。因此这两个值的选取会直接影响到滤波效果。
关于高斯距离的权值,还会受到滤波内核大小的影响,因此它的方差σd值对滤波结果的影响会受到一定的约束,但σr值的选取就难以把握,因此本算法的目的就是自适应的选取σr值的大小。
在opencv文档中没有说明该算法的出处,但从它的程序源码中可以分析得到,σ r值是通过领域内的像素值得到,具体公式为: (2)
其中,n表示邻域内的像素个数,该邻域指的是滤波内核,I(i)表示的是像素值。
下面我们来分析一下具体的代码,该函数的原型为:
void adaptiveBilateralFilter(InputArraysrc, OutputArray dst, Size ksize, double sigmaSpace, double maxSigmaColor=20.0,Point anchor=Point(-1, -1), int borderType=BORDER_DEFAULT )
_src为输入原图像;_dst为滤波后的图像;ksize为滤波内核的大小;sigmaSpace为距离权值公式中的方差,即公式1中的σd;maxSigmaColor为相似度权值公式中的方差(σr)的最大值,自适应双边滤波的相似度方差是通过公式2计算得到,但如果计算的结果太大,超过了该值,则以该值为准;anchor为内核锚点;borderType表示用什么方式来处理加宽后的图像四周边界。
该函数的源码是在/sources/modules/imgproc/scr/smooth.cpp内:
void cv::adaptiveBilateralFilter( InputArray _src, OutputArray _dst, Size ksize,
double sigmaSpace, double maxSigmaColor, Point anchor, int borderType )
{
//得到输入图像矩阵和与其尺寸类型一致的输出图像矩阵
Mat src = _src.getMat();
_dst.create(src.size(), src.type());
Mat dst = _dst.getMat();
//该算法只能处理8位二进制的灰度图像和三通道的彩色图像
CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3);
//得到滤波内核的锚点
anchor = normalizeAnchor(anchor,ksize);
if( src.depth() == CV_8U )
adaptiveBilateralFilter_8u( src, dst, ksize, sigmaSpace, maxSigmaColor, anchor, borderType );
else
CV_Error( CV_StsUnsupportedFormat,
"Adaptive Bilateral filtering is only implemented for 8u images" );
}
static void adaptiveBilateralFilter_8u( const Mat& src, Mat& dst, Size ksize, double sigmaSpace, double maxSigmaColor, Point anchor, int borderType )
{
Size size = src.size();
处理之前再次检查图像中的相关信息是否正确
CV_Assert( (src.type() == CV_8UC1 || src.type() == CV_8UC3) &&
src.type() == dst