I've been completely stuck on a portion of my assignment for a few days now. After plenty of searching around, I have been unsuccessful in discovering information that leads me to the correct solution. That said, this is for OpenCV in Python, using Numpy for matrix calculations.
The problem statement:
Construct the derivative of Gaussian kernels, 𝑔𝑥 and 𝑔𝑦 by convolving the above two kernels: 𝑔𝑥=𝑆𝑥∗𝑔𝜎; 𝑔𝑦=𝑆𝑦∗𝑔𝜎
Additionally, here's a screenshot of the problem in full form:
What I Have Attempted:
import cv2 import numpy as np def my_Normalize(img): if len(img.shape) != 2: img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #convert img to grayscale img_float = cv2.normalize(img.astype('float'), None, 0.0, 1.0, cv2.NORM_MINMAX) return img_float def my_DerivativesOfGaussian(img, sigma): #the two 3x3 Sobel kernels #Sx = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]], np.float) #Sy = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]], np.float) sobelx = cv2.Sobel(img,cv2.CV_32F,1,0,ksize=3) sobely = cv2.Sobel(img,cv2.CV_32F,0,1,ksize=3) #the Gaussian kernel, taken from example program 9 halfSize = 3 * sigma maskSize = 2 * halfSize + 1 gKern = np.ones((maskSize,maskSize)) / (float)( 2 * np.pi * (sigma**2)) xyRange = np.arange(-halfSize, halfSize+1) xx, yy = np.meshgrid(xyRange, xyRange) x2y2 = (xx**2 + yy**2) exp_part = np.exp(-(x2y2/(2.0*(sigma**2)))) gKern = gKern * exp_part #convolve the two kernels Gx = cv2.filter2D(sobelx, -1, gKern) IxN = my_Normalize(Gx) cv2.imshow('Gx Normalized', IxN) return Gx, Ix img1 = cv2.imread('TestImg1.jpg') Ix, Iy = my_DerivativesOfGaussian(img1, 1) cv2.waitKey(0) cv2.destroyAllWindows()
Here is a side-by-side comparison of the result I was given for a test image (left image), compared with the result I obtained from the above execution (right image):
Where I am confused:
The resulting image that was obtained is close to the target image, except blurred slightly. The blurring leads me to believe there's an error with the Gaussian kernel. I also obtain a drastically different image when I switch the order of the Gaussian and Sobel kernels in the
cv2.filter2D() function. However, this is counter-intuitive for me, as the association property states that convolution should be equivalent, regardless of the order in which the convolution occurs.
- Is the
cv2.filter2D()function able to convolve two kernels?
- Assuming the answer to ^ is false, do you know of a function that is able to perform such an operation?
- Where does my logic/understanding begin to fail? (i.e. what topics/concepts am I completely not understanding?)
Thanks so much for your time, any help is appreciated. This is the first time I have been absolutely stumped on an assignment, and can not think of a way to solve this problem without brute-forcing the convolution formula via nested loops.
Here are the images supplied for verifying correctness of the convolution, in their native formats:
Base input test image