0

I have this Gaussian function. which is not producing desired result. for that reason image cannot be blurred properly. In the bellow code I have taken the kernel size(5) and sigma value(1), which is same as I took in the link below. it would be very helpful if someone could point out the problem.

here is the link of of a website Gaussian kernle link

public class KernelDemo {

public double[][] Calculate(int lenght, double weight) {
    double[][] Kernel = new double[lenght][lenght];
    double sumTotal = 0;
    int kernelRadius = lenght / 2;
    double distance = 0;

    double calculatedEuler = 1.0 / (2.0 * Math.PI * Math.pow(weight, 2));

    for (int filterY = -kernelRadius; filterY <= kernelRadius; filterY++) {
        for (int filterX = -kernelRadius; filterX <= kernelRadius; filterX++) {
            distance = ((filterX * filterX) + (filterY * filterY)) / (2 * (weight * weight));

            Kernel[filterY + kernelRadius][filterX + kernelRadius] = calculatedEuler * Math.exp(-distance);

            sumTotal += Kernel[filterY + kernelRadius][filterX + kernelRadius];
        }
    }

    for (int y = 0; y < lenght; y++) {
        for (int x = 0; x < lenght; x++) {
            Kernel[y][x] = Kernel[y][x] * (1.0 / sumTotal);
        }
    }
    return Kernel;
}

public static void main(String args[]) {
    KernelDemo kd = new KernelDemo();
    double terms[][];
    terms = kd.Calculate(5,1);
    for (int i = 0; i < 5; i++) {
        for (int j = 0; j < 5; j++) {
            System.out.print(terms[i][j]);
        }
        System.out.println();
    }

}
}
Vikash Chauhan
  • 792
  • 2
  • 9
  • 18
NEKIBUR RAHMAN
  • 204
  • 3
  • 15

1 Answers1

1

This is how I have handled generating a 2d Gaussian distribution kernel. The Kernel class is just a double[][] wrapped to enforce certain stipulations (e.g. squared array 5x5 7x7, and also ensures that the length is odd)

public static Kernel generateBlurKernel(int length, double std){
    Kernel out = new Kernel(length);

    int center = length/2;
    for(int i=0;i<length;i++){
        for(int j=0;j<length;j++){
            int x = Math.abs(j-center);
            int y = Math.abs(i-center);
            out.setValueAt(j, i, ((1d/(2*Math.PI*std*std))*Math.pow(Math.E, -((x*x)+(y*y))/(2*std*std))));
        }
    }
    out.normalize();
    return out;
} 

In case you want it, here is my Kernel class too:

public class Kernel {

    private final double[][] matrix;

    public Kernel(int sidelength){
        if((sidelength&1)==0)throw new IllegalArgumentException();
        matrix = new double[sidelength][sidelength];
    }


    public double getValueAt(int x, int y){
        return matrix[x][y];
    }
    public void setValueAt(int x, int y, double value){
        matrix[x][y] = value;
    }
    public double sum(){
        double sum = 0.0d;
        for(double[] da:matrix){
            for(double d:da){
                sum+=d;
            }
        }
        return sum;
    }
    public double[][] getFullKernal(){
        return matrix;
    }
    public int getSideLegth(){
        return matrix.length;
    }
    public void normalize(){
        double normalizedConstant = 1d/sum();
        for(int i=0;i<matrix.length;i++){
            for(int j=0;j<matrix.length;j++){
                matrix[i][j] = matrix[i][j]*normalizedConstant;
            }
        }
    }
}
CraigR8806
  • 1,584
  • 13
  • 21
  • It is not generating the same result as the above website i have mentioned. but it works. – NEKIBUR RAHMAN Jun 09 '17 at 14:38
  • The difference in results may be attributed to the way that different languages and different implementations of the Java Virtual Machine or even the JDK handle floating point numbers like the `double` @NEKIBURRAHMAN – CraigR8806 Jun 09 '17 at 14:39