【OpenCV&PIL】彻底解决图像绘制文本出现中文乱码的问题

32 阅读2分钟

前言

OpenCV自身不支持中文字符渲染,导致在图像上绘制中文文本时出现乱码。可通过PIL的ImageDraw配合中文字体文件绘制文本,再将PIL图像转换为OpenCV格式,确保在任何环境下都能正确显示中文,完美解决中文乱码问题。

一、解决思路

  1. 使用 PIL.ImageFont.truetype(“simhei.ttf”, size) 加载字体。
  2. 用PIL的 ImageDraw.Draw().text() 绘制中文。
  3. 通过 np.array(pil_image) 和 cv2.cvtColor 将PIL图像转换为OpenCV可用的BGR格式。

二、获取中文字体文件

simhei.ttf字库文件是系统最原始的黑体字体,兼容性非常好,不管是win7还是win10、win11里面都可以使用的。常用于需要显示中文的场景,特别是在matplotlib等Python绘图库中显示中文时需要配置支持中文的字体文件。

image.png

三、代码实现

代码如下:

import os
import cv2
import numpy as np
from PIL import Image, ImageDraw, ImageFont

font = None
font_size = 40     # 统一字体大小

font_path = "./simhei.ttf"
try:
    font = ImageFont.truetype(font_path, font_size)
    print(f"成功加载字体:{font_path}")
except Exception as e:
    print(f"加载字体 {font_path} 失败: {e}")

# 确保font是ImageFont对象
if not isinstance(font, (ImageFont.FreeTypeFont, ImageFont.ImageFont)):
    raise TypeError(f"font必须是ImageFont对象,当前类型:{type(font)}")
    
img = cv2.imread("test.jpg")
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(img_rgb)
draw = ImageDraw.Draw(pil_img)
img_width, img_height = pil_img.size
color=(255, 255, 0)

text = "OpenCV 中文文本绘制功能!!!"
# 使用self.font(ImageFont对象)而非其他字符串变量
text_bbox = draw.textbbox((0, 0), text, font=font)
text_width = text_bbox[2] - text_bbox[0]
text_height = text_bbox[3] - text_bbox[1]
x = (img_width - text_width) // 2
y = (img_height - text_height) // 2

# 转换BGR颜色为RGB(OpenCV用BGR,PIL用RGB)
rgb_color = (color[2], color[1], color[0])
draw.text((x, y), text, font=font, fill=rgb_color)

# 转换回OpenCV的BGR格式
img_bgr = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)

cv2.imwrite("res.jpg", img_bgr)

确保simhei.ttf字库文件存在,在linux操作系统下同样适用,绘制效果如下:

image.png

总结

这种"PIL渲染 + OpenCV处理"的组合方案,不仅解决了中文乱码问题,还带来了更好的文本渲染效果和更大的灵活性。无论是图像标注、数据可视化还是视频处理,都能获得完美的中文显示效果。