为什么要将OpenCV帧转换为PIL图像
根本原因:字符编码和字体支持
cv2.putText(frame, "中文测试", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,255,255), 2)
# 结果:显示为方框 □□□□
OpenCV的问题:
内置字体限制: OpenCV只有7种内置英文字体(FONT_HERSHEY_*系列)
不支持Unicode: 无法正确渲染中文、日文、韩文等Unicode字符
无法加载外部字体: 不能使用系统TrueType字体(.ttf/.ttc)
字符编码问题: 对非ASCII字符处理有限
PIL/Pillow的优势
font = ImageFont.truetype("C:/Windows/Fonts/msyh.ttc", 24) # 微软雅黑
draw.text((x, y), "中文测试", font=font, fill=(255,255,255))
# 结果:完美显示 中文测试
PIL的优势:
TrueType字体支持: 可以加载系统中任何.ttf/.ttc字体文件
完整Unicode支持: 原生支持所有Unicode字符集
字体回退机制: 当某个字符不存在时,会尝试使用其他字体
更好的文本渲染: 支持抗锯齿、字距调整等高级特性
转换流程详解
# 1. OpenCV使用BGR色彩空间
frame = cv2.imread("video_frame.jpg") # BGR格式# 2. PIL使用RGB色彩空间
frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 转换色彩空间
pil_image = Image.fromarray(frame_rgb) # 转换为PIL图像# 3. 使用PIL进行文字渲染
draw = ImageDraw.Draw(pil_image)
font = ImageFont.truetype("msyh.ttc", 24) # 加载中文字体
draw.text((x, y), "中文文字", font=font, fill=(255,255,255))# 4. 转换回OpenCV格式
frame_with_text = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
性能对比 | ||
方面 | OpenCV | PIL转换方案 |
中文支持 | ❌ 不支持 | 完美支持 |
字体选择 | 7种内置 | 系统所有字体 |
渲染质量 | 基础 | 高质量抗锯齿 |
性能开销 | 最快 | 轻微开销 |
内存使用 | 最少 | 略微增加 |
为什么不直接用PIL处理整个视频?
虽然PIL支持中文,但OpenCV在视频处理方面有巨大优势:
# OpenCV的视频处理优势
cap = cv2.VideoCapture("video.mp4") # 硬件加速解码
ret, frame = cap.read() # 高效帧读取
cv2.VideoWriter("output.mp4", fourcc, fps, size) # 硬件加速编码
所以最佳方案是:
视频处理: 使用OpenCV(性能最优)
文字渲染: 使用PIL(中文支持最佳)
格式转换: 只在需要添加文字时转换
总结
这种"混合方案"是目前处理中文视频字幕的标准做法:
保持OpenCV的视频处理优势
借用PIL的字体渲染能力
最小化性能开销(只在添加文字时转换)
获得最佳的中文显示效果