Reputation: 60
So, I have the following code for resizing an image using nearest neighbor interpolation. The solution seems straightforward to me using 2 for loops, but I can't think of any way to do this while taking advantage of numpy to avoid those pesky loops. Here is my code:
def scale(img, factor):
# Calculate new image shape and create new image with it.
height, width = img.shape[:2]
new_height, new_width = (int(height * factor), int(width * factor))[:2]
scaled_img = np.zeros([new_height, new_width])
# Iterate over all pixels and set their values based on the input image.
for x in range(new_height):
for y in range(new_width):
scaled_img[x, y] = img[int(x / factor), int(y / factor)]
return scaled_img
Any input on how to avoid the for loops?
Upvotes: 0
Views: 155
Reputation: 3394
While the first answer is really great from a "how do I do this in numpy" point of view, I'd second Nils L's answer: if what you're wanting to do is resize an image, then you're likely much better off using one of the image processing libraries.
Pillow works well, as does ndimage: http://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.zoom.html#scipy.ndimage.zoom
Both will likely be faster than numpy, and also give you a lot more options in the details of how you want the resizing to work, and let you do different interpolation methods if that's what you need.
Upvotes: 0
Reputation: 2719
You can calculate the mapping of indices of new image to old indices and then use numpy.ix_ to unite them
import numpy as np
def scale(img, factor):
"""
>>> img = np.arange(9).reshape(3, 3)
>>> print(img)
[[0 1 2]
[3 4 5]
[6 7 8]]
>>> print(scale(img, 1.67))
[[0 0 1 1 2]
[0 0 1 1 2]
[3 3 4 4 5]
[3 3 4 4 5]
[6 6 7 7 8]]
"""
x_indices = (np.arange(int(img.shape[1] * factor)) / factor).astype(int) # [0 0 1 1 2]
y_indices = (np.arange(int(img.shape[0] * factor)) / factor).astype(int)
return img[np.ix_(y_indices, x_indices)]
Upvotes: 2