Pārlūkot izejas kodu

Delete static/examples/industrial_quality_inspection directory

FlyingQianMM 4 gadi atpakaļ
vecāks
revīzija
f83ce02393
29 mainītis faili ar 0 papildinājumiem un 1109 dzēšanām
  1. 0 99
      static/examples/industrial_quality_inspection/README.md
  2. 0 93
      static/examples/industrial_quality_inspection/accuracy_improvement.md
  3. 0 214
      static/examples/industrial_quality_inspection/cal_tp_fp.py
  4. 0 160
      static/examples/industrial_quality_inspection/compare.py
  5. 0 14
      static/examples/industrial_quality_inspection/dataset.md
  6. 0 26
      static/examples/industrial_quality_inspection/error_analysis.py
  7. 0 114
      static/examples/industrial_quality_inspection/gpu_solution.md
  8. BIN
      static/examples/industrial_quality_inspection/image/after_clahe.png
  9. BIN
      static/examples/industrial_quality_inspection/image/allclasses_analysis_example.png
  10. BIN
      static/examples/industrial_quality_inspection/image/before_clahe.png
  11. BIN
      static/examples/industrial_quality_inspection/image/budaodian_analysis_example.png
  12. BIN
      static/examples/industrial_quality_inspection/image/cahua_analysis_example.png
  13. BIN
      static/examples/industrial_quality_inspection/image/compare_budaodian-116.jpg
  14. BIN
      static/examples/industrial_quality_inspection/image/image-level_tp_fp.png
  15. BIN
      static/examples/industrial_quality_inspection/image/jiaoweiloudi_analysis_example.png
  16. BIN
      static/examples/industrial_quality_inspection/image/jupi_analysis_example.png
  17. BIN
      static/examples/industrial_quality_inspection/image/loudi_analysis_example.png
  18. BIN
      static/examples/industrial_quality_inspection/image/penliu_analysis_example.png
  19. BIN
      static/examples/industrial_quality_inspection/image/qikeng_analysis_example.png
  20. BIN
      static/examples/industrial_quality_inspection/image/qipao_analysis_example.png
  21. BIN
      static/examples/industrial_quality_inspection/image/visualize_budaodian-116.jpg
  22. BIN
      static/examples/industrial_quality_inspection/image/zangdian_analysis_example.png
  23. BIN
      static/examples/industrial_quality_inspection/image/zase_analysis_example.png
  24. 0 61
      static/examples/industrial_quality_inspection/params_analysis.py
  25. 0 35
      static/examples/industrial_quality_inspection/predict.py
  26. 0 102
      static/examples/industrial_quality_inspection/tp_fp_list.md
  27. 0 58
      static/examples/industrial_quality_inspection/train_pruned_yolov3.py
  28. 0 74
      static/examples/industrial_quality_inspection/train_rcnn.py
  29. 0 59
      static/examples/industrial_quality_inspection/train_yolov3.py

+ 0 - 99
static/examples/industrial_quality_inspection/README.md

@@ -1,99 +0,0 @@
-# 工业质检
-
-本案例面向工业质检场景里的铝材表面缺陷检测,提供了针对GPU端和CPU端两种部署场景下基于PaddleX的解决方案,希望通过梳理优化模型精度和性能的思路能帮助用户更高效地解决实际质检应用中的问题。
-
-## 1. GPU端解决方案
-
-### 1.1 数据集介绍
-
-本案例使用[天池铝材表面缺陷检测初赛](https://tianchi.aliyun.com/competition/entrance/231682/introduction)数据集,共有3005张图片,分别检测擦花、杂色、漏底、不导电、桔皮、喷流、漆泡、起坑、脏点和角位漏底10种缺陷,这10种缺陷的定义和示例可点击文档[天池铝材表面缺陷检测初赛数据集示例](./dataset.md)查看。
-
-将这3005张图片按9:1随机切分成2713张图片的训练集和292张图片的验证集。
-
-### 1.2 精度优化
-
-本小节侧重展示在模型迭代过程中优化精度的思路,在本案例中,有些优化策略获得了精度收益,而有些没有。在其他质检场景中,可根据实际情况尝试这些优化策略。点击文档[精度优化](./accuracy_improvement.md)查看。
-
-### 1.3 性能优化
-
-在完成模型精度优化之后,从以下两个方面对模型进行加速:
-
-#### (1) 减少FPN部分的通道数量
-
-将FPN部分的通道数量由原本的256减少至64,使用方式在定义模型[FasterRCNN](https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-fasterrcnn)类时设置参数`fpn_num_channels`为64即可,需要重新对模型进行训练。
-
-#### (2) 减少测试阶段的候选框数量
-
-将测试阶段RPN部分做非极大值抑制计算的候选框数量由原本的6000减少至500,将RPN部分做完非极大值抑制后保留的候选框数量由原本的1000减少至300。使用方式在定义模型[FasterRCNN](https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-fasterrcnn)类时设置参数`test_pre_nms_top_n`为500,`test_post_nms_top_n`为300。
-
-采用Fluid C++预测引擎在Tesla P40上测试模型的推理时间(输入数据拷贝至GPU的时间、计算时间、数据拷贝至CPU的时间),输入大小设置为800x1333,加速前后推理时间如下表所示:
-
-| 模型 | 推理时间 (ms/image)| VOC mAP (%) |
-| -- | -- | -- |
-| baseline | 66.51 | 88.87 |
-| + fpn channel=64 + test proposal=pre/post topk 500/300 | 46.08 | 87.72 |
-
-### 1.4 最终方案
-
-本案例面向GPU端的最终方案是选择二阶段检测模型FasterRCNN,其骨干网络选择加入了可变形卷积(DCN)的ResNet50_vd,训练时使用SSLD蒸馏方案训练得到的ResNet50_vd预训练模型,FPN部分的通道数量设置为64。使用复核过的数据集,训练阶段数据增强策略采用RandomHorizontalFlip、RandomDistort、RandomCrop,并加入背景图片。测试阶段的RPN部分做非极大值抑制计算的候选框数量由原本的6000减少至500、做完非极大值抑制后保留的候选框数量由原本的1000减少至300。模型在验证集上的VOC mAP为87.72%。
-
-在Tesla P40的Linux系统下,对于输入大小是800 x 1333的模型,图像预处理时长为30ms/image,模型的推理时间为46.08ms/image,包括输入数据拷贝至GPU的时间、计算时间、数据拷贝至CPU的时间。
-
-| 模型 | VOC mAP (%) | 推理时间 (ms/image)
-| -- | -- | -- |
-| FasterRCNN-ResNet50_vd_ssld | 81.05 | 48.62 |
-| + dcn | 88.09 | 66.51 |
-| + RandomHorizontalFlip/RandomDistort/RandomCrop | 90.23| 66.51 |
-| + background images | 88.87 | 66.51 |
-| + fpn channel=64 | 87.79 | 48.65 |
-| + test proposal=pre/post topk 500/300 | 87.72 | 46.08 |
-
-具体的训练和部署流程点击文档[GPU端最终解决方案](./gpu_solution.md)进行查看。
-
-## 2. CPU端解决方案
-
-为了实现高效的模型推理,面向CPU端的模型选择精度和效率皆优的单阶段检测模型YOLOv3,骨干网络选择基于PaddleClas中SSLD蒸馏方案训练得到的MobileNetv3_large。训练完成后,对模型做剪裁操作,以提升模型的性能。模型在验证集上的VOC mAP为79.02%。
-
-部署阶段,借助OpenVINO预测引擎完成在Intel(R) Core(TM) i9-9820X CPU @ 3.30GHz Windows系统下高效推理。对于输入大小是608 x 608的模型,图像预处理时长为38.69 ms/image,模型的推理时间为34.50ms/image。
-
-| 模型 | VOC mAP (%) | Inference Speed (ms/image)
-| -- | -- | -- |
-| YOLOv3-MobileNetv3_ssld | 81.31 | 56.71 |
-| pruned YOLOv3-MobileNetv3_ssld | 78.60 | 34.50 |
-
-### 模型训练
-
-[环境前置依赖](./gpu_solution.md#%E5%89%8D%E7%BD%AE%E4%BE%9D%E8%B5%96)、[下载PaddleX源码](./gpu_solution.md#1-%E4%B8%8B%E8%BD%BDpaddlex%E6%BA%90%E7%A0%81)、[下载数据集](./gpu_solution.md#2-%E4%B8%8B%E8%BD%BD%E6%95%B0%E6%8D%AE%E9%9B%86)与GPU端是一样的,可点击文档[GPU端最终解决方案](./gpu_solution.md)查看,在此不做赘述。
-
-如果不想再次训练模型,可以直接下载已经训练好的模型完成后面的模型测试和部署推理:
-
-```
-wget https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/models/yolov3_mobilenetv3_large_pruned.tar.gz
-tar xvf yolov3_mobilenetv3_large_pruned.tar.gz
-```
-
-运行以下代码进行模型训练,代码会自动下载数据集,如若事先下载了数据集,需将下载和解压铝材缺陷检测数据集的相关行注释掉。代码中默认使用0,1,2,3,4,5,6,7号GPU训练,可根据实际情况设置卡号并调整`batch_size`和`learning_rate`。
-
-```
-python train_yolov3.py
-```
-
-### 模型剪裁
-
-运行以下代码,分析在不同的精度损失下模型各层的剪裁比例:
-
-```
-python params_analysis.py
-```
-
-设置可允许的精度损失为0.05,对模型进行剪裁,剪裁后需要重新训练模型:
-
-```
-python train_pruned_yolov3.py
-```
-
-[分析预测错误的原因](./gpu_solution.md#4-%E5%88%86%E6%9E%90%E9%A2%84%E6%B5%8B%E9%94%99%E8%AF%AF%E7%9A%84%E5%8E%9F%E5%9B%A0)、[统计图片级召回率和误检率](./gpu_solution.md#5-%E7%BB%9F%E8%AE%A1%E5%9B%BE%E7%89%87%E7%BA%A7%E5%8F%AC%E5%9B%9E%E7%8E%87%E5%92%8C%E8%AF%AF%E6%A3%80%E7%8E%87)、[模型测试](./gpu_solution.md#6-%E6%A8%A1%E5%9E%8B%E6%B5%8B%E8%AF%95)这些步骤与GPU端是一样的,可点击文档[GPU端最终解决方案](./gpu_solution.md)查看,在此不做赘述。
-
-### 推理部署
-
-本案例采用C++部署方式,通过OpenVINO将模型部署在Intel(R) Core(TM) i9-9820X CPU @ 3.30GHz的Windows系统下,具体的部署流程请参考文档[PaddleX模型多端安全部署/OpenVINO部署](https://paddlex.readthedocs.io/zh_CN/develop/deploy/openvino/index.html)。

+ 0 - 93
static/examples/industrial_quality_inspection/accuracy_improvement.md

@@ -1,93 +0,0 @@
-# 精度优化
-
-本小节侧重展示在模型迭代过程中优化精度的思路,在本案例中,有些优化策略获得了精度收益,而有些没有。在其他质检场景中,可根据实际情况尝试这些优化策略。
-
-## (1) 基线模型选择
-
-相较于单阶段检测模型,二阶段检测模型的精度更高但是速度更慢。考虑到是部署到GPU端,本案例选择二阶段检测模型FasterRCNN作为基线模型,其骨干网络选择ResNet50_vd,并使用基于PaddleClas中SSLD蒸馏方案训练得到的ResNet50_vd预训练模型(ImageNet1k验证集上Top1 Acc为82.39%)。训练完成后,模型在验证集上的精度VOC mAP为73.36%。
-
-## (2) 模型效果分析
-
-使用PaddleX提供的[paddlex.det.coco_error_analysis](https://paddlex.readthedocs.io/zh_CN/develop/apis/visualize.html#paddlex-det-coco-error-analysis)接口对模型在验证集上预测错误的原因进行分析,分析结果以图表的形式展示如下:
-
-| all classes| 擦花 | 杂色 | 漏底 | 不导电 | 桔皮 | 喷流 | 漆泡 | 起坑 | 脏点 | 角位漏底 |
-| -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- |
-| ![](image/allclasses_analysis_example.png) | ![](image/cahua_analysis_example.png) | ![](image/zase_analysis_example.png) | ![](image/loudi_analysis_example.png) | ![](image/budaodian_analysis_example.png) | ![](image/jupi_analysis_example.png) | ![](image/penliu_analysis_example.png) | ![](image/qipao_analysis_example.png) | ![](image/qikeng_analysis_example.png) | ![](image/zangdian_analysis_example.png) | ![](image/jiaoweiloudi_analysis_example.png) |
-
-分析图表展示了7条Precision-Recall(PR)曲线,每一条曲线表示的Average Precision (AP)比它左边那条高,原因是逐步放宽了评估要求。以擦花类为例,各条PR曲线的评估要求解释如下:
-
-* C75: 在IoU设置为0.75时的PR曲线, AP为0.001。
-* C50: 在IoU设置为0.5时的PR曲线,AP为0.622。C50与C75之间的白色区域面积代表将IoU从0.75放宽至0.5带来的AP增益。
-* Loc: 在IoU设置为0.1时的PR曲线,AP为0.740。Loc与C50之间的蓝色区域面积代表将IoU从0.5放宽至0.1带来的AP增益。蓝色区域面积越大,表示越多的检测框位置不够精准。
-* Sim: 在Loc的基础上,如果检测框与真值框的类别不相同,但两者同属于一个亚类,则不认为该检测框是错误的,在这种评估要求下的PR曲线, AP为0.742。Sim与Loc之间的红色区域面积越大,表示子类间的混淆程度越高。VOC格式的数据集所有的类别都属于同一个亚类。
-* Oth: 在Sim的基础上,如果检测框与真值框的亚类不相同,则不认为该检测框是错误的,在这种评估要求下的PR曲线,AP为0.742。Oth与Sim之间的绿色区域面积越大,表示亚类间的混淆程度越高。VOC格式的数据集中所有的类别都属于同一个亚类,故不存在亚类间的混淆。
-* BG: 在Oth的基础上,背景区域上的检测框不认为是错误的,在这种评估要求下的PR曲线,AP为92.1。BG与Oth之间的紫色区域面积越大,表示背景区域被误检的数量越多。
-* FN: 在BG的基础上,漏检的真值框不认为是错误的,在这种评估要求下的PR曲线,AP为1.00。FN与BG之间的橙色区域面积越大,表示漏检的真值框数量越多。
-
-从分析图表中可以看出,杂色、桔皮、起坑三类检测效果较好,角位漏底存在少许检测框没有达到IoU 0.5的情况,问题较多的是擦花、不导电、喷流、漆泡、脏点。擦花类最严重的问题是误检、位置不精准、漏检,不导电类最严重的问题是漏检、位置不精准,喷流类和漆泡类最严重的问题是位置不精准、误检,脏点类最严重的问题是误检、漏检。为进一步理解造成这些问题的原因,将验证集上的预测结果进行了可视化,然后发现数据集标注存在以下问题:
-
-* 轻微的缺陷不视为缺陷,但轻微的界定不明确,有些轻微的缺陷被标注了,造成误检较多
-* 不导电、漏底、角位漏底外观极其相似,肉眼难以区分,导致这三类极其容易混淆而使得评估时误检或漏检的产生
-* 有些轻微的擦花和脏点被标注了,有些明显的反而没有被标注,造成了这两类误检和漏检情况都较为严重
-* 喷流和漆泡多为连续性的缺陷,一处喷流,其水平线上还会有其他喷流,一个气泡,其水平线上还会有一排气泡。但有时候把这些连续性的缺陷标注成一个目标,有时候又单独地标注不同的部分。导致模型有时候检测单独部分,有时候又检测整体,造成这两类位置不精准、误检较多。
-
-## (3) 数据复核
-
-为了减少原始数据标注的诸多问题对模型优化的影响,需要对数据进行复核。复核准则示例如下:
-
-* 擦花:不明显的擦花不标注,面状擦花以同一个框表示,条状擦花一条擦花以一个框表示
-* 漏底、角位漏底、不导电:三者过于相似,归为一类
-* 桔皮:忽略不是大颗粒状的表面
-* 喷流:明显是一条喷流的就用一个框表示,不是的话用多个框表示
-* 漆泡:不要单独标一个点,一连串点标一个框
-* 脏点:忽略轻微脏点
-
-对数据集复核并重新标注后,将FasterRCNN-ResNet50_vd_ssld重新在训练集上进行训练,模型在验证集上的VOC mAP为81.05%。
-
-## (4) 可变形卷积加入
-
-由于喷流、漆泡的形态不规则,导致这两类的很多预测框位置不精准。为了解决该问题,选择在骨干网络ResNet50_vd中使用可变形卷积(DCN)。重新训练后,模型在验证集上的VOC mAP为88.09%,喷流的VOC AP由57.3%提升至78.7%,漆泡的VOC AP由74.7%提升至96.7%。
-
-## (5) 数据增强选择
-
-在(4)的基础上,选择加入一些数据增强策略来进一步提升模型的精度。本案例选择同时使用[RandomHorizontalFlip](https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html#randomhorizontalflip)、[RandomDistort](https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html#randomdistort)、[RandomCrop](https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html#randomcrop)这三种数据增强方法,重新训练后的模型在验证集上的VOC mAP为90.23%。
-
-除此之外,还可以尝试的数据增强方式有[MultiScaleTraining](https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html#resizebyshort)、[RandomExpand](https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html#randomexpand)。本案例使用的铝材表面缺陷检测数据集中,同一个类别的尺度变化不大,使用MultiScaleTraining或者RandomExpand反而使得原始数据分布发生改变。对此,本案例也进行了实验验证,使用RandomHorizontalFlip + RandomDistort + RandomCrop + MultiScaleTraining数据增强方式训练得到的模型在验证集上的VOC mAP为87.15%,使用RandomHorizontalFlip + RandomDistort + RandomCrop + RandomExpand数据增强方式训练得到的模型在验证集上的的VOC mAP为88.56%。
-
-## (6) 背景图片加入
-
-本案例将数据集中提供的背景图片按9:1切分成了1116张、135张两部分,并使用(5)中训练好的模型在135张背景图片上进行测试,发现图片级误检率高达21.5%。为了降低模型的误检率,使用[paddlex.datasets.VOCDetection.add_negative_samples](https://paddlex.readthedocs.io/zh_CN/develop/apis/datasets.html#add-negative-samples)接口将1116张背景图片加入到原本的训练集中,重新训练后图片级误检率降低至4%。为了不让训练被背景图片主导,本案例通过将`train_list.txt`中的文件路径多写了一遍,从而增加有目标图片的占比。
-
-| 模型 | VOC mAP (%) | 有缺陷图片级召回率 | 背景图片级误检率 |
-| -- | -- | -- | -- |
-| FasterRCNN-ResNet50_vd_ssld + DCN + RandomHorizontalFlip + RandomDistort + RandomCrop | 90.23 | 95.5 | 21.5 |
-| FasterRCNN-ResNet50_vd_ssld + DCN + RandomHorizontalFlip + RandomDistort + RandomCrop + 背景图片 | 88.87 | 95.2 | 4 |
-
-【名词解释】
-
-* 图片级别的召回率:只要在有目标的图片上检测出目标(不论框的个数),该图片被认为召回。批量有目标图片中被召回图片所占的比例,即为图片级别的召回率。
-* 图片级别的误检率:只要在无目标的图片上检测出目标(不论框的个数),该图片被认为误检。批量无目标图片中被误检图片所占的比例,即为图片级别的误检率。
-
-## (7) 分类损失函数选择
-
-降低误检率的措施除了(6)中提到的将背景图片加入训练,还可以将RPN部分的分类损失函数选择为`SigmoidFocalLoss`,将更多的anchors加入训练,增加难分样本的在损失函数的比重进而降低误检率。在定义模型[FasterRCNN](https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-fasterrcnn)类时将参数`rpn_cls_loss`设置为'SigmoidFocalLoss',同时需要调整参数`rpn_focal_loss_alpha`、`rpn_focal_loss_gamma`、`rpn_batch_size_per_im`、`rpn_fg_fraction`的设置。
-
-## (8) 位置回归损失函数选择
-
-RCNN部分的位置回归损失函数除了'SmoothL1Loss'以外,还可以选择'CIoULoss',使用方式在定义模型[FasterRCNN](https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-fasterrcnn)类时设置参数`rcnn_bbox_loss`即可。在本案例中,选择'CIoULoss'并没有带来精度收益,故还是选择'SmoothL1Loss'。其他质检场景下,也可尝试使用'CIoULoss'。
-
-## (9) 正负样本采样方式选择
-
-当目标物体的区域只占图像的一小部分时,可以考虑采用[LibraRCNN](https://arxiv.org/abs/1904.02701)中提出的IoU-balanced Sampling采样方式来获取更多的难分负样本。使用方式在定义模型[FasterRCNN](https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-fasterrcnn)类时将参数`bbox_assigner`设置为'LibraBBoxAssigner'即可。
-
-## (10) 预处理对比度增强
-
-工业界常用灰度相机采集图片,会存在目标与周围背景对比度不明显而无法被检测出的情况。在这种情况下,可以在定义预处理的时候使用[paddlex.det.transforms.CLAHE](https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html#clahe)对灰度图像的对比度进行增强。
-
-| 灰度图 | 对比度增加后的灰度图 |
-| -- | -- |
-| ![](./image/before_clahe.png) | ![](./image/after_clahe.png) |
-
-## (11) 样本生成
-
-对于数量较少的类别或者小目标,可以通过把这些目标物体粘贴在背景图片上来生成新的图片和标注文件,并把这些新的样本加入到训练中从而提升模型精度。目前PaddleX提供了实现该功能的接口,详细见[paddlex.det.paste_objects](https://paddlex.readthedocs.io/zh_CN/develop/apis/tools.html#paddlex-det-paste-objects),需要注意的是,前景目标颜色与背景颜色差异较大时生成的新图片才会比较逼真。

+ 0 - 214
static/examples/industrial_quality_inspection/cal_tp_fp.py

@@ -1,214 +0,0 @@
-# coding: utf8
-# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# 环境变量配置,用于控制是否使用GPU
-# 说明文档:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html#gpu
-import argparse
-import os
-os.environ['CUDA_VISIBLE_DEVICES'] = '0'
-
-import os.path as osp
-import numpy as np
-import matplotlib
-matplotlib.use('Agg')
-import matplotlib.pyplot as plt
-import paddlex as pdx
-
-
-def cal_image_level_recall_rate(model, dataset_dir):
-    """计算置信度(Score)在[0, 1]内以间隔0.01递增取值时,模型在有目标的图像上的图片级召回率。
-
-    图片级召回率:只要在有目标的图片上检测出目标(不论框的个数),该图片被认为召回,
-       批量有目标图片中被召回的图片所占的比例,即为图片级别的召回率。
-
-    Args:
-        model (PaddleX model object): 已加载的PaddleX模型。
-        dataset_dir (str):数据集路径。
-
-    Returns:
-        numpy.array: 形状为101x1的数组,对应置信度从0到1按0.01递增取值时,计算所得图片级别的召回率。
-    """
-
-    print(
-        "Begin to calculate image-level recall rate of positive images. Please wait for a moment..."
-    )
-    file_list = osp.join(dataset_dir, 'val_list.txt')
-    tp = np.zeros((101, 1))
-    positive_num = 0
-    with open(file_list, 'r') as fr:
-        while True:
-            line = fr.readline()
-            if not line:
-                break
-            img_file, xml_file = [osp.join(dataset_dir, x) \
-                    for x in line.strip().split()[:2]]
-            if not osp.exists(img_file):
-                continue
-            if not osp.exists(xml_file):
-                continue
-
-            positive_num += 1
-            results = model.predict(img_file)
-            scores = list()
-            for res in results:
-                scores.append(res['score'])
-            if len(scores) > 0:
-                tp[0:int(np.round(max(scores) / 0.01)), 0] += 1
-    tp = tp / positive_num
-    return tp
-
-
-def cal_image_level_false_positive_rate(model, negative_dir):
-    """计算置信度(Score)在[0, 1]内以间隔0.01递增取值时,模型在无目标的图像上的图片级误检率。
-
-    图片级误检率:只要在无目标的图片上检测出目标(不论框的个数),该图片被认为误检,
-       批量无目标图片中被误检的图片所占的比例,即为图片级别的误检率。
-
-    Args:
-        model (PaddleX model object): 已加载的PaddleX模型。
-        negative_dir (str):无目标图片的文件夹路径。
-
-    Returns:
-        numpy.array: 形状为101x1的数组,对应置信度从0到1按0.01递增取值时,计算所得图片级别的误检率。
-    """
-
-    print(
-        "Begin to calculate image-level false positive rate of negative(background) images. Please wait for a moment..."
-    )
-    fp = np.zeros((101, 1))
-    negative_num = 0
-    for file in os.listdir(negative_dir):
-        file = osp.join(negative_dir, file)
-        results = model.predict(file)
-        negative_num += 1
-        scores = list()
-        for res in results:
-            scores.append(res['score'])
-        if len(scores) > 0:
-            fp[0:int(np.round(max(scores) / 0.01)), 0] += 1
-    fp = fp / negative_num
-    return fp
-
-
-def result2textfile(tp_list, fp_list, save_dir):
-    """将不同置信度阈值下的图片级召回率和图片级误检率保存为文本文件。
-
-    文本文件中内容按照| 置信度阈值 | 图片级召回率 | 图片级误检率 |的格式保存。
-
-    Args:
-        tp_list (numpy.array): 形状为101x1的数组,对应置信度从0到1按0.01递增取值时,计算所得图片级别的召回率。
-        fp_list (numpy.array): 形状为101x1的数组,对应置信度从0到1按0.01递增取值时,计算所得图片级别的误检率。
-        save_dir (str): 文本文件的保存路径。
-
-    """
-
-    tp_fp_list_file = osp.join(save_dir, 'tp_fp_list.txt')
-    with open(tp_fp_list_file, 'w') as f:
-        f.write("| score | recall rate | false-positive rate |\n")
-        f.write("| -- | -- | -- |\n")
-        for i in range(100):
-            f.write("| {:2f} | {:2f} | {:2f} |\n".format(0.01 * i, tp_list[
-                i, 0], fp_list[i, 0]))
-    print("The numerical score-recall_rate-false_positive_rate is saved as {}".
-          format(tp_fp_list_file))
-
-
-def result2imagefile(tp_list, fp_list, save_dir):
-    """将不同置信度阈值下的图片级召回率和图片级误检率保存为图片。
-
-    图片中左子图横坐标表示不同置信度阈值下计算得到的图片级召回率,纵坐标表示各图片级召回率对应的图片级误检率。
-        右边子图横坐标表示图片级召回率,纵坐标表示各图片级召回率对应的置信度阈值。
-
-    Args:
-        tp_list (numpy.array): 形状为101x1的数组,对应置信度从0到1按0.01递增取值时,计算所得图片级别的召回率。
-        fp_list (numpy.array): 形状为101x1的数组,对应置信度从0到1按0.01递增取值时,计算所得图片级别的误检率。
-        save_dir (str): 文本文件的保存路径。
-
-    """
-
-    plt.subplot(1, 2, 1)
-    plt.title("image-level false_positive-recall")
-    plt.xlabel("recall")
-    plt.ylabel("false_positive")
-    plt.xlim(0, 1)
-    plt.ylim(0, 1)
-    plt.grid(linestyle='--', linewidth=1)
-    plt.plot([0, 1], [0, 1], 'r--', linewidth=1)
-    my_x_ticks = np.arange(0, 1, 0.1)
-    my_y_ticks = np.arange(0, 1, 0.1)
-    plt.xticks(my_x_ticks, fontsize=5)
-    plt.yticks(my_y_ticks, fontsize=5)
-    plt.plot(tp_list, fp_list, color='b', label="image level", linewidth=1)
-    plt.legend(loc="lower left", fontsize=5)
-
-    plt.subplot(1, 2, 2)
-    plt.title("score-recall")
-    plt.xlabel('recall')
-    plt.ylabel('score')
-    plt.xlim(0, 1)
-    plt.ylim(0, 1)
-    plt.grid(linestyle='--', linewidth=1)
-    plt.xticks(my_x_ticks, fontsize=5)
-    plt.yticks(my_y_ticks, fontsize=5)
-    plt.plot(
-        tp_list,
-        np.arange(0, 1.01, 0.01),
-        color='b',
-        label="image level",
-        linewidth=1)
-    plt.legend(loc="lower left", fontsize=5)
-    tp_fp_chart_file = os.path.join(save_dir, "image-level_tp_fp.png")
-    plt.savefig(tp_fp_chart_file, dpi=800)
-    plt.close()
-    print(
-        "The diagrammatic score-recall_rate-false_positive_rate is saved as {}".
-        format(tp_fp_chart_file))
-
-
-if __name__ == '__main__':
-    parser = argparse.ArgumentParser(description=__doc__)
-    parser.add_argument(
-        "--model_dir",
-        default="./output/faster_rcnn_r50_vd_dcn/best_model/",
-        type=str,
-        help="The model directory path.")
-    parser.add_argument(
-        "--dataset_dir",
-        default="./aluminum_inspection",
-        type=str,
-        help="The VOC-format dataset directory path.")
-    parser.add_argument(
-        "--background_image_dir",
-        default="./aluminum_inspection/val_wu_xia_ci",
-        type=str,
-        help="The directory path of background images.")
-    parser.add_argument(
-        "--save_dir",
-        default="./visualize/faster_rcnn_r50_vd_dcn",
-        type=str,
-        help="The directory path of result.")
-
-    args = parser.parse_args()
-
-    if not osp.exists(args.save_dir):
-        os.makedirs(args.save_dir)
-
-    model = pdx.load_model(args.model_dir)
-
-    tp_list = cal_image_level_recall_rate(model, args.dataset_dir)
-    fp_list = cal_image_level_false_positive_rate(model,
-                                                  args.background_image_dir)
-    result2textfile(tp_list, fp_list, args.save_dir)
-    result2imagefile(tp_list, fp_list, args.save_dir)

+ 0 - 160
static/examples/industrial_quality_inspection/compare.py

@@ -1,160 +0,0 @@
-# coding: utf8
-# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# 环境变量配置,用于控制是否使用GPU
-# 说明文档:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html#gpu
-import argparse
-import os
-os.environ['CUDA_VISIBLE_DEVICES'] = '0'
-
-import os.path as osp
-import cv2
-import re
-import xml.etree.ElementTree as ET
-import paddlex as pdx
-
-
-def parse_xml_file(xml_file):
-    tree = ET.parse(xml_file)
-    pattern = re.compile('<object>', re.IGNORECASE)
-    obj_match = pattern.findall(str(ET.tostringlist(tree.getroot())))
-    if len(obj_match) == 0:
-        return False
-    obj_tag = obj_match[0][1:-1]
-    objs = tree.findall(obj_tag)
-    pattern = re.compile('<size>', re.IGNORECASE)
-    size_tag = pattern.findall(str(ET.tostringlist(tree.getroot())))[0][1:-1]
-    size_element = tree.find(size_tag)
-    pattern = re.compile('<width>', re.IGNORECASE)
-    width_tag = pattern.findall(str(ET.tostringlist(size_element)))[0][1:-1]
-    im_w = float(size_element.find(width_tag).text)
-    pattern = re.compile('<height>', re.IGNORECASE)
-    height_tag = pattern.findall(str(ET.tostringlist(size_element)))[0][1:-1]
-    im_h = float(size_element.find(height_tag).text)
-    gt_bbox = []
-    gt_class = []
-    for i, obj in enumerate(objs):
-        pattern = re.compile('<name>', re.IGNORECASE)
-        name_tag = pattern.findall(str(ET.tostringlist(obj)))[0][1:-1]
-        cname = obj.find(name_tag).text.strip()
-        gt_class.append(cname)
-        pattern = re.compile('<difficult>', re.IGNORECASE)
-        diff_tag = pattern.findall(str(ET.tostringlist(obj)))[0][1:-1]
-        try:
-            _difficult = int(obj.find(diff_tag).text)
-        except Exception:
-            _difficult = 0
-        pattern = re.compile('<bndbox>', re.IGNORECASE)
-        box_tag = pattern.findall(str(ET.tostringlist(obj)))[0][1:-1]
-        box_element = obj.find(box_tag)
-        pattern = re.compile('<xmin>', re.IGNORECASE)
-        xmin_tag = pattern.findall(str(ET.tostringlist(box_element)))[0][1:-1]
-        x1 = float(box_element.find(xmin_tag).text)
-        pattern = re.compile('<ymin>', re.IGNORECASE)
-        ymin_tag = pattern.findall(str(ET.tostringlist(box_element)))[0][1:-1]
-        y1 = float(box_element.find(ymin_tag).text)
-        pattern = re.compile('<xmax>', re.IGNORECASE)
-        xmax_tag = pattern.findall(str(ET.tostringlist(box_element)))[0][1:-1]
-        x2 = float(box_element.find(xmax_tag).text)
-        pattern = re.compile('<ymax>', re.IGNORECASE)
-        ymax_tag = pattern.findall(str(ET.tostringlist(box_element)))[0][1:-1]
-        y2 = float(box_element.find(ymax_tag).text)
-        x1 = max(0, x1)
-        y1 = max(0, y1)
-        if im_w > 0.5 and im_h > 0.5:
-            x2 = min(im_w - 1, x2)
-            y2 = min(im_h - 1, y2)
-        gt_bbox.append([x1, y1, x2, y2])
-    gts = []
-    for bbox, name in zip(gt_bbox, gt_class):
-        x1, y1, x2, y2 = bbox
-        w = x2 - x1 + 1
-        h = y2 - y1 + 1
-        gt = {
-            'category_id': 0,
-            'category': name,
-            'bbox': [x1, y1, w, h],
-            'score': 1
-        }
-        gts.append(gt)
-
-    return gts
-
-
-if __name__ == '__main__':
-    parser = argparse.ArgumentParser(description=__doc__)
-    parser.add_argument(
-        "--model_dir",
-        default="./output/faster_rcnn_r50_vd_dcn/best_model/",
-        type=str,
-        help="The model directory path.")
-    parser.add_argument(
-        "--dataset_dir",
-        default="./aluminum_inspection",
-        type=str,
-        help="The VOC-format dataset directory path.")
-    parser.add_argument(
-        "--save_dir",
-        default="./visualize/compare",
-        type=str,
-        help="The directory path of result.")
-    parser.add_argument(
-        "--score_threshold",
-        default=0.1,
-        type=float,
-        help="The predicted bbox whose score is lower than score_threshold is filtered."
-    )
-
-    args = parser.parse_args()
-
-    if not os.path.exists(args.save_dir):
-        os.makedirs(args.save_dir)
-    file_list = osp.join(args.dataset_dir, 'val_list.txt')
-
-    model = pdx.load_model(args.model_dir)
-
-    with open(file_list, 'r') as fr:
-        while True:
-            line = fr.readline()
-            if not line:
-                break
-            img_file, xml_file = [osp.join(args.dataset_dir, x) \
-                    for x in line.strip().split()[:2]]
-            if not osp.exists(img_file):
-                continue
-            if not osp.exists(xml_file):
-                continue
-
-            res = model.predict(img_file)
-            gts = parse_xml_file(xml_file)
-
-            det_vis = pdx.det.visualize(
-                img_file, res, threshold=args.score_threshold, save_dir=None)
-            if gts == False:
-                gts = cv2.imread(img_file)
-            else:
-                gt_vis = pdx.det.visualize(
-                    img_file,
-                    gts,
-                    threshold=args.score_threshold,
-                    save_dir=None)
-            vis = cv2.hconcat([gt_vis, det_vis])
-            cv2.imwrite(
-                os.path.join(args.save_dir, os.path.split(img_file)[-1]), vis)
-            print('The comparison has been made for {}'.format(img_file))
-
-    print(
-        "The visualized ground-truths and predictions are saved in {}. Ground-truth is on the left, prediciton is on the right".
-        format(args.save_dir))

+ 0 - 14
static/examples/industrial_quality_inspection/dataset.md

@@ -1,14 +0,0 @@
-# 天池铝材表面缺陷检测初赛数据集示例
-
-| 序号 | 瑕疵名称 | 瑕疵成因 | 瑕疵图片示例 | 图片数量 |
-| -- | -- | -- | -- | -- |
-| 1 | 擦花(擦伤)| 表面处理(喷涂)后有轻微擦到其它的东西,造成痕迹 | ![](https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/ca_hua_example.png) | 128 |
-| 2 | 杂色 | 喷涂换颜料的时候,装颜料的容器未清洗干净,造成喷涂时有少量其它颜色掺入 | ![](https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/za_se_example.png) |365 |
-| 3 | 漏底 | 喷粉效果不好,铝材大量底色露出 | ![](https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/lou_di_example.png) | 538 |
-| 4 | 不导电 | 直接喷不到铝材表面上去 | ![](https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/bu_dao_dian_example.png) | 390 |
-|5 | 桔皮 | 表面处理后涂层表面粗糙,大颗粒 | ![](https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/ju_pi_example.png) | 173 |
-| 6 | 喷流| 喷涂时油漆稀从上流下来,有流动痕迹 | ![](https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/pen_liu_example.png) | 86 |
-| 7 |漆泡 | 喷涂后表面起泡,小而多| ![](https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/qi_pao_example.png) | 82 |
-| 8 | 起坑 | 型材模具问题,做出来的型材一整条都有一条凹下去的部分 | ![](https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/qi_keng_example.png.png) | 407 |
-| 9 | 脏点 | 表面处理时,有灰尘或一些脏东西未能擦掉,导致涂层有颗粒比较突出 | ![](https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/zang_dian_example.png) | 261 |
-| 10 | 角位漏底 | 在型材角落出现的露底 | ![](https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/jiao_wei_lou_di_example.png) | 346 |

+ 0 - 26
static/examples/industrial_quality_inspection/error_analysis.py

@@ -1,26 +0,0 @@
-# coding: utf8
-# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import os.path as osp
-import paddlex as pdx
-
-model_dir = 'output/faster_rcnn_r50_vd_dcn/best_model/'
-save_dir = 'visualize/faster_rcnn_r50_vd_dcn'
-if not osp.exists(save_dir):
-    os.makedirs(save_dir)
-
-eval_details_file = osp.join(model_dir, 'eval_details.json')
-pdx.det.coco_error_analysis(eval_details_file, save_dir=save_dir)

+ 0 - 114
static/examples/industrial_quality_inspection/gpu_solution.md

@@ -1,114 +0,0 @@
-# GPU端最终解决方案
-
-本案例面向GPU端的最终方案是选择二阶段检测模型FasterRCNN,其骨干网络选择加入了可变形卷积(DCN)的ResNet50_vd,训练时使用SSLD蒸馏方案训练得到的ResNet50_vd预训练模型,FPN部分的通道数量设置为64,训练阶段数据增强策略采用RandomHorizontalFlip、RandomDistort、RandomCrop,并加入背景图片,测试阶段的RPN部分做非极大值抑制计算的候选框数量由原本的6000减少至500、做完非极大值抑制后保留的候选框数量由原本的1000减少至300。
-
-在Tesla P40的Linux系统下,对于输入大小是800 x 1333的模型,图像预处理时长为30ms/image,模型的推理时间为46.08ms/image,包括输入数据拷贝至GPU的时间、计算时间、数据拷贝至CPU的时间。
-
-| 模型 | VOC mAP (%) | 推理时间 (ms/image)
-| -- | -- | -- |
-| FasterRCNN-ResNet50_vd_ssld | 81.05 | 48.62 |
-| + dcn | 88.09 | 66.51 |
-| + RandomHorizontalFlip/RandomDistort/RandomCrop | 90.23| 66.51 |
-| + background images | 88.87 | 66.51 |
-| + fpn channel=64 | 87.79 | 48.65 |
-| + test proposal=pre/post topk 500/300 | 87.72 | 46.08 |
-
-## 前置依赖
-
-* Paddle paddle >= 1.8.0
-* Python >= 3.5
-* PaddleX >= 1.3.0
-
-## 模型训练
-
-### (1) 下载PaddleX源码
-
-```
-git clone https://github.com/PaddlePaddle/PaddleX
-
-cd PaddleX/examples/industrial_quality_inspection
-```
-
-### (2) 下载数据集
-
-因数据集较大,可运行以下代码提前将数据集下载并解压。训练代码中也会自动下载数据集,所以这一步不是必须的。
-
-```
-wget https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/aluminum_inspection.tar.gz
-tar xvf aluminum_inspection.tar.gz
-```
-### (3) 下载预先训练好的模型
-
-如果不想再次训练模型,可以直接下载已经训练好的模型完成后面的模型测试和部署推理:
-
-```
-wget https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/models/faster_rcnn_r50_vd_dcn.tar.gz
-tar xvf faster_rcnn_r50_vd_dcn.tar.gz
-```
-### (4) 训练
-
-运行以下代码进行模型训练,代码会自动下载数据集,如若事先下载了数据集,需将下载和解压铝材缺陷检测数据集的相关行注释掉。代码中默认使用0,1,2,3,4号GPU训练,可根据实际情况设置卡号并调整`batch_size`和`learning_rate`。
-
-```
-python train_rcnn.py
-```
-
-### (5) 分析预测错误的原因
-
-在模型迭代过程中,运行以下代码可完成模型效果的分析并生成分析结果图表:
-
-```
-python error_analysis.py
-```
-
-可参考[性能优化部分的模型效果分析](./accuracy_improvement.md#2-%E6%A8%A1%E5%9E%8B%E6%95%88%E6%9E%9C%E5%88%86%E6%9E%90)来理解当前模型预测错误的原因。
-
-运行以下代码,生成可视化真值和预测结果的对比图以进一步理解模型效果,代码中的置信度阈值可根据实际情况进行调整。
-
-```
-python compare.py
-```
-
-![](image/compare_budaodian-116.jpg)
-
-左边是可视化真值,右边是可视化预测结果。
-
-### (6) 统计图片级召回率和误检率
-
-模型迭代完成后,计算不同置信度阈值下[图片级召回率](./accuracy_improvement.md#6-%E8%83%8C%E6%99%AF%E5%9B%BE%E7%89%87%E5%8A%A0%E5%85%A5)和[图片级误检率](./accuracy_improvement.md#6-%E8%83%8C%E6%99%AF%E5%9B%BE%E7%89%87%E5%8A%A0%E5%85%A5),找到符合要求的召回率和误检率,对应的置信度阈值用于后续模型预测阶段。
-
-```
-python cal_tp_fp.py
-```
-
-执行后会生成图表`image-level_tp_fp.png`和文件`tp_fp_list.txt`,示意如下:
-
-| 图表`image-level_tp_fp.png` | 文件`tp_fp_list.txt` |
-| -- | -- |
-| ![](./image/image-level_tp_fp.png) | [tp_fp_list.txt](tp_fp_list.md) |
-
-图表`image-level_tp_fp.png`中左边子图,横坐标表示不同置信度阈值下计算得到的图片级召回率,纵坐标表示各图片级召回率对应的图片级误检率。右边子图横坐标表示图片级召回率,纵坐标表示各图片级召回率对应的置信度阈值。从图表中可较为直观地看出当前模型的图片级召回率和误检率的量级,从文件`tp_fp_list.txt`可以查到具体数值,例如在图片级召回率/图片级误检率为[0.9589,0.0074]这一组符合要求,就将对应的置信度阈值0.90选取为后续预测推理的阈值。
-
-### (7) 模型测试
-
-测试集因没有标注文件,这里单独下载测试集图片:
-
-```
-wget https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/aluminum_inspection_test.tar.gz
-tar xvf aluminum_inspection_test.tar.gz
-```
-
-加载训练好的模型,使用(5)选取的置信度阈值0.90对验证集图片或者测试集图片进行预测:
-
-```
-python predict.py
-```
-可视化预测结果示例如下:
-
-![](image/visualize_budaodian-116.jpg)
-
-## 推理部署
-
-本案例采用C++部署方式将模型部署在Tesla P40的Linux系统下,具体的C++部署流程请参考文档[PaddleX模型多端安全部署/C++部署](https://paddlex.readthedocs.io/zh_CN/develop/deploy/server/cpp/index.html)。
-
-对于输入大小是800 x 1333的模型,图像预处理时长为30ms/image。值得一提的是预处理中的Normalize操作比较耗时,因此在设置预处理操作时,可以先进行Resize操作再做Normalize。模型的推理时间为46.08ms/image,包括输入数据拷贝至GPU的时间、计算时间、数据拷贝至CPU的时间。

BIN
static/examples/industrial_quality_inspection/image/after_clahe.png


BIN
static/examples/industrial_quality_inspection/image/allclasses_analysis_example.png


BIN
static/examples/industrial_quality_inspection/image/before_clahe.png


BIN
static/examples/industrial_quality_inspection/image/budaodian_analysis_example.png


BIN
static/examples/industrial_quality_inspection/image/cahua_analysis_example.png


BIN
static/examples/industrial_quality_inspection/image/compare_budaodian-116.jpg


BIN
static/examples/industrial_quality_inspection/image/image-level_tp_fp.png


BIN
static/examples/industrial_quality_inspection/image/jiaoweiloudi_analysis_example.png


BIN
static/examples/industrial_quality_inspection/image/jupi_analysis_example.png


BIN
static/examples/industrial_quality_inspection/image/loudi_analysis_example.png


BIN
static/examples/industrial_quality_inspection/image/penliu_analysis_example.png


BIN
static/examples/industrial_quality_inspection/image/qikeng_analysis_example.png


BIN
static/examples/industrial_quality_inspection/image/qipao_analysis_example.png


BIN
static/examples/industrial_quality_inspection/image/visualize_budaodian-116.jpg


BIN
static/examples/industrial_quality_inspection/image/zangdian_analysis_example.png


BIN
static/examples/industrial_quality_inspection/image/zase_analysis_example.png


+ 0 - 61
static/examples/industrial_quality_inspection/params_analysis.py

@@ -1,61 +0,0 @@
-#copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-#
-#Licensed under the Apache License, Version 2.0 (the "License");
-#you may not use this file except in compliance with the License.
-#You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-#Unless required by applicable law or agreed to in writing, software
-#distributed under the License is distributed on an "AS IS" BASIS,
-#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#See the License for the specific language governing permissions and
-#limitations under the License.
-
-import argparse
-import os
-# 选择使用0号卡
-os.environ['CUDA_VISIBLE_DEVICES'] = '0'
-import paddlex as pdx
-
-
-def params_analysis(model_dir, dataset, batch_size, save_file):
-    # 加载模型
-    model = pdx.load_model(model_dir)
-
-    # 定义验证所用的数据集
-    eval_dataset = pdx.datasets.VOCDetection(
-        data_dir=dataset,
-        file_list=os.path.join(dataset, 'val_list.txt'),
-        label_list=os.path.join(dataset, 'labels.txt'),
-        transforms=model.eval_transforms)
-
-    pdx.slim.prune.analysis(
-        model,
-        dataset=eval_dataset,
-        batch_size=batch_size,
-        save_file=save_file)
-
-
-if __name__ == '__main__':
-    parser = argparse.ArgumentParser(description=__doc__)
-    parser.add_argument(
-        "--model_dir",
-        default="./output/yolov3_mobilenetv3/best_model",
-        type=str,
-        help="The model path.")
-    parser.add_argument(
-        "--dataset",
-        default="./aluminum_inspection",
-        type=str,
-        help="The model path.")
-    parser.add_argument("--batch_size", default=8, type=int, help="Batch size")
-    parser.add_argument(
-        "--save_file",
-        default="./sensitivities.data",
-        type=str,
-        help="The sensitivities file path.")
-
-    args = parser.parse_args()
-    params_analysis(args.model_dir, args.dataset, args.batch_size,
-                    args.save_file)

+ 0 - 35
static/examples/industrial_quality_inspection/predict.py

@@ -1,35 +0,0 @@
-# coding: utf8
-# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# 环境变量配置,用于控制是否使用GPU
-# 说明文档:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html#gpu
-import os
-os.environ['CUDA_VISIBLE_DEVICES'] = '0'
-
-import os.path as osp
-import paddlex as pdx
-
-img_file = 'aluminum_inspection/JPEGImages/budaodian-116.jpg'
-model_dir = 'output/faster_rcnn_r50_vd_dcn/best_model/'
-save_dir = './visualize/predict'
-# 设置置信度阈值
-score_threshold = 0.9
-
-if not os.path.exists(save_dir):
-    os.makedirs(save_dir)
-
-model = pdx.load_model(model_dir)
-res = model.predict(img_file)
-pdx.det.visualize(img_file, res, threshold=score_threshold, save_dir=save_dir)

+ 0 - 102
static/examples/industrial_quality_inspection/tp_fp_list.md

@@ -1,102 +0,0 @@
-| score | recall rate | false-positive rate |
-| -- | -- | -- |
-| 0.000000 | 0.982877 | 0.022222 |
-| 0.010000 | 0.982877 | 0.022222 |
-| 0.020000 | 0.982877 | 0.022222 |
-| 0.030000 | 0.982877 | 0.022222 |
-| 0.040000 | 0.982877 | 0.022222 |
-| 0.050000 | 0.982877 | 0.022222 |
-| 0.060000 | 0.982877 | 0.022222 |
-| 0.070000 | 0.979452 | 0.022222 |
-| 0.080000 | 0.979452 | 0.022222 |
-| 0.090000 | 0.979452 | 0.022222 |
-| 0.100000 | 0.979452 | 0.022222 |
-| 0.110000 | 0.979452 | 0.022222 |
-| 0.120000 | 0.979452 | 0.022222 |
-| 0.130000 | 0.979452 | 0.022222 |
-| 0.140000 | 0.976027 | 0.022222 |
-| 0.150000 | 0.976027 | 0.022222 |
-| 0.160000 | 0.976027 | 0.022222 |
-| 0.170000 | 0.976027 | 0.022222 |
-| 0.180000 | 0.976027 | 0.022222 |
-| 0.190000 | 0.976027 | 0.022222 |
-| 0.200000 | 0.976027 | 0.022222 |
-| 0.210000 | 0.976027 | 0.022222 |
-| 0.220000 | 0.976027 | 0.022222 |
-| 0.230000 | 0.976027 | 0.022222 |
-| 0.240000 | 0.976027 | 0.022222 |
-| 0.250000 | 0.976027 | 0.022222 |
-| 0.260000 | 0.976027 | 0.014815 |
-| 0.270000 | 0.976027 | 0.014815 |
-| 0.280000 | 0.976027 | 0.014815 |
-| 0.290000 | 0.976027 | 0.014815 |
-| 0.300000 | 0.976027 | 0.014815 |
-| 0.310000 | 0.976027 | 0.014815 |
-| 0.320000 | 0.976027 | 0.014815 |
-| 0.330000 | 0.976027 | 0.014815 |
-| 0.340000 | 0.976027 | 0.014815 |
-| 0.350000 | 0.976027 | 0.014815 |
-| 0.360000 | 0.976027 | 0.014815 |
-| 0.370000 | 0.976027 | 0.014815 |
-| 0.380000 | 0.976027 | 0.014815 |
-| 0.390000 | 0.976027 | 0.014815 |
-| 0.400000 | 0.976027 | 0.014815 |
-| 0.410000 | 0.976027 | 0.014815 |
-| 0.420000 | 0.976027 | 0.014815 |
-| 0.430000 | 0.976027 | 0.014815 |
-| 0.440000 | 0.972603 | 0.014815 |
-| 0.450000 | 0.972603 | 0.014815 |
-| 0.460000 | 0.972603 | 0.014815 |
-| 0.470000 | 0.972603 | 0.014815 |
-| 0.480000 | 0.972603 | 0.014815 |
-| 0.490000 | 0.972603 | 0.014815 |
-| 0.500000 | 0.972603 | 0.014815 |
-| 0.510000 | 0.972603 | 0.014815 |
-| 0.520000 | 0.972603 | 0.014815 |
-| 0.530000 | 0.972603 | 0.014815 |
-| 0.540000 | 0.972603 | 0.014815 |
-| 0.550000 | 0.972603 | 0.014815 |
-| 0.560000 | 0.969178 | 0.014815 |
-| 0.570000 | 0.969178 | 0.014815 |
-| 0.580000 | 0.969178 | 0.014815 |
-| 0.590000 | 0.969178 | 0.014815 |
-| 0.600000 | 0.969178 | 0.014815 |
-| 0.610000 | 0.969178 | 0.014815 |
-| 0.620000 | 0.969178 | 0.014815 |
-| 0.630000 | 0.969178 | 0.014815 |
-| 0.640000 | 0.969178 | 0.014815 |
-| 0.650000 | 0.969178 | 0.014815 |
-| 0.660000 | 0.969178 | 0.014815 |
-| 0.670000 | 0.969178 | 0.014815 |
-| 0.680000 | 0.969178 | 0.014815 |
-| 0.690000 | 0.969178 | 0.014815 |
-| 0.700000 | 0.969178 | 0.014815 |
-| 0.710000 | 0.969178 | 0.014815 |
-| 0.720000 | 0.969178 | 0.014815 |
-| 0.730000 | 0.969178 | 0.014815 |
-| 0.740000 | 0.969178 | 0.014815 |
-| 0.750000 | 0.969178 | 0.014815 |
-| 0.760000 | 0.969178 | 0.014815 |
-| 0.770000 | 0.965753 | 0.014815 |
-| 0.780000 | 0.965753 | 0.014815 |
-| 0.790000 | 0.965753 | 0.014815 |
-| 0.800000 | 0.962329 | 0.014815 |
-| 0.810000 | 0.962329 | 0.014815 |
-| 0.820000 | 0.962329 | 0.014815 |
-| 0.830000 | 0.962329 | 0.014815 |
-| 0.840000 | 0.962329 | 0.014815 |
-| 0.850000 | 0.958904 | 0.014815 |
-| 0.860000 | 0.958904 | 0.014815 |
-| 0.870000 | 0.958904 | 0.014815 |
-| 0.880000 | 0.958904 | 0.014815 |
-| 0.890000 | 0.958904 | 0.014815 |
-| 0.900000 | 0.958904 | 0.007407 |
-| 0.910000 | 0.958904 | 0.007407 |
-| 0.920000 | 0.958904 | 0.007407 |
-| 0.930000 | 0.955479 | 0.007407 |
-| 0.940000 | 0.955479 | 0.007407 |
-| 0.950000 | 0.955479 | 0.007407 |
-| 0.960000 | 0.955479 | 0.007407 |
-| 0.970000 | 0.955479 | 0.007407 |
-| 0.980000 | 0.941781 | 0.000000 |
-| 0.990000 | 0.893836 | 0.000000 |

+ 0 - 58
static/examples/industrial_quality_inspection/train_pruned_yolov3.py

@@ -1,58 +0,0 @@
-# 环境变量配置,用于控制是否使用GPU
-# 说明文档:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html#gpu
-import os
-os.environ['CUDA_VISIBLE_DEVICES'] = '0'
-
-from paddlex.det import transforms
-import paddlex as pdx
-
-# 定义训练和验证时的transforms
-# API说明 https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html
-train_transforms = transforms.Compose([
-    transforms.MixupImage(mixup_epoch=250), transforms.RandomDistort(),
-    transforms.RandomExpand(), transforms.RandomCrop(), transforms.Resize(
-        target_size=608, interp='RANDOM'), transforms.RandomHorizontalFlip(),
-    transforms.Normalize()
-])
-
-eval_transforms = transforms.Compose([
-    transforms.Resize(
-        target_size=608, interp='CUBIC'), transforms.Normalize()
-])
-
-# 定义训练和验证所用的数据集
-# API说明:https://paddlex.readthedocs.io/zh_CN/develop/apis/datasets.html#paddlex-datasets-vocdetection
-train_dataset = pdx.datasets.VOCDetection(
-    data_dir='aluminum_inspection',
-    file_list='aluminum_inspection/train_list.txt',
-    label_list='aluminum_inspection/labels.txt',
-    transforms=train_transforms,
-    shuffle=True)
-eval_dataset = pdx.datasets.VOCDetection(
-    data_dir='aluminum_inspection',
-    file_list='aluminum_inspection/val_list.txt',
-    label_list='aluminum_inspection/labels.txt',
-    transforms=eval_transforms)
-
-# 初始化模型,并进行训练
-# 可使用VisualDL查看训练指标,参考https://paddlex.readthedocs.io/zh_CN/develop/train/visualdl.html
-num_classes = len(train_dataset.labels)
-
-# API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-yolov3
-model = pdx.det.YOLOv3(num_classes=num_classes, backbone='MobileNetV3_large')
-
-# API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#train
-# 各参数介绍与调整说明:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html
-model.train(
-    num_epochs=400,
-    train_dataset=train_dataset,
-    train_batch_size=8,
-    eval_dataset=eval_dataset,
-    warmup_steps=4000,
-    learning_rate=0.000125,
-    lr_decay_epochs=[240, 320],
-    pretrain_weights='output/yolov3_mobilenetv3/best_model',
-    save_dir='output/yolov3_mobilenetv3_prune',
-    use_vdl=True,
-    sensitivities_file='./sensitivities.data',
-    eval_metric_loss=0.05)

+ 0 - 74
static/examples/industrial_quality_inspection/train_rcnn.py

@@ -1,74 +0,0 @@
-# 环境变量配置,用于控制是否使用GPU
-# 说明文档:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html#gpu
-import os
-os.environ['CUDA_VISIBLE_DEVICES'] = '0'
-
-from paddlex.det import transforms
-import paddlex as pdx
-
-# 下载和解压铝材缺陷检测数据集
-aluminum_dataset = 'https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/aluminum_inspection.tar.gz'
-pdx.utils.download_and_decompress(aluminum_dataset, path='./')
-
-# API说明 https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html
-train_transforms = transforms.Compose([
-    transforms.RandomDistort(), transforms.RandomCrop(),
-    transforms.RandomHorizontalFlip(), transforms.ResizeByShort(
-        short_size=[800], max_size=1333), transforms.Normalize(
-            mean=[0.5], std=[0.5]), transforms.Padding(coarsest_stride=32)
-])
-
-eval_transforms = transforms.Compose([
-    transforms.ResizeByShort(
-        short_size=800, max_size=1333),
-    transforms.Normalize(),
-    transforms.Padding(coarsest_stride=32),
-])
-
-# 定义训练和验证所用的数据集
-# API说明:https://paddlex.readthedocs.io/zh_CN/develop/apis/datasets.html#paddlex-datasets-vocdetection
-train_dataset = pdx.datasets.VOCDetection(
-    data_dir='aluminum_inspection',
-    file_list='aluminum_inspection/train_list.txt',
-    label_list='aluminum_inspection/labels.txt',
-    transforms=train_transforms,
-    num_workers=8,
-    shuffle=True)
-eval_dataset = pdx.datasets.VOCDetection(
-    data_dir='aluminum_inspection',
-    file_list='aluminum_inspection/val_list.txt',
-    label_list='aluminum_inspection/labels.txt',
-    num_workers=8,
-    transforms=eval_transforms)
-
-# 把背景图片加入训练集中
-train_dataset.add_negative_samples(
-    image_dir='./aluminum_inspection/train_wu_xia_ci')
-
-# 初始化模型,并进行训练
-# 可使用VisualDL查看训练指标,参考https://paddlex.readthedocs.io/zh_CN/develop/train/visualdl.html
-# num_classes 需要设置为包含背景类的类别数,即: 目标类别数量 + 1
-num_classes = len(train_dataset.labels) + 1
-
-# API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-fasterrcnn
-model = pdx.det.FasterRCNN(
-    num_classes=num_classes,
-    backbone='ResNet50_vd_ssld',
-    with_dcn=True,
-    fpn_num_channels=64,
-    with_fpn=True,
-    test_pre_nms_top_n=500,
-    test_post_nms_top_n=300)
-
-# API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#id1
-# 各参数介绍与调整说明:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html
-model.train(
-    num_epochs=80,
-    train_dataset=train_dataset,
-    train_batch_size=2,
-    eval_dataset=eval_dataset,
-    learning_rate=0.0025,
-    lr_decay_epochs=[60, 70],
-    warmup_steps=5000,
-    save_dir='output/faster_rcnn_r50_vd_dcn',
-    use_vdl=True)

+ 0 - 59
static/examples/industrial_quality_inspection/train_yolov3.py

@@ -1,59 +0,0 @@
-# 环境变量配置,用于控制是否使用GPU
-# 说明文档:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html#gpu
-import os
-os.environ['CUDA_VISIBLE_DEVICES'] = '0'
-
-from paddlex.det import transforms
-import paddlex as pdx
-
-# 下载和解压铝材缺陷检测数据集
-aluminum_dataset = 'https://bj.bcebos.com/paddlex/examples/industrial_quality_inspection/datasets/aluminum_inspection.tar.gz'
-pdx.utils.download_and_decompress(aluminum_dataset, path='./')
-
-# 定义训练和验证时的transforms
-# API说明 https://paddlex.readthedocs.io/zh_CN/develop/apis/transforms/det_transforms.html
-train_transforms = transforms.Compose([
-    transforms.MixupImage(mixup_epoch=250), transforms.RandomDistort(),
-    transforms.RandomExpand(), transforms.RandomCrop(), transforms.Resize(
-        target_size=608, interp='RANDOM'), transforms.RandomHorizontalFlip(),
-    transforms.Normalize()
-])
-
-eval_transforms = transforms.Compose([
-    transforms.Resize(
-        target_size=608, interp='CUBIC'), transforms.Normalize()
-])
-
-# 定义训练和验证所用的数据集
-# API说明:https://paddlex.readthedocs.io/zh_CN/develop/apis/datasets.html#paddlex-datasets-vocdetection
-train_dataset = pdx.datasets.VOCDetection(
-    data_dir='aluminum_inspection',
-    file_list='aluminum_inspection/train_list.txt',
-    label_list='aluminum_inspection/labels.txt',
-    transforms=train_transforms,
-    shuffle=True)
-eval_dataset = pdx.datasets.VOCDetection(
-    data_dir='aluminum_inspection',
-    file_list='aluminum_inspection/val_list.txt',
-    label_list='aluminum_inspection/labels.txt',
-    transforms=eval_transforms)
-
-# 初始化模型,并进行训练
-# 可使用VisualDL查看训练指标,参考https://paddlex.readthedocs.io/zh_CN/develop/train/visualdl.html
-num_classes = len(train_dataset.labels)
-
-# API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#paddlex-det-yolov3
-model = pdx.det.YOLOv3(num_classes=num_classes, backbone='MobileNetV3_large')
-
-# API说明: https://paddlex.readthedocs.io/zh_CN/develop/apis/models/detection.html#id1
-# 各参数介绍与调整说明:https://paddlex.readthedocs.io/zh_CN/develop/appendix/parameters.html
-model.train(
-    num_epochs=400,
-    train_dataset=train_dataset,
-    train_batch_size=8,
-    eval_dataset=eval_dataset,
-    warmup_steps=4000,
-    learning_rate=0.000125,
-    lr_decay_epochs=[240, 320],
-    save_dir='output/yolov3_mobilenetv3',
-    use_vdl=True)