如何在python中使用Matlab的imresize

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29958670/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 05:13:25  来源:igfitidea点击:

How to use Matlab's imresize in python

pythonimagematlabimage-processingscipy

提问by user3960019

I'm transferring Matlab's imresizecode into python. I found the scipy's imresize, but I get a different results from Matlab.

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

How to get the same results as Matlab by python.

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

Python/scipy imresize

蟒蛇/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

MATLAB imresize

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

These two pieces of code return different results.

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

采纳答案by rayryeng

The scipy.misc.imresizefunction is a bit odd for me. For one thing, this is what happens when I specify the sample 2D image you provided to a scipy.misc.imresizecall on this image with a scale of 1.0. Ideally, it should give you the same image, but what we get is this (in IPython):

这个scipy.misc.imresize功能对我来说有点奇怪。一方面,当我指定您提供给scipy.misc.imresize此图像的调用的示例 2D 图像时会发生这种情况,比例为 1.0。理想情况下,它应该给你相同的图像,但我们得到的是这个(在 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)

Not only does it change the type of the output to uint8, but it scalesthe values as well. For one thing, it looks like it makes the maximum value of the image equal to 255 and the minimum value equal to 0. MATLAB's imresizedoes not do this and it resizes an image in the way we expect:

它不仅将输出的类型更改为uint8,而且 还会缩放值。一方面,看起来它使图像的最大值等于 255,最小值等于 0。MATLABimresize不会这样做,它以我们期望的方式调整图像大小:

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

out =

     1     2     3
     4     5     6
     7     8     9

However, you need to be cognizant that MATLAB performs the resizing with anti-aliasing enabled by default. I'm not sure what scipy.misc.resizedoes here but I'll bet that there is no anti-aliasing enabled.

但是,您需要意识到 MATLAB 在默认启用抗锯齿的情况下执行调整大小。我不确定scipy.misc.resize这里有什么,但我敢打赌没有启用抗锯齿。

Edit - November 23rd, 2016

编辑 - 2016 年 11 月 23 日

As noted by Eric in his comments below, if you pre-cast the image to the desired type, you will get the expected results:

正如埃里克在下面的评论中所指出的,如果您将图像预先转换为所需的类型,您将获得预期的结果:

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)

We can see that the image is not scaled to the [0,255]range. To finally get where you need to go, we must obtain a floating-point representation of the image. scipy.misc.imresizehas an additional flag called 'mode'and you can specify this as 'F'to ensure the output is floating point.

我们可以看到图像没有缩放到[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)


As you will see later, the results that you see with scipy.misc.resizedon't match with what you see in MATLAB.

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

For the best results, don't specify a scale - specify a target output size to reproduce results. As such, 1/scalein your case is close to a 2 x 2size output, and so here's what you would do in 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

You can see that some of the values in the matrix don't align with scipy.misc.resize. To match what you see in MATLAB. The closest thing to what you want is either OpenCV's resizefunction, or scikit-image's resizefunction. Both of these have no anti-aliasing. If you want to make both Python and MATLAB match each other, use the bilinear interpolation method. imresizein MATLAB uses bicubic interpolation by default and I know for a fact that MATLAB uses custom kernels to do so, and so it will be much more difficult to match their outputs if you use bicubic interpolation between the methods. See this post for some more informative results:

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

MATLAB vs C++ vs OpenCV - imresize

MATLAB vs C++ vs OpenCV - imresize

With Python OpenCV:

使用 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. ]])

With scikit-image:

使用 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. ]])

One last interesting thing to note is that MATLAB, OpenCV and scikit-image when specifying a floating point scale act differently with each other. I did some experiments and by specifying a floating point size, I was unable to get the results to match. Besides which, scikit-image does not support taking in a scale factor which is more reason to explicitly state an output size rather than a scale.

需要注意的最后一件有趣的事情是,MATLAB、OpenCV 和 scikit-image 在指定浮点比例时彼此之间的行为不同。我做了一些实验,通过指定一个浮点大小,我无法得到匹配的结果。除此之外,scikit-image 不支持采用比例因子,这更有理由明确说明输出大小而不是比例。

回答by kratenko

To add one more option I found, while exploring the excellent answer by @rayryeng.

在探索@rayryeng出色答案的同时,再添加一个我发现的选项。

The scipy.misc.imresizeuses PIL (and hence converts the image to scaled integers). But the page links to another function: scipy.ndimage.zoom

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]])

It does not give me the same result as matlab, but it comes close:

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

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

ans =
    2.1296    3.5648
    6.4352    7.8704

Depending on what you want to achieve, this could be useful. For me it has the advantage of not needing to include another package to the project, since scipy is already used.

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

回答by Vik

After a lot of digging, the only solution that I found which replicates matlab's imresize with anti-aliasing is the code by Alex (fatheral)at https://github.com/fatheral/matlab_imresize. Currently it only uses the bicubic kernel, but can be easily expanded to any other kernel provided in Matlab.

经过大量挖掘,我发现唯一可以通过抗锯齿复制 matlab 的 imresize 的解决方案是Alex(fatheral)https://github.com/fatheral/matlab_imresize的代码。目前它只使用双三次内核,但可以很容易地扩展到 Matlab 中提供的任何其他内核。