5

I'm trying reproduce results from a paper, in which they convolve the image with an horizontal partial derivative of a Gaussian kernel. I haven't found any way to achieve that with OpenCV. Is that possible ?

Do I have to get Gaussian filter and then compute the partial derivatives by hand ?

Baptiste Wicht
  • 7,472
  • 7
  • 45
  • 110
  • No, you can do that with OpenCV. First build your kernel (e.g. [here](http://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html#getgaussiankernel)) and then [apply it](http://docs.opencv.org/2.4/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.html) – Miki Jan 26 '16 at 10:56

2 Answers2

4

As @akarsakov said OpenCV does not provide a built-in function for this. However, we can still use OpenCV's getGaussianKernel() and then apply a factor to get the derivative.

Since a Gaussian 2D kernel is separable, that function will simply return you a 1D kernel and assume that you will apply a 1D filter along the x-axis and then a 1D filter along the y-axis, which is faster than applying the 2D kernel directly.

Since you want the horizontal Gaussian derivative, ref:

enter image description here

You can simply multiply by -x/sigma^2 each point of the kernel.

import cv2
import numpy as np
import matplotlib.pyplot as plt

kernel_size = 13
sigma = 0.5
kernel = cv2.getGaussianKernel(kernel_size, sigma, cv2.CV_64F)
print(kernel)

gaussian_first_deriv_x = np.zeros_like(kernel)
assert(kernel_size % 2 == 1) # I assume you are using an odd kernel_size
half_kernel_size = int(kernel_size / 2)
for i in range(kernel_size):
    x = - half_kernel_size + i
    factor = - x/ (sigma**2)
    gaussian_first_deriv_x[i] = kernel[i] * factor

print(gaussian_first_deriv_x)

plt.plot(kernel[:], 'b')
plt.plot(gaussian_first_deriv_x[:], 'r')
plt.show()

enter image description here

Now, you can do your convolution using this kernel.

Note: if you are using Python you can alternatively use the function ndimage.gaussian_filter1d(data, sigma=1, order=1, mode='wrap') from from scipy import ndimage.

OpenCV by default uses the following: sigma = 0.3 * (kernel_size / 2.0 - 1) + 0.8.

João Cartucho
  • 3,688
  • 32
  • 39
3

OpenCV doesn't have built-in function to calculate Gaussian partial derivatives. But you may use cv::getGaussianKernel and cv::filter2D to do so.

For example:

  cv::Mat kernel = cv::getGaussianKernel(3, 0.85, CV_32F);
  kernel = kernel.reshape(1, 1);
  cv::filter2D(img, img, CV_8U, kernel);

Please note that cv::getGaussianKernel returns column filter, so you need reshape to make it horizontal.

akarsakov
  • 2,134
  • 4
  • 21
  • 26