From 486121eaa4ad142dde25ff7a77a2070f5a4571d4 Mon Sep 17 00:00:00 2001 From: Feng Ni Date: Wed, 24 Aug 2022 18:16:46 +0800 Subject: [PATCH] [smalldet] fix slice_infer (#6744) * fix slice_infer * fix doc, test=document_fix --- configs/smalldet/README.md | 262 ++++++++++++++++++++----------------- deploy/python/infer.py | 53 ++++++-- deploy/python/utils.py | 2 +- ppdet/engine/trainer.py | 60 +++++---- tools/eval.py | 2 +- tools/infer.py | 2 +- 6 files changed, 222 insertions(+), 159 deletions(-) diff --git a/configs/smalldet/README.md b/configs/smalldet/README.md index cdae33ea2..e8a16379c 100644 --- a/configs/smalldet/README.md +++ b/configs/smalldet/README.md @@ -1,10 +1,29 @@ -# PP-YOLOE 小目标检测模型 - -PaddleDetection团队提供了针对VisDrone-DET、DOTA水平框、Xview等小目标场景数据集的基于PP-YOLOE的检测模型,以及提供了一套使用[SAHI](https://github.com/obss/sahi)(Slicing Aided Hyper Inference)工具切图和拼图的方案,用户可以下载模型进行使用。 +# PP-YOLOE 小目标检测模型(PP-YOLOE smalldet) VisDroneVisDroneDOTAXview -## 基础模型: +## 内容 +- [简介](#简介) +- [模型库](#模型库) + - [基础模型](#基础模型) + - [拼图模型](#拼图模型) +- [数据集准备](#数据集准备) +- [模型库使用说明](#模型库使用说明) + - [训练](#训练) + - [评估](#评估) + - [预测](#预测) + - [部署](#部署) +- [切图使用说明](#切图使用说明) + - [统计数据集分布](#统计数据集分布) + - [SAHI切图](#SAHI切图) +- [引用](#引用) + +## 简介 +PaddleDetection团队提供了针对VisDrone-DET、DOTA水平框、Xview等小目标场景数据集的基于PP-YOLOE的检测模型,以及提供了一套使用[SAHI](https://github.com/obss/sahi)(Slicing Aided Hyper Inference)工具切图和拼图的方案,用户可以下载模型进行使用。不通过切图拼图而直接使用原图的方案也可以参照[visdrone](../visdrone)。**是否需要切图**,建议参照[切图使用说明](#切图使用说明)中的[统计数据集分布](#统计数据集分布)先分析一下数据集再确定。 + +## 模型库 + +### 基础模型 | 模型 | 数据集 | SLICE_SIZE | OVERLAP_RATIO | 类别数 | mAPval
0.5:0.95 | APval
0.5 | 下载链接 | 配置文件 | |:---------|:---------------:|:---------------:|:---------------:|:------:|:-----------------------:|:-------------------:|:---------:| :-----: | @@ -12,7 +31,7 @@ PaddleDetection团队提供了针对VisDrone-DET、DOTA水平框、Xview等小 |PP-YOLOE-P2-l| Xview | 400 | 0.25 | 60 | 14.9 | 27.0 | [下载链接](https://bj.bcebos.com/v1/paddledet/models/ppyoloe_p2_crn_l_80e_sliced_xview_400_025.pdparams) | [配置文件](./ppyoloe_p2_crn_l_80e_sliced_xview_400_025.yml) | |PP-YOLOE-l| VisDrone-DET| 640 | 0.25 | 10 | 38.5 | 60.2 | [下载链接](https://bj.bcebos.com/v1/paddledet/models/ppyoloe_crn_l_80e_sliced_visdrone_640_025.pdparams) | [配置文件](./ppyoloe_crn_l_80e_sliced_visdrone_640_025.yml) | -## 原图评估和拼图评估对比: +### 拼图模型 | 模型 | 数据集 | SLICE_SIZE | OVERLAP_RATIO | 类别数 | mAPval
0.5:0.95 | APval
0.5 | 下载链接 | 配置文件 | |:---------|:---------------:|:---------------:|:---------------:|:------:|:-----------------------:|:-------------------:|:---------:| :-----: | @@ -28,10 +47,100 @@ PaddleDetection团队提供了针对VisDrone-DET、DOTA水平框、Xview等小 - 自动切图和拼图的推理预测需添加设置`--slice_infer`,具体见下文使用说明。 - Assembled表示自动切图和拼图。 +## 数据集准备 + +### VisDrone-DET + +VisDrone-DET是一个无人机航拍场景的小目标数据集,整理后的COCO格式VisDrone-DET数据集[下载链接](https://bj.bcebos.com/v1/paddledet/data/smalldet/visdrone.zip),切图后的COCO格式数据集[下载链接](https://bj.bcebos.com/v1/paddledet/data/smalldet/visdrone_sliced.zip),检测其中的**10类**,包括 `pedestrian(1), people(2), bicycle(3), car(4), van(5), truck(6), tricycle(7), awning-tricycle(8), bus(9), motor(10)`,原始数据集[下载链接](https://github.com/VisDrone/VisDrone-Dataset)。 +具体使用和下载请参考[visdrone](../visdrone)。 + +### DOTA水平框 + +DOTA是一个大型的遥感影像公开数据集,这里使用**DOTA-v1.0**水平框数据集,切图后整理的COCO格式的DOTA水平框数据集[下载链接](https://bj.bcebos.com/v1/paddledet/data/smalldet/dota_sliced.zip),检测其中的**15类**, +包括 `plane(0), baseball-diamond(1), bridge(2), ground-track-field(3), small-vehicle(4), large-vehicle(5), ship(6), tennis-court(7),basketball-court(8), storage-tank(9), soccer-ball-field(10), roundabout(11), harbor(12), swimming-pool(13), helicopter(14)`, +图片及原始数据集[下载链接](https://captain-whu.github.io/DOAI2019/dataset.html)。 + +### Xview + +Xview是一个大型的航拍遥感检测数据集,目标极小极多,切图后整理的COCO格式数据集[下载链接](https://bj.bcebos.com/v1/paddledet/data/smalldet/xview_sliced.zip),检测其中的**60类**, +具体类别为: + +
+ +`Fixed-wing Aircraft(0), +Small Aircraft(1), +Cargo Plane(2), +Helicopter(3), +Passenger Vehicle(4), +Small Car(5), +Bus(6), +Pickup Truck(7), +Utility Truck(8), +Truck(9), +Cargo Truck(10), +Truck w/Box(11), +Truck Tractor(12), +Trailer(13), +Truck w/Flatbed(14), +Truck w/Liquid(15), +Crane Truck(16), +Railway Vehicle(17), +Passenger Car(18), +Cargo Car(19), +Flat Car(20), +Tank car(21), +Locomotive(22), +Maritime Vessel(23), +Motorboat(24), +Sailboat(25), +Tugboat(26), +Barge(27), +Fishing Vessel(28), +Ferry(29), +Yacht(30), +Container Ship(31), +Oil Tanker(32), +Engineering Vehicle(33), +Tower crane(34), +Container Crane(35), +Reach Stacker(36), +Straddle Carrier(37), +Mobile Crane(38), +Dump Truck(39), +Haul Truck(40), +Scraper/Tractor(41), +Front loader/Bulldozer(42), +Excavator(43), +Cement Mixer(44), +Ground Grader(45), +Hut/Tent(46), +Shed(47), +Building(48), +Aircraft Hangar(49), +Damaged Building(50), +Facility(51), +Construction Site(52), +Vehicle Lot(53), +Helipad(54), +Storage Tank(55), +Shipping container lot(56), +Shipping Container(57), +Pylon(58), +Tower(59) +` + +
+,原始数据集[下载链接](https://challenge.xviewdataset.org/download-links)。 + -# 使用说明 +### 用户自定义数据集准备 -## 1.训练 +用户自定义数据集准备请参考[DET数据集标注工具](../../docs/tutorials/data/DetAnnoTools.md)和[DET数据集准备教程](../../docs/tutorials/data/PrepareDetDataSet.md)去准备。 + + +## 模型库使用说明 + +### 训练 首先将你的数据集为COCO数据集格式,然后使用SAHI切图工具进行离线切图,对保存的子图按常规检测模型的训练流程走即可。 也可直接下载PaddleDetection团队提供的切图后的VisDrone-DET、DOTA水平框、Xview数据集。 @@ -45,9 +154,9 @@ python -m paddle.distributed.launch --gpus 0,1,2,3,4,5,6,7 tools/train.py -c con **注意:** - 使用默认配置训练需要设置`--amp`以避免显存溢出。 -## 2.评估 +### 评估 -### 2.1 子图评估: +#### 2.1 子图评估 默认评估方式是子图评估,子图数据集的验证集设置为: ``` @@ -62,7 +171,7 @@ EvalDataset: CUDA_VISIBLE_DEVICES=0 python tools/eval.py -c configs/smalldet/ppyoloe_crn_l_80e_sliced_visdrone_640_025.yml -o weights=https://paddledet.bj.bcebos.com/models/ppyoloe_crn_l_80e_sliced_visdrone_640_025.pdparams ``` -### 2.2 原图评估: +#### 2.2 原图评估 修改验证集的标注文件路径为原图标注文件: ``` EvalDataset: @@ -76,7 +185,7 @@ EvalDataset: CUDA_VISIBLE_DEVICES=0 python tools/eval.py -c configs/smalldet/ppyoloe_crn_l_80e_sliced_visdrone_640_025.yml -o weights=https://paddledet.bj.bcebos.com/models/ppyoloe_crn_l_80e_sliced_visdrone_640_025.pdparams ``` -### 2.3 子图拼图评估: +#### 2.3 子图拼图评估 修改验证集的标注文件路径为原图标注文件: ``` # very slow, preferly eval with a determined weights(xx.pdparams) @@ -94,17 +203,9 @@ EvalDataset: CUDA_VISIBLE_DEVICES=0 python tools/eval.py -c configs/smalldet/ppyoloe_crn_l_80e_sliced_visdrone_640_025_slice_infer.yml -o weights=https://paddledet.bj.bcebos.com/models/ppyoloe_crn_l_80e_sliced_visdrone_640_025.pdparams --slice_infer --combine_method=nms --match_threshold=0.6 --match_metric=ios ``` -- 设置`--slice_infer`表示切图预测并拼装重组结果,如果不使用则不写; -- 设置`--slice_size`表示切图的子图尺寸大小,设置`--overlap_ratio`表示子图间重叠率; -- 设置`--combine_method`表示子图结果重组去重的方式,默认是`nms`; -- 设置`--match_threshold`表示子图结果重组去重的阈值,默认是0.6; -- 设置`--match_metric`表示子图结果重组去重的度量标准,默认是`ios`表示交小比(两个框交集面积除以更小框的面积),也可以选择交并比`iou`(两个框交集面积除以并集面积),精度效果因数据集而而异,但选择`ios`预测速度会更快一点; - - - **注意:** - 设置`--slice_infer`表示切图预测并拼装重组结果,如果不使用则不写,注意需要确保EvalDataset的数据集类是选用的SlicedCOCODataSet而不是COCODataSet; -- 可以自行修改选择合适的子图尺度sliced_size和子图间重叠率overlap_ratio,如: +- 设置`--slice_size`表示切图的子图尺寸大小,设置`--overlap_ratio`表示子图间重叠率,可以自行修改选择合适的子图尺度sliced_size和子图间重叠率overlap_ratio,如: ``` EvalDataset: !SlicedCOCODataSet @@ -119,18 +220,21 @@ EvalDataset: - 设置`--match_metric`表示子图结果重组去重的度量标准,默认是`ios`表示交小比(两个框交集面积除以更小框的面积),也可以选择交并比`iou`(两个框交集面积除以并集面积),精度效果因数据集而而异,但选择`ios`预测速度会更快一点; -## 3.预测 +### 预测 -### 3.1 子图或原图直接预测: +#### 3.1 子图或原图直接预测 与评估流程基本相同,可以在提前切好并存下来的子图上预测,也可以对原图预测,如: ```bash CUDA_VISIBLE_DEVICES=0 python tools/infer.py -c configs/smalldet/ppyoloe_crn_l_80e_sliced_visdrone_640_025.yml -o weights=https://paddledet.bj.bcebos.com/models/ppyoloe_crn_l_80e_sliced_visdrone_640_025.pdparams --infer_img=demo.jpg --draw_threshold=0.25 ``` -### 3.2 原图自动切图并拼图预测: +#### 3.2 原图自动切图并拼图预测 也可以对原图进行自动切图并拼图重组来预测原图,如: ```bash +# 单张图 CUDA_VISIBLE_DEVICES=0 python tools/infer.py -c configs/smalldet/ppyoloe_crn_l_80e_sliced_visdrone_640_025.yml -o weights=https://paddledet.bj.bcebos.com/models/ppyoloe_crn_l_80e_sliced_visdrone_640_025.pdparams --infer_img=demo.jpg --draw_threshold=0.25 --slice_infer --slice_size 640 640 --overlap_ratio 0.25 0.25 --combine_method=nms --match_threshold=0.6 --match_metric=ios +# 或图片文件夹 +CUDA_VISIBLE_DEVICES=0 python tools/infer.py -c configs/smalldet/ppyoloe_crn_l_80e_sliced_visdrone_640_025.yml -o weights=https://paddledet.bj.bcebos.com/models/ppyoloe_crn_l_80e_sliced_visdrone_640_025.pdparams --infer_dir=demo/ --draw_threshold=0.25 --slice_infer --slice_size 640 640 --overlap_ratio 0.25 0.25 --combine_method=nms --match_threshold=0.6 --match_metric=ios ``` - 设置`--slice_infer`表示切图预测并拼装重组结果,如果不使用则不写; - 设置`--slice_size`表示切图的子图尺寸大小,设置`--overlap_ratio`表示子图间重叠率; @@ -139,24 +243,27 @@ CUDA_VISIBLE_DEVICES=0 python tools/infer.py -c configs/smalldet/ppyoloe_crn_l_8 - 设置`--match_metric`表示子图结果重组去重的度量标准,默认是`ios`表示交小比(两个框交集面积除以更小框的面积),也可以选择交并比`iou`(两个框交集面积除以并集面积),精度效果因数据集而而异,但选择`ios`预测速度会更快一点; -## 4.部署 +### 部署 -### 4.1 导出模型 +#### 4.1 导出模型 ```bash # export model CUDA_VISIBLE_DEVICES=0 python tools/export_model.py -c configs/smalldet/ppyoloe_crn_l_80e_sliced_visdrone_640_025.yml -o weights=https://paddledet.bj.bcebos.com/models/ppyoloe_crn_l_80e_sliced_visdrone_640_025.pdparams ``` -### 4.2 使用原图或子图直接推理: +#### 4.2 使用原图或子图直接推理 ```bash # deploy infer -CUDA_VISIBLE_DEVICES=0 python deploy/python/infer.py --model_dir=output_inference/ppyoloe_crn_l_80e_sliced_visdrone_640_025 --image_file=demo.jpg --device=GPU --threshold=0.25 +CUDA_VISIBLE_DEVICES=0 python deploy/python/infer.py --model_dir=output_inference/ppyoloe_crn_l_80e_sliced_visdrone_640_025 --image_file=demo.jpg --device=GPU --save_images --threshold=0.25 ``` -### 4.3 使用原图自动切图并拼图重组结果来推理: +#### 4.3 使用原图自动切图并拼图重组结果来推理 ```bash # deploy slice infer -CUDA_VISIBLE_DEVICES=0 python deploy/python/infer.py --model_dir=output_inference/ppyoloe_crn_l_80e_sliced_visdrone_640_025 --image_file=demo.jpg --device=GPU --threshold=0.25 --slice_infer --slice_size 640 640 --overlap_ratio 0.25 0.25 --combine_method=nms --match_threshold=0.6 --match_metric=ios +# 单张图 +CUDA_VISIBLE_DEVICES=0 python deploy/python/infer.py --model_dir=output_inference/ppyoloe_crn_l_80e_sliced_visdrone_640_025 --image_file=demo.jpg --device=GPU --save_images --threshold=0.25 --slice_infer --slice_size 640 640 --overlap_ratio 0.25 0.25 --combine_method=nms --match_threshold=0.6 --match_metric=ios +# 或图片文件夹 +CUDA_VISIBLE_DEVICES=0 python deploy/python/infer.py --model_dir=output_inference/ppyoloe_crn_l_80e_sliced_visdrone_640_025 --image_dir=demo/ --device=GPU --save_images --threshold=0.25 --slice_infer --slice_size 640 640 --overlap_ratio 0.25 0.25 --combine_method=nms --match_threshold=0.6 --match_metric=ios ``` - 设置`--slice_infer`表示切图预测并拼装重组结果,如果不使用则不写; - 设置`--slice_size`表示切图的子图尺寸大小,设置`--overlap_ratio`表示子图间重叠率; @@ -165,94 +272,10 @@ CUDA_VISIBLE_DEVICES=0 python deploy/python/infer.py --model_dir=output_inferenc - 设置`--match_metric`表示子图结果重组去重的度量标准,默认是`ios`表示交小比(两个框交集面积除以更小框的面积),也可以选择交并比`iou`(两个框交集面积除以并集面积),精度效果因数据集而而异,但选择`ios`预测速度会更快一点; -# SAHI切图工具使用说明 - -## 1. 数据集下载 - -### VisDrone-DET - -VisDrone-DET是一个无人机航拍场景的小目标数据集,整理后的COCO格式VisDrone-DET数据集[下载链接](https://bj.bcebos.com/v1/paddledet/data/smalldet/visdrone.zip),切图后的COCO格式数据集[下载链接](https://bj.bcebos.com/v1/paddledet/data/smalldet/visdrone_sliced.zip),检测其中的**10类**,包括 `pedestrian(1), people(2), bicycle(3), car(4), van(5), truck(6), tricycle(7), awning-tricycle(8), bus(9), motor(10)`,原始数据集[下载链接](https://github.com/VisDrone/VisDrone-Dataset)。 -具体使用和下载请参考[visdrone](../visdrone)。 - -### DOTA水平框: - -DOTA是一个大型的遥感影像公开数据集,这里使用**DOTA-v1.0**水平框数据集,切图后整理的COCO格式的DOTA水平框数据集[下载链接](https://bj.bcebos.com/v1/paddledet/data/smalldet/dota_sliced.zip),检测其中的**15类**, -包括 `plane(0), baseball-diamond(1), bridge(2), ground-track-field(3), small-vehicle(4), large-vehicle(5), ship(6), tennis-court(7),basketball-court(8), storage-tank(9), soccer-ball-field(10), roundabout(11), harbor(12), swimming-pool(13), helicopter(14)`, -图片及原始数据集[下载链接](https://captain-whu.github.io/DOAI2019/dataset.html)。 - -### Xview: - -Xview是一个大型的航拍遥感检测数据集,目标极小极多,切图后整理的COCO格式数据集[下载链接](https://bj.bcebos.com/v1/paddledet/data/smalldet/xview_sliced.zip),检测其中的**60类**, -具体类别为: - -
- -`Fixed-wing Aircraft(0), -Small Aircraft(1), -Cargo Plane(2), -Helicopter(3), -Passenger Vehicle(4), -Small Car(5), -Bus(6), -Pickup Truck(7), -Utility Truck(8), -Truck(9), -Cargo Truck(10), -Truck w/Box(11), -Truck Tractor(12), -Trailer(13), -Truck w/Flatbed(14), -Truck w/Liquid(15), -Crane Truck(16), -Railway Vehicle(17), -Passenger Car(18), -Cargo Car(19), -Flat Car(20), -Tank car(21), -Locomotive(22), -Maritime Vessel(23), -Motorboat(24), -Sailboat(25), -Tugboat(26), -Barge(27), -Fishing Vessel(28), -Ferry(29), -Yacht(30), -Container Ship(31), -Oil Tanker(32), -Engineering Vehicle(33), -Tower crane(34), -Container Crane(35), -Reach Stacker(36), -Straddle Carrier(37), -Mobile Crane(38), -Dump Truck(39), -Haul Truck(40), -Scraper/Tractor(41), -Front loader/Bulldozer(42), -Excavator(43), -Cement Mixer(44), -Ground Grader(45), -Hut/Tent(46), -Shed(47), -Building(48), -Aircraft Hangar(49), -Damaged Building(50), -Facility(51), -Construction Site(52), -Vehicle Lot(53), -Helipad(54), -Storage Tank(55), -Shipping container lot(56), -Shipping Container(57), -Pylon(58), -Tower(59) -` -
-,原始数据集[下载链接](https://challenge.xviewdataset.org/download-links)。 +## 切图使用说明 -## 2. 统计数据集分布 +### 统计数据集分布 首先统计所用数据集标注框的平均宽高占图片真实宽高的比例分布: @@ -275,11 +298,11 @@ Distribution saved as box_distribution.jpg - 当原始数据集全部有标注框的图片中,**有1/2以上的图片标注框的平均宽高与原图宽高比例小于0.04时**,建议进行切图训练。 -## 3. SAHI切图 +### SAHI切图 针对需要切图的数据集,使用[SAHI](https://github.com/obss/sahi)库进行切分: -### 安装SAHI库: +#### 安装SAHI库: 参考[SAHI installation](https://github.com/obss/sahi/blob/main/README.md#installation)进行安装 @@ -287,7 +310,7 @@ Distribution saved as box_distribution.jpg pip install sahi ``` -### 基于SAHI切图: +#### 基于SAHI切图 ```bash python slice_tools/slice_image.py --image_dir ../../dataset/DOTA/train/ --json_path ../../dataset/DOTA/annotations/train.json --output_dir ../../dataset/dota_sliced --slice_size 500 --overlap_ratio 0.25 @@ -301,7 +324,8 @@ python slice_tools/slice_image.py --image_dir ../../dataset/DOTA/train/ --json_p - 以上述代码为例,切分后的子图文件夹与json标注文件共同保存在`dota_sliced`文件夹下,分别命名为`train_images_500_025`、`train_500_025.json`。 -# 引用 + +## 引用 ``` @article{akyon2022sahi, title={Slicing Aided Hyper Inference and Fine-tuning for Small Object Detection}, diff --git a/deploy/python/infer.py b/deploy/python/infer.py index af4edfc9b..aefb0eb50 100644 --- a/deploy/python/infer.py +++ b/deploy/python/infer.py @@ -224,7 +224,9 @@ class Detector(object): overlap_ratio=[0.25, 0.25], combine_method='nms', match_threshold=0.6, - match_metric='iou', + match_metric='ios', + run_benchmark=False, + repeats=1, visual=True, save_results=False): # slice infer only support bs=1 @@ -249,10 +251,38 @@ class Detector(object): overlap_width_ratio=overlap_ratio[1]) sub_img_num = len(slice_image_result) merged_bboxs = [] - for _ind in range(sub_img_num): - im = slice_image_result.images[_ind] + + batch_image_list = [ + slice_image_result.images[_ind] for _ind in range(sub_img_num) + ] + if run_benchmark: + # preprocess + inputs = self.preprocess(batch_image_list) # warmup + self.det_times.preprocess_time_s.start() + inputs = self.preprocess(batch_image_list) + self.det_times.preprocess_time_s.end() + + # model prediction + result = self.predict(repeats=50) # warmup + self.det_times.inference_time_s.start() + result = self.predict(repeats=repeats) + self.det_times.inference_time_s.end(repeats=repeats) + + # postprocess + result_warmup = self.postprocess(inputs, result) # warmup + self.det_times.postprocess_time_s.start() + result = self.postprocess(inputs, result) + self.det_times.postprocess_time_s.end() + self.det_times.img_num += 1 + + cm, gm, gu = get_current_memory_mb() + self.cpu_mem += cm + self.gpu_mem += gm + self.gpu_util += gu + else: + # preprocess self.det_times.preprocess_time_s.start() - inputs = self.preprocess([im]) # should be list + inputs = self.preprocess(batch_image_list) self.det_times.preprocess_time_s.end() # model prediction @@ -266,10 +296,17 @@ class Detector(object): self.det_times.postprocess_time_s.end() self.det_times.img_num += 1 + st, ed = 0, result['boxes_num'][0] # start_index, end_index + for _ind in range(sub_img_num): + boxes_num = result['boxes_num'][_ind] + ed = boxes_num shift_amount = slice_image_result.starting_pixels[_ind] - result['boxes'][:, 2:4] = result['boxes'][:, 2:4] + shift_amount - result['boxes'][:, 4:6] = result['boxes'][:, 4:6] + shift_amount - merged_bboxs.append(result['boxes']) + result['boxes'][st:ed][:, 2:4] = result['boxes'][ + st:ed][:, 2:4] + shift_amount + result['boxes'][st:ed][:, 4:6] = result['boxes'][ + st:ed][:, 4:6] + shift_amount + merged_bboxs.append(result['boxes'][st:ed]) + st = ed merged_results = {'boxes': []} if combine_method == 'nms': @@ -392,7 +429,7 @@ class Detector(object): if not os.path.exists(self.output_dir): os.makedirs(self.output_dir) out_path = os.path.join(self.output_dir, video_out_name) - fourcc = cv2.VideoWriter_fourcc(*'mp4v') + fourcc = cv2.VideoWriter_fourcc(* 'mp4v') writer = cv2.VideoWriter(out_path, fourcc, fps, (width, height)) index = 1 while (1): diff --git a/deploy/python/utils.py b/deploy/python/utils.py index ae5553747..63831412c 100644 --- a/deploy/python/utils.py +++ b/deploy/python/utils.py @@ -199,7 +199,7 @@ def argsparser(): parser.add_argument( "--match_metric", type=str, - default='iou', + default='ios', help="Combine method matching metric, choose in ['iou', 'ios'].") return parser diff --git a/ppdet/engine/trainer.py b/ppdet/engine/trainer.py index 6701162c4..f46974aaf 100644 --- a/ppdet/engine/trainer.py +++ b/ppdet/engine/trainer.py @@ -718,7 +718,8 @@ class Trainer(object): match_metric='iou', draw_threshold=0.5, output_dir='output', - save_results=False): + save_results=False, + visualize=True): self.dataset.set_slice_images(images, slice_size, overlap_ratio) loader = create('TestReader')(self.dataset, 0) @@ -771,40 +772,41 @@ class Trainer(object): for key in ['im_shape', 'scale_factor', 'im_id']: if isinstance(data, typing.Sequence): - outs[key] = data[0][key] + merged_results[key] = data[0][key] else: - outs[key] = data[key] + merged_results[key] = data[key] for key, value in merged_results.items(): if hasattr(value, 'numpy'): merged_results[key] = value.numpy() results.append(merged_results) - # visualize results - for outs in results: - batch_res = get_infer_results(outs, clsid2catid) - bbox_num = outs['bbox_num'] - start = 0 - for i, im_id in enumerate(outs['im_id']): - image_path = imid2path[int(im_id)] - image = Image.open(image_path).convert('RGB') - image = ImageOps.exif_transpose(image) - self.status['original_image'] = np.array(image.copy()) - end = start + bbox_num[i] - bbox_res = batch_res['bbox'][start:end] \ - if 'bbox' in batch_res else None - mask_res, segm_res, keypoint_res = None, None, None - image = visualize_results( - image, bbox_res, mask_res, segm_res, keypoint_res, - int(im_id), catid2name, draw_threshold) - self.status['result_image'] = np.array(image.copy()) - if self._compose_callback: - self._compose_callback.on_step_end(self.status) - # save image with detection - save_name = self._get_save_image_name(output_dir, image_path) - logger.info("Detection bbox results save in {}".format( - save_name)) - image.save(save_name, quality=95) - start = end + if visualize: + for outs in results: + batch_res = get_infer_results(outs, clsid2catid) + bbox_num = outs['bbox_num'] + start = 0 + for i, im_id in enumerate(outs['im_id']): + image_path = imid2path[int(im_id)] + image = Image.open(image_path).convert('RGB') + image = ImageOps.exif_transpose(image) + self.status['original_image'] = np.array(image.copy()) + end = start + bbox_num[i] + bbox_res = batch_res['bbox'][start:end] \ + if 'bbox' in batch_res else None + mask_res, segm_res, keypoint_res = None, None, None + image = visualize_results( + image, bbox_res, mask_res, segm_res, keypoint_res, + int(im_id), catid2name, draw_threshold) + self.status['result_image'] = np.array(image.copy()) + if self._compose_callback: + self._compose_callback.on_step_end(self.status) + # save image with detection + save_name = self._get_save_image_name(output_dir, + image_path) + logger.info("Detection bbox results save in {}".format( + save_name)) + image.save(save_name, quality=95) + start = end def predict(self, images, diff --git a/tools/eval.py b/tools/eval.py index 231d7ce09..42a2fcafa 100755 --- a/tools/eval.py +++ b/tools/eval.py @@ -115,7 +115,7 @@ def parse_args(): parser.add_argument( "--match_metric", type=str, - default='iou', + default='ios', help="Combine method matching metric, choose in ['iou', 'ios'].") args = parser.parse_args() return args diff --git a/tools/infer.py b/tools/infer.py index d22f20638..d9bf3166e 100755 --- a/tools/infer.py +++ b/tools/infer.py @@ -113,7 +113,7 @@ def parse_args(): parser.add_argument( "--match_metric", type=str, - default='iou', + default='ios', help="Combine method matching metric, choose in ['iou', 'ios'].") parser.add_argument( "--visualize", -- GitLab