How do I convert a PIL Image into a NumPy array?
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.
Introduction
To convert a PIL (Pillow) image into a NumPy array, use numpy.array(image) or numpy.asarray(image). The resulting array has shape (height, width, channels) for color images and (height, width) for grayscale. np.array() creates a writable copy, while np.asarray() creates a read-only view when possible. To convert back, use Image.fromarray(array). This conversion is essential for image processing with libraries like OpenCV, scikit-image, TensorFlow, and PyTorch.
Basic Conversion
Array Shape by Image Mode
Different PIL image modes produce different array shapes:
| PIL Mode | Channels | Array Shape | Dtype |
L (grayscale) | 1 | (H, W) | uint8 |
RGB | 3 | (H, W, 3) | uint8 |
RGBA | 4 | (H, W, 4) | uint8 |
1 (binary) | 1 | (H, W) | bool |
F (float) | 1 | (H, W) | float32 |
I (32-bit int) | 1 | (H, W) | int32 |
np.array vs np.asarray
Use np.array() when you plan to modify pixel values. Use np.asarray() when you only need to read, as it avoids an unnecessary memory copy.
Converting Back: NumPy to PIL
Handling Float Arrays
Working with OpenCV
OpenCV uses BGR channel order while PIL uses RGB:
Working with TensorFlow/PyTorch
Pixel Manipulation Examples
Common Pitfalls
- Forgetting that PIL uses RGB while OpenCV uses BGR: Passing a PIL-converted array directly to OpenCV functions produces wrong colors (red and blue swapped). Always use
cv2.cvtColor()to convert between RGB and BGR. - Modifying a read-only
np.asarrayresult:np.asarray(img)may return a read-only array. Attempting to modify pixels raisesValueError: assignment destination is read-only. Usenp.array(img)or.copy()when you need to modify values. - Passing float arrays to
Image.fromarraywithout converting to uint8:Image.fromarrayexpectsuint8arrays (0-255) for RGB images. Passing a float array (0.0-1.0) produces garbage output. Multiply by 255 and cast with.astype(np.uint8)first. - Confusing (height, width) axis order with (width, height): NumPy arrays store images as
(height, width, channels)— rows first, columns second. PIL'sImage.sizereturns(width, height). This mismatch causes confusion when resizing or creating new images. - Not converting image mode before array conversion: A palette image (mode
P) or CMYK image produces unexpected array shapes. Always call.convert("RGB")or.convert("L")before converting to ensure a predictable array shape.
Summary
np.array(img)converts a PIL image to a writable NumPy arraynp.asarray(img)creates a read-only view (more memory efficient for reading)- RGB images produce
(H, W, 3)arrays; grayscale produces(H, W) - Convert back with
Image.fromarray(arr)— ensureuint8dtype for RGB images - Use
cv2.cvtColor()when bridging between PIL (RGB) and OpenCV (BGR)
Related reading
- How do I convert new data into the PCA components of my training data?
- How do I count occurrence of unique values inside a list
- How do I count the NaN values in a column in pandas DataFrame?
- How do I count the NaN values in a column in pandas DataFrame?
- How do I convert a string to a double in Python?
- How do I convert all of the items in a list to floats?
- How do I count the occurrence of a certain item in an ndarray?
- How do I count the occurrences of a list item?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
ML System Design practice on Codemia
Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.