因为opencv不能显示中文(会变成???),所以尝试通过opencv->pillow->opencv这种方式来实现,具体可参考这篇博客。
下面来简述一下使用情况:
# opencv-> pillow
cv2img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
pilimg = Image.fromarray(cv2img)
'''
进行一些操作
'''
# pillow -> opencv
cv2charimg = cv2.cvtColor(np.array(pilimg), cv2.COLOR_RGB2BGR)
可以显示中文了!
经过在主机上(cpu:12700F)测试
opencv与pil互转需要 2-3 ms,pil画图(目标检测的可视化,包括bbox绘制,文本输出)需要 10+ ms,算下来一帧的图像处理就在 15+ ms了,在我的主机上速度尚且可以,但是在agx上一帧的图像处理速度在 60+ ms了,达不到实时性要求。
后来,发现了一个好东西——pillow-smid,专门用来加速pillow的库,安装比较简单,见这篇博客,需要注意的是需要先卸载pillow再安装pillow-smid。在我的主机上安装十分顺利,但是在agx上pip安装会报错,具体错误如这个所示,总之就是编译错误。不过github上并没有回复,因此需要自行解决,可见本文最后部分。
——————————————————————————————————————————
pillow-smid的使用方法和pillow一模一样,原先的代码不用变。
加速效果(仅plot部分):
pillow | pillow-smid | opencv | |
---|---|---|---|
主机 | 10+ ms | 3~4 ms | 2~3 ms |
agx | 40++ ms | 21 ms左右 | 6~8 ms |
虽然整体速度还是不如opencv,而且还需要opencv和pil互转花费额外的时间,但至少解决了中文乱码的问题,在agx上也能保证一帧15fps以上,基本满足使用要求。
如果是在ros中的项目,通过cv_bridge来收发图片,则可以省去opencv的bgr编码与pillow的rgb编码互转步骤,还可以节省少量时间(时间就是慢慢挤出来的,因此发现互转耗费时间的是numpy和Image之间type的互转)。
# numpy -> pillow
pilimg = Image.fromarray(image)
# pillow -> numpy
npimg = np.array(pilimg)
注意:虽然pillow的图片编码只支持RGB的,但是采用这种办法的图片编码取决于cv_bridge的编码,如果你接收的是BGR格式的图片,那么按照这样的处理,在plot的前中后都是BGR编码的,一定注意通道的顺序,这么做只是为了少一步通道顺序变换。虽然听起来很拗口,但是就是这么NTR,相当于把pillow当opencv用了~
注意:pillow 需要提前定义画布、字体样式
from PIL import Image, ImageDraw, ImageFont
# 画布定义
draw = ImageDraw.Draw(pilimg)
# 字体样式,这步非常消耗时间,建议放在循环外面,只执行一次
font = ImageFont.truetype(font_path, 22, encoding="utf-8")
(1) 画boundbingbox
只画线框
# pillow
# “width=”需要 pillow >= 5.3.0, pillow-smid的版本与pillow的版本不一定一致,
# 比如我用源码安装的pillow-smid-7.0.0,但是里面的pil是5.1.0版本
draw.rectangle((c1,c2),fill=None,outline=color1,width=line_thickness)
# 低版本pillow替代方法,实现对线宽的控制
draw.line([(x1,y1),(x2,y1),(x2,y2),(x1,y2),(x1,y1)], width=line_thickness, fill=color1)
# opencv
cv2.rectangle(image,(x1,y1),(x2,y2),color1,thickness=tl, lineType=cv2.LINE_AA)
画实心框
# pillow
draw.rectangle((c1,c2),fill=color1,outline=None)
# opencv
cv2.rectangle(image, c1, c2, color1, cv2.FILLED)
# 或者
cv2.rectangle(image, c1, c2, color1,thickness=-1, lineType=cv2.LINE_AA)
(2) 展示文本
# pillow
draw.text((x1,y1),txt2,color1,font=font)
# opencv
cv2.putText(image, txt2, (x1,y1), 0, tl/3, color1,
thickness=tf, lineType=cv2.LINE_AA)
(3) 获取文本长度
# pillow
t_size = font.getsize(txt2)
# opencv
t_size = cv2.getTextSize(txt2, 0, fontScale=tf, thickness=tf)[0]
注意:pillow和opencv的区别
windows可以直接下载whl文件然后安装,window安装包链接https://www.lfd.uci.edu/~gohlke/pythonlibs/
我用的这个办法,直接在pypi或者github下载源码,放到工作空间目录下的/src,然后catkin_make,之后可以在这个工作空间下使用。