双边滤波

双边滤波是一种非线性滤波器,它可以达到保持边缘、降噪平滑的效果。和其他滤波原理一样,双边滤波也是采用加权平均的方法,用周边像素亮度值的加权平均代表某个像素的强度,所用的加权平均基于高斯分布[1]。最重要的是,双边滤波的权重不仅考虑了像素的欧氏距离(如普通的高斯低通滤波,只考虑了位置对中心像素的影响),还考虑了像素范围域中的辐射差异(例如卷积核中像素与中心像素之间相似程度、颜色强度,深度距离等),在计算中心像素的时候同时考虑这两个权重。 公式1a,1b给出了双边滤过的操作,Iq为输入图像,Ipbf为滤波后图像:

mark下双边滤波里的两个权重域的概念:空间域(spatial domain S)和像素范围域(range domain R),这个是它跟高斯滤波等方法的最大不同点。下面是我找到的对比说明,更好地理解双边滤波,首先是高斯滤波的情况:

然后对比再看一下双边滤波的过程:

双边滤波的核函数是空间域核与像素范围域核的综合结果:在图像的平坦区域,像素值变化很小,对应的像素范围域权重接近于1,此时空间域权重起主要作用,相当于进行高斯模糊;在图像的边缘区域,像素值变化很大,像素范围域权重变大,从而保持了边缘的信息。

为了更加形象的说明两个权重的影响,作者还给出了二维图像的直观说明:

双边滤波算法实现:

在原理部分,从双边滤波的公式就可以得到该算法的实现途径。由于直接的编码实现上述过程,其时间复杂度为O(σs2) ,比较耗时,所以后来出现了一些改进算法,比较经典的有:论文《Fast O(1) bilateral filtering using trigonometric range kernels》,提出了用Raised cosines函数来逼近高斯值域函数,并利用一些特性把值域函数分解为一些列函数的叠加,从而实现函数的加速[5,8]。
这里只对原始方法进行实现,从而有助于更加清楚的了解算法的原理。

matlab实现方法,这里也附一下核心代码:

 

 
  1. function output = bilateralFilter( data, edge, sigmaSpatial, sigmaRange, ...

  2. samplingSpatial, samplingRange )

  3.  
  4. if ~exist( 'edge', 'var' ),

  5. edge = data;

  6. end

  7.  
  8. inputHeight = size( data, 1 );

  9. inputWidth = size( data, 2 );

  10.  
  11. if ~exist( 'sigmaSpatial', 'var' ),

  12. sigmaSpatial = min( inputWidth, inputHeight ) / 16;

  13. end

  14.  
  15. edgeMin = min( edge( : ) );

  16. edgeMax = max( edge( : ) );

  17. edgeDelta = edgeMax - edgeMin;

  18.  
  19. if ~exist( 'sigmaRange', 'var' ),

  20. sigmaRange = 0.1 * edgeDelta;

  21. end

  22.  
  23. if ~exist( 'samplingSpatial', 'var' ),

  24. samplingSpatial = sigmaSpatial;

  25. end

  26.  
  27. if ~exist( 'samplingRange', 'var' ),

  28. samplingRange = sigmaRange;

  29. end

  30.  
  31. if size( data ) ~= size( edge ),

  32. error( 'data and edge must be of the same size' );

  33. end

  34.  
  35. % parameters

  36. derivedSigmaSpatial = sigmaSpatial / samplingSpatial;

  37. derivedSigmaRange = sigmaRange / samplingRange;

  38.  
  39. paddingXY = floor( 2 * derivedSigmaSpatial ) + 1;

  40. paddingZ = floor( 2 * derivedSigmaRange ) + 1;

  41.  
  42. % allocate 3D grid

  43. downsampledWidth = floor( ( inputWidth - 1 ) / samplingSpatial ) + 1 + 2 * paddingXY;

  44. downsampledHeight = floor( ( inputHeight - 1 ) / samplingSpatial ) + 1 + 2 * paddingXY;

  45. downsampledDepth = floor( edgeDelta / samplingRange ) + 1 + 2 * paddingZ;

  46.  
  47. gridData = zeros( downsampledHeight, downsampledWidth, downsampledDepth );

  48. gridWeights = zeros( downsampledHeight, downsampledWidth, downsampledDepth );

  49.  
  50. % compute downsampled indices

  51. [ jj, ii ] = meshgrid( 0 : inputWidth - 1, 0 : inputHeight - 1 );

  52.  
  53. di = round( ii / samplingSpatial ) + paddingXY + 1;

  54. dj = round( jj / samplingSpatial ) + paddingXY + 1;

  55. dz = round( ( edge - edgeMin ) / samplingRange ) + paddingZ + 1;

  56.  
  57. % perform scatter (there's probably a faster way than this)

  58. % normally would do downsampledWeights( di, dj, dk ) = 1, but we have to

  59. % perform a summation to do box downsampling

  60. for k = 1 : numel( dz ),

  61.  
  62. dataZ = data( k ); % traverses the image column wise, same as di( k )

  63. if ~isnan( dataZ ),

  64.  
  65. dik = di( k );

  66. djk = dj( k );

  67. dzk = dz( k );

  68.  
  69. gridData( dik, djk, dzk ) = gridData( dik, djk, dzk ) + dataZ;

  70. gridWeights( dik, djk, dzk ) = gridWeights( dik, djk, dzk ) + 1;

  71.  
  72. end

  73. end

  74.  
  75. % make gaussian kernel

  76. kernelWidth = 2 * derivedSigmaSpatial + 1;

  77. kernelHeight = kernelWidth;

  78. kernelDepth = 2 * derivedSigmaRange + 1;

  79.  
  80. halfKernelWidth = floor( kernelWidth / 2 );

  81. halfKernelHeight = floor( kernelHeight / 2 );

  82. halfKernelDepth = floor( kernelDepth / 2 );

  83.  
  84. [gridX, gridY, gridZ] = meshgrid( 0 : kernelWidth - 1, 0 : kernelHeight - 1, 0 : kernelDepth - 1 );

  85. gridX = gridX - halfKernelWidth;

  86. gridY = gridY - halfKernelHeight;

  87. gridZ = gridZ - halfKernelDepth;

  88. gridRSquared = ( gridX .* gridX + gridY .* gridY ) / ( derivedSigmaSpatial * derivedSigmaSpatial ) + ( gridZ .* gridZ ) / ( derivedSigmaRange * derivedSigmaRange );

  89. kernel = exp( -0.5 * gridRSquared );

  90.  
  91. % convolve

  92. blurredGridData = convn( gridData, kernel, 'same' );

  93. blurredGridWeights = convn( gridWeights, kernel, 'same' );

  94.  
  95. % divide

  96. blurredGridWeights( blurredGridWeights == 0 ) = -2; % avoid divide by 0, won't read there anyway

  97. normalizedBlurredGrid = blurredGridData ./ blurredGridWeights;

  98. normalizedBlurredGrid( blurredGridWeights < -1 ) = 0; % put 0s where it's undefined

  99. blurredGridWeights( blurredGridWeights < -1 ) = 0; % put zeros back

  100.  
  101. % upsample

  102. [ jj, ii ] = meshgrid( 0 : inputWidth - 1, 0 : inputHeight - 1 ); % meshgrid does x, then y, so output arguments need to be reversed

  103. % no rounding

  104. di = ( ii / samplingSpatial ) + paddingXY + 1;

  105. dj = ( jj / samplingSpatial ) + paddingXY + 1;

  106. dz = ( edge - edgeMin ) / samplingRange + paddingZ + 1;

  107.  
  108. % interpn takes rows, then cols, etc

  109. % i.e. size(v,1), then size(v,2), ...

  110. output = interpn( normalizedBlurredGrid, di, dj, dz );

双边滤波算法实例:

 

 
  1. %% 测试函数,其中参数设置请参见函数注释

  2. clc,clear all,close all;

  3. ori=imread('D:\proMatlab\vessel_edge_extration\image\3.jpg');

  4. ori=double(rgb2gray(ori))/255.0;

  5. [width, height]=size(ori);

  6. sigmaSpatial = min( width, height ) / 30;

  7. samplingSpatial=sigmaSpatial;

  8. sigmaRange = ( max( ori( : ) ) - min( ori( : ) ) ) / 30;

  9. samplingRange= sigmaRange;

  10. output = bilateralFilter( ori, ori, sigmaSpatial, sigmaRange, ...

  11. samplingSpatial, samplingRange );

  12. figure,

  13. subplot(1,2,1),imshow(ori,[]);title('input image');

  14. subplot(1,2,2),imshow(output,[]);title('output image');

参考:

  1. https://en.wikipedia.org/wiki/Bilateral_filtering
  2. http://people.csail.mit.edu/sparis/bf_course/
  3. http://people.csail.mit.edu/sparis/bf/
  4. http://blog.csdn.net/fightingforcv/article/details/52723376
  5. http://blog.csdn.net/mumusan2016/article/details/54578038
  6. http://blog.csdn.net/majinlei121/article/details/50463514
  7. http://kaiminghe.com/eccv10/index.html  (Guided Image Filtering)
  8. http://blog.csdn.net/dangchangying/article/details/14451963

你可能感兴趣的:(image,processing)