联合双边滤波器(joint bilateral filter)【OpenCV】

版权声明:涉猎过的知识都像是不断汇入大海的涓涓细流,你怎么知道是哪条汇入的溪流让海洋成为海洋呢【转载请注明出处】 https://blog.csdn.net/panda1234lee/article/details/52839205


前面介绍了双边滤波器(bilateral filter,LBF),然而BF的权值是不稳定的,因此在边缘附近会出现一些翻转。此外BF计算复杂度是O(r^2);为了改善BF权值的稳定性,引入了联合双边滤波器(joint bilateral filter ,LBF)。两者之间的差别就是JBF用了一个导向图作为值域权重的计算依据。下面我们通过数学公式展示二者的不同:

先看BF的,如(1)所示,

再次解释一下公式中的符号意义,其中I表示输入图像,p、q表示像素在图像中的坐标,Ip表示对应位置的像素值,J表示输出, f、g是权重分布函数,一般为高斯函数。这种滤波的结果就是周边像素的权值不仅和距离有关还和那个位置的像素值有关。
再看JBF,如(2)所示,

如果在值域的权重计算过程引入另外一幅图像,如下式,则称之为联合双边滤波。 ~I 就是引入的另外一幅图像。该图像 必须与待处理的图像相似。
JBF的原理图,如图(1)所示。

图(1)JBF原理图
 
联合双边滤波上采样技术也很简单,一种便于理解的也便于写代码的方式就是把下采样并进行处理过后的小图按照最近邻插值的方式放大到原图大小,然后再用原图的数据和这个放大的结果进行联合双边滤波处理  。

下面粘贴了JBF的matlab代码供大家学习参考。
function B = jbfltGray(D,C,w,sigma_d,sigma_r)
%    D should be a double precision matrix of size NxMx1 (i.e., grayscale)  with normalized values in the 
%    closed interval [0,1]. 
%    C should be similar to D, from which the weights are calculated, with normalized values in the
%   closed interval [0,1]. 
% Pre-compute Gaussian distance weights.
[X,Y] = meshgrid(-w:w,-w:w);
G = exp(-(X.^2+Y.^2)/(2*sigma_d^2));
% Apply bilateral filter.
dim = size(D);
B = zeros(dim);
for i = 1:dim(1)
   for j = 1:dim(2)      
         % Extract local region.
         iMin = max(i-w,1);
         iMax = min(i+w,dim(1));
         jMin = max(j-w,1);
         jMax = min(j+w,dim(2));
         I = D(iMin:iMax,jMin:jMax); 
         % To compute weights from the color image
         J = C(iMin:iMax,jMin:jMax);
         % Compute Gaussian intensity weights according to the color image
         H = exp(-(J-C(i,j)).^2/(2*sigma_r^2));
         % Calculate bilateral filter response.
         F = H.*G((iMin:iMax)-i+w+1,(jMin:jMax)-j+w+1);
         B(i,j) = sum(F(:).*I(:))/sum(F(:));   
   end
end

----------------------------------------------以上原理转载自: pplong的博客----------------------------------------------


OpenCV 3.x.x的扩展模块(ximgproc. Extended Image Processing) 也添加了JBF的 API  :
 




OpenCV的代码:

#include "stdafx.h"
#include <opencv2/opencv.hpp>
#include <ximgproc.hpp>

int main()
{
	cv::Mat src = cv::imread("data/dp.png", 1); // 原始带噪声的深度图
	cv::Mat joint = cv::imread("data/teddy.png", 0);

	cv::Mat dst;
	int64 begin = cvGetTickCount();
	cv::ximgproc::jointBilateralFilter(joint, src, dst, -1, 3, 9);
	int64 end = cvGetTickCount();

	float time = (end - begin) / (cvGetTickFrequency() * 1000.);
	printf("time = %fms\n", time);

	imshow("src", src);
	imshow("joint", joint);
	imshow("jointBilateralFilter", dst);
	cv::waitKey(0);


    return 0;
}

效果如图:









猜你喜欢

转载自blog.csdn.net/panda1234lee/article/details/52839205