The other day, when I was using OpenCV to read some images and print the image shape, I got an error:

‘NoneType’ object has no attribute ‘shape’.

I was confused and do not know why since the image path is valid. It tooks me a while to understand the cause.

The reason is that OpenCV only accepts ASCII characters for image paths when reading and writing images. There is an open PR to add Unicode path support, but it has not been merged. However, there are ways to work around this issue.

Read images with unicode paths

First, we can read the image with the help of Numpy fromfile() method, and then use cv2.imdecode() to read the image. Here is a sample code:

import numpy as np
import cv2

# img with unicode path
im_path = "测试目录/test.jpg"
# img is in BGR format if the underlying image is a color image
img = cv2.imdecode(np.fromfile(im_path, dtype=np.uint8),
                   cv2.IMREAD_UNCHANGED)

In the above script, the image is read with numpy and converted to a one-dimensional numpy ndarray of type np.uint8. Then we use imdecode() to decode the ndarray to OpenCV image format. cv2.IMREAD_UNCHANGED is a flag for imdecode1.

Write images with unicode paths

To write images with unicode paths, we can first encode the image in OpenCV format to one dimension numpy ndarray format. Then we convert this numpy ndarray to image on disk with the tofile() method.

import cv2
import numpy as np

img = cv2.imread("test.jpg", 1)
h, w = img.shape[:2]
im_resize = cv2.resize(img, (w//2, h//2))

im_save_path = "测试目录/small_img.jpg"
# encode the im_resize into the im_buf_arr, which is a one-dimensional ndarray
is_success, im_buf_arr = cv2.imencode(".jpg", im_resize)
im_buf_arr.tofile(im_save_path)

In the above code, cv2.imencode() will encode the image as a one-dimension numpy array and tofile() will save this array into disk.

References


  1. The complete list of flags available and their description can be found here. ↩︎