How do I get to show Gaussian Kernel for 2d? (opencv)
Question:
I am using this:
blur = cv2.GaussianBlur(dst,(5,5),0)
And I wanted to show the kernel matrix by this:
print(cv2.getGaussianKernel(ksize=(5,5),sigma=0))
But I am getting a type error:
TypeError: an integer is required (got type tuple)
If I only put 5, I get a 5×1 matrix. Isn’t the blur kernel 5×5? Or am I missing on something fundamental?
Answers:
The Gaussian kernel is separable. Therefore, the kernel generated is 1D. The GaussianBlur
function applies this 1D kernel along each image dimension in turn. The separability property means that this process yields exactly the same result as applying a 2D convolution (or 3D in case of a 3D image). But the amount of work is strongly reduced. For your 5×5 kernel, the 2D convolution does 25 multiplications and additions, the separable implementation does only 5+5=10. For larger kernels, the gains are increasingly significant.
To see the full 2D kernel, apply the GaussianBlur
function to an image that is all zeros and has a single pixel in the middle set to 1. This is the discrete equivalent to the Dirac delta function, which we can use to analyze linear time-invariant functions (==convolution filters).
As you can see in this example:
taken from https://theailearner.com/tag/cv2-getgaussiankernel/
We can get the dot product of the gaussian kernel with itself transposed.
First we get the 1d kernel:
k = cv2.getGaussianKernel(kSize, -1)
Then we can restore its original form before normalization just from the fact that the first element is always originally equals 1:
k /= k[0,0]
Now we can get the dot product as mentioned:
print(k @ k.T)
If you want it summed up to 1 (normalized), divide it by its sum:
kernel = k @ k.T
kernel /= kernel.sum()
print(kernel)
To get the 5×5 Gaussian kernel first we can form a 7×7 Numpy array with only one 1 in the middle.
img=np.zeros((7,7))
img[3,3]=1
img
The result of the code is
array([[0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 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., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0.]])
Then apply gaussian blur:
img1 = cv2.GaussianBlur(img, (5, 5), 0)
img1
The result is:
array([[0. , 0. , 0. , 0. , 0. ,0. , 0. ],
[0. , 0.00390625, 0.015625 , 0.0234375 , 0.015625 ,0.00390625, 0. ],
[0. , 0.015625 , 0.0625 , 0.09375 , 0.0625 ,0.015625 , 0. ],
[0. , 0.0234375 , 0.09375 , 0.140625 , 0.09375 ,0.0234375 , 0. ],
[0. , 0.015625 , 0.0625 , 0.09375 , 0.0625 ,0.015625 , 0. ],
[0. , 0.00390625, 0.015625 , 0.0234375 , 0.015625 ,0.00390625, 0. ],
[0. , 0. , 0. , 0. , 0. ,0. , 0. ]])
The nonzero numbers are the Gaussian kernel. We can confirm that the sum of the numbers are 1:
np.sum(img1)
1.0
I am using this:
blur = cv2.GaussianBlur(dst,(5,5),0)
And I wanted to show the kernel matrix by this:
print(cv2.getGaussianKernel(ksize=(5,5),sigma=0))
But I am getting a type error:
TypeError: an integer is required (got type tuple)
If I only put 5, I get a 5×1 matrix. Isn’t the blur kernel 5×5? Or am I missing on something fundamental?
The Gaussian kernel is separable. Therefore, the kernel generated is 1D. The GaussianBlur
function applies this 1D kernel along each image dimension in turn. The separability property means that this process yields exactly the same result as applying a 2D convolution (or 3D in case of a 3D image). But the amount of work is strongly reduced. For your 5×5 kernel, the 2D convolution does 25 multiplications and additions, the separable implementation does only 5+5=10. For larger kernels, the gains are increasingly significant.
To see the full 2D kernel, apply the GaussianBlur
function to an image that is all zeros and has a single pixel in the middle set to 1. This is the discrete equivalent to the Dirac delta function, which we can use to analyze linear time-invariant functions (==convolution filters).
As you can see in this example:
taken from https://theailearner.com/tag/cv2-getgaussiankernel/
We can get the dot product of the gaussian kernel with itself transposed.
First we get the 1d kernel:
k = cv2.getGaussianKernel(kSize, -1)
Then we can restore its original form before normalization just from the fact that the first element is always originally equals 1:
k /= k[0,0]
Now we can get the dot product as mentioned:
print(k @ k.T)
If you want it summed up to 1 (normalized), divide it by its sum:
kernel = k @ k.T
kernel /= kernel.sum()
print(kernel)
To get the 5×5 Gaussian kernel first we can form a 7×7 Numpy array with only one 1 in the middle.
img=np.zeros((7,7))
img[3,3]=1
img
The result of the code is
array([[0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 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., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0., 0.]])
Then apply gaussian blur:
img1 = cv2.GaussianBlur(img, (5, 5), 0)
img1
The result is:
array([[0. , 0. , 0. , 0. , 0. ,0. , 0. ],
[0. , 0.00390625, 0.015625 , 0.0234375 , 0.015625 ,0.00390625, 0. ],
[0. , 0.015625 , 0.0625 , 0.09375 , 0.0625 ,0.015625 , 0. ],
[0. , 0.0234375 , 0.09375 , 0.140625 , 0.09375 ,0.0234375 , 0. ],
[0. , 0.015625 , 0.0625 , 0.09375 , 0.0625 ,0.015625 , 0. ],
[0. , 0.00390625, 0.015625 , 0.0234375 , 0.015625 ,0.00390625, 0. ],
[0. , 0. , 0. , 0. , 0. ,0. , 0. ]])
The nonzero numbers are the Gaussian kernel. We can confirm that the sum of the numbers are 1:
np.sum(img1)
1.0