最近有一个比较火的ocr项目:chineseocr_lite[1],项目中很贴心地提供了ncnn的模型推理代码,只需要

  1. 交叉编译opencv
  2. 添加一点bitmap转cv::Mat的代码
  3. 写个简单的界面

具体过程参考:安卓端深度学习模型部署-以NCNN为例 - 带萝卜的文章 - 知乎 https://zhuanlan.zhihu.com/p/137453394

就可以得到一个安卓端的OCR工具了。

可能因为项目针对的是通用的自然场景,所以对小尺寸文本的识别效果不太理想,我对psenet进行了重训练,再转成NCNN进行部署。

PyTorch转NCNN的流程十分简单,如果顺利的话只需要两步:

  • PyTorch转ONNX
torch.onnx._export(model, x, path, opset_version=11) 

  • ONNX转NCNN
./onnx2ncnn model.onnx model.param model.bin 

可是世上哪有那么多一帆风顺的事,这篇文章记录的就是模型重训练之后转成NCNN的过程中遇到的问题和解决方案。

重训练代码参考:wenmuzhou/PSENet.pytorch[2],backbone选择了mobilenetv3。

注:下文中的resize、interp、interpolate都是一个意思

问题1: ReLU6不支持

概述:ReLU6算子在转换的时候容易出现不支持的情况,需要使用其他算子替代

解决:使用torch.clamp替代(虽然ReLU6可以通过组合ReLU的方式实现,但是组合得到的ReLU6在NCNN中容易转换失败,不建议使用。)

def relu6(x,inplace=True):return torch.clamp(x,0,6) 

问题2:Resize算子转换问题

概述:因为各个框架对Resize算子的支持都不尽相同[3],在转换过程中总会出现一些问题,pytorch中的interpolate算子转换成ONNX之后变成很多零散的算子,如cast、shape等,这些在ncnn里面不支持。你可以选择手动修改文件[4],也可以使用下面这个自动的方法:

解决:使用onnx_simplifier[5]对onnx模型进行简化,可以合并这些零散的算子。

python -m onnxsim model.onnx model_sim.onnx 

问题3:关于转ONNX及使用onnx_simplifier过程中出现的一系列奇怪问题

概述:使用不同版本的ONNX可能会遇到不同的问题,比如提示conv层无输入等(具体错误名称记不清了)。

解决:下载最新ONNX源码编译安装(onnx_simplifier中出现的一些错误也可以通过安装最新ONNX来解决)

git clone https://github.com/onnx/onnx.git
sudo apt-get install protobuf-compiler libprotoc-dev
cd ONNX
python setup.py install

问题4:模型输出结果的尺寸固定

概述:直接转换得到的onnx模型的Resize算子都是固定输出尺寸的,无论输入多大的图片都会输出同样大小的特征图,这无疑会影响到模型的精度及灵活性。

解决:修改NCNN模型的param文件,将Resize算子修改成按比例resize。

直接转换得到的param文件中的Interp算子是这样的:

Interp    913      1 1 901 913 0=2 1=1.000000e+00 2=1.000000e+00 3=640 4=640 

从下面的ncnn源码中可以看到,0代表resize_type,1和2分别是高和宽的缩放比例,3和4分别是输出的高和宽。

int Interp::load_param(const ParamDict& pd)
{resize_type = pd.get(0, 0);height_scale = pd.get(1, 1.f);width_scale = pd.get(2, 1.f);output_height = pd.get(3, 0);output_width = pd.get(4, 0);return 0;
} 

我们只需将其修改成如下格式即可实现按比例resize:

Interp      913       1 1 901 913 0=1 1=4.000000e+00 2=4.000000e+00

问题5:NCNN模型输出结果与ONNX模型不同

解决:逐层对比NCNN与onnx模型的输出结果

使用onnxruntime(Python)和NCNN(C++)分别提取每个节点的输出,进行对比。对于ncnn比较简单,可以使用

extractor.extract(node_name,preds); 

来提取不同节点的输出。

问题5衍生问题:ONNX没有提供提取中间层输出的方法

解决:给要提取的层添加一个输出节点,代码[6]如下:

def find_node_by_name(graph, node_name):for node in graph.node:if node.output[0] == node_name:return nodereturn None
def add_extra_output_node(model,target_node, output_name):extra_output = helper.make_empty_tensor_value_info(output_name)target_output = target_node.output[0]identity_node = helper.make_node("Identity",inputs=[target_output],outputs=[output_name],name=output_name)model.graph.node.append(identity_node)model.graph.output.append(extra_output)return model 

修改模型之后再使用

out = sess.run([output_name],{"input.1":img.astype(np.float32)}) 

就可以获取到模型的中间层输出了。

问题5衍生问题:发现最后一个Resize层的输出有差异

解决:参考chineseocr_lite里面的代码把mode由bilinear改成了nearest(这里错误的原因可能是wenmuzhou/PSENet.pytorch中的模型最后一个F.interpolate中的align_corners参数设置成了True。据说NCNN只实现了align_corners为False的情况[7])。

这里修改之后的模型跟原模型之间是会有少许误差的,如果误差不可接受,就要重新训练才行。

一些关于chineseocr项目的细节:

细节1:需要去掉推理代码中的normalize步骤(原因应该是WenmuZhou/PSENet.pytorch的训练过程中没有使用normalize)。

细节2:wenmuzhou/PSENet.pytorch代码中没有把sigmoid加入到模型类中,而是放在了推理代码中,在转换ONNX的时候需要加上sigmoid。

细节3:角度检测在对于小尺寸文字的识别精度不高,尤其是对较长的数字序列,可能需要重新训练。

参考:

1. chineseocr_lite: https://github.com/ouyanghuiyu/chineseocr_lite

2. PSENet: https://github.com/WenmuZhou/PSENet.pytorch

3. 是什么引起了各个框架 Resize 操作的结果不同: https://zhuanlan.zhihu.com/p/107761106

4. 手动修改ncnn模型文件:https://zhuanlan.zhihu.com/p/93017149

5. onnx_simplifier: https://github.com/daquexian/onnx-simplifier

6. 修改onnx节点: https://github.com/bindog/onnx-surgery/blob/master/surgery.py

7. 关于align_corners: https://github.com/Tencent/ncnn/issues/1610

最后,对pytorch和移动端部署感兴趣的话,来交个朋友吧,群号:747537854

c#和java部署pytorch同事识别两个图片_Pytorch转NCNN的流程记录相关推荐

  1. c#和java部署pytorch同事识别两个图片_身份证OCR识别移动端amp;服务器

    摘要:由Web Service和其相关网站接收客户端上传的需要识别的图片.当Web Service接收到图片后将其转发给调度服务器,由任务调度程序再把识别请求分发给空闲的识别服务器,终由Web Ser ...

  2. c#和java部署pytorch同事识别两个图片_人脸识别漏洞频出?这里有个开源静默活体检测算法,超低运算量、工业级可用...

    小视科技团队开源的基于 RGB 图像的活体检测模型,是专门面向工业落地场景,兼容各种复杂场景下的模型.该自研的剪枝轻量级模型,运算量为 0.081G,在麒麟 990 5G 芯片上仅需 9ms.同时基于 ...

  3. c#和java部署pytorch同事识别两个图片_身份证OCR识别移动端服务器

    摘要:由Web Service和其相关网站接收客户端上传的需要识别的图片.当Web Service接收到图片后将其转发给调度服务器,由任务调度程序再把识别请求分发给空闲的识别服务器,终由Web Ser ...

  4. pytorch checkpoint_pytorch的两种部署方式 web部署与c++部署

    知乎地址:  https://zhuanlan.zhihu.com/c_1101089619118026752 作者:   小哲 github:  https://github.com/lxztju/ ...

  5. 通过带Flask的REST API在Python中部署PyTorch

    通过带Flask的REST API在Python中部署PyTorch 在本文中,将使用Flask来部署PyTorch模型,并用讲解用于模型推断的 REST API.特别是,将部署一个预训练的Dense ...

  6. 使用pytorch模型学习框架easyocr模块识别行程码图片文字并使用Flask Web返回指定信息json字符串

    关注「WeiyiGeek」公众号 设为「特别关注」每天带你玩转网络安全运维.应用开发.物联网IOT学习! 本章目录: 使用pytorch模型学习框架easyocr模块行识别程码图片 安装部署 实践使用 ...

  7. 在北京做Java开发如何月薪达到两万,需要技术水平达到什么程度? 1

    觉得没有目标的时候看一看大家讨论到的技术点,就知道欠缺在哪了.共勉吧! 转载自:https://www.zhihu.com/question/39890405 在北京做Java开发如何月薪达到两万,需 ...

  8. Atitit java 二维码识别 图片识别

    Atitit java 二维码识别 图片识别 1.1. 解码1 1.2. 首先,我们先说一下二维码一共有40个尺寸.官方叫版本Version.1 1.3. 二维码的样例:2 1.4. 定位图案2 1. ...

  9. java部署jar还是war优劣_详解Spring Boot 部署jar和war的区别

    本文介绍了Spring Boot 部署jar和war两种方式的区别,分享给大家,具体如下: 1. packaging的方式不同,一种设置成jar一种是war xsi:schemaLocation=&q ...

最新文章

  1. 随机数生成算法-二谈
  2. 简明python教程txt-Python新手的数据批量处理教程(TXT文件)
  3. Mac上配置 Sublime Text 使其使用 Python3
  4. c# 值类型数据与引用类型数据
  5. 未能捍卫科学家的奇思狂想,这家公司与3000亿美元失之交臂
  6. 北大FAIR自动化所快手提出基于动量对比学习的层次Transformer—HiT,用于视频文本检索!代码已开源!...
  7. 泰山站和泰安站怎么区分?
  8. vs2017_enterprise正式版离线安装包bt下载
  9. Windows Azure Web Site (17) 设置Web App TimeOut时间
  10. Win10 打开MSDTC
  11. 计算机工程师英语简历模板,计算机软件工程师英文简历模板
  12. 工具网站:10个国外免费、无版权、高清图片素材站
  13. MCU方案分享----按摩贴方案
  14. php解析mpp文件
  15. android root工具排行榜,可root任何机?史上最强安卓root工具出炉
  16. MIPI扫盲——DSI介绍(一)
  17. 最全的程序化交易模型设计思路在这里
  18. 力扣随机数randX——透过现象看本质之二元独立随机分布
  19. 传奇世界手游活人最多服务器,传奇世界手游那些不为人知小技巧分享
  20. 11.03 CSS的基础应用

热门文章

  1. main java.lang,各位大哥办我看看,Exception in thread main java.lang.Error: 无法解析的编译有关问题...
  2. html 图片 气泡,微信气泡的图片铺满怎么做的?canvas做出来吗?css呢?
  3. 那些短,却叫人很心疼的句子(转)
  4. [论文笔记]AlignedReID
  5. django2.2 简单博客 一
  6. 微信 oauth2.0 php,微信公众平台OAuth2.0 认证
  7. Shell脚本入门学习
  8. buildroot_buildroot-我对多平台发行版创作的经验
  9. java append 报错_Append HDFS报错 is already the current lease holder
  10. springboot+Elasticsearch实现word,pdf,txt内容抽取并高亮分词全文检索