图像处理之基于一维高斯快速模糊
程序员文章站
2022-07-15 22:38:41
...
数学基础:
二维高斯模糊的数学表达如下:
简单表达为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;
}
}
转载文章请务必注明! 上一篇: 一维数组