how to get the gaussian filter?

Question:

I want to get a Gaussian window of size m rows and n columns.
I know how to get to 1-dimension. i.e below.

from scipy.stats import multivariate_normal
multivariate_normal(mean=[1, 5], cov=(2.5))

Now I want two dimensions of a matrix.
Purpose: I want fit this filter on top an image. the green color is a matrix of an image. Blue circle is a Gaussian filter. I am not sure how to get the blue window.

I am thinking to apply something like this –

gw = multivariate_normal(mean=[1, 5], cov=(2.5))

for i in range(image.shape[0):
    image_gauss_window[i:] = gw

enter image description here

Can you give a way to find out the Gaussian filter for an image? I see opencv many functions apply a Gaussian blur to an image. But here I want the filter before applying/convolving on top of an image.

Asked By: ajayramesh

||

Answers:

This function does not exist in OpenCV, but OpenCV provides the basic function to create it, which is called cv::getGaussianKernel. Because I am unfamiliar with python, I wrote my program in c++, but I know it is simple to convert this code to python.

Mat xdirectionGauss = getGaussianKernel(4,  //Size of kernel in x direction
                                        1.4);  // Sigma in x direction

Mat kernel =xdirectionGauss*xdirectionGauss.t();  //kernel * transpose(kernel)

kernels output will be like this:

[0.035183571, 0.058602851, 0.058602851, 0.035183571;
0.058602851, 0.097610727, 0.097610727, 0.058602851;
0.058602851, 0.097610727, 0.097610727, 0.058602851;
0.035183571, 0.058602851, 0.058602851, 0.035183571]

If you compare the results with MATLAB, which produced a 2D kernel, the output will be identical to opencv.

>> h = fspecial('gaussian',[4 4], 1.4)

h =

0.0352    0.0586    0.0586    0.0352
0.0586    0.0976    0.0976    0.0586
0.0586    0.0976    0.0976    0.0586
0.0352    0.0586    0.0586    0.0352
Answered By: Saeed Masoomi

Using np.fromfunction:

You can use some code from a basic computer vision library that I wrote.

So if you have size and sigma, you can get the 2d numpy array of the gaussian kernel with this one line:

kernel = np.fromfunction(lambda x, y: (1/(2*math.pi*sigma**2)) * math.e ** ((-1*((x-(size-1)/2)**2+(y-(size-1)/2)**2))/(2*sigma**2)), (size, size))

and then to normalise it, just divide each element by the sum:

kernel /= np.sum(kernel)

which (for example) with size as 5 and sigma as 1 would give kernel as:

array([[ 0.00296902,  0.01330621,  0.02193823,  0.01330621,  0.00296902],
       [ 0.01330621,  0.0596343 ,  0.09832033,  0.0596343 ,  0.01330621],
       [ 0.02193823,  0.09832033,  0.16210282,  0.09832033,  0.02193823],
       [ 0.01330621,  0.0596343 ,  0.09832033,  0.0596343 ,  0.01330621],
       [ 0.00296902,  0.01330621,  0.02193823,  0.01330621,  0.00296902]])

which you can see is a nice symmetric bell-curve in 2d that rises in the centre.


You can see this gaussian filter visualised with matplotlib:

gaussian

Answered By: Joe Iddon

If you are looking for a “python”ian way of creating a 2D Gaussian filter, you can create it by dot product of two 1D Gaussian filter.

Creating a single 1×5 Gaussian Filter

x = np.linspace(0, 5, 5, endpoint=False)
y = multivariate_normal.pdf(x, mean=2, cov=0.5)

Then change it into a 2D array

import numpy as np
y = y.reshape(1,5)

Dot product the y with its self to create a symmetrical 2D Gaussian Filter

GF = np.dot(y.T,y)
Answered By: yapws87

Using openCV in Python

Example: 5×5 kernel with Sigma=1.0:

First method: use a matrix with a single 1 in the middle:

    visualization_matrix = np.zeros((5,5))
    visualization_matrix[2,2] = 1.0
    print(visualization_matrix)
    [[0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0.]
     [0. 0. 1. 0. 0.]
     [0. 0. 0. 0. 0.]
     [0. 0. 0. 0. 0.]]
    gauss_kernel = cv2.GaussianBlur(visualization_matrix , (5, 5), 1.0, 
                                    borderType=cv2.BORDER_ISOLATED)
    print("Kernel: n", gauss_kernel)
    Kernel:
    [[0.00296902 0.01330621 0.02193823 0.01330621 0.00296902]
     [0.01330621 0.0596343  0.09832033 0.0596343  0.01330621]
     [0.02193823 0.09832033 0.16210282 0.09832033 0.02193823]
     [0.01330621 0.0596343  0.09832033 0.0596343  0.01330621]
     [0.00296902 0.01330621 0.02193823 0.01330621 0.00296902]]

Second method: use cv2.getGaussianKernel:

    xdir_gauss = cv2.getGaussianKernel(5, 1.0)
    kernel = np.multiply(xdir_gauss.T, xdir_gauss)
    print("Kernel: n", kernel)
    Kernel: 
    [[0.00296902 0.01330621 0.02193823 0.01330621 0.00296902]
     [0.01330621 0.0596343  0.09832033 0.0596343  0.01330621]
     [0.02193823 0.09832033 0.16210282 0.09832033 0.02193823]
     [0.01330621 0.0596343  0.09832033 0.0596343  0.01330621]
     [0.00296902 0.01330621 0.02193823 0.01330621 0.00296902]]

The result is the same.

Note that in Python the kernel size must be odd. So using e.g. a 4×4 kernel is not supported by the used functions.

Answered By: Peer Breier
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.