我试图在Python中复制Matlab的imgaussfilter行为,但是我无法重现结果。这些文档没有太大帮助,因为没有解释确切执行的操作(例如,该函数与fspecial有何不同,或者与Octave的不平滑(以高斯为参数)有何不同。
Matlab代码
imgaussfilt(image,sigma)
有输出
[[-0.02936392 -0.03168419 -0.0343706 ... 0.03136455 0.02864487
0.02585145]
[-0.03212093 -0.0347433 -0.03775943 ... 0.03507484 0.03209807
0.02906134]
[-0.03512981 -0.03808864 -0.04147075 ... 0.03873834 0.03549163
0.03219311]
...
[-0.07713804 -0.08337475 -0.08975262 ... -0.04314206 -0.03945251
-0.03606256]
[-0.07145457 -0.07714807 -0.08297654 ... -0.03986635 -0.03641579
-0.03323718]
[-0.06605107 -0.07122191 -0.07651892 ... -0.03684535 -0.03362917
-0.03065128]]
我设法通过Python获得的最接近的是:
Python
skimage.filters.gaussian(image, sigma=s,mode = 'nearest',truncate=2.0)
有输出
[[-0.02936397 -0.03168425 -0.03437067 ... 0.03136461 0.02864492
0.0258515 ]
[-0.03212099 -0.03474336 -0.03775951 ... 0.03507491 0.03209814
0.0290614 ]
[-0.03512988 -0.03808872 -0.04147083 ... 0.03873842 0.03549169
0.03219317]
...
[-0.07713819 -0.08337491 -0.08975279 ... -0.04314214 -0.03945259
-0.03606263]
[-0.07145471 -0.07714821 -0.0829767 ... -0.03986643 -0.03641586
-0.03323725]
[-0.06605119 -0.07122205 -0.07651907 ... -0.03684542 -0.03362923
-0.03065134]]
相似但不完全相同的结果。有没有一种更好的方法?我需要更改其中一个参数吗?
答案 0 :(得分:2)
有多种可能的原因。由于Matlab不是开源软件,因此不可能知道确切的原因,但是我们可以进行一些有根据的猜测。
关于Gaussian filtering的工作:它将每个像素替换为其邻居的加权总和。权重由Gaussian probability density function确定,精确权重由sigma决定,也由truncate
文档中可以看到的scipy.ndimage.gaussian_filter
参数决定。此参数是必需的,因为从技术上讲,高斯函数永远不会衰减为零,随着距离达到无穷大,它只会接近零,因此“完美”的高斯模糊将需要对无限数量的相邻像素求和,这是不可能的。因此,该函数需要确定您距离零的距离足够远以停止求和。
另一个复杂因素是高斯模糊为separable,这意味着您可以通过沿每个轴依次进行模糊处理来进行2D(或nD)模糊处理,从而降低了计算成本。可分离性会影响计算的顺序,浮点计算是not exact,因此,如果Matlab和Python以不同的顺序进行操作,那么您期望的结果会略有不同。
即使您以完全相同的顺序过滤轴(您也可以通过以下方式实现此目的:例如,将图像在Python中转置,过滤然后再转回),底层的底层数组计算库可能会将数组中的数组求和。不同的顺序,这将再次改变确切的结果。
简而言之,造成差异的一些可能原因:
可能无法解开这些问题,最后,我的建议也反映了克里斯·伦戈(Cris Luengo)的评论:您的结果可能不应该依赖比六个有效数字更精确的值。 Matlab和Python之间的精确匹配将毫无意义,因为它们都不能保证高斯滤波器理论值的完美准确性。两者都是近似值,完全匹配仅表示您在两者中都犯了相同的近似误差。
答案 1 :(得分:1)
在使用10e-10
填充选项调用的imgaussfilt
和使用{{1}调用的scipy.ndimage.gaussian_filter
之间,我能够获得相对较好的匹配度(优于circular
%) }参数,前提是mode='wrap'
使用默认过滤器大小imgaussfilt
,并且2*ceil(2*sigma)+1
指定gaussian_filter
。对于truncate=np.ceil(2*sigma)/sigma
填充情况,这些设置导致基础高斯内核的半径和整体大小相同。我尚未测试其他填充类型。
答案 2 :(得分:1)