双边滤波JAVA代码实现

1 篇文章 0 订阅
1 篇文章 0 订阅

原创文章地址:点击打开链接

双边滤波源代码如下:

 

package test;
/** 
 *  A simple and important case of bilateral filtering is shift-invariant Gaussian filtering 
 *  refer to - http://graphics.ucsd.edu/~iman/Denoising/ 
 *  refer to - http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html 
 *  thanks to cyber 
 */  
import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;  
import java.io.File;
import java.io.IOException;
import java.util.Date;

import javax.imageio.ImageIO;

/**
 * 双边滤波
 * 转载:http://blog.csdn.net/jia20003/article/details/7740683
 * @author Bob
 * 2017年9月9日12:25:41
 */
public class BilateralFilter extends AbstractBufferedImageOp {  
    private final static double factor = -0.5d;  
    private double ds; // distance sigma  
    private double rs; // range sigma  
    private int radius; // half length of Gaussian kernel Adobe Photoshop   
    private double[][] cWeightTable;  
    private double[] sWeightTable;  
    private int width;  
    private int height;  
      
    public BilateralFilter(double ds,double rs) {  
        this.ds = ds;  
        this.rs = rs;  
    }  
      
    private void buildDistanceWeightTable() {  
        int size = 2 * radius + 1;  
        cWeightTable = new double[size][size];  
        for(int semirow = -radius; semirow <= radius; semirow++) {  
            for(int semicol = - radius; semicol <= radius; semicol++) {  
                // calculate Euclidean distance between center point and close pixels  
                double delta = Math.sqrt(semirow * semirow + semicol * semicol)/ds;  
                double deltaDelta = delta * delta;  
                cWeightTable[semirow+radius][semicol+radius] = Math.exp(deltaDelta * factor);  
            }  
        }  
    }  
      
    /** 
     * 灰度图像
     * @param row 
     * @param col 
     * @param inPixels 
     */  
    private void buildSimilarityWeightTable() {  
        sWeightTable = new double[256]; // since the color scope is 0 ~ 255  
        for(int i=0; i<256; i++) {  
            double delta = Math.sqrt(i * i ) / rs;  
            double deltaDelta = delta * delta;  
            sWeightTable[i] = Math.exp(deltaDelta * factor);  
        }  
    }  
      
    public void setDistanceSigma(double ds) {  
        this.ds = ds;  
    }  
      
    public void setRangeSigma(double rs) {  
        this.rs = rs;  
    }  
  
    @Override  
    public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
        width = src.getWidth();  
        height = src.getHeight();  
        //int sigmaMax = (int)Math.max(ds, rs);  
        //radius = (int)Math.ceil(2 * sigmaMax);  
        radius = (int)Math.max(ds, rs);  
        buildDistanceWeightTable();  
        buildSimilarityWeightTable();  
        if ( dest == null )  
            dest = createCompatibleDestImage( src, null );  
  
        int[] inPixels = new int[width*height];  
        int[] outPixels = new int[width*height];  
        getRGB( src, 0, 0, width, height, inPixels );  
        int index = 0;  
        double redSum = 0, greenSum = 0, blueSum = 0;  
        double csRedWeight = 0, csGreenWeight = 0, csBlueWeight = 0;  
        double csSumRedWeight = 0, csSumGreenWeight = 0, csSumBlueWeight = 0;  
        for(int row=0; row> 24) & 0xff;  
                tr = (inPixels[index] >> 16) & 0xff;  
                tg = (inPixels[index] >> 8) & 0xff;  
                tb = inPixels[index] & 0xff;  
                int rowOffset = 0, colOffset = 0;  
                int index2 = 0;  
                int ta2 = 0, tr2 = 0, tg2 = 0, tb2 = 0;  
                for(int semirow = -radius; semirow <= radius; semirow++) {  
                    for(int semicol = - radius; semicol <= radius; semicol++) {  
                        if((row + semirow) >= 0 && (row + semirow) < height) {  
                            rowOffset = row + semirow;  
                        } else {  
                            rowOffset = 0;  
                        }  
                          
                        if((semicol + col) >= 0 && (semicol + col) < width) {  
                            colOffset = col + semicol;  
                        } else {  
                            colOffset = 0;  
                        }  
                        index2 = rowOffset * width + colOffset;  
                        ta2 = (inPixels[index2] >> 24) & 0xff;  
                        tr2 = (inPixels[index2] >> 16) & 0xff;  
                        tg2 = (inPixels[index2] >> 8) & 0xff;  
                        tb2 = inPixels[index2] & 0xff;  
                          
                        csRedWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tr2 - tr))];  
                        csGreenWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tg2 - tg))];  
                        csBlueWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tb2 - tb))];  
                          
                        csSumRedWeight += csRedWeight;  
                        csSumGreenWeight += csGreenWeight;  
                        csSumBlueWeight += csBlueWeight;  
                        redSum += (csRedWeight * (double)tr2);  
                        greenSum += (csGreenWeight * (double)tg2);  
                        blueSum += (csBlueWeight * (double)tb2);  
                    }  
                }  
                  
                tr = (int)Math.floor(redSum / csSumRedWeight);  
                tg = (int)Math.floor(greenSum / csSumGreenWeight);  
                tb = (int)Math.floor(blueSum / csSumBlueWeight);  
                outPixels[index] = (ta << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb);  
                  
                // clean value for next time...  
                redSum = greenSum = blueSum = 0;  
                csRedWeight = csGreenWeight = csBlueWeight = 0;  
                csSumRedWeight = csSumGreenWeight = csSumBlueWeight = 0;  
                  
            }  
        }  
        setRGB( dest, 0, 0, width, height, outPixels );  
        return dest;  
    }  
      
    public static int clamp(int p) {  
        return p < 0 ? 0 : ((p > 255) ? 255 : p);  
    }  
  
    public static void main(String[] args) {  
		try {
			long l1=System.currentTimeMillis();
			BilateralFilter bf = new BilateralFilter(3,8);//初始化   距离西格玛 和 半径西格玛  
			Image a = ImageIO.read(new File("e://old_1504255184945.png"));
			int width = a.getWidth(null);
			int height = a.getHeight(null);

			BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
			Graphics g = image.getGraphics();
			g.drawImage(a, 0, 0, width, height, null);
			g.dispose();
			BufferedImage dest =new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
			image=bf.filter(image, dest);
			ImageIO.write(image, "png",new File("e:/new_" + new Date().getTime() + ".png"));
			long l2=System.currentTimeMillis();
			System.out.println(l2-l1);
		} catch (IOException e) {
			e.printStackTrace();
		}
        
    }  
} > 24) & 0xff;  
                tr = (inPixels[index] >> 16) & 0xff;  
                tg = (inPixels[index] >> 8) & 0xff;  
                tb = inPixels[index] & 0xff;  
                int rowOffset = 0, colOffset = 0;  
                int index2 = 0;  
                int ta2 = 0, tr2 = 0, tg2 = 0, tb2 = 0;  
                for(int semirow = -radius; semirow <= radius; semirow++) {  
                    for(int semicol = - radius; semicol <= radius; semicol++) {  
                        if((row + semirow) >= 0 && (row + semirow) < height) {  
                            rowOffset = row + semirow;  
                        } else {  
                            rowOffset = 0;  
                        }  
                          
                        if((semicol + col) >= 0 && (semicol + col) < width) {  
                            colOffset = col + semicol;  
                        } else {  
                            colOffset = 0;  
                        }  
                        index2 = rowOffset * width + colOffset;  
                        ta2 = (inPixels[index2] >> 24) & 0xff;  
                        tr2 = (inPixels[index2] >> 16) & 0xff;  
                        tg2 = (inPixels[index2] >> 8) & 0xff;  
                        tb2 = inPixels[index2] & 0xff;  
                          
                        csRedWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tr2 - tr))];  
                        csGreenWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tg2 - tg))];  
                        csBlueWeight = cWeightTable[semirow+radius][semicol+radius]  * sWeightTable[(Math.abs(tb2 - tb))];  
                          
                        csSumRedWeight += csRedWeight;  
                        csSumGreenWeight += csGreenWeight;  
                        csSumBlueWeight += csBlueWeight;  
                        redSum += (csRedWeight * (double)tr2);  
                        greenSum += (csGreenWeight * (double)tg2);  
                        blueSum += (csBlueWeight * (double)tb2);  
                    }  
                }  
                  
                tr = (int)Math.floor(redSum / csSumRedWeight);  
                tg = (int)Math.floor(greenSum / csSumGreenWeight);  
                tb = (int)Math.floor(blueSum / csSumBlueWeight);  
                outPixels[index] = (ta << 24) | (clamp(tr) << 16) | (clamp(tg) << 8) | clamp(tb);  
                  
                // clean value for next time...  
                redSum = greenSum = blueSum = 0;  
                csRedWeight = csGreenWeight = csBlueWeight = 0;  
                csSumRedWeight = csSumGreenWeight = csSumBlueWeight = 0;  
                  
            }  
        }  
        setRGB( dest, 0, 0, width, height, outPixels );  
        return dest;  
    }  
      
    public static int clamp(int p) {  
        return p < 0 ? 0 : ((p > 255) ? 255 : p);  
    }  
  
    public static void main(String[] args) {  
		try {
			long l1=System.currentTimeMillis();
			BilateralFilter bf = new BilateralFilter(3,8);//初始化   距离西格玛 和 半径西格玛  
			Image a = ImageIO.read(new File("e://old_1504255184945.png"));
			int width = a.getWidth(null);
			int height = a.getHeight(null);

			BufferedImage image = new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
			Graphics g = image.getGraphics();
			g.drawImage(a, 0, 0, width, height, null);
			g.dispose();
			BufferedImage dest =new BufferedImage(width, height,BufferedImage.TYPE_INT_RGB);
			image=bf.filter(image, dest);
			ImageIO.write(image, "png",new File("e:/new_" + new Date().getTime() + ".png"));
			long l2=System.currentTimeMillis();
			System.out.println(l2-l1);
		} catch (IOException e) {
			e.printStackTrace();
		}
        
    }  
} 
需要继承AbstractBufferedImageOp:
package test;
/*
Copyright 2006 Jerry Huxtable
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
   http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 */
import java.awt.*;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp;
import java.awt.image.ColorModel;
/**
 * A convenience class which implements those methods of BufferedImageOp which are rarely changed.
 */
public abstract class AbstractBufferedImageOp implements BufferedImageOp, Cloneable {
	public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {
		if ( dstCM == null )
			dstCM = src.getColorModel();
		return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null);
	}

	public Rectangle2D getBounds2D( BufferedImage src ) {
		return new Rectangle(0, 0, src.getWidth(), src.getHeight());
	}

	public Point2D getPoint2D( Point2D srcPt, Point2D dstPt ) {
		if ( dstPt == null )
			dstPt = new Point2D.Double();
		dstPt.setLocation( srcPt.getX(), srcPt.getY() );
		return dstPt;
	}
	public RenderingHints getRenderingHints() {
		return null;
	}
	/**
	 * A convenience method for getting ARGB pixels from an image. This tries to avoid the performance
	 * penalty of BufferedImage.getRGB unmanaging the image.
	 * @param image   a BufferedImage object
	 * @param x       the left edge of the pixel block
	 * @param y       the right edge of the pixel block
	 * @param width   the width of the pixel arry
	 * @param height  the height of the pixel arry
	 * @param pixels  the array to hold the returned pixels. May be null.
	 * @return the pixels
	 * @see #setRGB
	 */
	public int[] getRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {
		int type = image.getType();
		if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )
			return (int [])image.getRaster().getDataElements( x, y, width, height, pixels );
		return image.getRGB( x, y, width, height, pixels, 0, width );
	}
	/**
	 * A convenience method for setting ARGB pixels in an image. This tries to avoid the performance
	 * penalty of BufferedImage.setRGB unmanaging the image.
	 * @param image   a BufferedImage object
	 * @param x       the left edge of the pixel block
	 * @param y       the right edge of the pixel block
	 * @param width   the width of the pixel arry
	 * @param height  the height of the pixel arry
	 * @param pixels  the array of pixels to set
	 * @see #getRGB
	 */
	public void setRGB( BufferedImage image, int x, int y, int width, int height, int[] pixels ) {
		int type = image.getType();
		if ( type == BufferedImage.TYPE_INT_ARGB || type == BufferedImage.TYPE_INT_RGB )
			image.getRaster().setDataElements( x, y, width, height, pixels );
		else
			image.setRGB( x, y, width, height, pixels, 0, width );
	}
	public Object clone() {
		try {
			return super.clone();
		}
		catch ( CloneNotSupportedException e ) {
			return null;
		}
	}
}
原图:
高斯滤波:
双边滤波

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值