如何使用Matlab在python中的imresize

时间:2015-04-30 03:47:06

标签: python image matlab image-processing scipy

我将Matlab的imresize代码转移到python中。我找到了scipy的imresize,但我从Matlab得到了不同的结果。

如何通过python获得与Matlab相同的结果。

Python / scipy imresize

from scipy.misc import imresize
import numpy as np

dtest = np.array(([1,2,3],[4,5,6],[7,8,9]))
scale = 1.4
dim = imresize(dtest,1/scale)

Matlab imresize

dtest = [1,2,3;
         4,5,6;
         7,8,9];
scale = 1.4;
dim = imresize(dtest,1/scale);

这两段代码会返回不同的结果。

3 个答案:

答案 0 :(得分:14)

scipy.misc.imresize函数对我来说有点奇怪。首先,当我指定您在此图像上以1.0为标度的scipy.misc.imresize调用提供的样本2D图像时,会发生这种情况。理想情况下,它应该给你相同的图像,但我们得到的是这个(在IPython中):

In [35]: from scipy.misc import imresize

In [36]: import numpy as np

In [37]: dtest = np.array(([1,2,3],[4,5,6],[7,8,9]))

In [38]: out = imresize(dtest, 1.0)

In [39]: out
Out[39]: 
array([[  0,  32,  64],
       [ 96, 127, 159],
       [191, 223, 255]], dtype=uint8)

它不仅会将输出类型更改为uint8,还会缩放值。首先,看起来它使图像的最大值等于255,最小值等于0. MATLAB' s imresize不会这样做,它会按照我们期望的方式调整图像大小:

>> dtest = [1,2,3;4,5,6;7,8,9];
>> out = imresize(dtest, 1)

out =

     1     2     3
     4     5     6
     7     8     9

但是,您需要认识到MATLAB执行调整大小with anti-aliasing enabled by default。我不确定scipy.misc.resize这里做了什么,但我打赌没有启用抗锯齿功能。

编辑 - 2016年11月23日

正如Eric在下面的评论中指出的那样,如果您将图像预先投射到所需的类型,您将获得预期的结果:

In [10]: dtest = np.array([[1,2,3],[4,5,6],[7,8,9]], dtype=np.uint8)

In [11]: out = imresize(dtest, 1.0)

In [12]: out
Out[12]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]], dtype=uint8)

我们可以看到图片未缩放到[0,255]范围。为了最终到达您需要的位置,我们必须获得图像的浮点表示。 scipy.misc.imresize有一个名为'mode'的附加标志,您可以将其指定为'F'以确保输出为浮点。

In [14]: scale = 1.4

In [15]: out = imresize(dtest, 1/scale, mode='F')

In [16]: out
Out[16]: 
array([[ 2.5 ,  3.75],
       [ 6.25,  7.5 ]], dtype=float32)

正如您稍后将看到的,您在scipy.misc.resize看到的结果与您在MATLAB中看到的结果不匹配。

为获得最佳效果,请勿指定比例 - 指定目标输出尺寸以重现结果。因此,在您的情况下,1/scale接近2 x 2大小输出,因此您将在MATLAB中执行以下操作:

>> dtest = [1,2,3;4,5,6;7,8,9];
>> out = imresize(dtest, [2,2], 'bilinear', 'AntiAliasing', false)

out =

    2.0000    3.5000
    6.5000    8.0000

您可以看到矩阵中的某些值与scipy.misc.resize不对齐。与您在MATLAB中看到的相匹配。与您想要的最接近的是OpenCV' resize功能或scikit-image的resize功能。这两者都没有抗锯齿。如果要使Python和MATLAB相互匹配,请使用双线性插值方法。 MATLAB中的imresize默认使用双三次插值,我知道MATLAB使用自定义内核这样做,因此如果在方法之间使用双三次插值,则匹配它们的输出要困难得多。有关更多信息性结果,请参阅此帖子:

MATLAB vs C++ vs OpenCV - imresize

使用Python OpenCV:

In [93]: import numpy as np

In [94]: import cv2

In [95]: dtest = np.array(([1,2,3],[4,5,6],[7,8,9]), dtype='float')

In [96]: out = cv2.resize(dtest, (2,2))

In [97]: out
Out[97]: 
array([[ 2. ,  3.5],
       [ 6.5,  8. ]])

使用scikit-image:

In [100]: from skimage.transform import resize

In [101]: dtest = np.array(([1,2,3],[4,5,6],[7,8,9]), dtype='uint8')

In [102]: out = resize(dtest, (2,2), order=1, preserve_range=True)

In [103]: out
Out[103]: 
array([[ 2. ,  3.5],
       [ 6.5,  8. ]])

最后一个值得注意的事情是,指定浮点刻度时,MATLAB,OpenCV和scikit-image的行为彼此不同。我做了一些实验,并通过指定浮点大小,我无法得到匹配的结果。除此之外,scikit-image不支持接受比例因子,这更明显地说明输出大小而不是比例。

答案 1 :(得分:2)

在浏览excellent answer by @rayryeng时添加一个我找到的选项。

scipy.misc.imresize使用PIL(因此将图像转换为缩放整数)。但该页面链接到另一个功能:scipy.ndimage.zoom

>>> from scipy import ndimage
>>> dtest = np.array(([1,2,3],[4,5,6],[7,8,9]), dtype='float')
>>> ndimage.zoom(dtest, 2/3)
array([[ 1.,  3.],
       [ 7.,  9.]])
>>> ndimage.zoom(dtest, 2/3, prefilter=False)
array([[ 2.33333333,  3.66666667],
       [ 6.33333333,  7.66666667]])

它没有给我与matlab相同的结果,但它接近:

>> dtest = [1,2,3;4,5,6;7,8,9];
>> imresize(dtest, [2,2])

ans =
    2.1296    3.5648
    6.4352    7.8704

根据您想要实现的目标,这可能很有用。对我来说,它的优点是不需要在项目中包含另一个包,因为已经使用了scipy。

答案 2 :(得分:0)

经过大量的挖掘,我发现唯一可以复制带有抗锯齿的matlab的大小调整的解决方案是Alex (fatheral)https://github.com/fatheral/matlab_imresize的代码。目前,它仅使用双三次内核,但可以轻松扩展为Matlab提供的任何其他内核。