{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "# 文本检测FAQ\n",
    "\n",
    "本节罗列一些开发者们使用PaddleOCR的文本检测模型常遇到的一些问题，并给出相应的问题解决方法或建议。\n",
    "\n",
    "FAQ分两个部分来介绍，分别是：\n",
    " - 文本检测训练相关\n",
    " - 文本检测预测相关"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## 1. 文本检测训练相关FAQ\n",
    "\n",
    "**1.1 PaddleOCR提供的文本检测算法包括哪些？**\n",
    "\n",
    "**A**：PaddleOCR中包含多种文本检测模型，包括基于回归的文本检测方法EAST、SAST，和基于分割的文本检测方法DB，PSENet。\n",
    "\n",
    "\n",
    "**1.2：请问PaddleOCR项目中的中文超轻量和通用模型用了哪些数据集？训练多少样本，gpu什么配置，跑了多少个epoch，大概跑了多久？**\n",
    "\n",
    "**A**：对于超轻量DB检测模型，训练数据包括开源数据集lsvt，rctw，CASIA，CCPD，MSRA，MLT，BornDigit，iflytek，SROIE和合成的数据集等，总数据量越10W，数据集分为5个部分，训练时采用随机采样策略，在4卡V100GPU上约训练500epoch，耗时3天。\n",
    "\n",
    "\n",
    "**1.3 文本检测训练标签是否需要具体文本标注，标签中的”###”是什么意思？**\n",
    "\n",
    "**A**：文本检测训练只需要文本区域的坐标即可，标注可以是四点或者十四点，按照左上，右上，右下，左下的顺序排列。PaddleOCR提供的标签文件中包含文本字段，对于文本区域文字不清晰会使用###代替。训练检测模型时，不会用到标签中的文本字段。\n",
    " \n",
    "**1.4 对于文本行较紧密的情况下训练的文本检测模型效果较差？**\n",
    "\n",
    "**A**：使用基于分割的方法，如DB，检测密集文本行时，最好收集一批数据进行训练，并且在训练时，并将生成二值图像的[shrink_ratio](https://github.com/PaddlePaddle/PaddleOCR/blob/8b656a3e13631dfb1ac21d2095d4d4a4993ef710/ppocr/data/imaug/make_shrink_map.py?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L37)参数调小一些。另外，在预测的时候，可以适当减小[unclip_ratio](https://github.com/PaddlePaddle/PaddleOCR/blob/8b656a3e13631dfb1ac21d2095d4d4a4993ef710/configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L59)参数，unclip_ratio参数值越大检测框就越大。\n",
    "\n",
    "\n",
    "**1.5 对于一些尺寸较大的文档类图片， DB在检测时会有较多的漏检，怎么避免这种漏检的问题呢？**\n",
    "\n",
    "**A**：首先，需要确定是模型没有训练好的问题还是预测时处理的问题。如果是模型没有训练好，建议多加一些数据进行训练，或者在训练的时候多加一些数据增强。\n",
    "如果是预测图像过大的问题，可以增大预测时输入的最长边设置参数[det_limit_side_len](https://github.com/PaddlePaddle/PaddleOCR/blob/8b656a3e13631dfb1ac21d2095d4d4a4993ef710/tools/infer/utility.py?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L47)，默认为960。\n",
    "其次，可以通过可视化后处理的分割图观察漏检的文字是否有分割结果，如果没有分割结果，说明是模型没有训练好。如果有完整的分割区域，说明是预测后处理的问题，建议调整[DB后处理参数](https://github.com/PaddlePaddle/PaddleOCR/blob/8b656a3e13631dfb1ac21d2095d4d4a4993ef710/tools/infer/utility.py?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L51-L53)。\n",
    "\n",
    "\n",
    "**1.6  DB模型弯曲文本（如略微形变的文档图像）漏检问题?**\n",
    "\n",
    "**A**: DB后处理中计算文本框平均得分时，是求rectangle区域的平均分数，容易造成弯曲文本漏检，已新增求polygon区域的平均分数，会更准确，但速度有所降低，可按需选择，在相关pr中可查看[可视化对比效果](https://github.com/PaddlePaddle/PaddleOCR/pull/2604)。该功能通过参数 [det_db_score_mode](https://github.com/PaddlePaddle/PaddleOCR/blob/release/2.1/tools/infer/utility.py#L51)进行选择，参数值可选[`fast`(默认)、`slow`]，`fast`对应原始的rectangle方式，`slow`对应polygon方式。感谢用户[buptlihang](https://github.com/buptlihang)提[pr](https://github.com/PaddlePaddle/PaddleOCR/pull/2574)帮助解决该问题。\n",
    "\n",
    "\n",
    "**1.7 简单的对于精度要求不高的OCR任务，数据集需要准备多少张呢？**\n",
    "\n",
    "**A**：（1）训练数据的数量和需要解决问题的复杂度有关系。难度越大，精度要求越高，则数据集需求越大，而且一般情况实际中的训练数据越多效果越好。\n",
    "\n",
    "（2）对于精度要求不高的场景，检测任务和识别任务需要的数据量是不一样的。对于检测任务，500张图像可以保证基本的检测效果。对于识别任务，需要保证识别字典中每个字符出现在不同场景的行文本图像数目需要大于200张（举例，如果有字典中有5个字，每个字都需要出现在200张图片以上，那么最少要求的图像数量应该在200-1000张之间），这样可以保证基本的识别效果。\n",
    "\n",
    "\n",
    "**1.8 当训练数据量少时，如何获取更多的数据？**\n",
    "\n",
    "**A**：当训练数据量少时，可以尝试以下三种方式获取更多的数据：（1）人工采集更多的训练数据，最直接也是最有效的方式。（2）基于PIL和opencv基本图像处理或者变换。例如PIL中ImageFont, Image, ImageDraw三个模块将文字写到背景中，opencv的旋转仿射变换，高斯滤波等。（3）利用数据生成算法合成数据，例如pix2pix等算法。\n",
    "\n",
    "\n",
    "**1.9 如何更换文本检测/识别的backbone？**\n",
    "\n",
    "A：无论是文字检测，还是文字识别，骨干网络的选择是预测效果和预测效率的权衡。一般，选择更大规模的骨干网络，例如ResNet101_vd，则检测或识别更准确，但预测耗时相应也会增加。而选择更小规模的骨干网络，例如MobileNetV3_small_x0_35，则预测更快，但检测或识别的准确率会大打折扣。幸运的是不同骨干网络的检测或识别效果与在ImageNet数据集图像1000分类任务效果正相关。飞桨图像分类套件PaddleClas汇总了ResNet_vd、Res2Net、HRNet、MobileNetV3、GhostNet等23种系列的分类网络结构，在上述图像分类任务的top1识别准确率，GPU(V100和T4)和CPU(骁龙855)的预测耗时以及相应的117个预训练模型下载地址。\n",
    "\n",
    "（1）文字检测骨干网络的替换，主要是确定类似与ResNet的4个stages，以方便集成后续的类似FPN的检测头。此外，对于文字检测问题，使用ImageNet训练的分类预训练模型，可以加速收敛和效果提升。\n",
    "\n",
    "（2）文字识别的骨干网络的替换，需要注意网络宽高stride的下降位置。由于文本识别一般宽高比例很大，因此高度下降频率少一些，宽度下降频率多一些。可以参考[PaddleOCR中MobileNetV3骨干网络的改动](https://github.com/PaddlePaddle/PaddleOCR/blob/release%2F2.3/ppocr/modeling/backbones/rec_mobilenet_v3.py)。\n",
    "\n",
    "\n",
    "**1.10 如何对检测模型finetune，比如冻结前面的层或某些层使用小的学习率学习？**\n",
    "\n",
    "**A**：如果是冻结某些层，可以将变量的stop_gradient属性设置为True，这样计算这个变量之前的所有参数都不会更新了，参考：https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/faq/train_cn.html#id4\n",
    "\n",
    "如果对某些层使用更小的学习率学习，静态图里还不是很方便，一个方法是在参数初始化的时候，给权重的属性设置固定的学习率，参考：https://www.paddlepaddle.org.cn/documentation/docs/zh/develop/api/paddle/fluid/param_attr/ParamAttr_cn.html#paramattr\n",
    "\n",
    "实际上我们实验发现，直接加载模型去fine-tune，不设置某些层不同学习率，效果也都不错\n",
    "\n",
    "**1.11 DB的预处理部分，图片的长和宽为什么要处理成32的倍数？**\n",
    "\n",
    "**A**：和网络下采样的倍数（stride）有关。以检测中的resnet骨干网络为例，图像输入网络之后，需要经过5次2倍降采样，共32倍，因此建议输入的图像尺寸为32的倍数。\n",
    "\n",
    "\n",
    "**1.12 在PP-OCR系列的模型中，文本检测的骨干网络为什么没有使用SEBlock？**\n",
    "\n",
    "**A**：SE模块是MobileNetV3网络一个重要模块，目的是估计特征图每个特征通道重要性，给特征图每个特征分配权重，提高网络的表达能力。但是，对于文本检测，输入网络的分辨率比较大，一般是640\\*640，利用SE模块估计特征图每个特征通道重要性比较困难，网络提升能力有限，但是该模块又比较耗时，因此在PP-OCR系统中，文本检测的骨干网络没有使用SE模块。实验也表明，当去掉SE模块，超轻量模型大小可以减小40%，文本检测效果基本不受影响。详细可以参考PP-OCR技术文章，https://arxiv.org/abs/2009.09941.\n",
    "\n",
    "\n",
    "**1.13 PP-OCR检测效果不好，该如何优化？**\n",
    "\n",
    "A： 具体问题具体分析:\n",
    "- 如果在你的场景上检测效果不可用，首选是在你的数据上做finetune训练；\n",
    "- 如果图像过大，文字过于密集，建议不要过度压缩图像，可以尝试修改检测预处理的resize逻辑，防止图像被过度压缩；\n",
    "- 检测框大小过于紧贴文字或检测框过大，可以调整db_unclip_ratio这个参数，加大参数可以扩大检测框，减小参数可以减小检测框大小；\n",
    "- 检测框存在很多漏检问题，可以减小DB检测后处理的阈值参数det_db_box_thresh，防止一些检测框被过滤掉，也可以尝试设置det_db_score_mode为'slow';\n",
    "- 其他方法可以选择use_dilation为True，对检测输出的feature map做膨胀处理，一般情况下，会有效果改善；\n",
    "\n",
    "\n",
    "## 2. 文本检测预测相关FAQ\n",
    "\n",
    "**2.1 DB有些框太贴文本了反而去掉了一些文本的边角影响识别，这个问题有什么办法可以缓解吗？**\n",
    "\n",
    "**A**：可以把后处理的参数[unclip_ratio](https://github.com/PaddlePaddle/PaddleOCR/blob/d80afce9b51f09fd3d90e539c40eba8eb5e50dd6/tools/infer/utility.py?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L52)适当调大一点，该参数越大文本框越大。\n",
    "\n",
    "\n",
    "**2.2 为什么PaddleOCR检测预测是只支持一张图片测试？即test_batch_size_per_card=1**\n",
    "\n",
    "**A**：预测的时候，对图像等比例缩放，最长边960，不同图像等比例缩放后长宽不一致，无法组成batch，所以设置为test_batch_size为1。\n",
    "\n",
    "\n",
    "**2.3 在CPU上加速PaddleOCR的文本检测模型预测？**\n",
    "\n",
    "**A**：x86 CPU可以使用mkldnn（OneDNN）进行加速；在支持mkldnn加速的CPU上开启[enable_mkldnn](https://github.com/PaddlePaddle/PaddleOCR/blob/8b656a3e13631dfb1ac21d2095d4d4a4993ef710/tools/infer/utility.py#L105)参数。另外，配合增加CPU上预测使用的[线程数num_threads](https://github.com/PaddlePaddle/PaddleOCR/blob/8b656a3e13631dfb1ac21d2095d4d4a4993ef710/tools/infer/utility.py#L106)，可以有效加快CPU上的预测速度。\n",
    "\n",
    "**2.4 在GPU上加速PaddleOCR的文本检测模型预测？**\n",
    "\n",
    "**A**：GPU加速预测推荐使用TensorRT。\n",
    "- 1. 从[链接](https://paddleinference.paddlepaddle.org.cn/master/user_guides/download_lib.html)下载带TensorRT的Paddle安装包或者预测库。\n",
    "- 2. 从Nvidia官网下载TensorRT版本，注意下载的TensorRT版本与paddle安装包中编译的TensorRT版本一致。\n",
    "- 3. 设置环境变量LD_LIBRARY_PATH，指向TensorRT的lib文件夹\n",
    "```\n",
    "export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:<TensorRT-${version}/lib>\n",
    "```\n",
    "- 4. 开启PaddleOCR预测的[tensorrt选项](https://github.com/PaddlePaddle/PaddleOCR/blob/8b656a3e13631dfb1ac21d2095d4d4a4993ef710/tools/infer/utility.py?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L38)。\n",
    "\n",
    "**2.5 如何在移动端部署PaddleOCR模型？**\n",
    "\n",
    "**A**: 飞桨Paddle有专门针对移动端部署的工具[PaddleLite](https://github.com/PaddlePaddle/Paddle-Lite)，并且PaddleOCR提供了DB+CRNN为demo的android arm部署代码，参考[链接](https://github.com/PaddlePaddle/PaddleOCR/blob/release%2F2.3/deploy/lite/readme.md)。\n",
    "\n",
    "\n",
    "**2.6 如何使用PaddleOCR多进程预测？**\n",
    "\n",
    "**A**: 近期PaddleOCR新增了[多进程预测控制参数](https://github.com/PaddlePaddle/PaddleOCR/blob/8b656a3e13631dfb1ac21d2095d4d4a4993ef710/tools/infer/utility.py?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L111)，`use_mp`表示是否使用多进程，`total_process_num`表示在使用多进程时的进程数。具体使用方式请参考[文档](https://github.com/PaddlePaddle/PaddleOCR/blob/release%2F2.3/doc/doc_ch/inference.md#1-%E8%B6%85%E8%BD%BB%E9%87%8F%E4%B8%AD%E6%96%87ocr%E6%A8%A1%E5%9E%8B%E6%8E%A8%E7%90%86)。\n",
    "\n",
    "**2.7 预测时显存爆炸、内存泄漏问题？**\n",
    "\n",
    "**A**: 如果是训练模型的预测，由于模型太大或者输入图像太大导致显存不够用，可以参考代码在主函数运行前加上paddle.no_grad()，即可减小显存占用。如果是inference模型预测时显存占用过高，可以配置Config时，加入[config.enable_memory_optim()](https://github.com/PaddlePaddle/PaddleOCR/blob/8b656a3e13631dfb1ac21d2095d4d4a4993ef710/tools/infer/utility.py?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L267)用于减小内存占用。\n",
    "\n",
    "另外关于使用Paddle预测时出现内存泄漏的问题，建议安装paddle最新版本，内存泄漏已修复。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "py35-paddle1.2.0"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
