user3960019 user3960019 - 20 days ago 10
Python Question

How to use Matlab's imresize in python

I'm transferring Matlab's

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

How to get the same results as Matlab by python.

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


These two pieces of code return different results.

Answer

The scipy.misc.imresize function 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.imresize call 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):

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 scales the 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 imresize does not do this and it resizes an image in the way we expect:

>> 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.resize does here but I'll bet that there is no anti-aliasing enabled.

As such, I probably would not use scipy.misc.imresize. The closest thing to what you want is either OpenCV's resize function, or scikit-image's resize function. Both of these have no anti-aliasing. If you want to make both Python and MATLAB match each other, use the bilinear interpolation method. imresize 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. See this post for some more informative results:

MATLAB vs C++ vs OpenCV - imresize

For the best results, don't specify a scale - specify a target output size to reproduce results. 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.

As such, 1/scale in your case is close to a 2 x 2 size output, and so here's what you would do in 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

With 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:

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