Search code examples
pythonscipypython-imaging-libraryimage-resizing

Nearest neighbor image resizing wrong using scipy and PIL


I'm trying to take a small image and make a large ("pixelated") version of it using Python. I've tried using the nearest neighbor resizing methods in both scipy and PIL.Image and both output the same wrong result. Here's an example when trying to upsample an image by a factor of 3:

import numpy as np
from scipy.misc import imresize
from PIL import Image

img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.uint8)
img_nn_scipy = imresize(img, (9, 9), interp='nearest')
img_nn_pil   = np.array(Image.fromarray(img).resize((9, 9), Image.NEAREST))

print img_nn_scipy
print img_nn_pil

Both print statements output the same result:

[[1 1 1 2 2 2 2 3 3]
 [1 1 1 2 2 2 2 3 3]
 [1 1 1 2 2 2 2 3 3]
 [4 4 4 5 5 5 5 6 6]
 [4 4 4 5 5 5 5 6 6]
 [4 4 4 5 5 5 5 6 6]
 [4 4 4 5 5 5 5 6 6]
 [7 7 7 8 8 8 8 9 9]
 [7 7 7 8 8 8 8 9 9]]

I expected that each number in the original image would now be replaced by a 3x3 block all containing the same value. Instead, the blocks have varying sizes, and only the 1 block is 3x3.

Is there a reason for this? Is there a way to reasonably solve this in Python?

Thanks!


Solution

  • Try the latest Pillow instead of PIL.

    In [1]: import numpy as np
       ...: from PIL import Image
       ...: 
    
    In [2]: img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.uint8)
    
    In [3]: img_nn_pil   = np.array(Image.fromarray(img).resize((9, 9), Image.NEAREST))
    
    In [4]: print img_nn_pil
    [[1 1 1 2 2 2 3 3 3]
     [1 1 1 2 2 2 3 3 3]
     [1 1 1 2 2 2 3 3 3]
     [4 4 4 5 5 5 6 6 6]
     [4 4 4 5 5 5 6 6 6]
     [4 4 4 5 5 5 6 6 6]
     [7 7 7 8 8 8 9 9 9]
     [7 7 7 8 8 8 9 9 9]
     [7 7 7 8 8 8 9 9 9]]
    

    This was just a bug that was fixed.