在 OpenCV 中,由于编码的缘故,对于中文的处理并不是很友好,比如中文路径的图片读取和写入以及在图片上绘制中文文字等,这几个问题都是笔者经常遇到的,本文列出这几个问题的解决办法,希望能够帮助到大家。

读取中文路径的图片

首先是中文路径的读取

一般我们使用 cv2.imread 进行图片的读取,但是一遇到中文,就会出现错误,如下:

  1. import cv2
  2. image = cv2.imread("F:\莫山山.jpg")
  3. print(image)
  4. cv2.imshow("image", image)
  5. cv2.waitKey(0)
  6. cv2.destroyAllWindows()

image.png

解决的方法如下:
我们借助 np.fromfilecv2.imdecode 来实现中文路径的读取

  1. import cv2
  2. import numpy as np
  3. image = cv2.imdecode(np.fromfile(file="F:\莫山山.jpg", dtype=np.uint8), cv2.IMREAD_COLOR)
  4. # print(image)
  5. cv2.imshow("image", image)
  6. cv2.waitKey(0)
  7. cv2.destroyAllWindows()

image.png

其中 np.fromfile 代表的含义是从文本或者二进制文件构造 array,参数:file 是文件名,参数dtype 是数据类型,因为是图像,所以我们使用 np.uint8 格式

其中 np.fromfile 有个 shape 属性,其值是文件的字节数
image.png**

cv2.imdecode 的含义是从内存中的指定缓冲区读取图像,参数:buf 就是数据缓存了,即上面 np.fromfile 得到的内容,参数:flag 见下图,即读取什么样的图片(彩色、灰度等)
image.png
参考:https://vovkos.github.io/doxyrest-showcase/opencv/sphinx_rtd_theme/enum_cv_ImreadModes.html

保存中文路径的图片

既然有读取,那就有写入中文路径图片的需求
通常我们使用的是 cv2.imwrite 保存图片,但是遇见中文路径时,就会出现编码错误或者保存失败(我在不同的电脑上进行过测试,如果保存成功了,得到的文件名会是乱码)

  1. import cv2
  2. import numpy as np
  3. path = "F:/莫山山.jpg"
  4. image = cv2.imdecode(np.fromfile(file=path, dtype=np.uint8), cv2.IMREAD_COLOR)
  5. cv2.imwrite("F:/莫山山2.jpg", image)

解决方法如下:
上面我们读取用的是 imdecode 那么写入自然是 imencode

  1. import cv2
  2. import numpy as np
  3. path = r"F:\莫山山.jpg"
  4. image = cv2.imdecode(np.fromfile(file=path, dtype=np.uint8), cv2.IMREAD_COLOR)
  5. dst = r"F:/莫山山2.jpg"
  6. cv2.imencode(ext='.jpg', img=image)[1].tofile(dst)

cv2.imencode 中的参数:ext 是图片的扩展名,参数:img 就是 array 矩阵了

单独运行 cv2.imencode('.jpg', image) 得到的是一个元组(2部分,第二部分才是 array),所以上面程序中有一个取
[1] ** 的操作
image.png

在图像中绘制中文文字

OpenCV 处理中另外一个中文会出现问题是在图上绘制中文文字,要想在图片上绘制文字,我们一般使用的是 cv2.putText() 函数,一个示例如下:

  1. import cv2
  2. import numpy as np
  3. path = r"F:\莫山山.jpg"
  4. image = cv2.imdecode(np.fromfile(file=path, dtype=np.uint8), cv2.IMREAD_COLOR)
  5. dst = r"F:/莫山山2.jpg"
  6. font = cv2.FONT_HERSHEY_SIMPLEX # 指定字体
  7. cv2.putText(image, 'Person', (60, 60), font, 2, (20, 20, 255), 2, cv2.LINE_AA) # 绘制的图像,文字,文字左下角的坐标,字体,字体颜色,厚度等
  8. cv2.imshow("image", image)
  9. cv2.waitKey(0)
  10. cv2.destroyAllWindows()

绘制英文文字一般没什么问题
image.png
但是一到绘制中文文字时,小朋友你是否会有很多问号?????
image.png

OpenCV 内置的函数不能帮助我们解决这个问题,我们需要借助另外一个库 PIL(pillow)
不过实现起来会稍微有点麻烦

  1. import cv2
  2. from PIL import Image, ImageDraw, ImageFont
  3. import numpy as np
  4. path = r"F:\莫山山.jpg"
  5. image = cv2.imdecode(np.fromfile(file=path, dtype=np.uint8), cv2.IMREAD_COLOR)
  6. font = ImageFont.truetype('STZHONGS.TTF', 40) # 字体设置,Windows系统可以在 "C:\Windows\Fonts" 下查找
  7. img_PIL = Image.fromarray(image[..., ::-1]) # 转成 PIL 格式
  8. draw = ImageDraw.Draw(img_PIL) # 创建绘制对象
  9. draw.text(xy=(60, 60), text="莫山山", font=font, fill=(255, 0, 0))
  10. image = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR) # 再转成 OpenCV 的格式,记住 OpenCV 中通道排布是 BGR
  11. cv2.imshow("image", image)
  12. cv2.waitKey(0)
  13. cv2.destroyAllWindows()

image.png
OpenCV图像处理:中文路径读存取和图像绘制中文文字.md