From 38ebb263c7751679ba2661c9022d113f8e84e977 Mon Sep 17 00:00:00 2001 From: Feng Ni Date: Tue, 31 Jan 2023 11:12:36 +0800 Subject: [PATCH] fix slice infer one image save_results (#7654) --- configs/smalldet/README.md | 6 ++-- ppdet/engine/trainer.py | 69 ++++++++++++++++++++++++++++++++------ 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/configs/smalldet/README.md b/configs/smalldet/README.md index c0b428e32..be0b0e34f 100644 --- a/configs/smalldet/README.md +++ b/configs/smalldet/README.md @@ -294,7 +294,7 @@ CUDA_VISIBLE_DEVICES=0 python tools/infer.py -c configs/smalldet/ppyoloe_crn_l_8 也可以对原图进行自动切图并拼图重组来预测原图,如: ```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/0000315_01601_d_0000509.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_img=demo/0000315_01601_d_0000509.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 --save_results=True # 或图片文件夹 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 ``` @@ -303,6 +303,7 @@ CUDA_VISIBLE_DEVICES=0 python tools/infer.py -c configs/smalldet/ppyoloe_crn_l_8 - 设置`--combine_method`表示子图结果重组去重的方式,默认是`nms`; - 设置`--match_threshold`表示子图结果重组去重的阈值,默认是0.6; - 设置`--match_metric`表示子图结果重组去重的度量标准,默认是`ios`表示交小比(两个框交集面积除以更小框的面积),也可以选择交并比`iou`(两个框交集面积除以并集面积),精度效果因数据集而而异,但选择`ios`预测速度会更快一点; +- 设置`--save_results`表示保存图片结果为json文件,一般只单张图预测时使用; ### 部署 @@ -323,7 +324,7 @@ CUDA_VISIBLE_DEVICES=0 python deploy/python/infer.py --model_dir=output_inferenc ```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/0000315_01601_d_0000509.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_file=demo/0000315_01601_d_0000509.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 --save_results=True # 或图片文件夹 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 ``` @@ -332,6 +333,7 @@ CUDA_VISIBLE_DEVICES=0 python deploy/python/infer.py --model_dir=output_inferenc - 设置`--combine_method`表示子图结果重组去重的方式,默认是`nms`; - 设置`--match_threshold`表示子图结果重组去重的阈值,默认是0.6; - 设置`--match_metric`表示子图结果重组去重的度量标准,默认是`ios`表示交小比(两个框交集面积除以更小框的面积),也可以选择交并比`iou`(两个框交集面积除以并集面积),精度效果因数据集而而异,但选择`ios`预测速度会更快一点; +- 设置`--save_results`表示保存图片结果为json文件,一般只单张图预测时使用; diff --git a/ppdet/engine/trainer.py b/ppdet/engine/trainer.py index 362140ac2..35aa92d4b 100644 --- a/ppdet/engine/trainer.py +++ b/ppdet/engine/trainer.py @@ -774,6 +774,44 @@ class Trainer(object): loader = create('TestReader')(self.dataset, 0) imid2path = self.dataset.get_imid2path() + def setup_metrics_for_loader(): + # mem + metrics = copy.deepcopy(self._metrics) + mode = self.mode + save_prediction_only = self.cfg[ + 'save_prediction_only'] if 'save_prediction_only' in self.cfg else None + output_eval = self.cfg[ + 'output_eval'] if 'output_eval' in self.cfg else None + + # modify + self.mode = '_test' + self.cfg['save_prediction_only'] = True + self.cfg['output_eval'] = output_dir + self.cfg['imid2path'] = imid2path + self._init_metrics() + + # restore + self.mode = mode + self.cfg.pop('save_prediction_only') + if save_prediction_only is not None: + self.cfg['save_prediction_only'] = save_prediction_only + + self.cfg.pop('output_eval') + if output_eval is not None: + self.cfg['output_eval'] = output_eval + + self.cfg.pop('imid2path') + + _metrics = copy.deepcopy(self._metrics) + self._metrics = metrics + + return _metrics + + if save_results: + metrics = setup_metrics_for_loader() + else: + metrics = [] + anno_file = self.dataset.get_anno() clsid2catid, catid2name = get_categories( self.cfg.metric, anno_file=anno_file) @@ -819,6 +857,9 @@ class Trainer(object): merged_bboxs = [] data['im_id'] = data['ori_im_id'] + for _m in metrics: + _m.update(data, merged_results) + for key in ['im_shape', 'scale_factor', 'im_id']: if isinstance(data, typing.Sequence): merged_results[key] = data[0][key] @@ -829,31 +870,36 @@ class Trainer(object): merged_results[key] = value.numpy() results.append(merged_results) + for _m in metrics: + _m.accumulate() + _m.reset() + 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 = batch_res['mask'][start:end] \ + if 'mask' in batch_res else None + segm_res = batch_res['segm'][start:end] \ + if 'segm' in batch_res else None + keypoint_res = batch_res['keypoint'][start:end] \ + if 'keypoint' in batch_res else None + pose3d_res = batch_res['pose3d'][start:end] \ + if 'pose3d' in batch_res else None image = visualize_results( - image, - bbox_res, - mask_res=None, - segm_res=None, - keypoint_res=None, - pose3d_res=None, - im_id=int(im_id), - catid2name=catid2name, - threshold=draw_threshold) - + image, bbox_res, mask_res, segm_res, keypoint_res, + pose3d_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) @@ -863,6 +909,7 @@ class Trainer(object): logger.info("Detection bbox results save in {}".format( save_name)) image.save(save_name, quality=95) + start = end def predict(self, -- GitLab