PaddleOCR 尝试下OpenCV-DNN推理
完整代码:https://github.com/VITA-Alchemy/PaddleOCR-OpenCV-DNN
onnx 1.11.0
onnxruntime 1.10.0
opencv 4.5.5.62
paddle2onnx 1.0.1
paddlpaddle 2.3.2
paddleocr v2 模型 :det 模型,rec模型
Netron 查看模型结构
onnx-simplifier
#检测模型
paddle2onnx -m paddle2onnx.optimize --model_dir .\ch_ppocr_mobile_v2.0_det_infer\ --model_filename inference.pdmodel --params_filename inference.pdiparams --save_file ./ch_ppocr_mobile_v2.0_det_infer/model.onnx --opset_version 10 --input_shape_dict="{'x':[1,3,640,640]}" --enable_onnx_checker True --enable_dev_version False
#识别模型
paddle2onnx -m paddle2onnx.optimize --model_dir ./ch_ppocr_mobile_v2.0_rec_infer --model_filename inference.pdmodel --params_filename inference.pdiparams --save_file ./ch_ppocr_mobile_v2.0_rec_infer/model.onnx --opset_version 10 --input_shape_dict="{'x':[1,3,32,1000]}" --enable_onnx_checker True --enable_dev_version False
这里直接使用在线简化 :https://convertmodel.com/
# 直接在源码中修改的部分代码
def resize_image_type2(self, img):
h, w, _ = img.shape
resize_w = w
resize_h = h
if resize_h > resize_w:
ratio = float(self.resize_long) / resize_h
else:
ratio = float(self.resize_long) / resize_w
resize_h = int(resize_h * ratio)
resize_w = int(resize_w * ratio)
img = cv2.resize(img, (resize_w, resize_h))
#这里加个0填充,适配固定shape模型
img = self.image_padding_640(img)
return img, [ratio, ratio]
def boxes_from_bitmap(self, pred, _bitmap, dest_width, dest_height,ratio):
'''
_bitmap: single map with shape (1, H, W),
whose values are binarized as {0, 1}
'''
bitmap = _bitmap
#height, width = bitmap.shape
#长宽都乘以缩放比,还原到原来大小
height, width = dest_height*ratio, dest_width*ratio,
# 这里 imgC, imgH, imgW 改成自己模型对应的shape
def resize_norm_img(self, img):
# self.model_shape = [3,32,1000]
imgC, imgH, imgW = [int(v) for v in self.model_shape]
assert imgC == img.shape[2]
h, w = img.shape[:2]
ratio = w / float(h)
opencv dnn :[('使用深度学习和OpenCV进行目标检测', 0.9423162), ('基于深度学习的对象检测时,您可能会遇到三种主要的对象检测方法:', 0.9942412), ('·Faster R-CNNs(Ren etal,2015)', 0.9131796), ('You Only Look Once (YOLO)(Redmon et al,2015)', 0.9224724), ('SingleShotDetectors(ssD)(Liu等人,2015年)', 0.9578045), ('FasterR-CNNs可能是使用深度学习进行对象检测最“听说”的方法;然而,该技术可能难以理', 0.9848377), ('解(特别是对于深度学习的初学者)、难以实施且难以训练。', 0.9785821), ('此外,即使使用“更快”的R-CNN实现(其中“R”代表“区域提议”),算法也可能非常慢', 0.9776404), ('大约为7FPS。', 0.96622694), ('如果追求纯粹的速度,那么我们倾向于使用YOLO,因为这种算法要快得多,能够在Titan×GPU', 0.98800766), ('上处理40-90FPS。YOLO的超快变体甚至可以达到155FPS。', 0.9868126), ('YOLO的问题在于它的准确性不高。', 0.98904663), ('最初由Google开发的SSD是两者之间的平衡。该算法比FasterR-CNN更直接', 0.9916604)]
------------------------------
onnxruntime :[('使用深度学习和OpenCV进行目标检测', 0.94230413), ('基于深度学习的对象检测时,您可能会遇到三种主要的对象检测方法:', 0.99423134), ('·Faster R-CNNs(Ren etal,2015)', 0.9131659), ('You Only Look Once (YOLO)(Redmon et al,2015)', 0.9224635), ('SingleShotDetectors(ssD)(Liu等人,2015年)', 0.9577948), ('FasterR-CNNs可能是使用深度学习进行对象检测最“听说”的方法;然而,该技术可能难以理', 0.98482645), ('解(特别是对于深度学习的初学者)、难以实施且难以训练。', 0.9785724), ('此外,即使使用“更快”的R-CNN实现(其中“R”代表“区域提议”),算法也可能非常慢', 0.9776268), ('大约为7FPS。', 0.96620893), ('如果追求纯粹的速度,那么我们倾向于使用YOLO,因为这种算法要快得多,能够在Titan×GPU', 0.9879988), ('上处理40-90FPS。YOLO的超快变体甚至可以达到155FPS。', 0.98680395), ('YOLO的问题在于它的准确性不高。', 0.9890286), ('最初由Google开发的SSD是两者之间的平衡。该算法比FasterR-CNN更直接', 0.99165064)]
由于固化模型shape,使得部分特殊场景下效果不良,如长条形图片,降低了通用性;可根据自己对应的场景去固化模型尺寸(通用场景下建议导出dynamic shape模型,使用onnxruntime推理)。
相同图片下(前后处理一致),速度方面DNN比onnxruntime慢(大约2~3倍)。
精度未与原始paddle模型对比;简单测试效果尚可。
测试PaddleOCR v3版本,det模型dnn支持,rec模型dnn推理失败。
https://github.com/PaddlePaddle/PaddleOCR
https://github.com/PaddlePaddle/Paddle2ONNX
https://github.com/daquexian/onnx-simplifier
https://blog.csdn.net/favorxin/article/details/115270800