Matlab的imgaussfilt等效于Python

时间:2019-10-16 15:53:55

标签: python python-3.x image matlab scikit-image

我试图在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]]

相似但不完全相同的结果。有没有一种更好的方法?我需要更改其中一个参数吗?

3 个答案:

答案 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)

最近,我正致力于将Matlab代码转换为python,并在互联网上寻找相同的功能,并且文档中的函数发现与OpenCV实施完全相同的结果。

% In Matlab
imgaussfilt(image, 100)

等同于

import cv2
# in python
cv2.GaussianBlur(image, ksize=(0, 0), sigmaX=100, borderType=cv2.BORDER_REPLICATE)

enter image description here