8

I have created a NumPy array in the following way:

data = numpy.zeros((1, 15, 3), dtype = numpy.uint8)

I then filled this array with RGB pixel values, resulting in a little colour image that can be saved using a procedure such as the following:

image = Image.fromarray(data)
image.save("image.png")

How could I scale up the size of the NumPy array (without interpolation) for the purposes of creating an image that is, say, 600 x 300 pixels?

d3pd
  • 7,935
  • 24
  • 76
  • 127
  • 3
    Can you expand on what you mean by "without interpolation"? If you just want to multiply the pixels, [there are already some answers for that](http://stackoverflow.com/q/7525214/377366) on SO. Unless you are scaling by integers, there must be some interpolation involved. I'll mark this as duplicate but please let me know if you think it is different. – KobeJohn Sep 01 '15 at 17:03
  • 2
    possible duplicate of [How to "scale" a numpy array?](http://stackoverflow.com/questions/7525214/how-to-scale-a-numpy-array) – KobeJohn Sep 01 '15 at 17:03
  • Thanks for the suggestion. No, this doesn't appear to be an appropriate answer because the dimensions of the array are changed quiet a lot. The array I am dealing with features RGB values, which require an invariant dimension of 3. – d3pd Sep 01 '15 at 17:22
  • 1
    Are you sure for all the solutions? I don't have a pc to check now but I think the `repeat()` solution works even for ndim arrays like images. Also again if you need something besides integer scale factors, you will require interpolation. I'm not sure how critical that point is for you but it's probably a good idea to clarify whether you want an arbitrary final resolution or non-interpolated integer scaling. – KobeJohn Sep 01 '15 at 17:36
  • 1
    @kobejohn Oh, you're quite right. I looked only at the solution involving the Kronecker product. The repeat approach works when applied first to the first axis and then to the second (and not to the third). Thanks! – d3pd Sep 01 '15 at 17:46
  • Great! Thanks for going back to check it. – KobeJohn Sep 01 '15 at 17:47

3 Answers3

10

You can use numpy.kron as suggested in the comment or you can use the following below options

1] Using PILLOW to maintain the Aspect Ratio

  • If you want to maintain the aspect ratio of the image then you can use thumbnail() method

    from PIL import Image
    
    def scale_image(input_image_path,
                output_image_path,
                width=None,
                height=None):
        original_image = Image.open(input_image_path)
        w, h = original_image.size
        print('The original image size is {wide} wide x {height} '
              'high'.format(wide=w, height=h))
    
        if width and height:
            max_size = (width, height)
        elif width:
            max_size = (width, h)
        elif height:
            max_size = (w, height)
        else:
            # No width or height specified
            raise RuntimeError('Width or height required!')
    
        original_image.thumbnail(max_size, Image.ANTIALIAS)
        original_image.save(output_image_path)
    
        scaled_image = Image.open(output_image_path)
        width, height = scaled_image.size
        print('The scaled image size is {wide} wide x {height} '
              'high'.format(wide=width, height=height))
    
    
    if __name__ == '__main__':
         scale_image(input_image_path='caterpillar.jpg',
                     output_image_path='caterpillar_scaled.jpg',
                     width=800)
    
  • I used Image.ANTIALIAS flag which will apply a high quality down sampling filter which results in a better image

2] Using OpenCV

  • OpenCV has cv2.resize() function

    import cv2
    image = cv2.imread("image.jpg")   # when reading the image the image original size is 150x150
    print(image.shape)
    scaled_image = cv2.resize(image, (24, 24))  # when scaling we scale original image to 24x24 
    print(scaled_image.shape)
    
  • Output

    (150, 150)
    (24, 24)
    
  • cv2.resize() function also has interpolation as argument by which you can specify how you want to resize the image
  • INTERPOLATION METHODS:

    • INTER_NEAREST - a nearest-neighbor interpolation
    • INTER_LINEAR - a bilinear interpolation (used by default)
    • INTER_AREA - resampling using pixel area relation. It may be a preferred method for image decimation, as it gives moire’-free results. But when the image is zoomed, it is similar to the INTER_NEAREST method.
    • INTER_CUBIC - a bicubic interpolation over 4x4 pixel neighborhood
    • INTER_LANCZOS4 - a Lanczos interpolation over 8x8 pixel neighborhood

3] Using PILLOW library

  • Use Image.resize()

    from PIL import Image
    sourceimage= Image.open("image.jpg")   # original image of size 150x150
    resized_image = sourceimage.resize((24, 24), resample=NEAREST)  # resized image of size 24x24
    resized_image.show()
    

4] Using SK-IMAGE library

  • Use skimage.transform.resize()

    from skimage import io
    image = io.imread("image.jpg")
    print(image.shape)
    resized_image = skimage.transform.resize(image, (24, 24))
    print(resized_image.shape)
    
  • Output

    (150, 150)
    (24, 24)
    

5] Use SciPy

  • Use scipy.misc.imresize() function

    import numpy as np
    import scipy.misc
    
    image = scipy.misc.imread("image.jpg")
    print(image.shape)
    resized_image = scipy.misc.imresize(x, (24, 24))
    resized_image
    print(resized_image.shape)
    
  • Output

    (150, 150)
    (24, 24)
    
Community
  • 1
  • 1
Jai
  • 3,211
  • 2
  • 17
  • 26
  • Thanks! Using Sk-Image and SciPy directly answer the question - "scale the image stored as numpy array, while keeping the data in numpy format." – MonsieurBeilto Nov 04 '18 at 03:54
3

In scikit-image, we have transform

from skimage import transform as tf
import matplotlib.pyplot as plt
import numpy as np
data = np.random.random((1, 15, 3))*255
data = data.astype(np.uint8)
new_data = tf.resize(data, (600, 300, 3), order=0) # order=0, Nearest-neighbor interpolation
f, (ax1, ax2, ax3) = plt.subplots(1,3, figsize=(10, 10))
ax1.imshow(data)
ax2.imshow(new_data)
ax3.imshow(tf.resize(data, (600, 300, 3), order=1))

enter image description here

CT Zhu
  • 52,648
  • 17
  • 120
  • 133
0

Here's a snippet of code that resizes an image stored in a numpy array using PIL. In this example, img is a two-dimensional numpy array.

from PIL import Image
import numpy as np
nr,nc = img.shape
shrinkFactor = .5
img_pil = Image.fromarray(img)
img_pil = img_pil.resize((round(nc*shrinkFactor),round(nr*shrinkFactor)))
img_resized = np.array(img_pil)
littleO
  • 942
  • 1
  • 11
  • 26