图像处理之双边滤波效果(Bilateral Filtering for Gray and Color Image)

图像处理之双边滤波效果(Bilateral Filtering for Gray and Color Image)

基本介绍:

普通的时空域的低通滤波器,在像素空间完成滤波以后,导致图像的边缘部分也变得不那么明显,

整张图像都变得同样的模糊,图像边缘细节丢失。双边滤波器(ABilateral Filter)可以很好的保

留边缘的同时消除噪声。双边滤波器能做到这些原因在于它不像普通的高斯/卷积低通滤波,只考

虑了位置对中心像素的影响,它还考虑了卷积核中像素与中心像素之间相似程度的影响,根据位置

影响与像素值之间的相似程度生成两个不同的权重表(WeightTable),在计算中心像素的时候加以

考虑这两个权重,从而实现双边低通滤波。据说AdobePhotoshop的高斯磨皮功能就是应用了

双边低通滤波算法实现。




程序效果:


看我们的美女lena应用双边滤镜之后



程序关键代码解释:

建立距离高斯权重表(Weight Table)如下:

[java]  view plain copy
  1. private void buildDistanceWeightTable() {  
  2.     int size = 2 * radius + 1;  
  3.     cWeightTable = new double[size][size];  
  4.     for(int semirow = -radius; semirow <= radius; semirow++) {  
  5.         for(int semicol = - radius; semicol <= radius; semicol++) {  
  6.             // calculate Euclidean distance between center point and close pixels  
  7.             double delta = Math.sqrt(semirow * semirow + semicol * semicol)/ds;  
  8.             double deltaDelta = delta * delta;  
  9.             cWeightTable[semirow+radius][semicol+radius] = Math.exp(deltaDelta * factor);  
  10.         }  
  11.     }  
  12. }  
建立RGB值像素度高斯权重代码如下:

[java]  view plain copy
  1. private void buildSimilarityWeightTable() {  
  2.     sWeightTable = new double[256]; // since the color scope is 0 ~ 255  
  3.     for(int i=0; i<256; i++) {  
  4.         double delta = Math.sqrt(i * i ) / rs;  
  5.         double deltaDelta = delta * delta;  
  6.         sWeightTable[i] = Math.exp(deltaDelta * factor);  
  7.     }  
  8. }  
完成权重和计算与像素×权重和计算代码如下:

[java]  view plain copy
  1. for(int semirow = -radius; semirow <= radius; semirow++) {  
  2.     for(int semicol = - radius; semicol <= radius; semicol++) {  
  3.         if((row + semirow) >= 0 && (row + semirow) < height) {  
  4.             rowOffset = row + semirow;  
  5.         } else {  
  6.             rowOffset = 0;  
  7.         }  
  8.           
  9.         if((semicol + col) >= 0 && (semicol + col) < width) {  
  10.             colOffset = col + semicol;  
  11.         } else {  
  12.             colOffset = 0;  
  13.         }  
  14.         index2 = rowOffset * width + colOffset;  
  15.         ta2 = (inPixels[index2] >> 24) & 0xff;  
  16.         tr2 = (inPixels[index2] >> 16) & 0xff;  
  17.         tg2 = (inPixels[index2] >> 8) & 0xff;  
  18.         tb2 = inPixels[index2] & 0xff;  
  19.           
  20.         csRedWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tr2 - tr))];  
  21.         csGreenWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tg2 - tg))];  
  22.         csBlueWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tb2 - tb))];  
  23.           
  24.         csSumRedWeight += csRedWeight;  
  25.         csSumGreenWeight += csGreenWeight;  
  26.         csSumBlueWeight += csBlueWeight;  
  27.         redSum += (csRedWeight * (double)tr2);  
  28.         greenSum += (csGreenWeight * (double)tg2);  
  29.         blueSum += (csBlueWeight * (double)tb2);  
  30.     }  
  31. }  
完成归一化,得到输出像素点RGB值得代码如下:

[java]  view plain copy
  1. tr = (int)Math.floor(redSum / csSumRedWeight);  
  2. tg = (int)Math.floor(greenSum / csSumGreenWeight);  
  3. tb = (int)Math.floor(blueSum / csSumBlueWeight);  
  4. outPixels[index] = (ta << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb);  
关于什么卷积滤波,请参考:

http://blog.csdn.net/jia20003/article/details/7038938

关于高斯模糊算法,请参考:
http://blog.csdn.net/jia20003/article/details/7234741
最后想说,不给出源代码的博文不是好博文,基于Java完成的双边滤波速度有点慢

可以自己优化,双边滤镜完全源代码如下:

[java]  view plain copy
  1. package com.gloomyfish.blurring.study;  
  2. /** 
  3.  *  A simple and important case of bilateral filtering is shift-invariant Gaussian filtering 
  4.  *  refer to - http://graphics.ucsd.edu/~iman/Denoising/ 
  5.  *  refer to - http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html 
  6.  *  thanks to cyber 
  7.  */  
  8. import java.awt.image.BufferedImage;  
  9.   
  10. public class BilateralFilter extends AbstractBufferedImageOp {  
  11.     private final static double factor = -0.5d;  
  12.     private double ds; // distance sigma  
  13.     private double rs; // range sigma  
  14.     private int radius; // half length of Gaussian kernel Adobe Photoshop   
  15.     private double[][] cWeightTable;  
  16.     private double[] sWeightTable;  
  17.     private int width;  
  18.     private int height;  
  19.       
  20.     public BilateralFilter() {  
  21.         this.ds = 1.0f;  
  22.         this.rs = 1.0f;  
  23.     }  
  24.       
  25.     private void buildDistanceWeightTable() {  
  26.         int size = 2 * radius + 1;  
  27.         cWeightTable = new double[size][size];  
  28.         for(int semirow = -radius; semirow <= radius; semirow++) {  
  29.             for(int semicol = - radius; semicol <= radius; semicol++) {  
  30.                 // calculate Euclidean distance between center point and close pixels  
  31.                 double delta = Math.sqrt(semirow * semirow + semicol * semicol)/ds;  
  32.                 double deltaDelta = delta * delta;  
  33.                 cWeightTable[semirow+radius][semicol+radius] = Math.exp(deltaDelta * factor);  
  34.             }  
  35.         }  
  36.     }  
  37.       
  38.     /** 
  39.      * for gray image 
  40.      * @param row 
  41.      * @param col 
  42.      * @param inPixels 
  43.      */  
  44.     private void buildSimilarityWeightTable() {  
  45.         sWeightTable = new double[256]; // since the color scope is 0 ~ 255  
  46.         for(int i=0; i<256; i++) {  
  47.             double delta = Math.sqrt(i * i ) / rs;  
  48.             double deltaDelta = delta * delta;  
  49.             sWeightTable[i] = Math.exp(deltaDelta * factor);  
  50.         }  
  51.     }  
  52.       
  53.     public void setDistanceSigma(double ds) {  
  54.         this.ds = ds;  
  55.     }  
  56.       
  57.     public void setRangeSigma(double rs) {  
  58.         this.rs = rs;  
  59.     }  
  60.   
  61.     @Override  
  62.     public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
  63.         width = src.getWidth();  
  64.         height = src.getHeight();  
  65.         //int sigmaMax = (int)Math.max(ds, rs);  
  66.         //radius = (int)Math.ceil(2 * sigmaMax);  
  67.         radius = (int)Math.max(ds, rs);  
  68.         buildDistanceWeightTable();  
  69.         buildSimilarityWeightTable();  
  70.         if ( dest == null )  
  71.             dest = createCompatibleDestImage( src, null );  
  72.   
  73.         int[] inPixels = new int[width*height];  
  74.         int[] outPixels = new int[width*height];  
  75.         getRGB( src, 00, width, height, inPixels );  
  76.         int index = 0;  
  77.         double redSum = 0, greenSum = 0, blueSum = 0;  
  78.         double csRedWeight = 0, csGreenWeight = 0, csBlueWeight = 0;  
  79.         double csSumRedWeight = 0, csSumGreenWeight = 0, csSumBlueWeight = 0;  
  80.         for(int row=0; row<height; row++) {  
  81.             int ta = 0, tr = 0, tg = 0, tb = 0;  
  82.             for(int col=0; col<width; col++) {  
  83.                 index = row * width + col;  
  84.                 ta = (inPixels[index] >> 24) & 0xff;  
  85.                 tr = (inPixels[index] >> 16) & 0xff;  
  86.                 tg = (inPixels[index] >> 8) & 0xff;  
  87.                 tb = inPixels[index] & 0xff;  
  88.                 int rowOffset = 0, colOffset = 0;  
  89.                 int index2 = 0;  
  90.                 int ta2 = 0, tr2 = 0, tg2 = 0, tb2 = 0;  
  91.                 for(int semirow = -radius; semirow <= radius; semirow++) {  
  92.                     for(int semicol = - radius; semicol <= radius; semicol++) {  
  93.                         if((row + semirow) >= 0 && (row + semirow) < height) {  
  94.                             rowOffset = row + semirow;  
  95.                         } else {  
  96.                             rowOffset = 0;  
  97.                         }  
  98.                           
  99.                         if((semicol + col) >= 0 && (semicol + col) < width) {  
  100.                             colOffset = col + semicol;  
  101.                         } else {  
  102.                             colOffset = 0;  
  103.                         }  
  104.                         index2 = rowOffset * width + colOffset;  
  105.                         ta2 = (inPixels[index2] >> 24) & 0xff;  
  106.                         tr2 = (inPixels[index2] >> 16) & 0xff;  
  107.                         tg2 = (inPixels[index2] >> 8) & 0xff;  
  108.                         tb2 = inPixels[index2] & 0xff;  
  109.                           
  110.                         csRedWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tr2 - tr))];  
  111.                         csGreenWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tg2 - tg))];  
  112.                         csBlueWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tb2 - tb))];  
  113.                           
  114.                         csSumRedWeight += csRedWeight;  
  115.                         csSumGreenWeight += csGreenWeight;  
  116.                         csSumBlueWeight += csBlueWeight;  
  117.                         redSum += (csRedWeight * (double)tr2);  
  118.                         greenSum += (csGreenWeight * (double)tg2);  
  119.                         blueSum += (csBlueWeight * (double)tb2);  
  120.                     }  
  121.                 }  
  122.                   
  123.                 tr = (int)Math.floor(redSum / csSumRedWeight);  
  124.                 tg = (int)Math.floor(greenSum / csSumGreenWeight);  
  125.                 tb = (int)Math.floor(blueSum / csSumBlueWeight);  
  126.                 outPixels[index] = (ta << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb);  
  127.                   
  128.                 // clean value for next time...  
  129.                 redSum = greenSum = blueSum = 0;  
  130.                 csRedWeight = csGreenWeight = csBlueWeight = 0;  
  131.                 csSumRedWeight = csSumGreenWeight = csSumBlueWeight = 0;  
  132.                   
  133.             }  
  134.         }  
  135.         setRGB( dest, 00, width, height, outPixels );  
  136.         return dest;  
  137.     }  
  138.       
  139.     public static int clamp(int p) {  
  140.         return p < 0 ? 0 : ((p > 255) ? 255 : p);  
  141.     }  
  142.   
  143.     public static void main(String[] args) {  
  144.         BilateralFilter bf = new BilateralFilter();  
  145.         bf.buildSimilarityWeightTable();  
  146.     }  
  147. }  


转自: http://blog.csdn.net/jia20003/article/details/7740683
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值