图像处理之基于一维高斯快速模糊

数学基础:

二维高斯模糊的数学表达如下:


简单表达为G(x, y) = G(x)G(y)由此,对一个二维的像素矩阵可以分别在水平与垂直方向

进行一维高斯模糊其效果等同与二维高斯模糊效果。由于计算量的减少,速度却比二维

高斯模糊更快。

运行结果:


关键代码解析:

生成一维高斯核的代码如下,其中对高斯核实现归一化预处理

private float[] generateGaussianKeneral(int n, float sigma) {
	float sigma22 = 2*sigma*sigma;
	float Pi2 = 2*(float)Math.PI;
	float sqrtSigmaPi2 = (float)Math.sqrt(Pi2) * sigma ;
	int size = 2*n + 1;
	int index = 0;
	gaussianKeneral = new float[size];
	float sum = 0.0f;
	for(int i=-n; i<=n; i++) {
		float distance = i*i;
		gaussianKeneral[index] = (float)Math.exp((-distance)/sigma22)/sqrtSigmaPi2;
		//System.out.println("\t" + gaussianKeneral[index]);
		sum += gaussianKeneral[index];
		index++;
	}
	
	// nomalization to 1
	for(int i=0; i<gaussianKeneral.length; i++) {
		gaussianKeneral[i] = gaussianKeneral[i]/sum;
		//System.out.println("final gaussian data " + i + " = " + gaussianKeneral[i]);
	} 
	return gaussianKeneral;
}
实现对越界像素值的处理:

public static int clamp(float a) {
	return (int)(a < 0 ?  0 : ((a > 255) ? 255 : a));
}
全部算法源代码如下:

package com.gloomyfish.filter.study;

import java.awt.image.BufferedImage;

public class HVGaussianFilter extends AbstractBufferedImageOp {
	private float[] gaussianKeneral = null;
	private int radius = 2; // default value
	private float sigma = 10;
	public HVGaussianFilter() {
		
	}
	
	public void setSigma(float a) {
		this.sigma = a;
	}
	
	public void setRadius(int size) {
		this.radius = size;
	}
	
	public float[][] getHVGaussianKeneral() {
		float[][] hvKeneralData = new float[5][5];
		for(int i=0; i<5; i++)
		{
			for(int j=0; j<5; j++) 
			{
				hvKeneralData[i][j] = gaussianKeneral[i] * gaussianKeneral[j];
			}
		}
		return hvKeneralData;
	}
	
	@Override
	public BufferedImage filter(BufferedImage src, BufferedImage dest) {
		generateGaussianKeneral(radius, sigma);
        int width = src.getWidth();
        int height = src.getHeight();

        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);
        blur( inPixels, outPixels, width, height); // H Gaussian
        blur( outPixels, inPixels, height, width); // V Gaussain
        setRGB(dest, 0, 0, width, height, inPixels );
        return dest;
	}

	/**
	 * <p> here is 1D Gaussian        , </p>
	 * 
	 * @param inPixels
	 * @param outPixels
	 * @param width
	 * @param height
	 */
	private void blur(int[] inPixels, int[] outPixels, int width, int height)
	{
		int subCol = 0;
		int index = 0, index2 = 0;
		float redSum=0, greenSum=0, blueSum=0;
        for(int row=0; row<height; row++) {
        	int ta = 0, tr = 0, tg = 0, tb = 0;
        	index = row;
        	for(int col=0; col<width; col++) {
        		// index = row * width + col;
        		redSum=0;
        		greenSum=0;
        		blueSum=0;
        		for(int m=-2; m<=2; m++) {
        			subCol = col + m;
        			if(subCol < 0 || subCol >= width) {
        				subCol = 0;
        			}
        			index2 = row * width + subCol;
            		ta = (inPixels[index2] >> 24) & 0xff;
                    tr = (inPixels[index2] >> 16) & 0xff;
                    tg = (inPixels[index2] >> 8) & 0xff;
                    tb = inPixels[index2] & 0xff;
                    redSum += (tr * gaussianKeneral[m + 2]);
                    greenSum += (tg * gaussianKeneral[m + 2]);
                    blueSum += (tb * gaussianKeneral[m + 2]);
        		}
        		outPixels[index] = (ta << 24) | (clamp(redSum) << 16) | (clamp(greenSum) << 8) | clamp(blueSum);
        		index += height;// correct index at here!!!, out put pixels matrix,
        	}
        }
	}
	
	public static int clamp(float a) {
		return (int)(a < 0 ?  0 : ((a > 255) ? 255 : a));
	}
	
	private float[] generateGaussianKeneral(int n, float sigma) {
		float sigma22 = 2*sigma*sigma;
		float Pi2 = 2*(float)Math.PI;
		float sqrtSigmaPi2 = (float)Math.sqrt(Pi2) * sigma ;
		int size = 2*n + 1;
		int index = 0;
		gaussianKeneral = new float[size];
		float sum = 0.0f;
		for(int i=-n; i<=n; i++) {
			float distance = i*i;
			gaussianKeneral[index] = (float)Math.exp((-distance)/sigma22)/sqrtSigmaPi2;
			//System.out.println("\t" + gaussianKeneral[index]);
			sum += gaussianKeneral[index];
			index++;
		}
		
		// nomalization to 1
		for(int i=0; i<gaussianKeneral.length; i++) {
			gaussianKeneral[i] = gaussianKeneral[i]/sum;
			//System.out.println("final gaussian data " + i + " = " + gaussianKeneral[i]);
		} 
		return gaussianKeneral;
	}

}
转载文章请务必注明!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gloomyfish

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值