双边滤波器

1.双边滤波

双边滤波很有名,使用广泛,简单的说就是一种同时考虑了像素空间差异与强度差异的滤波器,因此具有保持图像边缘的特性。

先看看我们熟悉的高斯滤波器


其中W是权重,i和j是像素索引,K是归一化常量。公式中可以看出,权重只和像素之间的空间距离有关系,无论图像的内容是什么,都有相同的滤波效果。

再来看看双边滤波器,它只是在原有高斯函数的基础上加了一项,如下


其中 I 是像素的强度值,所以在强度差距大的地方(边缘),权重会减小,滤波效应也就变小。总体而言,在像素强度变换不大的区域,双边滤波有类似于高斯滤波的效果,而在图像边缘等强度梯度较大的地方,可以保持梯度。


一、原理

     双边滤波(Bilateral filter)是一种可以去噪保边的滤波器。之所以可以达到此效果,是因为滤波器是由两个函数构成:一个函数是由几何空间距离决定滤波器系数,另一个由像素差值决定滤波器系数。
 原理示意图如下:

     双边滤波器中,输出像素的值依赖于邻域像素的值的加权组合,
          
     权重系数w(i,j,k,l)取决于 定义域核
          
     和 值域核
          
     的乘积
          

二、C++实现
     2.1 OpenCV调用方法:
[cpp]  view plain  copy
  1. cvSmooth(m_iplImg, dstImg, CV_BILATERAL, 2 * r + 1, 0, sigma_r, sigma_d);  


     2.2 MATLAB版代码:
调用方法参见资料[1]     

     2.3 C++代码
     
[cpp]  view plain  copy
  1. void CImageObj::Bilateral_Filter(int r, double sigma_d, double sigma_r)  
  2. {  
  3.     int i, j, m, n, k;  
  4.     int nx = m_width, ny = m_height;  
  5.     int w_filter = 2 * r + 1; // 滤波器边长  
  6.   
  7.     double gaussian_d_coeff = -0.5 / (sigma_d * sigma_d);  
  8.     double gaussian_r_coeff = -0.5 / (sigma_r * sigma_r);  
  9.   
  10.     double** d_metrix = NewDoubleMatrix(w_filter, w_filter);  // spatial weight  
  11.     double r_metrix[256];  // similarity weight  
  12.   
  13.     // copy the original image  
  14.     double* img_tmp = new double[m_nChannels * nx * ny];  
  15.     for (i = 0; i < ny; i++)  
  16.         for (j = 0; j < nx; j++)  
  17.             for (k = 0; k < m_nChannels; k++)  
  18.             {  
  19.                 img_tmp[i * m_nChannels * nx + m_nChannels * j + k] = m_imgData[i * m_nChannels * nx + m_nChannels * j + k];  
  20.             }  
  21.   
  22.     // compute spatial weight  
  23.     for (i = -r; i <= r; i++)  
  24.         for (j = -r; j <= r; j++)  
  25.         {  
  26.             int x = j + r;  
  27.             int y = i + r;  
  28.   
  29.             d_metrix[y][x] = exp((i * i + j * j) * gaussian_d_coeff);  
  30.         }  
  31.   
  32.     // compute similarity weight  
  33.     for (i = 0; i < 256; i++)  
  34.     {  
  35.         r_metrix[i] = exp(i * i * gaussian_r_coeff);  
  36.     }  
  37.   
  38.     // bilateral filter  
  39.     for (i = 0; i < ny; i++)  
  40.         for (j = 0; j < nx; j++)  
  41.         {  
  42.             for (k = 0; k < m_nChannels; k++)  
  43.             {  
  44.                 double weight_sum, pixcel_sum;  
  45.                 weight_sum = pixcel_sum = 0.0;  
  46.   
  47.                 for (m = -r; m <= r; m++)  
  48.                     for (n = -r; n <= r; n++)  
  49.                     {  
  50.                         if (m*m + n*n > r*r) continue;  
  51.   
  52.                         int x_tmp = j + n;  
  53.                         int y_tmp = i + m;  
  54.   
  55.                         x_tmp = x_tmp < 0 ? 0 : x_tmp;  
  56.                         x_tmp = x_tmp > nx - 1 ? nx - 1 : x_tmp;   // 边界处理,replicate  
  57.                         y_tmp = y_tmp < 0 ? 0 : y_tmp;  
  58.                         y_tmp = y_tmp > ny - 1 ? ny - 1 : y_tmp;  
  59.   
  60.                         int pixcel_dif = (int)abs(img_tmp[y_tmp * m_nChannels * nx + m_nChannels * x_tmp + k] - img_tmp[i * m_nChannels * nx + m_nChannels * j + k]);  
  61.                         double weight_tmp = d_metrix[m + r][n + r] * r_metrix[pixcel_dif];  // 复合权重  
  62.   
  63.                         pixcel_sum += img_tmp[y_tmp * m_nChannels * nx + m_nChannels * x_tmp + k] * weight_tmp;  
  64.                         weight_sum += weight_tmp;  
  65.                     }  
  66.   
  67.                 pixcel_sum = pixcel_sum / weight_sum;  
  68.                 m_imgData[i * m_nChannels * nx + m_nChannels * j + k] = (uchar)pixcel_sum;  
  69.                   
  70.             } // 一个通道  
  71.   
  72.         } // END ALL LOOP  
  73.   
  74.     UpdateImage();  
  75.     DeleteDoubleMatrix(d_metrix, w_filter, w_filter);  
  76.     delete[] img_tmp;  
  77. }  
性能方面,跟OpenCV处理速度有差距,有兴趣的,可以自己研究OpenCV版本的源代码

三、效果图




四、参考资料
     资料[4]是MIT的学习资料,最全面,包括课件、论文、代码等,涵盖原理、改进、应用、与PDE的联系等等,最值得一看。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值