Reputation: 31
I am trying to port some lua/torch code in Python, there's a sequence that runs a Gaussian blur over an image as follows:
local gauK = image.gaussian(math.ceil(3*sigma)*2+1, sigma)
inp = image.convolve(inp, gauK, 'same')
To replicate this in my approach, I have been looking at cv2.GaussianBlur() and cv2.filter2D with passing in a gaussian kernel.
Method 1 (cv2.GaussianBlur):
kernel_size = int(math.ceil(3 * sigma) * 2 + 1) # same size as the lua code
blurred_image = cv2.GaussianBlur(img, ksize=(kernel_size, kernel_size), sigma)
Method 2 (cv2.filter2D)
kernel_size = int(math.ceil(3 * sigma) * 2 + 1) # same size as the lua code
gaussian_kernel = cv2.getGaussianKernel(kernel_size, sigma)
blurred_image_2 = cv2.filter2D(img, -1, gaussian_kernel)
Between Method 1 & Method 2, I get different images. It appears that the Method 1 image is a bit more blurred than in Method 2. Is there any reason why I might be getting different results here? I am trying to figure out which one would match the lua code. Thanks.
Upvotes: 3
Views: 7888
Reputation: 208
cv2.getGaussianKernel function return 1D vector, to make it 2D gaussian matrix, you can multiply it with its transpose ( @ is used for matrix multiplication). Could you try this code:
gaussian_kernel = cv2.getGaussianKernel(kernel_size, sigma)
kernel_2D = gaussian_kernel @ gaussian_kernel.transpose()
blurred_image_2 = cv2.filter2D(img, -1, kernel_2D)
Upvotes: 4
Reputation: 600
This is a weird one; for practicality's sake, I'd suggest you just pick one you're happy with and use it. That aside, I'm guessing that the semantics of how the multiple arguments are handled cause this mismatch. Also, opencv's equation for inferring sigma from kernelsize and vice versa does not appear to match yours.
From GaussianBlur docs:
- ksize: Gaussian kernel size. ksize.width and ksize.height can differ but they both must be positive and odd. Or, they can be zero's and then they are computed from sigma.
- sigmaX: Gaussian kernel standard deviation in X direction.
- sigmaY: Gaussian kernel standard deviation in Y direction; if sigmaY is zero, it is set to be equal to sigmaX, if both sigmas are zeros, they are computed from ksize.width and ksize.height, respectively (see cv::getGaussianKernel for details); to fully control the result regardless of possible future modifications of all this semantics, it is recommended to specify all of ksize, sigmaX, and sigmaY.
And the getGaussianKernel docs:
- If it is non-positive, it is computed from ksize as
sigma = 0.3\*((ksize-1)\*0.5 - 1) + 0.8
All emphasis mine. Is there any chance your sigma is negative? That might cause a mismatch.
EDIT: just noticed you want this to match the lua code. My advice would be to save out the results, then compare them in photoshop or your favorite image editor. If you subtract the test from the reference, you should be able to see the difference, and as your attempts get closer, there should be less difference overall. Barring that, you could try and read the source to figure out the difference in definition, or write your own!
Good luck!
Upvotes: 2