3

I am reading images with Image.open() and converting them into an ndarray using np.asarray(). I also need bounding boxes; for that I'm using Image.getbbox() when importing images and ndarray.shape later in the code.

I need to reconcile the usual Width-Height coordinate order of the images and the Height-Width order of arrays. Should I transpose the array after np.asarray(image) for preserving Width-Height ordering, or asarray takes care of that?

1 Answer 1

2

No, it does not. The way PIL and numpy deals with images is different. Reason being that PIL uses column-major scheme for storing data, on the other hand numpy uses row-major.

So in order to create a column-major equivalent of the matrix in numpy, we have to swap the two dimensions.

img = Image.open(r"image_path")

arr = np.asarray(img)

arr = arr.transpose((1, 0, 2))

The above code transposes the dimensions of images having color channels > 1 (RGB, LA, PA, RGBA etc). If the image has a single channel (L, 1, I etc) then use:-

arr = arr.transpose((1, 0))

instead.

Sign up to request clarification or add additional context in comments.

6 Comments

I think PIL actually uses "row major" storage.
@MarkSetchell Actually, It does not!!! Here's why. In order to understand why PIL uses column major ordering scheme, we need to first know about orders, or how they are found. In imaging ordering could be defined in layman's terms as which axis is at the first index. Where axis could be x (horizontal axis) or y (vertical axis). In imaging when we say an image is (1920, 1080) it means that the image contains 1920 columns and 1080 rows (y, x) (generally columns are more then the number of rows).
When we try to open a (1920, 1080) in PIL using Image.open() we get Image.size (1920, 1080). But when we try to open the same image using numpy or cv2 (both use numpy arrays for storing image data) via cv2.imread() etc. and then find it's dimensions (using shape) we get (1080, 1920). This states that numpy uses row major. Why? Because the number of rows (1080 in this case) is at the first index.
The order of the indices tells you the "access ordering" which is not the same as the "storage ordering". PIL/Pillow is based on its C core routines and C uses row major ordering. If you load a 4-column by 2-row image with known values and dump it using Image.tobytes() you will see that it gives you the pixels in the first row followed by the pixels in the second row, i.e. row major storage.
@MarkSetchell Well, I won't put a string on your claim, as currently i am unaware of how is pixel data stored? So probably you would be right on that. What i was trying to convey via the means of this answer, is the fact that numpy and PIL uses different ordering scheme for accessing pixel data when opening images. Which results in swapped dimensions when transitioned from one library to the other.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.