Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resize all images stored in array

I stored images read through cv2.imread in an array masks. The shape of the array is (10, 5248, 7936, 3) (10 images, image height, image width, 3 channels).

I am now trying to copy this array but with every image resized to the values monitor_h and monitor_w. Here is what I have:

resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])

for i in range(masks.shape[0]):
    resized_masks[i] = cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h))

But the images I get from cv2.imshow are black and white. Something must have happened with the channels. Any leads?

like image 872
Nawra C Avatar asked Dec 06 '25 12:12

Nawra C


1 Answers

To see why your images are coming out black and white, let's step through the code.

resized_masks = np.empty([masks.shape[0], monitor_h, monitor_w, masks.shape[3]])

This line creates an array of type np.float by default.

resized_masks[i] = cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h))

This line assigns the result of cv2.resize to a slice of resized_masks.

Your original images, and therefore the result of cv2.resize, are presumably of type np.uint8. The assignment casts the values into floats to put them in the buffer. The cast is fine in and of itself: 5 converts to 5.0, 255 converts to 255.0. The problem is that float values are interpreted as being clipped to the range [0.0, 1.0], not [0.0, 255.0]. You therefore end up with images that are effectively all zeros and ones, even though they contain what looks like the correct values.

You can verify that the values are correct by displaying

resized_masks.astype(masks.dtype)

This is not a real fix. The real fix is to start with the correct output type:

resized_masks = np.empty((masks.shape[0], monitor_h, monitor_w, masks.shape[3]), dtype=masks.dtype)

Note that it's conventional to use tuples for shapes, not lists, but it doesn't matter functionally.

Now let's look at why your patch worked.

resized_masks = list(resized_masks)

This creates a Python list of references to each sub-array. Since you are really slicing, they will still point to a contiguous buffer under the hood, but the important thing is that each resized_masks[i] is a separate reference, not a slice into the same array object.

resized_masks[i] = list(cv2.resize(np.copy(masks[i]), (monitor_w, monitor_h)))

Since resized_masks is a list containing references, this is now assigning the result of cv2.resize to the ith list element, not assigning the contents into an appropriately sized slice. You don't need the list wrapper here, as it introduces an unnecessary dimension.

resized_masks = np.asarray(resized_masks)

This just recombines the list into an array, since all the elements are of the right size (although you will see an extra unit dimension, as mentioned above). As you can imagine this solution is extremely inefficient. On top of the fact that you are going to and from lists and allocating multiple unnecessary buffers, you are also discarding the original np.empty array without using it.

Your patch is roughly equivalent to doing

resized_masks = np.array([cv2.resize(np.copy(mask), (monitor_w, monitor_h)) for mask in masks])

I don't recommend doing it like that.

like image 95
Mad Physicist Avatar answered Dec 09 '25 00:12

Mad Physicist



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!