diff --git a/README_ch.md b/README_ch.md index a231800cbe56df3a9096785f5713b565daa03ead..a788c227ad4055ec85af907a09471a8b58ae4625 100755 --- a/README_ch.md +++ b/README_ch.md @@ -8,7 +8,7 @@ PaddleOCR同时支持动态图与静态图两种编程范式 - 静态图版本:develop分支 **近期更新** -- 2021.1.4 [FAQ](./doc/doc_ch/FAQ.md)新增5个高频问题,总数142个,每周一都会更新,欢迎大家持续关注。 +- 2021.1.11 [FAQ](./doc/doc_ch/FAQ.md)新增5个高频问题,总数147个,每周一都会更新,欢迎大家持续关注。 - 2020.12.15 更新数据合成工具[Style-Text](./StyleText/README_ch.md),可以批量合成大量与目标场景类似的图像,在多个场景验证,效果明显提升。 - 2020.11.25 更新半自动标注工具[PPOCRLabel](./PPOCRLabel/README_ch.md),辅助开发者高效完成标注任务,输出格式与PP-OCR训练任务完美衔接。 - 2020.9.22 更新PP-OCR技术文章,https://arxiv.org/abs/2009.09941 @@ -102,7 +102,7 @@ PaddleOCR同时支持动态图与静态图两种编程范式 - FAQ - [【精选】OCR精选10个问题](./doc/doc_ch/FAQ.md) - [【理论篇】OCR通用31个问题](./doc/doc_ch/FAQ.md) - - [【实战篇】PaddleOCR实战101个问题](./doc/doc_ch/FAQ.md) + - [【实战篇】PaddleOCR实战106个问题](./doc/doc_ch/FAQ.md) - [技术交流群](#欢迎加入PaddleOCR技术交流群) - [参考文献](./doc/doc_ch/reference.md) - [许可证书](#许可证书) diff --git a/StyleText/README.md b/StyleText/README.md index 3e14e320334c77723f0a493718d731efd354ea69..df4fbf3cfed44b26d690f70e2ab0d4b5c0aa1ff0 100644 --- a/StyleText/README.md +++ b/StyleText/README.md @@ -52,7 +52,7 @@ If you save the model in another location, please modify the address of the mode ``` bg_generator: - pretrain: style_text_rec/bg_generator + pretrain: style_text_models/bg_generator ... text_generator: pretrain: style_text_models/text_generator diff --git a/configs/det/det_mv3_db.yml b/configs/det/det_mv3_db.yml index bdb4afc085f9a565defb3d34df86f9ecdb2492d5..00a16b5a38f2a271825a470684be401944eafec0 100644 --- a/configs/det/det_mv3_db.yml +++ b/configs/det/det_mv3_db.yml @@ -102,6 +102,7 @@ Train: drop_last: False batch_size_per_card: 16 num_workers: 8 + use_shared_memory: False Eval: dataset: @@ -128,4 +129,5 @@ Eval: shuffle: False drop_last: False batch_size_per_card: 1 # must be 1 - num_workers: 8 \ No newline at end of file + num_workers: 8 + use_shared_memory: False \ No newline at end of file diff --git a/configs/rec/rec_icdar15_train.yml b/configs/rec/rec_icdar15_train.yml index 3de0ce7741cc8086b41cd1f5b98f6a8bbced90fa..8a743b501618dc6dabf9b1d419431a148236c690 100644 --- a/configs/rec/rec_icdar15_train.yml +++ b/configs/rec/rec_icdar15_train.yml @@ -76,6 +76,7 @@ Train: batch_size_per_card: 256 drop_last: True num_workers: 8 + use_shared_memory: False Eval: dataset: @@ -96,3 +97,4 @@ Eval: drop_last: False batch_size_per_card: 256 num_workers: 4 + use_shared_memory: False diff --git a/deploy/cpp_infer/include/preprocess_op.h b/deploy/cpp_infer/include/preprocess_op.h index bda7d1230fdc11c3b1a7d99130df755d26895de8..ab4c140059fdcaed9872d2d99b4aea57c7e5208f 100644 --- a/deploy/cpp_infer/include/preprocess_op.h +++ b/deploy/cpp_infer/include/preprocess_op.h @@ -47,18 +47,20 @@ public: class ResizeImgType0 { public: virtual void Run(const cv::Mat &img, cv::Mat &resize_img, int max_size_len, - float &ratio_h, float &ratio_w); + float &ratio_h, float &ratio_w, bool use_tensorrt); }; class CrnnResizeImg { public: virtual void Run(const cv::Mat &img, cv::Mat &resize_img, float wh_ratio, + bool use_tensorrt = false, const std::vector &rec_image_shape = {3, 32, 320}); }; class ClsResizeImg { public: virtual void Run(const cv::Mat &img, cv::Mat &resize_img, + bool use_tensorrt = false, const std::vector &rec_image_shape = {3, 48, 192}); }; diff --git a/deploy/cpp_infer/src/main.cpp b/deploy/cpp_infer/src/main.cpp index f40e5edfcc2c19e0a61894bed11aef636317e056..49c68f55234980009aa8e139acc3f22bf6a17bcf 100644 --- a/deploy/cpp_infer/src/main.cpp +++ b/deploy/cpp_infer/src/main.cpp @@ -77,7 +77,7 @@ int main(int argc, char **argv) { auto end = std::chrono::system_clock::now(); auto duration = std::chrono::duration_cast(end - start); - std::cout << "Cost" + std::cout << "Cost " << double(duration.count()) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den diff --git a/deploy/cpp_infer/src/ocr_cls.cpp b/deploy/cpp_infer/src/ocr_cls.cpp index 3aeda2ed0c286d1ec5e816e15ac5500f53c9a3a2..9199e082e5df42b0c9c42e668d2df37acf4521c4 100644 --- a/deploy/cpp_infer/src/ocr_cls.cpp +++ b/deploy/cpp_infer/src/ocr_cls.cpp @@ -25,7 +25,7 @@ cv::Mat Classifier::Run(cv::Mat &img) { int index = 0; float wh_ratio = float(img.cols) / float(img.rows); - this->resize_op_.Run(img, resize_img, cls_image_shape); + this->resize_op_.Run(img, resize_img, this->use_tensorrt_, cls_image_shape); this->normalize_op_.Run(&resize_img, this->mean_, this->scale_, this->is_scale_); diff --git a/deploy/cpp_infer/src/ocr_det.cpp b/deploy/cpp_infer/src/ocr_det.cpp index 3678f37dfb1c0c4aed392dd31830e732e2854899..489940f062fa9f8093282d20441704dd5cb8b382 100644 --- a/deploy/cpp_infer/src/ocr_det.cpp +++ b/deploy/cpp_infer/src/ocr_det.cpp @@ -61,7 +61,8 @@ void DBDetector::Run(cv::Mat &img, cv::Mat srcimg; cv::Mat resize_img; img.copyTo(srcimg); - this->resize_op_.Run(img, resize_img, this->max_side_len_, ratio_h, ratio_w); + this->resize_op_.Run(img, resize_img, this->max_side_len_, ratio_h, ratio_w, + this->use_tensorrt_); this->normalize_op_.Run(&resize_img, this->mean_, this->scale_, this->is_scale_); diff --git a/deploy/cpp_infer/src/ocr_rec.cpp b/deploy/cpp_infer/src/ocr_rec.cpp index 27cfe4c95009c6454514a43e304a23503fe5fa9a..fa1e44ff7a62f178d64b2494f4b769e8618128ac 100644 --- a/deploy/cpp_infer/src/ocr_rec.cpp +++ b/deploy/cpp_infer/src/ocr_rec.cpp @@ -33,7 +33,7 @@ void CRNNRecognizer::Run(std::vector>> boxes, float wh_ratio = float(crop_img.cols) / float(crop_img.rows); - this->resize_op_.Run(crop_img, resize_img, wh_ratio); + this->resize_op_.Run(crop_img, resize_img, wh_ratio, this->use_tensorrt_); this->normalize_op_.Run(&resize_img, this->mean_, this->scale_, this->is_scale_); diff --git a/deploy/cpp_infer/src/preprocess_op.cpp b/deploy/cpp_infer/src/preprocess_op.cpp index cdb20c31973dac50322016ed0124e8c3b1d8d4e7..87d8dbbd774f7dd29843d9a2c2533368f1914272 100644 --- a/deploy/cpp_infer/src/preprocess_op.cpp +++ b/deploy/cpp_infer/src/preprocess_op.cpp @@ -60,7 +60,8 @@ void Normalize::Run(cv::Mat *im, const std::vector &mean, } void ResizeImgType0::Run(const cv::Mat &img, cv::Mat &resize_img, - int max_size_len, float &ratio_h, float &ratio_w) { + int max_size_len, float &ratio_h, float &ratio_w, + bool use_tensorrt) { int w = img.cols; int h = img.rows; @@ -89,14 +90,19 @@ void ResizeImgType0::Run(const cv::Mat &img, cv::Mat &resize_img, resize_w = 32; else resize_w = (resize_w / 32) * 32; - - cv::resize(img, resize_img, cv::Size(resize_w, resize_h)); - - ratio_h = float(resize_h) / float(h); - ratio_w = float(resize_w) / float(w); + if (!use_tensorrt) { + cv::resize(img, resize_img, cv::Size(resize_w, resize_h)); + ratio_h = float(resize_h) / float(h); + ratio_w = float(resize_w) / float(w); + } else { + cv::resize(img, resize_img, cv::Size(640, 640)); + ratio_h = float(640) / float(h); + ratio_w = float(640) / float(w); + } } void CrnnResizeImg::Run(const cv::Mat &img, cv::Mat &resize_img, float wh_ratio, + bool use_tensorrt, const std::vector &rec_image_shape) { int imgC, imgH, imgW; imgC = rec_image_shape[0]; @@ -111,12 +117,27 @@ void CrnnResizeImg::Run(const cv::Mat &img, cv::Mat &resize_img, float wh_ratio, resize_w = imgW; else resize_w = int(ceilf(imgH * ratio)); - - cv::resize(img, resize_img, cv::Size(resize_w, imgH), 0.f, 0.f, - cv::INTER_LINEAR); + if (!use_tensorrt) { + cv::resize(img, resize_img, cv::Size(resize_w, imgH), 0.f, 0.f, + cv::INTER_LINEAR); + cv::copyMakeBorder(resize_img, resize_img, 0, 0, 0, + int(imgW - resize_img.cols), cv::BORDER_CONSTANT, + {127, 127, 127}); + } else { + int k = int(img.cols * 32 / img.rows); + if (k >= 100) { + cv::resize(img, resize_img, cv::Size(100, 32), 0.f, 0.f, + cv::INTER_LINEAR); + } else { + cv::resize(img, resize_img, cv::Size(k, 32), 0.f, 0.f, cv::INTER_LINEAR); + cv::copyMakeBorder(resize_img, resize_img, 0, 0, 0, int(100 - k), + cv::BORDER_CONSTANT, {127, 127, 127}); + } + } } void ClsResizeImg::Run(const cv::Mat &img, cv::Mat &resize_img, + bool use_tensorrt, const std::vector &rec_image_shape) { int imgC, imgH, imgW; imgC = rec_image_shape[0]; @@ -130,11 +151,15 @@ void ClsResizeImg::Run(const cv::Mat &img, cv::Mat &resize_img, else resize_w = int(ceilf(imgH * ratio)); - cv::resize(img, resize_img, cv::Size(resize_w, imgH), 0.f, 0.f, - cv::INTER_LINEAR); - if (resize_w < imgW) { - cv::copyMakeBorder(resize_img, resize_img, 0, 0, 0, imgW - resize_w, - cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0)); + if (!use_tensorrt) { + cv::resize(img, resize_img, cv::Size(resize_w, imgH), 0.f, 0.f, + cv::INTER_LINEAR); + if (resize_w < imgW) { + cv::copyMakeBorder(resize_img, resize_img, 0, 0, 0, imgW - resize_w, + cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0)); + } + } else { + cv::resize(img, resize_img, cv::Size(100, 32), 0.f, 0.f, cv::INTER_LINEAR); } } diff --git a/doc/doc_ch/FAQ.md b/doc/doc_ch/FAQ.md index da31d608bfdead2734d11d0ab0619cdff7aeeb78..e1d1f1b61e83ef59683163d98e8d2b7a814a882c 100755 --- a/doc/doc_ch/FAQ.md +++ b/doc/doc_ch/FAQ.md @@ -9,49 +9,47 @@ ## PaddleOCR常见问题汇总(持续更新) -* [近期更新(2021.1.4)](#近期更新) +* [近期更新(2021.1.11)](#近期更新) * [【精选】OCR精选10个问题](#OCR精选10个问题) * [【理论篇】OCR通用31个问题](#OCR通用问题) * [基础知识7题](#基础知识) * [数据集7题](#数据集2) * [模型训练调优17题](#模型训练调优2) -* [【实战篇】PaddleOCR实战101个问题](#PaddleOCR实战问题) - * [使用咨询31题](#使用咨询) +* [【实战篇】PaddleOCR实战106个问题](#PaddleOCR实战问题) + * [使用咨询36题](#使用咨询) * [数据集17题](#数据集3) * [模型训练调优26题](#模型训练调优3) * [预测部署27题](#预测部署3) -## 近期更新(2021.1.4) +## 近期更新(2021.1.11) -#### Q3.1.29: PPOCRLabel创建矩形框时只能拖出正方形,如何进行矩形标注? -**A**: 取消勾选:“编辑”-“正方形标注” +#### Q3.1.32 能否修改StyleText配置文件中的分辨率? -#### Q3.1.30: Style-Text 如何不文字风格迁移,就像普通文本生成程序一样默认字体直接输出到分割的背景图? +**A**:StyleText目前的训练数据主要是高度32的图片,建议不要改变高度。未来我们会支持更丰富的分辨率。 -**A**: 使用image_synth模式会输出fake_bg.jpg,即为背景图。如果想要批量提取背景,可以稍微修改一下代码,将fake_bg保存下来即可。要修改的位置: -https://github.com/PaddlePaddle/PaddleOCR/blob/de3e2e7cd3b8b65ee02d7a41e570fa5b511a3c1d/StyleText/engine/synthesisers.py#L68 +#### Q3.1.33 StyleText是否可以更换字体文件? -#### Q3.1.31: 怎么输出网络结构以及每层的参数信息? +**A**:StyleText项目中的字体文件为标准字体,主要用作模型的输入部分,不能够修改。 +StyleText的用途主要是:提取style_image中的字体、背景等style信息,根据语料生成同样style的图片。 -**A**: 可以使用 `paddle.summary`, 具体参考:https://www.paddlepaddle.org.cn/documentation/docs/zh/2.0-rc1/api/paddle/hapi/model_summary/summary_cn.html#summary。 +#### Q3.1.34 StyleText批量生成图片为什么没有输出? -#### Q3.4.26: 目前paddle hub serving 只支持 imgpath,如果我想用imgurl 去哪里改呢? +**A**:需要检查以下您配置文件中的路径是否都存在。尤其要注意的是[label_file配置](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/StyleText/README_ch.md#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B)。 +如果您使用的style_image输入没有label信息,您依然需要提供一个图片文件列表。 -**A**: 图片是在这里读取的:https://github.com/PaddlePaddle/PaddleOCR/blob/67ef25d593c4eabfaaceb22daade4577f53bed81/deploy/hubserving/ocr_system/module.py#L55, -可以参考下面的写法,将url path转化为np array(https://cloud.tencent.com/developer/article/1467840) -``` -response = request.urlopen('http://i1.whymtj.com/uploads/tu/201902/9999/52491ae4ba.jpg') -img_array = np.array(bytearray(response.read()), dtype=np.uint8) -img = cv.imdecode(img_array, -1) -``` +#### Q3.1.35 怎样把OCR输出的结果组成有意义的语句呢? -#### Q3.4.27: C++ 端侧部署可以只对OCR的检测部署吗? +**A**:OCR输出的结果包含坐标信息和文字内容两部分。如果您不关心文字的顺序,那么可以直接按box的序号连起来。 +如果需要将文字按照一定的顺序排列,则需要您设定一些规则,对文字的坐标进行处理,例如按照坐标从上到下,从左到右连接识别结果。 +对于一些有规律的垂类场景,可以设定模板,根据位置、内容进行匹配。 +例如识别身份证照片,可以先匹配"姓名","性别"等关键字,根据这些关键字的坐标去推测其他信息的位置,再与识别的结果匹配。 -**A**: 可以的,识别和检测模块是解耦的。如果想对检测部署,需要自己修改一下main函数, -只保留检测相关就可以:https://github.com/PaddlePaddle/PaddleOCR/blob/de3e2e7cd3b8b65ee02d7a41e570fa5b511a3c1d/deploy/cpp_infer/src/main.cpp#L72 +#### Q3.1.36 如何识别竹简上的古文? +**A**:对于字符都是普通的汉字字符的情况,只要标注足够的数据,finetune模型就可以了。如果数据量不足,您可以尝试StyleText工具。 +而如果使用的字符是特殊的古文字、甲骨文、象形文字等,那么首先需要构建一个古文字的字典,之后再进行训练。 @@ -161,7 +159,7 @@ img = cv.imdecode(img_array, -1) **A**:端到端在文字分布密集的业务场景,效率会比较有保证,精度的话看自己业务数据积累情况,如果行级别的识别数据积累比较多的话two-stage会比较好。百度的落地场景,比如工业仪表识别、车牌识别都用到端到端解决方案。 #### Q2.1.4 印章如何识别 -**A**: 1. 使用带tps的识别网络或abcnet,2.使用极坐标变换将图片拉平之后使用crnn +**A**:1. 使用带tps的识别网络或abcnet,2.使用极坐标变换将图片拉平之后使用crnn #### Q2.1.5 多语言的字典里是混合了不同的语种,这个是有什么讲究吗?统一到一个字典里会对精度造成多大的损失? **A**:统一到一个字典里,会造成最后一层FC过大,增加模型大小。如果有特殊需求的话,可以把需要的几种语言合并字典训练模型,合并字典之后如果引入过多的形近字,可能会造成精度损失,字符平衡的问题可能也需要考虑一下。在PaddleOCR里暂时将语言字典分开。 @@ -198,11 +196,11 @@ img = cv.imdecode(img_array, -1) #### Q2.2.6: 当训练数据量少时,如何获取更多的数据? -**A**: 当训练数据量少时,可以尝试以下三种方式获取更多的数据:(1)人工采集更多的训练数据,最直接也是最有效的方式。(2)基于PIL和opencv基本图像处理或者变换。例如PIL中ImageFont, Image, ImageDraw三个模块将文字写到背景中,opencv的旋转仿射变换,高斯滤波等。(3)利用数据生成算法合成数据,例如pix2pix等算法。 +**A**:当训练数据量少时,可以尝试以下三种方式获取更多的数据:(1)人工采集更多的训练数据,最直接也是最有效的方式。(2)基于PIL和opencv基本图像处理或者变换。例如PIL中ImageFont, Image, ImageDraw三个模块将文字写到背景中,opencv的旋转仿射变换,高斯滤波等。(3)利用数据生成算法合成数据,例如pix2pix等算法。 #### Q2.2.7: 论文《Editing Text in the Wild》中文本合成方法SRNet有什么特点? -**A**: SRNet是借鉴GAN中图像到图像转换、风格迁移的想法合成文本数据。不同于通用GAN的方法只选择一个分支,SRNet将文本合成任务分解为三个简单的子模块,提升合成数据的效果。这三个子模块为不带背景的文本风格迁移模块、背景抽取模块和融合模块。PaddleOCR计划将在2020年12月中旬开源基于SRNet的实用模型。 +**A**:SRNet是借鉴GAN中图像到图像转换、风格迁移的想法合成文本数据。不同于通用GAN的方法只选择一个分支,SRNet将文本合成任务分解为三个简单的子模块,提升合成数据的效果。这三个子模块为不带背景的文本风格迁移模块、背景抽取模块和融合模块。PaddleOCR计划将在2020年12月中旬开源基于SRNet的实用模型。 ### 模型训练调优 @@ -352,7 +350,7 @@ img = cv.imdecode(img_array, -1) #### Q3.1.13:识别模型框出来的位置太紧凑,会丢失边缘的文字信息,导致识别错误 -**A**: 可以在命令中加入 --det_db_unclip_ratio ,参数[定义位置](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/tools/infer/utility.py#L48),这个参数是检测后处理时控制文本框大小的,默认1.6,可以尝试改成2.5或者更大,反之,如果觉得文本框不够紧凑,也可以把该参数调小。 +**A**:可以在命令中加入 --det_db_unclip_ratio ,参数[定义位置](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/tools/infer/utility.py#L48),这个参数是检测后处理时控制文本框大小的,默认1.6,可以尝试改成2.5或者更大,反之,如果觉得文本框不够紧凑,也可以把该参数调小。 #### Q3.1.14:英文手写体识别有计划提供的预训练模型吗? @@ -416,7 +414,7 @@ python3 -m pip install paddlepaddle-gpu==2.0.0rc1 -i https://mirror.baidu.com/py #### Q3.1.24: PaddleOCR develop分支和dygraph分支的区别? -**A** 目前PaddleOCR有四个分支,分别是: +**A**:目前PaddleOCR有四个分支,分别是: - develop:基于Paddle静态图开发的分支,推荐使用paddle1.8 或者2.0版本,该分支具备完善的模型训练、预测、推理部署、量化裁剪等功能,领先于release/1.1分支。 - release/1.1:PaddleOCR 发布的第一个稳定版本,基于静态图开发,具备完善的训练、预测、推理部署、量化裁剪等功能。 @@ -429,34 +427,59 @@ python3 -m pip install paddlepaddle-gpu==2.0.0rc1 -i https://mirror.baidu.com/py #### Q3.1.25: 使用dygraph分支,在docker中训练PaddleOCR的时候,数据路径没有任何问题,但是一直报错`reader rasied an exception`,这是为什么呢? -**A** 创建docker的时候,`/dev/shm`的默认大小为64M,如果使用多进程读取数据,共享内存可能不够,因此需要给`/dev/shm`分配更大的空间,在创建docker的时候,传入`--shm-size=8g`表示给`/dev/shm`分配8g的空间。 +**A**:创建docker的时候,`/dev/shm`的默认大小为64M,如果使用多进程读取数据,共享内存可能不够,因此需要给`/dev/shm`分配更大的空间,在创建docker的时候,传入`--shm-size=8g`表示给`/dev/shm`分配8g的空间。 #### Q3.1.26: 在repo中没有找到Lite和PaddleServing相关的部署教程,这是在哪里呢? -**A** 目前PaddleOCR的默认分支为dygraph,关于Lite和PaddleLite的动态图部署还在适配中,如果希望在Lite端或者使用PaddleServing部署,推荐使用develop分支(静态图)的代码。 +**A**:目前PaddleOCR的默认分支为dygraph,关于Lite和PaddleLite的动态图部署还在适配中,如果希望在Lite端或者使用PaddleServing部署,推荐使用develop分支(静态图)的代码。 #### Q3.1.27: 如何可视化acc,loss曲线图,模型网络结构图等? -**A** 在配置文件里有`use_visualdl`的参数,设置为True即可,更多的使用命令可以参考:[VisualDL使用指南](https://www.paddlepaddle.org.cn/documentation/docs/zh/2.0-rc1/guides/03_VisualDL/visualdl.html)。 +**A**:在配置文件里有`use_visualdl`的参数,设置为True即可,更多的使用命令可以参考:[VisualDL使用指南](https://www.paddlepaddle.org.cn/documentation/docs/zh/2.0-rc1/guides/03_VisualDL/visualdl.html)。 #### Q3.1.28: 在使用StyleText数据合成工具的时候,报错`ModuleNotFoundError: No module named 'utils.config'`,这是为什么呢? -**A** 有2个解决方案 +**A**:有2个解决方案 - 在StyleText路径下面设置PYTHONPATH:`export PYTHONPATH=./` - 拉取最新的代码 #### Q3.1.29: PPOCRLabel创建矩形框时只能拖出正方形,如何进行矩形标注? -**A** 取消勾选:“编辑”-“正方形标注” +**A**:取消勾选:“编辑”-“正方形标注” #### Q3.1.30: Style-Text 如何不文字风格迁移,就像普通文本生成程序一样默认字体直接输出到分割的背景图? -**A** 使用image_synth模式会输出fake_bg.jpg,即为背景图。如果想要批量提取背景,可以稍微修改一下代码,将fake_bg保存下来即可。要修改的位置: +**A**:使用image_synth模式会输出fake_bg.jpg,即为背景图。如果想要批量提取背景,可以稍微修改一下代码,将fake_bg保存下来即可。要修改的位置: https://github.com/PaddlePaddle/PaddleOCR/blob/de3e2e7cd3b8b65ee02d7a41e570fa5b511a3c1d/StyleText/engine/synthesisers.py#L68 #### Q3.1.31: 怎么输出网络结构以及每层的参数信息? -**A** 可以使用 `paddle.summary`, 具体参考:https://www.paddlepaddle.org.cn/documentation/docs/zh/2.0-rc1/api/paddle/hapi/model_summary/summary_cn.html#summary。 +**A**:可以使用 `paddle.summary`, 具体参考:https://www.paddlepaddle.org.cn/documentation/docs/zh/2.0-rc1/api/paddle/hapi/model_summary/summary_cn.html#summary。 + +#### Q3.1.32 能否修改StyleText配置文件中的分辨率? + +**A**:StyleText目前的训练数据主要是高度32的图片,建议不要改变高度。未来我们会支持更丰富的分辨率。 + +#### Q3.1.33 StyleText是否可以更换字体文件? + +**A**:StyleText项目中的字体文件为标准字体,主要用作模型的输入部分,不能够修改。 +StyleText的用途主要是:提取style_image中的字体、背景等style信息,根据语料生成同样style的图片。 + +#### Q3.1.34 StyleText批量生成图片为什么没有输出? + +**A**:需要检查以下您配置文件中的路径是否都存在。尤其要注意的是[label_file配置](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/StyleText/README_ch.md#%E5%BF%AB%E9%80%9F%E4%B8%8A%E6%89%8B)。 +如果您使用的style_image输入没有label信息,您依然需要提供一个图片文件列表。 + +#### Q3.1.35 怎样把OCR输出的结果组成有意义的语句呢? + +**A**:OCR输出的结果包含坐标信息和文字内容两部分。如果您不关心文字的顺序,那么可以直接按box的序号连起来。 +如果需要将文字按照一定的顺序排列,则需要您设定一些规则,对文字的坐标进行处理,例如按照坐标从上到下,从左到右连接识别结果。 +对于一些有规律的垂类场景,可以设定模板,根据位置、内容进行匹配。 +例如识别身份证照片,可以先匹配"姓名","性别"等关键字,根据这些关键字的坐标去推测其他信息的位置,再与识别的结果匹配。 + +#### Q3.1.36 如何识别竹简上的古文? +**A**:对于字符都是普通的汉字字符的情况,只要标注足够的数据,finetune模型就可以了。如果数据量不足,您可以尝试StyleText工具。 +而如果使用的字符是特殊的古文字、甲骨文、象形文字等,那么首先需要构建一个古文字的字典,之后再进行训练。 ### 数据集 @@ -519,8 +542,8 @@ https://github.com/PaddlePaddle/PaddleOCR/blob/de3e2e7cd3b8b65ee02d7a41e570fa5b5 #### Q3.2.11:有哪些标注工具可以标注OCR数据集? -**A**:您可以参考:https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_en/data_annotation_en.md。 -我们计划推出高效标注OCR数据的标注工具,请您持续关注PaddleOCR的近期更新。 +**A**:推荐您使用PPOCRLabel工具。 +您还可以参考:https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_en/data_annotation_en.md。 #### Q3.2.12:一些特殊场景的数据识别效果差,但是数据量很少,不够用来finetune怎么办? @@ -539,15 +562,15 @@ https://github.com/PaddlePaddle/PaddleOCR/blob/de3e2e7cd3b8b65ee02d7a41e570fa5b5 #### Q3.2.15: 文本标注工具PPOCRLabel有什么特色? -**A**: PPOCRLabel是一个半自动文本标注工具,它使用基于PPOCR的中英文OCR模型,预先预测文本检测和识别结果,然后用户对上述结果进行校验和修正就行,大大提高用户的标注效率。同时导出的标注结果直接适配PPOCR训练所需要的数据格式, +**A**:PPOCRLabel是一个半自动文本标注工具,它使用基于PPOCR的中英文OCR模型,预先预测文本检测和识别结果,然后用户对上述结果进行校验和修正就行,大大提高用户的标注效率。同时导出的标注结果直接适配PPOCR训练所需要的数据格式, #### Q3.2.16: 文本标注工具PPOCRLabel,可以更换模型吗? -**A**: PPOCRLabel中OCR部署方式采用的基于pip安装whl包快速推理,可以参考相关文档更换模型路径,进行特定任务的标注适配。基于pip安装whl包快速推理的文档如下,https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_ch/whl.md。 +**A**:PPOCRLabel中OCR部署方式采用的基于pip安装whl包快速推理,可以参考相关文档更换模型路径,进行特定任务的标注适配。基于pip安装whl包快速推理的文档如下,https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_ch/whl.md。 #### Q3.2.17: 文本标注工具PPOCRLabel支持的运行环境有哪些? -**A**: PPOCRLabel可运行于Linux、Windows、MacOS等多种系统。操作步骤可以参考文档,https://github.com/PaddlePaddle/PaddleOCR/blob/develop/PPOCRLabel/README.md +**A**:PPOCRLabel可运行于Linux、Windows、MacOS等多种系统。操作步骤可以参考文档,https://github.com/PaddlePaddle/PaddleOCR/blob/develop/PPOCRLabel/README.md @@ -660,15 +683,15 @@ ps -axu | grep train.py | awk '{print $2}' | xargs kill -9 #### Q3.3.20: 文字检测时怎么模糊的数据增强? -**A**: 模糊的数据增强需要修改代码进行添加,以DB为例,参考[Normalize](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/ppocr/data/imaug/operators.py#L60) ,添加模糊的增强就行 +**A**:模糊的数据增强需要修改代码进行添加,以DB为例,参考[Normalize](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/ppocr/data/imaug/operators.py#L60) ,添加模糊的增强就行 #### Q3.3.21: 文字检测时怎么更改图片旋转的角度,实现360度任意旋转? -**A**: 将[这里](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/ppocr/data/imaug/iaa_augment.py#L64) 的(-10,10) 改为(-180,180)即可 +**A**:将[这里](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/ppocr/data/imaug/iaa_augment.py#L64) 的(-10,10) 改为(-180,180)即可 #### Q3.3.22: 训练数据的长宽比过大怎么修改shape -**A**: 识别修改[这里](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yaml#L75) , +**A**:识别修改[这里](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/configs/rec/ch_ppocr_v2.0/rec_chinese_lite_train_v2.0.yaml#L75) , 检测修改[这里](https://github.com/PaddlePaddle/PaddleOCR/blob/dygraph/configs/det/ch_ppocr_v2.0/ch_det_mv3_db_v2.0.yml#L85) #### Q3.3.23:检测模型训练或预测时出现elementwise_add报错 @@ -677,15 +700,15 @@ ps -axu | grep train.py | awk '{print $2}' | xargs kill -9 #### Q3.3.24: DB检测训练输入尺寸640,可以改大一些吗? -**A**: 不建议改大。检测模型训练输入尺寸是预处理中random crop后的尺寸,并非直接将原图进行resize,多数场景下这个尺寸并不小了,改大后可能反而并不合适,而且训练会变慢。另外,代码里可能有的地方参数按照预设输入尺寸适配的,改大后可能有隐藏风险。 +**A**:不建议改大。检测模型训练输入尺寸是预处理中random crop后的尺寸,并非直接将原图进行resize,多数场景下这个尺寸并不小了,改大后可能反而并不合适,而且训练会变慢。另外,代码里可能有的地方参数按照预设输入尺寸适配的,改大后可能有隐藏风险。 #### Q3.3.25: 识别模型训练时,loss能正常下降,但acc一直为0 -**A**: 识别模型训练初期acc为0是正常的,多训一段时间指标就上来了。 +**A**:识别模型训练初期acc为0是正常的,多训一段时间指标就上来了。 #### Q3.3.26: PaddleOCR在训练的时候一直使用cosine_decay的学习率下降策略,这是为什么呢? -**A**: cosine_decay表示在训练的过程中,学习率按照cosine的变化趋势逐渐下降至0,在迭代轮数更长的情况下,比常量的学习率变化策略会有更好的收敛效果,因此在实际训练的时候,均采用了cosine_decay,来获得精度更高的模型。 +**A**:cosine_decay表示在训练的过程中,学习率按照cosine的变化趋势逐渐下降至0,在迭代轮数更长的情况下,比常量的学习率变化策略会有更好的收敛效果,因此在实际训练的时候,均采用了cosine_decay,来获得精度更高的模型。 @@ -808,7 +831,7 @@ ps -axu | grep train.py | awk '{print $2}' | xargs kill -9 ### Q3.4.26: 目前paddle hub serving 只支持 imgpath,如果我想用imgurl 去哪里改呢? -**A**: 图片是在这里读取的:https://github.com/PaddlePaddle/PaddleOCR/blob/67ef25d593c4eabfaaceb22daade4577f53bed81/deploy/hubserving/ocr_system/module.py#L55, +**A**:图片是在这里读取的:https://github.com/PaddlePaddle/PaddleOCR/blob/67ef25d593c4eabfaaceb22daade4577f53bed81/deploy/hubserving/ocr_system/module.py#L55, 可以参考下面的写法,将url path转化为np array(https://cloud.tencent.com/developer/article/1467840) ``` response = request.urlopen('http://i1.whymtj.com/uploads/tu/201902/9999/52491ae4ba.jpg') @@ -818,5 +841,5 @@ img = cv.imdecode(img_array, -1) ### Q3.4.27: C++ 端侧部署可以只对OCR的检测部署吗? -**A** 可以的,识别和检测模块是解耦的。如果想对检测部署,需要自己修改一下main函数, +**A**:可以的,识别和检测模块是解耦的。如果想对检测部署,需要自己修改一下main函数, 只保留检测相关就可以:https://github.com/PaddlePaddle/PaddleOCR/blob/de3e2e7cd3b8b65ee02d7a41e570fa5b511a3c1d/deploy/cpp_infer/src/main.cpp#L72 diff --git a/doc/doc_ch/algorithm_overview.md b/doc/doc_ch/algorithm_overview.md index 361e251bc5a35812abc3081e64343b0d8c2c9c05..8cebce3adf5c414674d2990c1b2a018ae52e57f6 100755 --- a/doc/doc_ch/algorithm_overview.md +++ b/doc/doc_ch/algorithm_overview.md @@ -21,13 +21,13 @@ PaddleOCR开源的文本检测算法列表: |EAST|MobileNetV3|78.24%|79.15%|78.69%|[下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_mv3_east_v2.0_train.tar)| |DB|ResNet50_vd|86.41%|78.72%|82.38%|[下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_db_v2.0_train.tar)| |DB|MobileNetV3|77.29%|73.08%|75.12%|[下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_mv3_db_v2.0_train.tar)| -|SAST|ResNet50_vd|91.83%|81.80%|86.52%|[下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_icdar15_v2.0_train.tar)| +|SAST|ResNet50_vd|91.39%|83.77%|87.42%|[下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_icdar15_v2.0_train.tar)| 在Total-text文本检测公开数据集上,算法效果如下: |模型|骨干网络|precision|recall|Hmean|下载链接| | --- | --- | --- | --- | --- | --- | -|SAST|ResNet50_vd|89.05%|76.80%|82.47%|[下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_totaltext_v2.0_train.tar)| +|SAST|ResNet50_vd|89.63%|78.44%|83.66%|[下载链接](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_totaltext_v2.0_train.tar)| **说明:** SAST模型训练额外加入了icdar2013、icdar2017、COCO-Text、ArT等公开数据集进行调优。PaddleOCR用到的经过整理格式的英文公开数据集下载:[百度云地址](https://pan.baidu.com/s/12cPnZcVuV1zn5DOd4mqjVw) (提取码: 2bpi) diff --git a/doc/doc_en/algorithm_overview_en.md b/doc/doc_en/algorithm_overview_en.md index 427b3de685f2708dc9de812ef4d5d2ff64770e6c..f2349a1c3cb5096db23ff2a4465c51e0abfca36b 100755 --- a/doc/doc_en/algorithm_overview_en.md +++ b/doc/doc_en/algorithm_overview_en.md @@ -23,13 +23,13 @@ On the ICDAR2015 dataset, the text detection result is as follows: |EAST|MobileNetV3|78.24%|79.15%|78.69%|[Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_mv3_east_v2.0_train.tar)| |DB|ResNet50_vd|86.41%|78.72%|82.38%|[Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_db_v2.0_train.tar)| |DB|MobileNetV3|77.29%|73.08%|75.12%|[Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_mv3_db_v2.0_train.tar)| -|SAST|ResNet50_vd|91.83%|81.80%|86.52%|[Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_icdar15_v2.0_train.tar)| +|SAST|ResNet50_vd|91.39%|83.77%|87.42%|[Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_icdar15_v2.0_train.tar)| On Total-Text dataset, the text detection result is as follows: |Model|Backbone|precision|recall|Hmean|Download link| | --- | --- | --- | --- | --- | --- | -|SAST|ResNet50_vd|89.05%|76.80%|82.47%|[Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_totaltext_v2.0_train.tar)| +|SAST|ResNet50_vd|89.63%|78.44%|83.66%|[Download link](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r50_vd_sast_totaltext_v2.0_train.tar)| **Note:** Additional data, like icdar2013, icdar2017, COCO-Text, ArT, was added to the model training of SAST. Download English public dataset in organized format used by PaddleOCR from [Baidu Drive](https://pan.baidu.com/s/12cPnZcVuV1zn5DOd4mqjVw) (download code: 2bpi). diff --git a/ppocr/data/__init__.py b/ppocr/data/__init__.py index 7b0faf1260117297bfb6a77dda1e7898df1e0466..4e1ff0ae6c0adeb8ebed5fdb18d2596aeba1fbff 100644 --- a/ppocr/data/__init__.py +++ b/ppocr/data/__init__.py @@ -66,8 +66,10 @@ def build_dataloader(config, mode, device, logger): batch_size = loader_config['batch_size_per_card'] drop_last = loader_config['drop_last'] num_workers = loader_config['num_workers'] - - use_shared_memory = False + if 'use_shared_memory' in loader_config.keys(): + use_shared_memory = loader_config['use_shared_memory'] + else: + use_shared_memory = True if mode == "Train": #Distribute data to multiple cards batch_sampler = DistributedBatchSampler( @@ -75,7 +77,6 @@ def build_dataloader(config, mode, device, logger): batch_size=batch_size, shuffle=False, drop_last=drop_last) - use_shared_memory = True else: #Distribute data to single card batch_sampler = BatchSampler(