一.问题复现
1.代码
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# File: show_img.py
import cv2
# 读取图片
img = cv2.imread("车牌素材/冀A.png")
# 显示图片
cv2.imshow("img", img)
cv2.waitKey(0)
2.报错截图
3.报错内容
[ WARN:0@0.057] global loadsave.cpp:248 cv::findDecoder imread_(‘***’): can’t open/read file: check file path/integrity
Traceback (most recent call last):
File “***”, line 7, in <module>
cv2.imshow(“img”, img)
cv2.error: OpenCV(4.9.0) D:\a\opencv-python\opencv-python\opencv\modules\highgui\src\window.cpp:971: error: (-215:Assertion failed) size.width>0 && size.height>0 in function ‘cv::imshow’
二.解决方法
1.代码
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# File: show_img_with_CNpath.py
import cv2
import numpy as np
from PIL import Image
import os
def cv_imread(file_path: str):
"""
使用PIL读取一张图片并转换成OpenCV格式, 从而支持读取中文路径的图片。
Args:
file_path (str): 图片文件的路径。这个路径可以包含中文字符, 因为PIL库能够正确处理Unicode字符串。
Returns:
np.ndarray: 转换后的OpenCV格式的图像数据, 形状为(H, W, C), 数据类型为np.uint8。
其中H代表图像的高度, W代表图像的宽度, C代表图像的通道数( 对于彩色图像通常是3 )。
OpenCV中图像的颜色通道顺序是BGR( 蓝-绿-红 ), 与PIL的RGB( 红-绿-蓝 )不同。
Raises:
IOError: 如果文件无法打开或读取, 将抛出IOError异常。
流程说明:
1. 使用PIL库的Image.open()函数打开指定路径的图片文件。PIL库能够正确处理包含中文的文件路径。
2. 将PIL图像对象转换为NumPy数组。PIL图像对象本质上是一个NumPy数组, 所以这一步是直接转换。
3. 使用OpenCV库的cvtColor()函数将图像从RGB颜色空间转换为BGR颜色空间。这是因为OpenCV默认使用BGR格式,
而PIL和其他图像处理库通常使用RGB格式。
4. 返回转换后的NumPy数组, 这个数组现在可以被OpenCV函数直接使用。
注意:
- 确保已经安装了Pillow和OpenCV库, 可以通过pip安装: `pip install Pillow opencv-python`。
- 该函数假设输入的图片是RGB格式。如果图片是灰度图或其他格式, 可能需要额外的处理步骤。
- 在使用该函数之前, 确保`cv2`和`Image`模块已经被正确导入。
"""
# 使用PIL打开图片文件
img = Image.open(file_path)
# 将PIL图像转换为NumPy数组( RGB格式 )
cv_img_rgb = np.array(img)
# 使用OpenCV将RGB格式的NumPy数组转换为BGR格式
cv_img_bgr = cv2.cvtColor(cv_img_rgb, cv2.COLOR_RGB2BGR)
# 返回转换后的BGR格式的NumPy数组
return cv_img_bgr
def cv_imwrite(file_path: str, img: cv2.typing.MatLike):
"""
使用OpenCV将图像写入指定的文件路径, 支持中文路径。
Args:
file_path (str): 要保存图像的文件路径。这个路径可以包含中文字符。
img (np.ndarray): 要保存的图像数据, 应该是一个OpenCV格式的NumPy数组, 形状为(H, W, C),
其中H是高度, W是宽度, C是通道数。数据类型应该是np.uint8。
Returns:
None
Raises:
ValueError: 如果图像数据不是NumPy数组或者数据类型不正确。
流程说明:
1. 使用os.path.splitext()函数从文件路径中提取文件扩展名。
2. 使用cv2.imencode()函数对图像进行编码。这个函数接受文件扩展名和图像数组作为参数,
并返回一个包含编码图像数据的元组。
3. 通过索引[1]获取cv2.imencode()返回的元组中的图像数据部分。
4. 使用tofile()方法将编码后的图像数据写入指定的文件路径。如果文件已存在, 将被覆盖。
注意:
- 确保已经安装了OpenCV库。
- 该函数假设输入的图像数据是OpenCV格式的NumPy数组, 并且数据类型为np.uint8。
- 如果文件路径包含中文字符, 该函数应该能够正确处理。
- 如果保存过程中发生任何错误(如文件写入权限问题), 将抛出异常。
"""
# 从文件路径中提取文件扩展名
extension = os.path.splitext(file_path)[1]
# 使用OpenCV的imencode函数对图像进行编码
# 注意: extension包括点(.), 例如 '.jpg' 而不是 'jpg'
# 编码后的图像数据将根据文件扩展名自动选择正确的格式
encoded_img = cv2.imencode(extension, img)[1]
# 将编码后的图像数据写入文件
encoded_img.tofile(file_path)
# 读取图片
img = cv_imread("车牌素材/冀A.png")
# 显示图片
cv2.imshow("img", img)
cv2.waitKey(0)
# 保存图片
cv_imwrite("车牌素材/冀A_保存.png", img)
三.其他
使用cv2.imdecode()
配合np.fromfile()
并不能读取中文路径的图片,但是使用cv2.imencode()
可以保存图片