Reputation: 3804
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
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.
Upvotes: 6
Views: 16303
Reputation: 1834
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
Upvotes: 3
Reputation: 391
Using openCV in Python
Example: 5x5 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 4x4 kernel is not supported by the used functions.
Upvotes: 7
Reputation: 20434
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
:
Upvotes: 8
Reputation: 1839
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 1x5 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)
Upvotes: 5