import cv2
import numpy as np
from PIL import Image
def imread_cn(path: str, flags=cv2.IMREAD_COLOR):
"""用 PIL 读含中文路径的图片,返回 OpenCV ndarray"""
if path is None:
raise ValueError('path 不能为 None')
pil_img = Image.open(path)
if pil_img.mode != 'RGB':
pil_img = pil_img.convert('RGB')
img = np.array(pil_img)
if flags == cv2.IMREAD_GRAYSCALE:
img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
elif flags == cv2.IMREAD_COLOR:
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
return img
def imwrite_cn(path: str, img: np.ndarray, params=None):
"""把 OpenCV ndarray 用 PIL 保存到含中文路径"""
if path is None or img is None:
raise ValueError('path 和 img 都不能为 None')
if not isinstance(img, np.ndarray):
raise TypeError('img 必须是 numpy.ndarray')
if len(img.shape) == 2:
rgb = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
else:
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(rgb)
save_kwargs = {}
if params and len(params) >= 2:
key, val = params[0], params[1]
if key == cv2.IMWRITE_JPEG_QUALITY:
save_kwargs['quality'] = val
elif key == cv2.IMWRITE_PNG_COMPRESSION:
save_kwargs['compress_level'] = val
pil_img.save(path, **save_kwargs)
return True
if __name__ == "__main__":
# 1. 读取含中文路径的图片
img = imread_cn(r'C:\测试\图片\小猫.png', cv2.IMREAD_COLOR)
print('读入成功,shape =', img.shape)
# 2. 随便做点 OpenCV 处理,例如转灰度+高斯模糊
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (15, 15), 0)
# 3. 把结果保存到新的中文路径
save_ok = imwrite_cn(r'C:\测试\结果\模糊后.jpg', blur,
[cv2.IMWRITE_JPEG_QUALITY, 90])
print('保存成功' if save_ok else '保存失败')
总结:
opencv读取和写入的时候如果遇到中文路径的问题,可以使用PIL读取或者写入图片,但是由于PIL需要的是RGB格式,而opencv需要的是BGR格式,所以用PIL读取之后需要转成BGR才能被opencv使用,而要想使用PIL写入opencv图片,则要将BGR格式的图片转为RGB。