我将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);
这两段代码会返回不同的结果。
答案 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
这里做了什么,但我打赌没有启用抗锯齿功能。
正如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提供的任何其他内核。