如何使用OpenCV在图片上绘制汉字
目前我的项目使用OpenCV来处理图片,绘制一些信息,然后通过ffmpeg推送视频帧。因为这是一个实时推送的视频流,所以每一帧的处理速度必须很快。如果处理速度慢,就会导致视频流中掉帧。经过排查,发现最耗时的过程是绘制中文字符。由于OpenCV不支持绘制中文字符,我每次绘制时都要用Pillow来转换图像格式,然后在绘制完后再把Pillow的图像转换回numpy格式。以下是绘制中文字符的关键代码步骤:
cv2_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
pil_img = Image.fromarray(cv2_img)
draw = ImageDraw.Draw(pil_img)
font = ImageFont.truetype("simhei.ttf", 15, encoding="utf-8")
delta_y = 20
draw.text((x, y + delta_y), f"中文xxxxx", (255, 255, 255), font=font)
img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
以下是已知有效的解决方案:
- 所有绘制都使用Pillow完成(包括绘制矩形框、线段等)。
- 编译包含freetype模块的OpenCV包。编译包含freetype模块的OpenCV包。
- 对于我提出的这两个解决方案,由于一些复杂的原因,处理起来可能不是很简单:
- 代码中的绘制是交叉绘制,OpenCV -> Pillow -> OpenCV...... 如果完全使用Pillow来绘制,改动的量会更大。
- 我正在编译带有freetype模块的OpenCV-python,但即使编译成功,也会遇到一些跨平台移植、跨版本使用等一系列问题,这些问题只能通过重新编译来解决,而这个程序目前只是作为备用方案。
当然还有其他解决方案,如果有程序能满足我对高处理速度的要求,欢迎大佬们提供参考。
1 个回答
0
你的问题有几个方面我不太明白,所以我这里有一些一般性的想法:
- 如果性能是个问题,你一定要先分析一下你的代码,这样才能避免浪费时间去优化那些并不重要的部分。
- 如果你只是想在视频的某几个角落加注释,没必要把整个视频画面都转换成
PIL.Image
,你可以只处理那些角落。 - 如果你选择在一个纯黑的背景上加注释,也不一定要把OpenCV的画面传给PIL。
- 你不需要为每一帧都创建一个新的
PIL.Image
,可以在视频开始时创建一个,然后在每一帧开始时把它填充成黑色,再在上面绘制文字,这样就不需要为每一帧都创建新的绘图环境了。 - 你不需要把颜色从BGR转成RGB再转回BGR,你可以直接用BGR颜色来绘制。
- 你只需要在视频开始时获取一次字体,而不是每一帧都获取。