Why is Gaussian Filter different between cv2 and skimage?
Solution 1
If anyone is curious about how to make skimage.gaussian_filter() match Matlab's equivalent imgaussfilt() (the reason I found this question), pass the parameter 'truncate=2' to skimage.gaussian_filter(). Both skimage and Matlab calculate the kernel size as a function of sigma. Matlab's default is 2. Skimage's default is 4, resulting in a significantly larger kernel by default.
Solution 2
For GaussianBlur, you are using a rather large kernel (size=33), which causes a lot of smoothing. Smoothing will depend drastically on you kernel size. With your parameters each new pixel value is "averaged" in a 33*33 pixel "window".
A definition of cv2.GaussianBlur can be found here http://docs.opencv.org/3.1.0/d4/d13/tutorial_py_filtering.html#gsc.tab=0
In contrast, skimage.filters.gaussian seems to work on a smaller kernel. In skimage, the "size" is defined by sigma which is related to kernel size as described here: https://en.wikipedia.org/wiki/Gaussian_filter
Definition can be found here: http://scikit-image.org/docs/dev/api/skimage.filters.html#skimage.filters.gaussian
In order to get corresponding results, you'd have to work with a smaller kernel for OpenCV.
Furthermore, for both libraries, I'd strongly recommend to use up to date library versions.
Solution 3
These two are equal:
gau_img = cv2.GaussianBlur(img, (5,5), 10.0) # 5*5 kernal, 2 on each side. 2 = 1/5 * 10 = 1/5 * sigma
gau_img = skimage.filters.gaussian(img, sigma=10, truncate=1/5)
The whole Gaussian kernel is defined by sigma only. But which part of gaussian kernel do you use to blur the image is defined by truncate
(in skimage) or ksize
(in opencv).
waldol1
Updated on June 11, 2022Comments
-
waldol1 almost 2 years
I've got an image that I apply a Gaussian Blur to using both
cv2.GaussianBlur
andskimage.gaussian_filter
libraries, but I get significantly different results. I'm curious as to why, and what can be done to makeskimage
look more likecv2
. I knowskimage.gaussian_filter
is a wrapper aroundscipy.scipy.ndimage.filters.gaussian_filter
. To clearly state the question, why are the two functions different and what can be done to make them more similar?Here is my test image:
Here is the
cv2
version (appears blurrier):Here is the
skimage
/scipy
version (appears sharper):Details:
skimage_response = skimage.filters.gaussian_filter(im, 2, multichannel=True, mode='reflect')
cv2_response = cv2.GaussianBlur(im, (33, 33), 2)
So sigma=2 and the size of the filter is big enough that it shouldn't make a difference. Imagemagick
covnert -gaussian-blur 0x2
visually agrees withcv2
.Versions:
cv2
=2.4.10,skimage
=0.11.3,scipy
=0.13.3 -
waldol1 about 8 yearsThe amount of smoothing is controlled by sigma, not the size. Pixels are not straight averaged, they are weighted averaged by a Gaussian kernel. Size just truncates computation and skimage computes a size that's 4*sigma. The versions shouldn't be the issue. This is old and basic functionality.
-
tfv about 8 yearsAs far as I can read here, you are using a deprecated funtion gaussian_filter scikit-image.org/docs/dev/api/… , but you are correct that this is basic functionality. You are also corrrect that sigma correlates to kernel size. However, I do not understand why a siga of 2 you are using in scikit should be equivalent to a kernel size of 33 in OpenCV.
-
tfv about 8 yearsI am no mathematician, but the way I read en.wikipedia.org/wiki/Gaussian_filter , [quote] "A gaussian kernel requires 6{\sigma}-1 values, e.g. for a {\sigma} of 3 it needs a kernel of length 17". This would mean that your sima=2 is equivalent to a kernel of size 6*2-1=11. Sorry, I am no expert on this, but you may want to review your size assumtion.
-
waldol1 about 8 yearsMathematically, a Gaussian kernel has infinite size, just the values far away from the center are so small that they can be ignored. The function gaussian_filter is deprecated, but I suspect that it is a name change only because they both just wrap the scipy filter. Scipy makes the size 8 * sigma + 1 (or 4 * sigma * 2 sides + 1 center), and opencv does something similar, but adding precision by a larger size shouldn't make it more or less blurry visually.
-
Paulo Scardine over 6 yearsGood to know but this is not really an answer. Sometimes I abuse the site posting a comment as an answer because the text would not fit a comment or because the comment includes code and the comment system does not handle well longer snippets of code - but I guess your text fits a comment.
-
dhamechaSpeaks over 3 yearsIf I use the above, if truncate is 4.0 and sigma is 5.0, this may not work, right? Then it looks like the kernel size should be (0.25, 0.25)? But opencv requires the ksize to be positive and odd.
-
Haotao Wang over 3 years@dhamechaSpeaks The ksize is required to be positive and odd because the kernel has to be symmetric. If ksize=5, then there are 2 pixels on each side. In this case, the truncate parameter in skimage should be set to (ksize-1)/2/sigma = 2/sigma
-
Andrew Marshall over 2 yearsYes, this answer is not correct. You can have as large a kernel as you like, but sigma controls the weights in the kernel. A sigma value of 1.0 and a kernel size of, say 99, should give the same result as sigma=1.0 and a kernel size of 9. It's just that the larger kernel will contain mostly zeroes.