From 530524ff5382f65e7700027e7876b9f4bd6a1b53 Mon Sep 17 00:00:00 2001 From: wangying Date: Tue, 8 Aug 2023 20:14:22 +0800 Subject: [PATCH] =?UTF-8?q?0808=E6=9B=B4=E6=96=B0=E9=A1=B9=E7=9B=AE?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detect_process/PP_TSMv2_infer.py | 164 ++ .../detect_process/analysisPoint.py | 152 ++ .../detect_process/holisticDet.py | 104 + .../detect_process/paddlevideo/__init__.py | 15 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 202 bytes .../__pycache__/version.cpython-310.pyc | Bin 0 -> 201 bytes .../paddlevideo/loader/__init__.py | 22 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 432 bytes .../__pycache__/builder.cpython-310.pyc | Bin 0 -> 2995 bytes .../__pycache__/dali_loader.cpython-310.pyc | Bin 0 -> 5310 bytes .../__pycache__/registry.cpython-310.pyc | Bin 0 -> 257 bytes .../paddlevideo/loader/builder.py | 132 ++ .../paddlevideo/loader/dali_loader.py | 206 ++ .../paddlevideo/loader/dataset/MRI.py | 109 ++ .../loader/dataset/MRI_SlowFast.py | 111 ++ .../paddlevideo/loader/dataset/__init__.py | 41 + .../dataset/__pycache__/MRI.cpython-310.pyc | Bin 0 -> 2970 bytes .../__pycache__/MRI_SlowFast.cpython-310.pyc | Bin 0 -> 3017 bytes .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1130 bytes .../actbert_dataset.cpython-310.pyc | Bin 0 -> 2216 bytes .../__pycache__/asrf_dataset.cpython-310.pyc | Bin 0 -> 2147 bytes .../__pycache__/ava_dataset.cpython-310.pyc | Bin 0 -> 6892 bytes .../dataset/__pycache__/base.cpython-310.pyc | Bin 0 -> 2447 bytes .../__pycache__/bmn_dataset.cpython-310.pyc | Bin 0 -> 2138 bytes .../__pycache__/davis_dataset.cpython-310.pyc | Bin 0 -> 4666 bytes .../__pycache__/feature.cpython-310.pyc | Bin 0 -> 1999 bytes .../dataset/__pycache__/frame.cpython-310.pyc | Bin 0 -> 4766 bytes .../ms_tcn_dataset.cpython-310.pyc | Bin 0 -> 2643 bytes .../__pycache__/msrvtt.cpython-310.pyc | Bin 0 -> 5701 bytes .../__pycache__/oxford.cpython-310.pyc | Bin 0 -> 2053 bytes .../__pycache__/skeleton.cpython-310.pyc | Bin 0 -> 2543 bytes .../slowfast_video.cpython-310.pyc | Bin 0 -> 3984 bytes .../ucf101_skeleton.cpython-310.pyc | Bin 0 -> 2888 bytes .../__pycache__/ucf24_dataset.cpython-310.pyc | Bin 0 -> 2451 bytes .../dataset/__pycache__/video.cpython-310.pyc | Bin 0 -> 2781 bytes .../loader/dataset/actbert_dataset.py | 74 + .../loader/dataset/asrf_dataset.py | 104 + .../paddlevideo/loader/dataset/ava_dataset.py | 249 +++ .../paddlevideo/loader/dataset/base.py | 80 + .../paddlevideo/loader/dataset/bmn_dataset.py | 72 + .../loader/dataset/davis_dataset.py | 189 ++ .../paddlevideo/loader/dataset/feature.py | 80 + .../paddlevideo/loader/dataset/frame.py | 177 ++ .../loader/dataset/ms_tcn_dataset.py | 110 ++ .../paddlevideo/loader/dataset/msrvtt.py | 220 +++ .../paddlevideo/loader/dataset/oxford.py | 62 + .../paddlevideo/loader/dataset/skeleton.py | 78 + .../loader/dataset/slowfast_video.py | 143 ++ .../loader/dataset/ucf101_skeleton.py | 89 + .../loader/dataset/ucf24_dataset.py | 76 + .../paddlevideo/loader/dataset/video.py | 95 + .../paddlevideo/loader/pipelines/__init__.py | 56 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 2327 bytes .../__pycache__/anet_pipeline.cpython-310.pyc | Bin 0 -> 4308 bytes .../__pycache__/augmentations.cpython-310.pyc | Bin 0 -> 39673 bytes .../augmentations_ava.cpython-310.pyc | Bin 0 -> 21444 bytes .../__pycache__/compose.cpython-310.pyc | Bin 0 -> 2122 bytes .../__pycache__/decode.cpython-310.pyc | Bin 0 -> 7999 bytes .../__pycache__/decode_image.cpython-310.pyc | Bin 0 -> 4383 bytes .../decode_sampler.cpython-310.pyc | Bin 0 -> 2470 bytes .../decode_sampler_MRI.cpython-310.pyc | Bin 0 -> 4924 bytes .../pipelines/__pycache__/mix.cpython-310.pyc | Bin 0 -> 3369 bytes .../__pycache__/multimodal.cpython-310.pyc | Bin 0 -> 8511 bytes .../__pycache__/sample.cpython-310.pyc | Bin 0 -> 8513 bytes .../__pycache__/sample_ava.cpython-310.pyc | Bin 0 -> 11039 bytes .../__pycache__/sample_ucf24.cpython-310.pyc | Bin 0 -> 1993 bytes .../__pycache__/segmentation.cpython-310.pyc | Bin 0 -> 2494 bytes .../segmentation_pipline.cpython-310.pyc | Bin 0 -> 971 bytes .../skeleton_pipeline.cpython-310.pyc | Bin 0 -> 46357 bytes .../loader/pipelines/anet_pipeline.py | 150 ++ .../loader/pipelines/augmentations.py | 1427 ++++++++++++++ .../loader/pipelines/augmentations_ava.py | 749 ++++++++ .../paddlevideo/loader/pipelines/compose.py | 76 + .../paddlevideo/loader/pipelines/decode.py | 348 ++++ .../loader/pipelines/decode_image.py | 206 ++ .../loader/pipelines/decode_sampler.py | 93 + .../loader/pipelines/decode_sampler_MRI.py | 224 +++ .../paddlevideo/loader/pipelines/mix.py | 116 ++ .../loader/pipelines/multimodal.py | 380 ++++ .../paddlevideo/loader/pipelines/sample.py | 382 ++++ .../loader/pipelines/sample_ava.py | 375 ++++ .../loader/pipelines/sample_ucf24.py | 69 + .../loader/pipelines/segmentation.py | 130 ++ .../loader/pipelines/segmentation_pipline.py | 40 + .../loader/pipelines/skeleton_pipeline.py | 1554 +++++++++++++++ .../paddlevideo/loader/registry.py | 18 + .../metrics/ActivityNet/__init__.py | 3 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 239 bytes .../__pycache__/anet_prop.cpython-310.pyc | Bin 0 -> 9800 bytes .../metrics/ActivityNet/anet_prop.py | 359 ++++ .../paddlevideo/metrics/__init__.py | 36 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1025 bytes .../__pycache__/ava_metric.cpython-310.pyc | Bin 0 -> 2406 bytes .../__pycache__/ava_utils.cpython-310.pyc | Bin 0 -> 10787 bytes .../metrics/__pycache__/base.cpython-310.pyc | Bin 0 -> 1768 bytes .../__pycache__/bmn_metric.cpython-310.pyc | Bin 0 -> 8162 bytes .../metrics/__pycache__/build.cpython-310.pyc | Bin 0 -> 357 bytes .../center_crop_metric.cpython-310.pyc | Bin 0 -> 2381 bytes .../center_crop_metric_MRI.cpython-310.pyc | Bin 0 -> 1759 bytes .../__pycache__/depth_metric.cpython-310.pyc | Bin 0 -> 2368 bytes .../__pycache__/msrvtt_metric.cpython-310.pyc | Bin 0 -> 2069 bytes .../multi_crop_metric.cpython-310.pyc | Bin 0 -> 2741 bytes .../__pycache__/recall.cpython-310.pyc | Bin 0 -> 2299 bytes .../__pycache__/registry.cpython-310.pyc | Bin 0 -> 223 bytes .../segmentation_metric.cpython-310.pyc | Bin 0 -> 8149 bytes .../skeleton_metric.cpython-310.pyc | Bin 0 -> 2689 bytes .../transnetv2_metric.cpython-310.pyc | Bin 0 -> 5594 bytes .../__pycache__/ucf24_utils.cpython-310.pyc | Bin 0 -> 21997 bytes .../__pycache__/vos_metric.cpython-310.pyc | Bin 0 -> 8918 bytes .../__pycache__/yowo_metric.cpython-310.pyc | Bin 0 -> 2554 bytes .../metrics/ava_evaluation/README.md | 2 + .../metrics/ava_evaluation/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 174 bytes .../__pycache__/metrics.cpython-310.pyc | Bin 0 -> 4487 bytes .../__pycache__/np_box_list.cpython-310.pyc | Bin 0 -> 4861 bytes .../__pycache__/np_box_ops.cpython-310.pyc | Bin 0 -> 2883 bytes ...bject_detection_evaluation.cpython-310.pyc | Bin 0 -> 21478 bytes .../per_image_evaluation.cpython-310.pyc | Bin 0 -> 14716 bytes .../standard_fields.cpython-310.pyc | Bin 0 -> 4585 bytes .../metrics/ava_evaluation/metrics.py | 143 ++ .../metrics/ava_evaluation/np_box_list.py | 138 ++ .../metrics/ava_evaluation/np_box_ops.py | 98 + .../object_detection_evaluation.py | 658 +++++++ .../ava_evaluation/per_image_evaluation.py | 452 +++++ .../metrics/ava_evaluation/standard_fields.py | 115 ++ .../paddlevideo/metrics/ava_metric.py | 92 + .../paddlevideo/metrics/ava_utils.py | 394 ++++ .../paddlevideo/metrics/base.py | 52 + .../paddlevideo/metrics/bmn_metric.py | 304 +++ .../paddlevideo/metrics/build.py | 20 + .../paddlevideo/metrics/center_crop_metric.py | 79 + .../metrics/center_crop_metric_MRI.py | 61 + .../paddlevideo/metrics/depth_metric.py | 77 + .../paddlevideo/metrics/msrvtt_metric.py | 62 + .../paddlevideo/metrics/multi_crop_metric.py | 108 ++ .../paddlevideo/metrics/recall.py | 84 + .../paddlevideo/metrics/registry.py | 17 + .../metrics/segmentation_metric.py | 389 ++++ .../paddlevideo/metrics/skeleton_metric.py | 96 + .../paddlevideo/metrics/transnetv2_metric.py | 174 ++ .../paddlevideo/metrics/ucf24_utils.py | 783 ++++++++ .../paddlevideo/metrics/vos_metric.py | 276 +++ .../paddlevideo/metrics/youtube8m/__init__.py | 0 .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 169 bytes ...erage_precision_calculator.cpython-310.pyc | Bin 0 -> 9058 bytes .../__pycache__/eval_util.cpython-310.pyc | Bin 0 -> 7500 bytes ...erage_precision_calculator.cpython-310.pyc | Bin 0 -> 4601 bytes .../youtube8m/average_precision_calculator.py | 274 +++ .../metrics/youtube8m/eval_util.py | 205 ++ .../mean_average_precision_calculator.py | 114 ++ .../paddlevideo/metrics/yowo_metric.py | 82 + .../paddlevideo/modeling/__init__.py | 37 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1249 bytes .../__pycache__/bbox_utils.cpython-310.pyc | Bin 0 -> 14172 bytes .../__pycache__/builder.cpython-310.pyc | Bin 0 -> 3294 bytes .../__pycache__/registry.cpython-310.pyc | Bin 0 -> 698 bytes .../__pycache__/weight_init.cpython-310.pyc | Bin 0 -> 3982 bytes .../modeling/assigners/__init__.py | 17 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 254 bytes .../max_iou_assigner_ava.cpython-310.pyc | Bin 0 -> 3765 bytes .../assigners/max_iou_assigner_ava.py | 148 ++ .../modeling/backbones/__init__.py | 60 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1769 bytes .../__pycache__/actbert.cpython-310.pyc | Bin 0 -> 28508 bytes .../__pycache__/adds.cpython-310.pyc | Bin 0 -> 26709 bytes .../__pycache__/agcn.cpython-310.pyc | Bin 0 -> 3531 bytes .../__pycache__/agcn2s.cpython-310.pyc | Bin 0 -> 7194 bytes .../__pycache__/asrf.cpython-310.pyc | Bin 0 -> 1975 bytes .../backbones/__pycache__/bmn.cpython-310.pyc | Bin 0 -> 6020 bytes .../__pycache__/cfbi.cpython-310.pyc | Bin 0 -> 2532 bytes .../__pycache__/ctrgcn.cpython-310.pyc | Bin 0 -> 13695 bytes .../__pycache__/darknet.cpython-310.pyc | Bin 0 -> 4583 bytes .../__pycache__/deeplab.cpython-310.pyc | Bin 0 -> 9563 bytes .../__pycache__/movinet.cpython-310.pyc | Bin 0 -> 15202 bytes .../__pycache__/ms_tcn.cpython-310.pyc | Bin 0 -> 4723 bytes .../__pycache__/pptsm_mv2.cpython-310.pyc | Bin 0 -> 6496 bytes .../__pycache__/pptsm_mv3.cpython-310.pyc | Bin 0 -> 9847 bytes .../__pycache__/pptsm_v2.cpython-310.pyc | Bin 0 -> 9793 bytes .../__pycache__/resnet.cpython-310.pyc | Bin 0 -> 6983 bytes .../__pycache__/resnet3d.cpython-310.pyc | Bin 0 -> 18435 bytes .../resnet3d_slowonly.cpython-310.pyc | Bin 0 -> 6053 bytes .../resnet_slowfast.cpython-310.pyc | Bin 0 -> 19220 bytes .../resnet_slowfast_MRI.cpython-310.pyc | Bin 0 -> 19241 bytes .../__pycache__/resnet_tsm.cpython-310.pyc | Bin 0 -> 8100 bytes .../resnet_tsm_MRI.cpython-310.pyc | Bin 0 -> 7842 bytes .../resnet_tsn_MRI.cpython-310.pyc | Bin 0 -> 7560 bytes .../resnet_tweaks_tsm.cpython-310.pyc | Bin 0 -> 8256 bytes .../resnet_tweaks_tsn.cpython-310.pyc | Bin 0 -> 7542 bytes .../__pycache__/resnext101.cpython-310.pyc | Bin 0 -> 4902 bytes .../__pycache__/stgcn.cpython-310.pyc | Bin 0 -> 9884 bytes .../swin_transformer.cpython-310.pyc | Bin 0 -> 22182 bytes .../__pycache__/toshift_vit.cpython-310.pyc | Bin 0 -> 10782 bytes .../__pycache__/transnetv2.cpython-310.pyc | Bin 0 -> 17837 bytes .../backbones/__pycache__/vit.cpython-310.pyc | Bin 0 -> 11880 bytes .../__pycache__/vit_tweaks.cpython-310.pyc | Bin 0 -> 12832 bytes .../__pycache__/yowo.cpython-310.pyc | Bin 0 -> 4390 bytes .../paddlevideo/modeling/backbones/actbert.py | 1158 ++++++++++++ .../paddlevideo/modeling/backbones/adds.py | 1146 +++++++++++ .../paddlevideo/modeling/backbones/agcn.py | 128 ++ .../paddlevideo/modeling/backbones/agcn2s.py | 229 +++ .../paddlevideo/modeling/backbones/asrf.py | 75 + .../paddlevideo/modeling/backbones/bmn.py | 290 +++ .../paddlevideo/modeling/backbones/cfbi.py | 88 + .../paddlevideo/modeling/backbones/ctrgcn.py | 514 +++++ .../paddlevideo/modeling/backbones/darknet.py | 165 ++ .../paddlevideo/modeling/backbones/deeplab.py | 454 +++++ .../paddlevideo/modeling/backbones/movinet.py | 574 ++++++ .../paddlevideo/modeling/backbones/ms_tcn.py | 154 ++ .../modeling/backbones/pptsm_mv2.py | 282 +++ .../modeling/backbones/pptsm_mv3.py | 408 ++++ .../modeling/backbones/pptsm_v2.py | 405 ++++ .../paddlevideo/modeling/backbones/resnet.py | 283 +++ .../modeling/backbones/resnet3d.py | 641 +++++++ .../modeling/backbones/resnet3d_slowonly.py | 214 +++ .../modeling/backbones/resnet_slowfast.py | 795 ++++++++ .../modeling/backbones/resnet_slowfast_MRI.py | 796 ++++++++ .../modeling/backbones/resnet_tsm.py | 353 ++++ .../modeling/backbones/resnet_tsm_MRI.py | 327 ++++ .../modeling/backbones/resnet_tsn_MRI.py | 331 ++++ .../modeling/backbones/resnet_tweaks_tsm.py | 362 ++++ .../modeling/backbones/resnet_tweaks_tsn.py | 328 ++++ .../modeling/backbones/resnext101.py | 191 ++ .../paddlevideo/modeling/backbones/stgcn.py | 343 ++++ .../modeling/backbones/swin_transformer.py | 742 ++++++++ .../modeling/backbones/toshift_vit.py | 413 ++++ .../modeling/backbones/transnetv2.py | 582 ++++++ .../paddlevideo/modeling/backbones/vit.py | 465 +++++ .../modeling/backbones/vit_tweaks.py | 515 +++++ .../paddlevideo/modeling/backbones/yowo.py | 150 ++ .../paddlevideo/modeling/bbox_utils.py | 528 ++++++ .../paddlevideo/modeling/builder.py | 127 ++ .../modeling/framework/__init__.py | 28 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 722 bytes .../modeling/framework/detectors/__init__.py | 17 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 349 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 1956 bytes .../__pycache__/fast_rcnn.cpython-310.pyc | Bin 0 -> 783 bytes .../__pycache__/two_stage.cpython-310.pyc | Bin 0 -> 4705 bytes .../modeling/framework/detectors/base.py | 51 + .../modeling/framework/detectors/fast_rcnn.py | 34 + .../modeling/framework/detectors/two_stage.py | 186 ++ .../modeling/framework/estimators/__init__.py | 4 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 306 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 2321 bytes .../depth_estimator.cpython-310.pyc | Bin 0 -> 1871 bytes .../modeling/framework/estimators/base.py | 82 + .../framework/estimators/depth_estimator.py | 59 + .../modeling/framework/localizers/__init__.py | 19 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 361 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 2406 bytes .../__pycache__/bmn_localizer.cpython-310.pyc | Bin 0 -> 1710 bytes .../yowo_localizer.cpython-310.pyc | Bin 0 -> 3358 bytes .../__pycache__/yowo_utils.cpython-310.pyc | Bin 0 -> 7379 bytes .../modeling/framework/localizers/base.py | 74 + .../framework/localizers/bmn_localizer.py | 69 + .../framework/localizers/yowo_localizer.py | 161 ++ .../framework/localizers/yowo_utils.py | 359 ++++ .../modeling/framework/multimodal/__init__.py | 16 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 292 bytes .../__pycache__/actbert.cpython-310.pyc | Bin 0 -> 2259 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 2586 bytes .../modeling/framework/multimodal/actbert.py | 64 + .../modeling/framework/multimodal/base.py | 81 + .../framework/partitioners/__init__.py | 18 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 324 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 2561 bytes .../transnetv2_partitioner.cpython-310.pyc | Bin 0 -> 1935 bytes .../modeling/framework/partitioners/base.py | 84 + .../partitioners/transnetv2_partitioner.py | 68 + .../framework/recognizers/__init__.py | 30 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 922 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 2530 bytes .../__pycache__/recognizer1d.cpython-310.pyc | Bin 0 -> 2865 bytes .../__pycache__/recognizer2d.cpython-310.pyc | Bin 0 -> 1831 bytes .../__pycache__/recognizer3d.cpython-310.pyc | Bin 0 -> 2244 bytes .../recognizer3dMRI.cpython-310.pyc | Bin 0 -> 1975 bytes .../recognizerDistillation.cpython-310.pyc | Bin 0 -> 5739 bytes .../__pycache__/recognizerMRI.cpython-310.pyc | Bin 0 -> 1984 bytes .../recognizer_gcn.cpython-310.pyc | Bin 0 -> 2249 bytes .../recognizer_movinet_frame.cpython-310.pyc | Bin 0 -> 1992 bytes .../recognizer_transformer.cpython-310.pyc | Bin 0 -> 2904 bytes ...recognizer_transformer_MRI.cpython-310.pyc | Bin 0 -> 3028 bytes .../modeling/framework/recognizers/base.py | 81 + .../framework/recognizers/recognizer1d.py | 111 ++ .../framework/recognizers/recognizer2d.py | 69 + .../framework/recognizers/recognizer3d.py | 93 + .../framework/recognizers/recognizer3dMRI.py | 81 + .../recognizers/recognizerDistillation.py | 231 +++ .../framework/recognizers/recognizerMRI.py | 76 + .../framework/recognizers/recognizer_gcn.py | 87 + .../recognizers/recognizer_movinet_frame.py | 78 + .../recognizers/recognizer_transformer.py | 98 + .../recognizers/recognizer_transformer_MRI.py | 104 + .../modeling/framework/segment/__init__.py | 16 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 280 bytes .../segment/__pycache__/base.cpython-310.pyc | Bin 0 -> 2535 bytes .../segment/__pycache__/cfbi.cpython-310.pyc | Bin 0 -> 6388 bytes .../segment/__pycache__/utils.cpython-310.pyc | Bin 0 -> 18111 bytes .../modeling/framework/segment/base.py | 90 + .../modeling/framework/segment/cfbi.py | 286 +++ .../modeling/framework/segment/utils.py | 754 ++++++++ .../modeling/framework/segmenters/__init__.py | 17 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 328 bytes .../__pycache__/asrf.cpython-310.pyc | Bin 0 -> 2679 bytes .../__pycache__/base.cpython-310.pyc | Bin 0 -> 2608 bytes .../__pycache__/ms_tcn.cpython-310.pyc | Bin 0 -> 2184 bytes .../__pycache__/utils.cpython-310.pyc | Bin 0 -> 8384 bytes .../modeling/framework/segmenters/asrf.py | 143 ++ .../modeling/framework/segmenters/base.py | 100 + .../modeling/framework/segmenters/ms_tcn.py | 101 + .../modeling/framework/segmenters/utils.py | 343 ++++ .../paddlevideo/modeling/heads/__init__.py | 49 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 1485 bytes .../__pycache__/adds_head.cpython-310.pyc | Bin 0 -> 3538 bytes .../__pycache__/agcn2s_head.cpython-310.pyc | Bin 0 -> 1829 bytes .../__pycache__/asrf_head.cpython-310.pyc | Bin 0 -> 5158 bytes .../attention_lstm_head.cpython-310.pyc | Bin 0 -> 6904 bytes .../heads/__pycache__/base.cpython-310.pyc | Bin 0 -> 4224 bytes .../__pycache__/bbox_head.cpython-310.pyc | Bin 0 -> 6688 bytes .../__pycache__/cfbi_head.cpython-310.pyc | Bin 0 -> 10113 bytes .../__pycache__/ctrgcn_head.cpython-310.pyc | Bin 0 -> 1983 bytes .../__pycache__/i3d_head.cpython-310.pyc | Bin 0 -> 2537 bytes .../__pycache__/movinet_head.cpython-310.pyc | Bin 0 -> 849 bytes .../__pycache__/ms_tcn_head.cpython-310.pyc | Bin 0 -> 4314 bytes .../pptimesformer_head.cpython-310.pyc | Bin 0 -> 2160 bytes .../__pycache__/pptsm_head.cpython-310.pyc | Bin 0 -> 2509 bytes .../__pycache__/pptsn_head.cpython-310.pyc | Bin 0 -> 2874 bytes .../__pycache__/roi_extractor.cpython-310.pyc | Bin 0 -> 1151 bytes .../__pycache__/roi_head.cpython-310.pyc | Bin 0 -> 4722 bytes .../single_straight3d.cpython-310.pyc | Bin 0 -> 2260 bytes .../__pycache__/slowfast_head.cpython-310.pyc | Bin 0 -> 3625 bytes .../__pycache__/stgcn_head.cpython-310.pyc | Bin 0 -> 1541 bytes .../timesformer_head.cpython-310.pyc | Bin 0 -> 1997 bytes .../token_shift_head.cpython-310.pyc | Bin 0 -> 2325 bytes .../transnetv2_head.cpython-310.pyc | Bin 0 -> 1337 bytes .../__pycache__/tsm_head.cpython-310.pyc | Bin 0 -> 2714 bytes .../__pycache__/tsn_head.cpython-310.pyc | Bin 0 -> 2353 bytes .../paddlevideo/modeling/heads/adds_head.py | 146 ++ .../paddlevideo/modeling/heads/agcn2s_head.py | 59 + .../paddlevideo/modeling/heads/asrf_head.py | 212 +++ .../modeling/heads/attention_lstm_head.py | 288 +++ .../paddlevideo/modeling/heads/base.py | 178 ++ .../paddlevideo/modeling/heads/bbox_head.py | 225 +++ .../paddlevideo/modeling/heads/cfbi_head.py | 448 +++++ .../paddlevideo/modeling/heads/ctrgcn_head.py | 65 + .../paddlevideo/modeling/heads/i3d_head.py | 95 + .../modeling/heads/movinet_head.py | 15 + .../paddlevideo/modeling/heads/ms_tcn_head.py | 165 ++ .../modeling/heads/pptimesformer_head.py | 74 + .../paddlevideo/modeling/heads/pptsm_head.py | 92 + .../paddlevideo/modeling/heads/pptsn_head.py | 103 + .../modeling/heads/roi_extractor.py | 53 + .../paddlevideo/modeling/heads/roi_head.py | 177 ++ .../modeling/heads/single_straight3d.py | 79 + .../modeling/heads/slowfast_head.py | 137 ++ .../paddlevideo/modeling/heads/stgcn_head.py | 50 + .../modeling/heads/timesformer_head.py | 70 + .../modeling/heads/token_shift_head.py | 79 + .../modeling/heads/transnetv2_head.py | 45 + .../paddlevideo/modeling/heads/tsm_head.py | 99 + .../paddlevideo/modeling/heads/tsn_head.py | 93 + .../paddlevideo/modeling/losses/__init__.py | 29 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 703 bytes .../__pycache__/actbert_loss.cpython-310.pyc | Bin 0 -> 2321 bytes .../__pycache__/asrf_loss.cpython-310.pyc | Bin 0 -> 10342 bytes .../losses/__pycache__/base.cpython-310.pyc | Bin 0 -> 1528 bytes .../__pycache__/bmn_loss.cpython-310.pyc | Bin 0 -> 4301 bytes .../cross_entropy_loss.cpython-310.pyc | Bin 0 -> 1107 bytes .../__pycache__/depth_loss.cpython-310.pyc | Bin 0 -> 7026 bytes .../distillation_loss.cpython-310.pyc | Bin 0 -> 2437 bytes .../transnetv2_loss.cpython-310.pyc | Bin 0 -> 1489 bytes .../__pycache__/yowo_loss.cpython-310.pyc | Bin 0 -> 6236 bytes .../modeling/losses/actbert_loss.py | 75 + .../paddlevideo/modeling/losses/asrf_loss.py | 401 ++++ .../paddlevideo/modeling/losses/base.py | 49 + .../paddlevideo/modeling/losses/bmn_loss.py | 155 ++ .../modeling/losses/cross_entropy_loss.py | 36 + .../paddlevideo/modeling/losses/depth_loss.py | 290 +++ .../modeling/losses/distillation_loss.py | 79 + .../modeling/losses/transnetv2_loss.py | 56 + .../paddlevideo/modeling/losses/yowo_loss.py | 251 +++ .../paddlevideo/modeling/registry.py | 31 + .../paddlevideo/modeling/samplers/__init__.py | 17 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 243 bytes .../random_sampler.cpython-310.pyc | Bin 0 -> 3581 bytes .../modeling/samplers/random_sampler.py | 146 ++ .../paddlevideo/modeling/weight_init.py | 157 ++ .../paddlevideo/solver/__init__.py | 16 + .../paddlevideo/solver/custom_lr.py | 338 ++++ .../detect_process/paddlevideo/solver/lr.py | 52 + .../paddlevideo/solver/optimizer.py | 132 ++ .../paddlevideo/tasks/__init__.py | 20 + .../detect_process/paddlevideo/tasks/test.py | 90 + .../detect_process/paddlevideo/tasks/train.py | 426 +++++ .../paddlevideo/tasks/train_dali.py | 143 ++ .../paddlevideo/tasks/train_multigrid.py | 335 ++++ .../paddlevideo/utils/__init__.py | 24 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 734 bytes .../__pycache__/build_utils.cpython-310.pyc | Bin 0 -> 768 bytes .../utils/__pycache__/config.cpython-310.pyc | Bin 0 -> 4706 bytes .../__pycache__/dist_utils.cpython-310.pyc | Bin 0 -> 749 bytes .../utils/__pycache__/logger.cpython-310.pyc | Bin 0 -> 2515 bytes .../__pycache__/precise_bn.cpython-310.pyc | Bin 0 -> 2950 bytes .../__pycache__/profiler.cpython-310.pyc | Bin 0 -> 3548 bytes .../utils/__pycache__/record.cpython-310.pyc | Bin 0 -> 4869 bytes .../__pycache__/registry.cpython-310.pyc | Bin 0 -> 2465 bytes .../__pycache__/save_load.cpython-310.pyc | Bin 0 -> 7342 bytes .../paddlevideo/utils/build_utils.py | 35 + .../paddlevideo/utils/config.py | 174 ++ .../paddlevideo/utils/dist_utils.py | 30 + .../paddlevideo/utils/logger.py | 113 ++ .../paddlevideo/utils/multigrid/__init__.py | 10 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 540 bytes .../batchnorm_helper.cpython-310.pyc | Bin 0 -> 4486 bytes .../interval_helper.cpython-310.pyc | Bin 0 -> 824 bytes .../__pycache__/multigrid.cpython-310.pyc | Bin 0 -> 6647 bytes .../save_load_helper.cpython-310.pyc | Bin 0 -> 6813 bytes .../__pycache__/short_sampler.cpython-310.pyc | Bin 0 -> 5085 bytes .../utils/multigrid/batchnorm_helper.py | 142 ++ .../utils/multigrid/interval_helper.py | 19 + .../paddlevideo/utils/multigrid/multigrid.py | 233 +++ .../utils/multigrid/save_load_helper.py | 237 +++ .../utils/multigrid/short_sampler.py | 147 ++ .../paddlevideo/utils/precise_bn.py | 94 + .../paddlevideo/utils/profiler.py | 128 ++ .../paddlevideo/utils/record.py | 163 ++ .../paddlevideo/utils/registry.py | 96 + .../paddlevideo/utils/save_load.py | 289 +++ .../detect_process/paddlevideo/version.py | 16 + Bank_second_part/detect_process/personDet.py | 42 + Bank_second_part/detect_process/tools.py | 212 --- .../detect_process/tools/__init__.py | 19 + .../__pycache__/__init__.cpython-310.pyc | Bin 0 -> 286 bytes .../__pycache__/ava_predict.cpython-310.pyc | Bin 0 -> 12615 bytes .../tools/__pycache__/utils.cpython-310.pyc | Bin 0 -> 42787 bytes .../tools/__pycache__/wheel.cpython-310.pyc | Bin 0 -> 8958 bytes .../detect_process/tools/ava_predict.py | 509 +++++ .../detect_process/tools/export_model.py | 267 +++ .../detect_process/tools/predict.py | 327 ++++ .../detect_process/tools/summary.py | 82 + .../detect_process/tools/utils.py | 1670 +++++++++++++++++ .../detect_process/tools/wheel.py | 354 ++++ .../detect_process/tools_function.py | 353 ++++ .../detect_process/video_process.py | 572 +++--- 444 files changed, 46725 insertions(+), 427 deletions(-) create mode 100644 Bank_second_part/detect_process/PP_TSMv2_infer.py create mode 100644 Bank_second_part/detect_process/analysisPoint.py create mode 100644 Bank_second_part/detect_process/holisticDet.py create mode 100644 Bank_second_part/detect_process/paddlevideo/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/__pycache__/version.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/__pycache__/builder.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/__pycache__/dali_loader.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/__pycache__/registry.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/builder.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dali_loader.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/MRI.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/MRI_SlowFast.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/MRI.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/MRI_SlowFast.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/actbert_dataset.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/asrf_dataset.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/ava_dataset.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/bmn_dataset.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/davis_dataset.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/feature.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/frame.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/ms_tcn_dataset.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/msrvtt.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/oxford.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/skeleton.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/slowfast_video.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/ucf101_skeleton.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/ucf24_dataset.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/video.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/actbert_dataset.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/asrf_dataset.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/ava_dataset.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/bmn_dataset.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/davis_dataset.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/feature.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/frame.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/ms_tcn_dataset.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/msrvtt.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/oxford.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/skeleton.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/slowfast_video.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/ucf101_skeleton.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/ucf24_dataset.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/dataset/video.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/anet_pipeline.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/augmentations.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/augmentations_ava.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/compose.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/decode.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/decode_image.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/decode_sampler.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/decode_sampler_MRI.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/mix.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/multimodal.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/sample.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/sample_ava.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/sample_ucf24.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/segmentation.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/segmentation_pipline.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/skeleton_pipeline.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/anet_pipeline.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/augmentations.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/augmentations_ava.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/compose.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_image.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_sampler.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_sampler_MRI.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/mix.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/multimodal.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample_ava.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample_ucf24.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/segmentation.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/segmentation_pipline.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/pipelines/skeleton_pipeline.py create mode 100644 Bank_second_part/detect_process/paddlevideo/loader/registry.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/__pycache__/anet_prop.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/anet_prop.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/ava_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/ava_utils.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/bmn_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/build.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/center_crop_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/center_crop_metric_MRI.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/depth_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/msrvtt_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/multi_crop_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/recall.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/registry.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/segmentation_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/skeleton_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/transnetv2_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/ucf24_utils.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/vos_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/yowo_metric.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/README.md create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/metrics.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/np_box_list.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/np_box_ops.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/object_detection_evaluation.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/per_image_evaluation.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/standard_fields.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/metrics.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/np_box_list.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/np_box_ops.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/object_detection_evaluation.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/per_image_evaluation.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/standard_fields.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ava_utils.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/bmn_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/build.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/center_crop_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/center_crop_metric_MRI.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/depth_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/msrvtt_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/multi_crop_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/recall.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/registry.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/segmentation_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/skeleton_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/transnetv2_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/ucf24_utils.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/vos_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__pycache__/average_precision_calculator.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__pycache__/eval_util.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__pycache__/mean_average_precision_calculator.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/average_precision_calculator.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/eval_util.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/mean_average_precision_calculator.py create mode 100644 Bank_second_part/detect_process/paddlevideo/metrics/yowo_metric.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/bbox_utils.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/builder.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/registry.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/weight_init.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/assigners/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/assigners/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/assigners/__pycache__/max_iou_assigner_ava.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/assigners/max_iou_assigner_ava.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/actbert.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/adds.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/agcn.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/agcn2s.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/asrf.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/bmn.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/cfbi.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/ctrgcn.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/darknet.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/deeplab.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/movinet.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/ms_tcn.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/pptsm_mv2.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/pptsm_mv3.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/pptsm_v2.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet3d.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet3d_slowonly.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_slowfast.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_slowfast_MRI.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_tsm.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_tsm_MRI.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_tsn_MRI.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_tweaks_tsm.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_tweaks_tsn.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnext101.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/stgcn.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/swin_transformer.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/toshift_vit.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/transnetv2.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/vit.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/vit_tweaks.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/yowo.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/actbert.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/adds.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/agcn.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/agcn2s.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/asrf.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/bmn.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/cfbi.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/ctrgcn.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/darknet.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/deeplab.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/movinet.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/ms_tcn.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_mv2.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_mv3.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_v2.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet3d.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet3d_slowonly.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_slowfast.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_slowfast_MRI.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsm.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsm_MRI.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsn_MRI.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tweaks_tsm.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tweaks_tsn.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnext101.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/stgcn.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/swin_transformer.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/toshift_vit.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/transnetv2.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/vit.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/vit_tweaks.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/backbones/yowo.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/bbox_utils.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/builder.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__pycache__/fast_rcnn.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__pycache__/two_stage.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/fast_rcnn.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/two_stage.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/__pycache__/depth_estimator.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/depth_estimator.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/bmn_localizer.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/yowo_localizer.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/yowo_utils.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/bmn_localizer.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/yowo_localizer.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/yowo_utils.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__pycache__/actbert.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/actbert.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__pycache__/transnetv2_partitioner.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/transnetv2_partitioner.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer1d.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer2d.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer3d.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer3dMRI.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizerDistillation.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizerMRI.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer_gcn.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer_movinet_frame.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer_transformer.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer_transformer_MRI.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer1d.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer2d.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer3d.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer3dMRI.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizerDistillation.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizerMRI.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_gcn.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_movinet_frame.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_transformer.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_transformer_MRI.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__pycache__/cfbi.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__pycache__/utils.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/cfbi.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/utils.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__pycache__/asrf.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__pycache__/ms_tcn.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__pycache__/utils.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/asrf.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/ms_tcn.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/utils.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/adds_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/agcn2s_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/asrf_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/attention_lstm_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/bbox_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/cfbi_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/ctrgcn_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/i3d_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/movinet_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/ms_tcn_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/pptimesformer_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/pptsm_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/pptsn_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/roi_extractor.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/roi_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/single_straight3d.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/slowfast_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/stgcn_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/timesformer_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/token_shift_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/transnetv2_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/tsm_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/tsn_head.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/adds_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/agcn2s_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/asrf_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/attention_lstm_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/bbox_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/cfbi_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/ctrgcn_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/i3d_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/movinet_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/ms_tcn_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/pptimesformer_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/pptsm_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/pptsn_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/roi_extractor.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/roi_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/single_straight3d.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/slowfast_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/stgcn_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/timesformer_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/token_shift_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/transnetv2_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/tsm_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/heads/tsn_head.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/actbert_loss.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/asrf_loss.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/base.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/bmn_loss.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/cross_entropy_loss.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/depth_loss.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/distillation_loss.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/transnetv2_loss.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/yowo_loss.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/actbert_loss.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/asrf_loss.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/base.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/bmn_loss.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/cross_entropy_loss.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/depth_loss.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/distillation_loss.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/transnetv2_loss.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/losses/yowo_loss.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/registry.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/samplers/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/samplers/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/samplers/__pycache__/random_sampler.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/samplers/random_sampler.py create mode 100644 Bank_second_part/detect_process/paddlevideo/modeling/weight_init.py create mode 100644 Bank_second_part/detect_process/paddlevideo/solver/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/solver/custom_lr.py create mode 100644 Bank_second_part/detect_process/paddlevideo/solver/lr.py create mode 100644 Bank_second_part/detect_process/paddlevideo/solver/optimizer.py create mode 100644 Bank_second_part/detect_process/paddlevideo/tasks/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/tasks/test.py create mode 100644 Bank_second_part/detect_process/paddlevideo/tasks/train.py create mode 100644 Bank_second_part/detect_process/paddlevideo/tasks/train_dali.py create mode 100644 Bank_second_part/detect_process/paddlevideo/tasks/train_multigrid.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__pycache__/build_utils.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__pycache__/config.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__pycache__/dist_utils.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__pycache__/logger.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__pycache__/precise_bn.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__pycache__/profiler.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__pycache__/record.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__pycache__/registry.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/__pycache__/save_load.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/build_utils.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/config.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/dist_utils.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/logger.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/__init__.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/batchnorm_helper.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/interval_helper.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/multigrid.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/save_load_helper.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/short_sampler.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/batchnorm_helper.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/interval_helper.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/multigrid.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/save_load_helper.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/multigrid/short_sampler.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/precise_bn.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/profiler.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/record.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/registry.py create mode 100644 Bank_second_part/detect_process/paddlevideo/utils/save_load.py create mode 100644 Bank_second_part/detect_process/paddlevideo/version.py create mode 100644 Bank_second_part/detect_process/personDet.py delete mode 100644 Bank_second_part/detect_process/tools.py create mode 100644 Bank_second_part/detect_process/tools/__init__.py create mode 100644 Bank_second_part/detect_process/tools/__pycache__/__init__.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/tools/__pycache__/ava_predict.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/tools/__pycache__/utils.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/tools/__pycache__/wheel.cpython-310.pyc create mode 100644 Bank_second_part/detect_process/tools/ava_predict.py create mode 100644 Bank_second_part/detect_process/tools/export_model.py create mode 100644 Bank_second_part/detect_process/tools/predict.py create mode 100644 Bank_second_part/detect_process/tools/summary.py create mode 100644 Bank_second_part/detect_process/tools/utils.py create mode 100644 Bank_second_part/detect_process/tools/wheel.py create mode 100644 Bank_second_part/detect_process/tools_function.py diff --git a/Bank_second_part/detect_process/PP_TSMv2_infer.py b/Bank_second_part/detect_process/PP_TSMv2_infer.py new file mode 100644 index 0000000..0a2b9de --- /dev/null +++ b/Bank_second_part/detect_process/PP_TSMv2_infer.py @@ -0,0 +1,164 @@ +import os +import os.path as osp +from paddlevideo.utils.config import get_config +from paddle.inference import Config, create_predictor +from tools.utils import build_inference_helper + +class PP_TSMv2_predict(object): + + """PP-TSMv2模型中常用的参数初始化""" + + def __init__(self,use_gpu=True,ir_optim=True, + disable_glog=False,save_name=None,enable_mklddn=False, + precision="fp32",gpu_mem=8000,cpu_threads=None): + + self.use_gpu = use_gpu #是否使用GPU + self.cpu_threads = cpu_threads #cpu线程数 + self.ir_optim = ir_optim #是否开启IR优化 + self.disable_glog = disable_glog + self.gpu_mem = gpu_mem #GPU存储大小 + self.enable_mkldnn = enable_mklddn #是否开启mkldnn + self.precision = precision #mfldnn精度 + self.save_name = save_name #转化推理模型存放名称 + + + + def parse_file_paths(self,input_path: str) -> list: + + """ + 获取模型输入数据 + input_path:模型的输入文件 + """ + if osp.isfile(input_path): + files = [ + input_path, + ] + else: + files = os.listdir(input_path) + files = [ + file for file in files + if (file.endswith(".avi") or file.endswith(".mp4")) + ] + files = [osp.join(input_path, file) for file in files] + return files + + + def create_paddle_predictor(self,model_f,pretr_p,cfg): + """ + 创建推理引擎 + model_f:可推理模型存放的路径+配置文件 + pretr_p:训练后的参数存放文件 + cfg:模型配置文件 + + """ + config = Config(model_f,pretr_p) + if self.use_gpu: + config.enable_use_gpu(self.gpu_mem,0) + else: + config.disable_gpu() + if self.cpu_threads: + config.set_cpu_math_library_num_threads(self.cpu_threads) + if self.enable_mkldnn: + config.set_mkldnn_cache_capacity(10) + config.enable_mkldnn() + if self.precision == "fp16": + config.enable_mkldnn_bfloat16() + + config.switch_ir_optim(self.ir_optim) + + config.enable_memory_optim() + config.switch_use_feed_fetch_ops(False) + + if self.disable_glog: + config.disable_glog_info() + + predictor = create_predictor(config) + + return config,predictor + + def create_inference_model(self,config,model_f,params_f): + """ + 创建推理模型以及引擎 + config:模型配置文件 + model_f:可推理模型的存放路径 + params_f:可推理模型的参数 + """ + cfg = get_config(config, overrides=None, show=False) + InferenceHelper = build_inference_helper(cfg.INFERENCE) + _, predictor = self.create_paddle_predictor(model_f, params_f, cfg) + + return InferenceHelper,predictor + + + def predict(self,input_f,batch_size,predictor,InferenceHelper): + + """ + 推理模型,对数据进行推理、预测 + config :PP-TSMv2模型的配置文件 + input_f:待推理数据集的存放路径 + batch_size:模型推理中所取数据的多少,default = 1 + predictor:推理引擎 + InferenceHelper:推理模型 + """ + result = {} + + # cfg = get_config(config, overrides=None, show=False) + # model_name = cfg.model_name + # print(f"Inference model({model_name})...") + + # get input_tensor and output_tensor + input_names = predictor.get_input_names() + output_names = predictor.get_output_names() + input_tensor_list = [] + output_tensor_list = [] + for item in input_names: + input_tensor_list.append(predictor.get_input_handle(item)) + for item in output_names: + output_tensor_list.append(predictor.get_output_handle(item)) + + files = self.parse_file_paths(input_f)#input_path=input_f + + batch_num = batch_size + for st_idx in range(0, len(files), batch_num): + ed_idx = min(st_idx + batch_num, len(files)) + + #输出数据预处理 + batched_inputs = InferenceHelper.preprocess_batch(files[st_idx:ed_idx]) + for i in range(len(input_tensor_list)): + input_tensor_list[i].copy_from_cpu(batched_inputs[i]) + + #推理引擎开始推理 + predictor.run() + + batched_outputs = [] + for j in range(len(output_tensor_list)): + batched_outputs.append(output_tensor_list[j].copy_to_cpu()) + + #输出推理结果 + res = InferenceHelper.postprocess(batched_outputs,False,True) + result["video_id"] = res[0]["video_id"] + result["topk_class"] = res[0]["topk_class"].tolist()[0] + result["topk_scores"] = res[0]["topk_scores"].tolist()[0] + # print(result) + + return result + + + +# def main(): +# config = 'D:/download/PaddleVideo1/output/output/pptsm_lcnet_k400_16frames_uniform.yaml' # 配置文件地址 +# input_file='C:/Users/Administrator/Pictures/video_seg_re_hand/test01_3.avi' #待推理数据集存放的地址 +# model_file = 'D:/download/PaddleVideo1/output/output/ppTSMv2.pdmodel' # 推理模型存放地址 +# params_file = 'D:/download/PaddleVideo1/output/output/ppTSMv2.pdiparams' +# batch_size= 1 #输出推理模型 +# infer,predictor = PP_TSMv2_predict().create_inference_model(config,model_file,params_file) +# PP_TSMv2_predict().predict(config,input_file,batch_size,predictor,infer) #推理模型推理、预测 + + + + +# if __name__ == "__main__": +# main() + + + diff --git a/Bank_second_part/detect_process/analysisPoint.py b/Bank_second_part/detect_process/analysisPoint.py new file mode 100644 index 0000000..2297fdc --- /dev/null +++ b/Bank_second_part/detect_process/analysisPoint.py @@ -0,0 +1,152 @@ +# Copyright 2020 The MediaPipe Authors. +# +# 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. +"""MediaPipe solution drawing utils.""" + +import math +from typing import List, Mapping, Optional, Tuple, Union + +import cv2 +import dataclasses +import matplotlib.pyplot as plt +import numpy as np + +from mediapipe.framework.formats import detection_pb2 +from mediapipe.framework.formats import location_data_pb2 +from mediapipe.framework.formats import landmark_pb2 + +_PRESENCE_THRESHOLD = 0.5 +_VISIBILITY_THRESHOLD = 0.5 +_BGR_CHANNELS = 3 + +WHITE_COLOR = (224, 224, 224) +BLACK_COLOR = (0, 0, 0) +RED_COLOR = (0, 0, 255) +GREEN_COLOR = (0, 128, 0) +BLUE_COLOR = (255, 0, 0) + + +@dataclasses.dataclass +class DrawingSpec: + # Color for drawing the annotation. Default to the white color. + color: Tuple[int, int, int] = WHITE_COLOR + # Thickness for drawing the annotation. Default to 2 pixels. + thickness: int = 2 + # Circle radius. Default to 2 pixels. + circle_radius: int = 2 + + +def _normalized_to_pixel_coordinates( + normalized_x: float, normalized_y: float, image_width: int, + image_height: int) -> Union[None, Tuple[int, int]]: + """Converts normalized value pair to pixel coordinates.""" + + # Checks if the float value is between 0 and 1. + def is_valid_normalized_value(value: float) -> bool: + return (value > 0 or math.isclose(0, value)) and (value < 1 or + math.isclose(1, value)) + + if not (is_valid_normalized_value(normalized_x) and + is_valid_normalized_value(normalized_y)): + # TODO: Draw coordinates even if it's outside of the image bounds. + return None + x_px = min(math.floor(normalized_x * image_width), image_width - 1) + y_px = min(math.floor(normalized_y * image_height), image_height - 1) + return x_px, y_px + + + +def draw_landmarks( + image: np.ndarray, + landmark_list: landmark_pb2.NormalizedLandmarkList, + connections: Optional[List[Tuple[int, int]]] = None): + """Draws the landmarks and the connections on the image. + + Args: + image: A three channel BGR image represented as numpy ndarray. + landmark_list: A normalized landmark list proto message to be annotated on + the image. + connections: A list of landmark index tuples that specifies how landmarks to + be connected in the drawing. + landmark_drawing_spec: Either a DrawingSpec object or a mapping from hand + landmarks to the DrawingSpecs that specifies the landmarks' drawing + settings such as color, line thickness, and circle radius. If this + argument is explicitly set to None, no landmarks will be drawn. + connection_drawing_spec: Either a DrawingSpec object or a mapping from hand + connections to the DrawingSpecs that specifies the connections' drawing + settings such as color and line thickness. If this argument is explicitly + set to None, no landmark connections will be drawn. + + Raises: + ValueError: If one of the followings: + a) If the input image is not three channel BGR. + b) If any connetions contain invalid landmark index. + """ + if not landmark_list: + return + if image.shape[2] != _BGR_CHANNELS: + raise ValueError('Input image must contain three channel bgr data.') + image_rows, image_cols, _ = image.shape + + # 所有的点转换成坐标的字典 + idx_to_coordinates = {} + for idx, landmark in enumerate(landmark_list.landmark): + # print('landmark:',landmark) + if ((landmark.HasField('visibility') and + landmark.visibility < _VISIBILITY_THRESHOLD) or + (landmark.HasField('presence') and + landmark.presence < _PRESENCE_THRESHOLD)): + continue + landmark_px = _normalized_to_pixel_coordinates(landmark.x, landmark.y, + image_cols, image_rows) + # print('landmark_px:',landmark_px) + if landmark_px: + idx_to_coordinates[idx] = landmark_px + + + if connections: + num_landmarks = len(landmark_list.landmark) + # print('connections:',connections) + + # Draws the connections if the start and end landmarks are both visible. + + start_list = [] + end_list = [] + for connection in connections: + # print(connection) + + start_idx = connection[0] + end_idx = connection[1] + + start_list.append(start_idx) + end_list.append(end_idx) + + + point_list = [] + for point_idx in end_list: + + # if point_idx not in start_list: + + # print(point_idx) + point_list.append(point_idx) + + + point_axis_list = [] + for point in point_list: + + if point in list(idx_to_coordinates.keys()): + point_axis_list.append(idx_to_coordinates[point]) + + + return point_axis_list + \ No newline at end of file diff --git a/Bank_second_part/detect_process/holisticDet.py b/Bank_second_part/detect_process/holisticDet.py new file mode 100644 index 0000000..f282bdf --- /dev/null +++ b/Bank_second_part/detect_process/holisticDet.py @@ -0,0 +1,104 @@ +import cv2 +import mediapipe as mp + +import analysisPoint as mp_drawing +mp_holistic = mp.solutions.holistic +import numpy as np + +class MediapipeProcess: + + def mediapipe_det(image,holistic): + + ''' + 调用模型推理获得检测结果 + ''' + + image.flags.writeable = False + image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) + results = holistic.process(image) + + return results + + def get_analysis_result(image,results): + + ''' + images: 检测的图片 + results: 图片的检测结果 + 对上述结果进行分析 + ''' + + image.flags.writeable = True + image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) + + face_result = mp_drawing.draw_landmarks( + image, + results.face_landmarks, + mp_holistic.FACEMESH_CONTOURS) + + right_hand_result = mp_drawing.draw_landmarks( + image, + results.right_hand_landmarks, + mp_holistic.HAND_CONNECTIONS) + + left_hand_result = mp_drawing.draw_landmarks( + image, + results.left_hand_landmarks, + mp_holistic.HAND_CONNECTIONS) + + face_bbox = MediapipeProcess.point_to_bbox(face_result) + right_hand_bbox = MediapipeProcess.point_to_bbox(right_hand_result) + left_hand_bbox = MediapipeProcess.point_to_bbox(left_hand_result) + + result_dict = {'face_bbox':[face_bbox],'hand_bbox':[right_hand_bbox,left_hand_bbox]} + + + return result_dict + + + + def point_to_bbox(result_list): + + ''' + 根据关键点坐标,获取坐标点的最小外接矩形 + ''' + + result_array = np.array(result_list) + + if result_array.all(): + + rect = cv2.minAreaRect(result_array) # 得到最小外接矩形的(中心(x,y), (宽,高), 旋转角度) + bbox = cv2.boxPoints(rect) # 获取最小外接矩形的4个顶点坐标(ps: cv2.boxPoints(rect) for OpenCV 3.x) + bbox = np.int0(bbox) + bbox=bbox.tolist() + + left_top = [min(bbox, key=lambda p: p[0])[0], min(bbox, key=lambda p: p[1])[1]] + right_bottom = [max(bbox, key=lambda p: p[0])[0], max(bbox, key=lambda p: p[1])[1]] + + bbox_list = left_top + right_bottom + + # print('bbox:',bbox) + # print('bbox_list:',bbox_list) + + + # bbox_list = [] + + # bbox_list.append(bbox[0][0]) + # bbox_list.append(bbox[0][1]) + # bbox_list.append(bbox[2][0]) + # bbox_list.append(bbox[2][1]) + + return bbox_list + + else: + pass + + + + + + + + +# if __name__ == '__main__': +# # media_holistic(video_file='E:/Bank_files/Bank_02/dataset/video_person/after_1/0711-1_199_0.avi', + # video_save_path='E:/Bank_files/Bank_02/videos_mediapipe/test_data/0725_test') \ No newline at end of file diff --git a/Bank_second_part/detect_process/paddlevideo/__init__.py b/Bank_second_part/detect_process/paddlevideo/__init__.py new file mode 100644 index 0000000..8b03acf --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/__init__.py @@ -0,0 +1,15 @@ +# 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. + +from .version import paddlevideo_version diff --git a/Bank_second_part/detect_process/paddlevideo/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0c62e182dde63014118168a52404b0521ffe4b15 GIT binary patch literal 202 zcmd1j<>g`kf(xwODcwvA439w^WB?RnZ~)?B0U(jWkiwY5kjogw$jFew6wIK>{E`tU ztjTywxF9hlB`38kGbJ@YzAUwg`kf(xwODT|mG7#@Q-$bb>ZaRB0CJ|L08kj@yzkiroB#j- literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/__init__.py b/Bank_second_part/detect_process/paddlevideo/loader/__init__.py new file mode 100644 index 0000000..4ed9b11 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/__init__.py @@ -0,0 +1,22 @@ +# 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. + +from .builder import build_dataset, build_dataloader, build_batch_pipeline +from .dataset import VideoDataset +from .dali_loader import TSN_Dali_loader, get_input_data + +__all__ = [ + 'build_dataset', 'build_dataloader', 'build_batch_pipeline', 'VideoDataset', + 'TSN_Dali_loader', 'get_input_data' +] diff --git a/Bank_second_part/detect_process/paddlevideo/loader/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..55be03260c8d442555e9ea6fedc3b00b830e67a2 GIT binary patch literal 432 zcmZ9IzfQw25XSBNr)^4yzC;#;7*T})b?#EcU`0B)JyR^~Byv(Do`HpDVB>9=y)y9% zOxQ`KA}sl*yOY1W?_B5kh`93^zv5d+$d^z4p1>v7?zRgDBuEv}lu;e9K!+@(z80uR z$1LvSP$fELsm@qN$&O(3PT2{@Yf>cN)U_x=n{W0~At3K~D>^$nrmE&BjGYga4ez#( z(8xw8S&4$$$-P8TF9%%_*wef93YJ_+I0&aZ(SfX*eb;v{665U~w-+&yN9>V!qz=o9L{Jg$!|LexIhwUlEuUbkN{Bx!}iJ>2=NNWN(Y0GGoYq>M%0i) zy2)8v3g;vPSs>T|x#u7Ox%jW-lyhHm@=w@B7TK?wGkQ3eT@u}_s%~~ySAA90+0v44 z;Q6=nSN_?uVf=@f%a0A_5nAytbll)9F~a)GLZ*2$H1RbPE44#AbwY<3+~RiPrj4+X zdZ7p2;cn7Q{m|EAjii;f!!~Gxd&yGT2|Jo@CfCyCa9PtVSqWD~hx;ciyv|#^{niL? z@Fm{C_a?u_m+`&TT*15AWc)V2&TqVB;cb4C-@?cpVVoMmIJ_(FoS6)i=I+%TXFEps z&U>84*zTIj-;B!WSr&02)$Pr=C}q4qEd_rPm4kzwD9sZg-!n|cTyOL7?&F=OyF04+ zeCzqsXItA(cix*c#+0)^jT8Qksm3Q+nrDT8%pZxepJbzvkl-$_zH^Yta=yB1<6SU$6x(Xf`o6@B-l;BS2Eavg%6WTk-<6I>1MD+Xs&to|%)-^@k zU^oiacswY(>w(O&G8kl&VLS>*RL|d*P3!Pv@L|}Hb2uAJI`}~kI5B~SI$g`bI|mee+r^9 z_RJZZnK-X`!YbBhrCG7k;*6VLSu?A$U<2!TT-$)dn}wJk>4%s=Tk3OBPUYm1+2+fw z2Upfr?l6;SRFbjA;;3uuV<>NNNa;auNvFV22cNJ7oA&2xgl%FLb5&z5)&{RTM53XV zYQxP(e-2SW%X&?pb(qcMEihLsM@X^IwB=}5LP*I@V7-cP!T|SLGqOKutyyQEfPSvd zhg#gIwYWOzH~7CGNBJfcxea3X(*Y^Bc-kO{Z=n@`LRY!6Me0-xZX?Ipv*yGr8A&R; za=1m3zZgTtZSK7FW~Cz=s#-Xj7d=3% z)ChR4gDKbq5Nb5`eC^v8FJ1)VO`b&YBsj=k2jzj#UacnuuQNIRsGfNhHgg9AYcoU@3@$l?H`IoP*LdBwkzUe5v;`%3P3Fhv?QD0I~gS+7(|lSkw`yHrfHv4 z5_0j=h2%V_i-YNKn25FgEK9KL>jQy9$)L=F`N;VpgQyI|7eXEdBF_c~^**~@OSLYv zD^z3tn`&~I<^3coN=)%DrpUYSrM!pk3i1d~g!b!b#UZ-V_!7B^a7Q_6W{iv(+_`DI z{Agyu>DCDYeGhSM&m1@!ag83*u>mKWr&i^R*coHStJTV^?7Id@YW`K5;PV!_V6)DC z*7g-uCr1=%~vKRPO0-cQ+D(wE|A~NNv@otj0R(3 zdJmLcBw6`kNcbBG%ESO!{^5vrp)Kzj#~T;%I>+5ck`1Dyc-TwhH~m4DBvC2)!%6R4 zez6ep1ci}m3b=lH#NiU5~nR*oDn>nw0TK#$5gqBg!4Wj!@_T z-FkodF-cn#i>SO*)oUaCf|k*Fb@{`?{T@Tb19bLvo0=3X`He%fFECKpwAdWz&f=#J9PkV>&zrzW6Z6r zvT^90;ljcRo!0SBf^nQAL4-Cq&;`COyQ0t;;CL;iTt>Ax`11_8EiON<|CpEOU?j6? zj@9uuO-Mue2z{uaC z18#KQR?T^ujWZ1h4GrZech9JcalFPu{!07@<=+ICFj^e+*jwjyk%u==!UJR>MF(f=szE*4Fl}Hrnpf z&p*3l7rIW>0Q5G}j87Bskg`ufc=eVj3@HTL^B277S)T7*GyNKf{@32aj=##j1Ij=A A=>Px# literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/__pycache__/dali_loader.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/__pycache__/dali_loader.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b3d04dc6830191ce1d440a1658815ee376a37215 GIT binary patch literal 5310 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 XR5kiJx{lH!eiXA2JUB+(YP|Iy7$zt| literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/__pycache__/registry.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/__pycache__/registry.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ffc259675edc3fce2323c9f15279fa253b35bf15 GIT binary patch literal 257 zcmd1j<>g`kf(xwODF>Mt7#@Q-$N(tD-~hzM3P2)-A%!uAA(t_Vk&z*lF@>p_F^UOD zGXrVn6qaBHP1ctn^_q;gID%5sGmA@#DsOQVWEQ06Wag#b;z&s>Ni0q+DfZK3xy4#q zl9^Ln1X6yBGr%*z)yLD%HTV{Xi(`mmuxm*0N`@j1pd6U^<(O&}V+s;eQgTwuGE-9XV{-BnQ&Nj!ilA=LD*!sfCO1E&G$+-L5ol^L N8<61P<6z=p1ON)(M0)@L literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/builder.py b/Bank_second_part/detect_process/paddlevideo/loader/builder.py new file mode 100644 index 0000000..23a65c3 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/builder.py @@ -0,0 +1,132 @@ +# 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 signal +import os +import paddle +from paddle.io import DataLoader, DistributedBatchSampler +from .registry import DATASETS, PIPELINES +from ..utils.build_utils import build +from .pipelines.compose import Compose +from paddlevideo.utils import get_logger +from paddlevideo.utils.multigrid import DistributedShortSampler +import numpy as np + +logger = get_logger("paddlevideo") + + +def build_pipeline(cfg): + """Build pipeline. + Args: + cfg (dict): root config dict. + """ + if cfg == None: + return + return Compose(cfg) + + +def build_dataset(cfg): + """Build dataset. + Args: + cfg (dict): root config dict. + + Returns: + dataset: dataset. + """ + #XXX: ugly code here! + cfg_dataset, cfg_pipeline = cfg + cfg_dataset.pipeline = build_pipeline(cfg_pipeline) + dataset = build(cfg_dataset, DATASETS, key="format") + return dataset + + +def build_batch_pipeline(cfg): + + batch_pipeline = build(cfg, PIPELINES) + return batch_pipeline + + +def build_dataloader(dataset, + batch_size, + num_workers, + places, + shuffle=True, + drop_last=True, + multigrid=False, + collate_fn_cfg=None, + **kwargs): + """Build Paddle Dataloader. + + XXX explain how the dataloader work! + + Args: + dataset (paddle.dataset): A PaddlePaddle dataset object. + batch_size (int): batch size on single card. + num_worker (int): num_worker + shuffle(bool): whether to shuffle the data at every epoch. + """ + if multigrid: + sampler = DistributedShortSampler(dataset, + batch_sizes=batch_size, + shuffle=True, + drop_last=True) + else: + sampler = DistributedBatchSampler(dataset, + batch_size=batch_size, + shuffle=shuffle, + drop_last=drop_last) + + #NOTE(shipping): when switch the mix operator on, such as: mixup, cutmix. + # batch like: [[img, label, attibute, ...], [imgs, label, attribute, ...], ...] will recollate to: + # [[img, img, ...], [label, label, ...], [attribute, attribute, ...], ...] as using numpy.transpose. + + def mix_collate_fn(batch): + pipeline = build_batch_pipeline(collate_fn_cfg) + batch = pipeline(batch) + slots = [] + for items in batch: + for i, item in enumerate(items): + if len(slots) < len(items): + slots.append([item]) + else: + slots[i].append(item) + return [np.stack(slot, axis=0) for slot in slots] + + #if collate_fn_cfg is not None: + #ugly code here. collate_fn is mix op config + # collate_fn = mix_collate_fn(collate_fn_cfg) + + data_loader = DataLoader( + dataset, + batch_sampler=sampler, + places=places, + num_workers=num_workers, + collate_fn=mix_collate_fn if collate_fn_cfg is not None else None, + return_list=True, + **kwargs) + + return data_loader + + +def term_mp(sig_num, frame): + """ kill all child processes + """ + pid = os.getpid() + pgid = os.getpgid(os.getpid()) + logger.info("main proc {} exit, kill process group " "{}".format(pid, pgid)) + os.killpg(pgid, signal.SIGKILL) + return + + +signal.signal(signal.SIGINT, term_mp) +signal.signal(signal.SIGTERM, term_mp) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dali_loader.py b/Bank_second_part/detect_process/paddlevideo/loader/dali_loader.py new file mode 100644 index 0000000..4fb0e28 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dali_loader.py @@ -0,0 +1,206 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 random +import math + +import paddle +from paddle.distributed import ParallelEnv +import paddle.distributed as dist +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + +try: + from nvidia.dali.pipeline import Pipeline + import nvidia.dali.ops as ops + import nvidia.dali.types as types + import tempfile + from nvidia.dali.plugin.paddle import DALIGenericIterator +except: + Pipeline = object + + +def get_input_data(data): + return paddle.to_tensor(data[0]['image']), paddle.to_tensor( + data[0]['label']) + + +class TSN_Dali_loader(object): + def __init__(self, cfg): + self.batch_size = cfg.batch_size + self.file_path = cfg.file_path + + self.num_seg = cfg.num_seg + self.seglen = cfg.seglen + self.short_size = cfg.short_size + self.target_size = cfg.target_size + + # set num_shards and shard_id when distributed training is implemented + self.num_shards = dist.get_world_size() + self.shard_id = ParallelEnv().local_rank + self.dali_mean = cfg.mean * (self.num_seg * self.seglen) + self.dali_std = cfg.std * (self.num_seg * self.seglen) + + def build_dali_reader(self): + """ + build dali training reader + """ + def reader_(): + with open(self.file_path) as flist: + full_lines = [line for line in flist] + if (not hasattr(reader_, 'seed')): + reader_.seed = 0 + random.Random(reader_.seed).shuffle(full_lines) + logger.info(f"reader shuffle seed: {reader_.seed}.") + if reader_.seed is not None: + reader_.seed += 1 + + per_node_lines = int( + math.ceil(len(full_lines) * 1.0 / self.num_shards)) + total_lines = per_node_lines * self.num_shards + + # aligned full_lines so that it can evenly divisible + full_lines += full_lines[:(total_lines - len(full_lines))] + assert len(full_lines) == total_lines + + # trainer get own sample + lines = full_lines[self.shard_id:total_lines:self.num_shards] + assert len(lines) == per_node_lines + + logger.info( + f"shard_id: {self.shard_id}, trainer_count: {self.num_shards}" + ) + logger.info( + f"read videos from {self.shard_id * per_node_lines}, " + f"length: {per_node_lines}, " + f"lines length: {len(lines)}, " + f"total: {len(full_lines)}") + + video_files = ''.join([item for item in lines]) + tf = tempfile.NamedTemporaryFile() + tf.write(str.encode(video_files)) + tf.flush() + video_files = tf.name + + device_id = ParallelEnv().local_rank + logger.info(f'---------- device_id: {device_id} -----------') + + pipe = VideoPipe(batch_size=self.batch_size, + num_threads=1, + device_id=device_id, + file_list=video_files, + sequence_length=self.num_seg * self.seglen, + num_seg=self.num_seg, + seg_length=self.seglen, + resize_shorter_scale=self.short_size, + crop_target_size=self.target_size, + is_training=True, + num_shards=self.num_shards, + shard_id=self.shard_id, + dali_mean=self.dali_mean, + dali_std=self.dali_std) + + logger.info( + 'initializing dataset, it will take several minutes if it is too large .... ' + ) + video_loader = DALIGenericIterator([pipe], ['image', 'label'], + len(lines), + dynamic_shape=True, + auto_reset=True) + + return video_loader + + dali_reader = reader_() + return dali_reader + + +class VideoPipe(Pipeline): + def __init__(self, + batch_size, + num_threads, + device_id, + file_list, + sequence_length, + num_seg, + seg_length, + resize_shorter_scale, + crop_target_size, + is_training=False, + initial_prefetch_size=20, + num_shards=1, + shard_id=0, + dali_mean=0., + dali_std=1.0): + super(VideoPipe, self).__init__(batch_size, num_threads, device_id) + self.input = ops.VideoReader(device="gpu", + file_list=file_list, + sequence_length=sequence_length, + num_seg=num_seg, + seg_length=seg_length, + is_training=is_training, + num_shards=num_shards, + shard_id=shard_id, + random_shuffle=is_training, + initial_fill=initial_prefetch_size) + # the sequece data read by ops.VideoReader is of shape [F, H, W, C] + # Because the ops.Resize does not support sequence data, + # it will be transposed into [H, W, F, C], + # then reshaped to [H, W, FC], and then resized like a 2-D image. + self.transpose = ops.Transpose(device="gpu", perm=[1, 2, 0, 3]) + self.reshape = ops.Reshape(device="gpu", + rel_shape=[1.0, 1.0, -1], + layout='HWC') + self.resize = ops.Resize(device="gpu", + resize_shorter=resize_shorter_scale) + # crops and mirror are applied by ops.CropMirrorNormalize. + # Normalization will be implemented in paddle due to the difficulty of dimension broadcast, + # It is not sure whether dimension broadcast can be implemented correctly by dali, just take the Paddle Op instead. + self.pos_rng_x = ops.Uniform(range=(0.0, 1.0)) + self.pos_rng_y = ops.Uniform(range=(0.0, 1.0)) + self.mirror_generator = ops.Uniform(range=(0.0, 1.0)) + self.cast_mirror = ops.Cast(dtype=types.DALIDataType.INT32) + self.crop_mirror_norm = ops.CropMirrorNormalize( + device="gpu", + crop=[crop_target_size, crop_target_size], + mean=dali_mean, + std=dali_std) + self.reshape_back = ops.Reshape( + device="gpu", + shape=[num_seg, seg_length * 3, crop_target_size, crop_target_size], + layout='FCHW') + self.cast_label = ops.Cast(device="gpu", dtype=types.DALIDataType.INT64) + + def define_graph(self): + output, label = self.input(name="Reader") + output = self.transpose(output) + output = self.reshape(output) + + output = self.resize(output) + output = output / 255. + pos_x = self.pos_rng_x() + pos_y = self.pos_rng_y() + mirror_flag = self.mirror_generator() + mirror_flag = (mirror_flag > 0.5) + mirror_flag = self.cast_mirror(mirror_flag) + output = self.crop_mirror_norm(output, + crop_pos_x=pos_x, + crop_pos_y=pos_y, + mirror=mirror_flag) + output = self.reshape_back(output) + label = self.cast_label(label) + return output, label + + def __len__(self): + return self.epoch_size() diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/MRI.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/MRI.py new file mode 100644 index 0000000..990cb87 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/MRI.py @@ -0,0 +1,109 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import random +import numpy as np + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class MRIDataset(BaseDataset): + """Rawframe dataset for action recognition. + The dataset loads raw frames from frame files, and apply specified transform operatation them. + The indecx file is a text file with multiple lines, and each line indicates the directory of frames of a video, toatl frames of the video, and its label, which split with a whitespace. + Example of an index file: + + .. code-block:: txt + + file_path-1 150 1 + file_path-2 160 1 + file_path-3 170 2 + file_path-4 180 2 + + Args: + file_path (str): Path to the index file. + pipeline(XXX): + data_prefix (str): directory path of the data. Default: None. + test_mode (bool): Whether to bulid the test dataset. Default: False. + suffix (str): suffix of file. Default: 'img_{:05}.jpg'. + + """ + def __init__(self, + file_path, + pipeline, + num_retries=5, + data_prefix=None, + test_mode=False, + suffix='img_{:05}.jpg'): + self.num_retries = num_retries + self.suffix = suffix + super().__init__(file_path, pipeline, data_prefix, test_mode) + + def load_file(self): + """Load index file to get video information.""" + info = [] + with open(self.file_path, 'r') as fin: + for line in fin: + line_split = line.strip().split() + frame_dir, frames_len, labels = line_split + if self.data_prefix is not None: + frame_dir = osp.join(self.data_prefix, frame_dir) + info.append( + dict( + frame_dir=frame_dir, + #suffix=self.suffix, + frames_len=frames_len, + labels=int(labels))) + return info + + def prepare_train(self, idx): + """Prepare the frames for training/valid gisven index. """ + #Try to catch Exception caused by reading missing frames files + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['frame_dir'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return np.array(results['imgs']), np.array([results['labels']]) + + def prepare_test(self, idx): + """Prepare the frames for test given index. """ + #Try to catch Exception caused by reading missing frames files + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['frame_dir'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return np.array(results['imgs']), np.array([results['labels']]) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/MRI_SlowFast.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/MRI_SlowFast.py new file mode 100644 index 0000000..db905e4 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/MRI_SlowFast.py @@ -0,0 +1,111 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import random +import numpy as np + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class SFMRIDataset(BaseDataset): + """Rawframe dataset for action recognition. + The dataset loads raw frames from frame files, and apply specified transform operatation them. + The indecx file is a text file with multiple lines, and each line indicates the directory of frames of a video, toatl frames of the video, and its label, which split with a whitespace. + Example of an index file: + + .. code-block:: txt + + file_path-1 150 1 + file_path-2 160 1 + file_path-3 170 2 + file_path-4 180 2 + + Args: + file_path (str): Path to the index file. + pipeline(XXX): + data_prefix (str): directory path of the data. Default: None. + test_mode (bool): Whether to bulid the test dataset. Default: False. + suffix (str): suffix of file. Default: 'img_{:05}.jpg'. + + """ + def __init__(self, + file_path, + pipeline, + num_retries=5, + data_prefix=None, + test_mode=False, + suffix='img_{:05}.jpg'): + self.num_retries = num_retries + self.suffix = suffix + super().__init__(file_path, pipeline, data_prefix, test_mode) + + def load_file(self): + """Load index file to get video information.""" + info = [] + with open(self.file_path, 'r') as fin: + for line in fin: + line_split = line.strip().split() + frame_dir, frames_len, labels = line_split + if self.data_prefix is not None: + frame_dir = osp.join(self.data_prefix, frame_dir) + info.append( + dict( + frame_dir=frame_dir, + #suffix=self.suffix, + frames_len=frames_len, + labels=int(labels))) + return info + + def prepare_train(self, idx): + """Prepare the frames for training/valid gisven index. """ + #Try to catch Exception caused by reading missing frames files + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['frame_dir'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return np.array(results['imgs'][0]), np.array( + results['imgs'][1]), np.array([results['labels']]) + + def prepare_test(self, idx): + """Prepare the frames for test given index. """ + #Try to catch Exception caused by reading missing frames files + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['frame_dir'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return np.array(results['imgs'][0]), np.array( + results['imgs'][1]), np.array([results['labels']]) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__init__.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__init__.py new file mode 100644 index 0000000..e974191 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__init__.py @@ -0,0 +1,41 @@ +# 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. + +from .actbert_dataset import ActBertDataset +from .ava_dataset import AVADataset +from .bmn_dataset import BMNDataset +from .davis_dataset import DavisDataset +from .feature import FeatureDataset +from .frame import FrameDataset, FrameDataset_Sport +from .MRI import MRIDataset +from .MRI_SlowFast import SFMRIDataset +from .msrvtt import MSRVTTDataset +from .actbert_dataset import ActBertDataset +from .asrf_dataset import ASRFDataset +from .ms_tcn_dataset import MSTCNDataset +from .oxford import MonoDataset +from .skeleton import SkeletonDataset +from .slowfast_video import SFVideoDataset +from .video import VideoDataset +from .ucf101_skeleton import UCF101SkeletonDataset +from .ucf24_dataset import UCF24Dataset + + +__all__ = [ + 'VideoDataset', 'FrameDataset', 'SFVideoDataset', 'BMNDataset', + 'FeatureDataset', 'SkeletonDataset', 'AVADataset', 'MonoDataset', + 'MSRVTTDataset', 'ActBertDataset', 'DavisDataset', 'MRIDataset', + 'SFMRIDataset', 'FrameDataset_Sport', 'MSTCNDataset', 'ASRFDataset', + 'UCF101SkeletonDataset', 'UCF24Dataset' +] diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/MRI.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/MRI.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..58b431f699952a895a52c97ed6c7a4356710a121 GIT binary patch literal 2970 zcmZ`*TW{RP6`tW`mwS`t#`UG`!yru>ZzHcI$7x!@NMl!WP@oag*nr)I8iL}?u4r?Y z^pLVH;T8pCGzE&He_{3L*Zz_|&ugFboV>&hntq2|No&{Pf`@ZCbIzG_`OYStPLtvJ zm-{#Q*G0zuO_TY@#pENrSqvhXwDmFq#HLz z&3+T(nykmIQM=#fOtqzV$on1TO&5;X$4oY4^BI#()jYJZeopdxtlK(`%;a2l>$_>v7c8U3t*%XzZ#jP+gFlr4N~vMoFK*1u#9>w7TvoN0dY z*>7jo1Q%e=XTk132O}k9Wuh1)S_EMpC1asgm<-1ejeAXj=l=E?Uz`Lo6FS%x<@pSs zWK@mCAc|GCB!aONL7K+jsOlE0 z&C-3no(L1Eu5HCh_;__yFwLB1uQ`Du`EUt19??=Op$^2p0OH^j;>Ucd96SovUC z+<48In_}gcv{P=~*28S||Cz+qEZ5yt@hQ~9Bc8uBsK7$2n{z0%Nu{my<_r-wff&7XU!Q~I6}%bU zyH>C9i~Qh?Gc@U)7#|Ywoje`}4ZOd>oBai3$R<2z1$)FLKeYa_GO-G4js5ZMiCx%J z>j-{3ViTuuHtmT!sZHwObfmSz^;@|+g?As3N3Drl@M%5w3b&}`jiP?YrTusNh;#O& z^?*ss0pK0loE1Rm6_(xF#SZ=cfS1;~&O!HgxaC}pQkDUhtK!ExVN?lDJ;U`z*G4P| zCw*kLX;zTu$7*b9B|K!^rg4C1V|^Z%L_iVX6dyth{RS=BNtPPtQ4-+@Kv9jQaR5}g zv7>R`^)$K~GY;uB_5e%{6`E-h^(!$y0*C%Fk)IH`bV@E`WEvE;GM2Y6&3*>rSPR_a zZQjIhfjiuypH<_|x3%xA|1`gI+KXR1?Sl(*K|B=_Qa?L+s2*B)DT-hH6QqjZAxGqX zKd}zZ__66!XTkDV@AUG7(#TnIY!<0pcg!iSsAtiCcYl`7X=b(+*D8Nb_u5zru$6 zhz~3a@xF&Mh`4uf^HZ(TKm$SmBPUG@-3~1YWj7vPe;N?T45RF+nxS`3XllVP-dooi zoV(lDAQypKd@)%P+rd+X0YvPh-|a?mOhXY2AyJp{qGH%UTt~yK4BPVs_t$k)1784x!!T)mn$9pE-O#V@_^2{eBtKo)F^FCuC1vnX-e-1+ZCyUo2n zTi?9tIbR=Ko=cjSM0{`J=$}I_!qEM`Fc7d0qgQ>e-^H;xU+N{Amlbf0M!zERN-eZc zErQI?iQ(5E2bW%FGdQ}Arhk_kcQqw>w?RNWrdsz+)2EiSgVyYuw(mdL3F6sK-S=e@ z`hJOvx=TtvB=Ql6>CE6aRB;TJGxL5(EL5+WP?3r`y8z;$R;^2Aee#7DUdubbc)sN5 zE}D9h^{9y&ho}}{*Vl>M1Til93G(Ix8hctHd69sc+LCd$@Sjst?HYF{kK#;I*U~rU oSd}id%o$jkS^|o9tGfAzl)|Nz?FA2b0z|ReNC?lW*%$f$0O4aGSO5S3 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/MRI_SlowFast.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/MRI_SlowFast.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..08be8bc6b96299c9c9b400fffb8da1d469f9e0e7 GIT binary patch literal 3017 zcmZ`*&2QYs6`vuwyWB5XNgc;Zdl zk{(iCN#Pa+WHg7O=)bT!`XA}J=ehQzOE1Z#Zc+F5$d$Bm9TI%=^=96i_wjp-+wBI! z^Y_Z1$sdN>(5!QA{(-awklh)jkfkRb6C%XvX@M2 zYvcZxpU?F1FGHa({c&IWLnUOXr0B<5_(2xNBcW9g4@M#NyA6To!R|R<6#Ft2+8>Kz ze~Km^mVMC=Bb6=-eBwM4ELfeOd=(saC9n1`N3{67T6sIex_1^Q-ut1i!9a$BJQ7Rik>eD zlP`-b_Oobif%eRnNc}KNMda_OXjzPRLx@O|D9l8mhEG$FllXxum0#cYholz?7?C2X zyv16hFkiPTf>^5SJ5d}wSz8m?epW7!ZOLX{;%B?pSHFxe) zQ0RDxR{e1Q^rUmM)0M~|g)_j|757x%hX>chW;~i1jt++96_Cjy9&EB zX|%H!g$N!vhuBVob?&SUKT78gOZWP7+RR220kHDit`EcE!24=#<>N{BaWeR@TUzOa z@MLr2W&6TvP@79m>R0h0gIM}QklfCh$MPyD&#WUhwR4_Zxsz9p9l{}`AK&aara9Uh zdRk>VRH>c&&+F8Tld7n1>Ss}5+*9N07Q~t6oY77F%yzns#TVSv zJuis-H1)g}?B#v6wtd$hJ@JaXEW0Z=w-X%)3M@3cJ%>Zvl-f#f&k$i7h~aHT@p!{e zvu<*rFG0jAzLX45tyTFIe)!HjuyjxF5fBQVJ}x?Se80k%{t0BjCOl&~d(0(2vi`a{ zv2yDk`~3$KJGZCSF-&;OCQj~b+mp(qI;nxvk=7p9?`M@M4E>mlYfUOSpVl%rujJLN zp4X1JwEtosbIzVNA2Mk1xHrzsx=^@BXqeMS1QX^9>kRt6gj012R>9=r6_!hoS&=7Fw@6nVUr-^YM z$04==AJs@22bh%^I~-*lSEIx+LuRP{GaOm$7`2mr4&&XBuOr0E9 zxb-%M>5oAiYk|AG#T$4RxWg@attxl^Q+;LqyYb3tEq?2?4zFBr9b9j?YD>*zeu^+P04TojbgLMwia(4J5q)6fa ztLzEWD_Ly{4^Q3Pmi7|Mtz(P)nAN8Z>10hh6W--l8NALP!h^ChasJ>ut(5JUk6G55 zwz0dqgtAW3=f;ILvvF;S4frwd+ZLi=3+EsX+{0U6XqEUH7z3O+t!gNTs9DI%(cs22 zpHOHJrq9$2-n&9mm45lry4K(v?_z<>25#}yWLfO`&lEa1;s6D497Yj!g+IWFy6_^U z$R@l!9HfOaUo4mkY9xLRiad9MI5{w`R4SpK{s8RyZ4gsm-w#wmXn@3@iN;NPt5+-{lah z0fX>$FX*3Q+niPPGL4H2xlX-b5P2C_adxPpI!| zg+N9yYN}zz*}*TWrrb7_y)2AUO(jm>oMTnGkTR!Wp=tp+?(OpCpHes%TDBHkAPz9c NY9TmWt7>22{{st-Eo}e* literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8da8e88bbe3476047c1aab762ef8904d9b8fb764 GIT binary patch literal 1130 zcmZWoO>fgc5Vey!UtT+D`avlLNAw=5BQV;2&E4rwFi5)^}&j|Uu}3Et%cV9`Y+pTci%4j-Y`Fjb$%vtk;S=jTD|LDNuBgB zmWrK;=_p%jKZr$sr{lR(DOjL|n(LxlRy>@fnlkh+&*v-bf`!3f+Utjx*H>4|7u;TW z87w91hgYYin%sUmPM43{;cYDAJRL7BKMbx%QCxb7{i8SDp9Y5qhyO2S=E2eNJXBY& zny%?OLI+_5!JH~fw-KrcK7xyYM@u^hO$0oLx`E&!FoZ6`nt_Y`7tj{N{Km|JN3&s2 z0C2@rEF8=L?u{BR94rC622lIn;WP&BgpF;Hi~&rJNp#OG6-1a+@) zW*mD8?Ym)OCcqcVuruHp_vm<$8yi*BITuoL{>{?cMicx#k6#Z?#Q2scBN=BidT=zD z=yVuo8M%Xrh$0zN&Vfut6zjo#qX(Ri#-p6`SCh|0eDcFzsH+`PhKKU=?B|S&GPHdO-p(AwWcII5ZbIwfB>$M5AzgoZZFFZp2 z#>w%9yEoxi7A1rePE(T6(4e!i8Jf+S6Ymgu8o#lF*~1?u#}z zg!c#G=AY&srDTKr3KB!_o|m^~{SMukN$!N5Mou^E)-H^!w3qe6KAxFNz5g$%t^bs2 zb0=NM2H^l~ce$6I$ri&!7`J&RJ)4~i&ru@I@$McC&x^tS(gFE_@E-3!BfKvb_rTup z0;hLLuyBa@tkvE|B=aO6zwg)IUGwjy8Gmr!FQa%n8Vf(lxt~-YE1!!}kmQ~fyMqKIMpM6>2IbrS}Hgp`xe zfasZ?;hCPrd(X*;@)ozBd5{$jcb}24#Xa7J-sTdXV+x&8o5zCOug==j?0*gj?%j`2r-)Kwr;b4nPg=pNZOrgUmdt!e83 z(wGy_OVR)o24vb0W7$>c?|H) zw1~Knn{)R!qqu6!Jc6U#m3`2D4c)|8*zOXoFPsE%c;rQl5kG2(j06Ao@T)Z-71^Rw zvIWuO#tY*qt;{V8=1_~=d|?23_Lu;5rgW9u?>&W;Eoa}YJiwA{+1z?z96%L6TEca} zv{eT`gYA9-3ID`Lzx=B3A+P)<1?%XdGSlWt|v zMiV*t5r{Z#Yxj+MIQ%0pDAZ~h^_6#-34DM;2e{U52Oidb4gfQz+YE1o3DiB)UB(_w zqIACFFvg3Rv8DzkhEaZkBmkm&^RkacngYw)R62_+m`@VlQ#_y+fw*9uVH=Q5{a0?s zZ4aDgKe(u!LJgZM$7-lqs8W6iC$uf$X(=+@$|o5_^9rt6`1a_|Pgz;W>Xwv+)KutJ zDU-a?_N=_LwWW$&FTHtGh7i$QVL=M1W<}&mF-}w^cO^zhTX@+@47YAgsw7p?Z7i5S z5_4`L8=H?g`?h%8Z)PZdi=kIv0qOQ#il0Hdv=6jR2d~}VjMuJ(Yl9POU8@URu3?)? F^dCUPNN@lE literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/asrf_dataset.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/asrf_dataset.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6dd42b06f9661def5ef33dc0d348881fb2fab9bb GIT binary patch literal 2147 zcmaJ?%WvF77@zTT?0qB+G!UqSd8n{FmZ~iXRiTj57F8+%HBk>%B;)SPZk>8xkBj#PDArC=~Fb}5eqF;{}Bmo zR2{w!XWWCY`I2IBCBE~x_$to z=jiuqaN%RYY``o(1gOXX*`-rDHTp(Erp|BlS4zp$nv%$v+JNTN1hhB-E$C*)R(3fm zz-SglNtRSmr2I6#C(@{htNW^TFCS$*mgAai_C;Kcq|j8yRaPm|zViA>TC)@@l0u|O zCM2W*kxhgafN~!E7|TIbM3B34 zDjGX!9&;gg7LMA9OWBVWM7J1Abi*4kO9rs&In<#(oxFU?)!kz=dzcKz1A~h5E0|>$ zpdwRnBc}((J~(q`%*hP$b56O*t)GlFvTp#_niFuX0gkjMo!g*UkYrr!1*mmUuOndPG?@_?D}wqz2Hnk zpFzo{KIfqp-1^1Pr(1B^uiCSvsWXR+=k_|$6w{Qmpx_PIbJroHv*jrS5o`n5H3%Jd zG`ee~Z$cQ^8@vXiX(^m1Kl4Y60m8IO1}ES1{_;p);wW%cr6tQZ%f zz?D1$PaHPt>@pL+r(7w@QCdAyHj9U1QQEi++o-+HFfNCw;Y)_;qh@5Ej5{h8gkRHHmFiULH4E)_RS(~}buj`#oOI|{$_W_ihjfRjk z*j*HpVvv-T97}AO%DM;tQHg(eWsj;PEhYYxl(YDmE~JIjm!8t&B>rr@Ht;G|PPqcW RTFhXyX*6k*GQ%-f>EDw>Gamo| literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/ava_dataset.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/ava_dataset.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..03146edf4a6fd0bc0459ba76d980561c883ab880 GIT binary patch literal 6892 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/base.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5264812308e57e9468c00473fb16e2e31e601c5a GIT binary patch literal 2447 zcmZ`)OK%%D5GHq5(rP6+PMVkdK#8_UBcN4-pg;kkXzM%?v=xdv2#kdRX0@d3P4}UY zD<>AzlLO??KVcvJZ+hmnr<{B1C7t0)vg|elI2^ve8GbV?I-P((`Lp(i*lrQ>7j{-l z4LUzS)lWbOB4|o78alMn-O#mTURZsE_5@8|(2 zl7v){&=C|+t-mHCYHw?Xo~((wXuKkaG^`6>G+&XhAp+5Y))#Hjfwn2u#06-B*Tf@X z3s7A&tvhh({OafpB?S8{P9v?^s8CE)sB{o8D4S`z9ASE|n52T~$*@|Ul)dGm<=}i# zu`ksNm6Wny9rPvp*&5zwPtzh2e3Yc}=@$%jmgJ*?jZ~3=Cge+obJfW!yT(e6BPBUF zG09=)SQYz;Nb+4~M=Z*BZ<4w^y9Wm5TPhROuI^h6twsQR9F=?QCOlfVzk-Y5aCHx^ z94BL$Cb?ucx8(DQ%wx&6x3{~?lhB(SppTN5i?c+cWLy^Nz#hel5i9p(g@xUdqiB+r zeKsiaxeM@?643Ij5OB?~C{h6QVh_A26)OuioFwolxMcBCz0-3ZM5%^@ES|xG7>U0q zsJrv3e*&c>hvbMJ6G~=uMz}MBFqlwvwRDfXnR{GmHPmuCb74h&=7DU?9FYEu95s&# zXn`O=G&<A~Bu`4tO>^m4;}&{sYKaDS7+=XKMaP=fio;BEX}9qgjyBCD zeT;|1>DG*=Wjazmn4s2Bv{7_GoKVx`+>({^6Y|e}+26Sn<-b|>=}NtIdk3f#OReqb z&Nvbxl|U_7?BG>W?aV`BX9$tf8y~0!9NmSgFM$YXonCT+w+{8*)}1i z9z&=t3+hy-_j>G?Dt?z_x5>taF2wLx`%#(*wwvtB z+^(=T_TYuHU2W=VG?b}6sT(gY#s|h1QjSqm>wwO_xp8t}Q>0XMaN=4=7&j3wO+!fy z0j1Bm#dOZ3lW)+{I*4^Qpx2%0#;TLftbC`V)HT=+X5V^zf9rAo9oAxup0`n5M;kU! zypQ5z6!@U0k7(LU3~<8tIQJ=t>Gl7G2}}ONHGE#nHT)M#h|*{D5I-q8{cu;7*5f*v z%GG29KT{7suTrNue80zRya^B-YeBOmHcK*6MIXH8nJ>pFu6-8Sa8Jjx{Gw}4}sp1|+HO`G%Q zlPI0ffTu(eb8eG|Li25CT38jp8#wkk2-BJ8tXQTg>^KFA`9|5W#`r|y*c9XwkFKpd z&4Buz4`tm`IN$ATWcQ6+ViEW$IN1G|j5*C56Ha iWsh9JVo@O$<9}P({2gXAjTyMT=2M@pQ{QRRtM0#UgLhB> literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/bmn_dataset.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/bmn_dataset.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..725e9cb075cb066c32e7802f738d01dbbefaf042 GIT binary patch literal 2138 zcmb7FPjB2r6rZujf7aQAKug=S94vt%mO@$;icl35Qc|HxC8|hNq1B?1vopJO>b2b& zZ)mn&2`Q0!K;;u~*hpORY2Z9pPWcKP2=CdOX8Y&DSo8d5=K0NgzxmB`Ha{N_Xn#4s zia#5K{EdUz=D^?^==w(xf(V+BcKxPpDlB0q*1&Gtln5rAgbkdw1G+1`#2t8Tj}qw# zf1kE}X-^u5G`k;vUx$gB&?uQasBroRFq34~4BmY{9>Iq6j?9QbX9 z;UAE;gQ3IQ6~1V|+j~wJY5NdjV1hf}Z%kttU44jKg`y5A>}4v9x<#C&VUl&DBpyXL zSP4RCT~=*h3&a!0bI^4NqO?oGNkR9?j#bjq>RB-<*&p;b3OEwjm~OOeo+>N%DNIvaJDmpYA4AeAysFZac6sw@~OU(@2Mv2^Z|5@xw+nD zIy!fT*2-zLT|Cay=7Zuv{}#Ib9YmjuX+b8muu8H6+&H9TtF$KUkgSuRE{*NdD(xj; z;1U@#uy9JYOVn~nCvM>ZiuJ1X!a4-xo-7Dkumdu7O1k5hj&NSUY|$v`J_T<<#~Qn1 zuXF)%7ks*_-~gQE!26JSFuoDfH`*&gXS(yb5U*Of}Y(MJu51A($tlOEbW| zV*CbpE__&lhi?8qcmSaT5IO*%JG#DgcXR6uIm8AFQjMO}#T%HZtFWp16vbyKR#03< zaSg={6tB^#`7#}FSOtETdJ|K>__ox+w$;EIjW?fj6L3Dr#1QH;H%-o;45MVa;&Cpr zF6UMKRG(l3U!b@N!pu+0byp?{n4E?7E}G!|SMbLsm!NB`zdlgCY59SFVbQBrT65|; zT3rEQd?ov_F4Uev78|w=|5AlyHqNk!6Rofos}E;PrK-HlY+QvfEj)Ebx3PZdMG*di OPn#BAG@rWm1^OS!&lf@f literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/davis_dataset.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/davis_dataset.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2069db91f5c161ca070691cefbfaf2f58cdbb7e6 GIT binary patch literal 4666 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/frame.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/frame.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a3b93799f54189721da86b3d6476f25432789cc0 GIT binary patch literal 4766 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 PkzQXB)IU)7X@L62ek)%`*K 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/ucf101_skeleton.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/ucf101_skeleton.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2ff935a2d756e8c3d58c388d894d1eecd1e42191 GIT binary patch literal 2888 zcma)8TW{RP6`mP#ce&Rnj-pnLn-K0pylJqO)1ntaFzUp0fFei@*oBdW3WD01T~p?g z%naAD7VDSFfE*M>k$)gP>fhvfUi0MVytNPQcZR#V7*1LeJaap9=3KsWhIzN!VtBr- z{avPQ#=fJ$#ixeBAMlwMAd*R*vMC=5UiH19=jQyO@7mh1?%Kw%;o4vrpcQFz+8Va7 z$CG~Ao_2;E^lP%7cBj2z5B-J=(l@4S!!^#-nrt5O;hU;+eC33F%4AEnpEKE3y+aT4 zZ%KZi^*b-24g0*$ZR1W{#zvJd1tu^K?%aNG`~Dvv+<(cdiT1}>UNL#qTx+7rD9tAm zrER;2rA*b6M5=s*~*%&qA$6`6NrIKXA+s9;q|FG>@eT%~EbSR&hDg>ccS3WEdAkdJty0o`!j$G$fM@ zQwh1PCuZA;qw~i}s-hw;ABERVsr%dEJ?fWvSmLZClj^BsskYLFA}LgwWa@gpw-5F^ zYK(#7Uaf@r*l8ISS`|7UDPxjsaxS4%ri`Y!RN?i#JWnCy;Uk6PG#$G)OB3nD5!=ez z0i6@i(sDbz8>dE9!tRdh7ve~L!ZAhPY=bPk1&i3i2j!(WWc%KNFT|oI`9D0)O3d%q z4mnoqQh+uj@dL?-n@^x?o++vcW!Ar!8`W>xnkmwxv>jLnr$=QnRR)tYc-jV0lptbJ zWW7{n)=#o=j>%jn5sllXjCBbX_|*pRK@3R;{krvyO2@W&77ZJ$ys5i5Tla_{bJ;2M zilR{(8xuvR>|giP_U^}V_Bf)grs{5ew7c}Xo87&D{au2M(z{Ev?aoGHpfg&*XiyyJ zHJtJRKGOlI*X#TW@9;Wr@%g*2#qwZf@`${&dZUZ%m<%ADF8RiE1){W5g3rbp-WjH5qU9nFdoePLGd{4d-^93YXg-@^Howlvg>49 zgr(?QlsV;k18n-8Gjf%7H61Vc?6(*issL*u;PdxhZ{ivEB^$}U0G~tL0-ch*;QO%g zQ2ev|4469x;!gN8@ep;?$9o9eWx-8mHooGV(fb8H?D6%^LP)X6K)p>S#Mk1PkUmDW zP49zRowe zFXkWo|H_TXp4CIxAh(jC-~Sq3?y;6zYw11=?mpij}}JCr9i!UFY<>kDy0H=#G* zx`%QT>#EYa2pV@)lsZPi$tK|>d7`rOsy)ze<1oDra@w%|C@&6dAeAbpr?1c&Mf#je zQ<9!8edHzbscmRwP;$+yxznY(4pky|_NUnPJ!Qd$XrV~7#QYbpch#j`Kj zjUTcXx5AH`tG6IQ|BA>fN#8kB0Yd&v43zxyYyU%EFki|PDs2>Ehg||oNkQXumF$ak zDrtOvl}Z;~p(dFtx)72d|KWj=}`SL}62rxX13Z;1Sk$nQaHcX`u{ zRGNbMT)|CZaalwEm888PNCnInqSyO(&<$!qI|$YSP3!%2+sMs;{xYoZsF#~U-^7xw zYy7a}Q(MbsQ$SQ?h5n_RuP!aytlB}6Yx02&w3;B}^?|0EZT&s`_i4KNZEaR2snG;Q sTVMY6ExA#LNRJB!oEM{Dr}EJ)3aj}UNT(O@*1!v6SwEzGB literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/ucf24_dataset.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/dataset/__pycache__/ucf24_dataset.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98407161a9bd3a9201ee5ebfd579dc78fc745236 GIT binary patch literal 2451 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/actbert_dataset.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/actbert_dataset.py new file mode 100644 index 0000000..8cccf5c --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/actbert_dataset.py @@ -0,0 +1,74 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import random +import numpy as np +try: + import lmdb +except ImportError as e: + print( + f"Warning! {e}, [lmdb] package and it's dependencies is required for ActBERT." + ) +import pickle +import json +try: + from paddlenlp.transformers import BertTokenizer +except ImportError as e: + print( + f"Warning! {e}, [paddlenlp] package and it's dependencies is required for ActBERT." + ) +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class ActBertDataset(BaseDataset): + """ActBert dataset. + """ + def __init__( + self, + file_path, + pipeline, + bert_model="bert-base-uncased", + data_prefix=None, + test_mode=False, + ): + self.bert_model = bert_model + super().__init__(file_path, pipeline, data_prefix, test_mode) + + def load_file(self): + """Load index file to get video information.""" + feature_data = np.load(self.file_path, allow_pickle=True) + self.tokenizer = BertTokenizer.from_pretrained(self.bert_model, + do_lower_case=True) + self.info = [] + for item in feature_data: + self.info.append(dict(feature=item, tokenizer=self.tokenizer)) + return self.info + + def prepare_train(self, idx): + """Prepare the frames for training/valid given index. """ + results = copy.deepcopy(self.info[idx]) + #print('==results==', results) + results = self.pipeline(results) + return results['features'] + + def prepare_test(self, idx): + """Prepare the frames for test given index. """ + pass diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/asrf_dataset.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/asrf_dataset.py new file mode 100644 index 0000000..15bd35a --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/asrf_dataset.py @@ -0,0 +1,104 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 copy + +import os +import numpy as np + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class ASRFDataset(BaseDataset): + """Video dataset for action segmentation. + """ + + def __init__( + self, + file_path, + pipeline, + feature_path, + label_path, + boundary_path, + **kwargs, + ): + super().__init__(file_path, pipeline, **kwargs) + self.label_path = label_path + self.boundary_path = boundary_path + self.feature_path = feature_path + + def load_file(self): + """Load index file to get video information.""" + file_ptr = open(self.file_path, 'r') + info = file_ptr.read().split('\n')[:-1] + file_ptr.close() + return info + + def prepare_train(self, idx): + """TRAIN & VALID: Prepare data for training/valid given the index.""" + results = {} + video_name = self.info[idx] + # load video feature + file_name = video_name.split('.')[0] + ".npy" + feat_file_path = os.path.join(self.feature_path, file_name) + #TODO: check path + video_feat = np.load(feat_file_path) + + # load label + file_name = video_name.split('.')[0] + ".npy" + label_file_path = os.path.join(self.label_path, file_name) + label = np.load(label_file_path).astype(np.int64) + + # load boundary + file_name = video_name.split('.')[0] + ".npy" + boundary_file_path = os.path.join(self.boundary_path, file_name) + boundary = np.expand_dims(np.load(boundary_file_path),axis=0).astype(np.float32) + + results['video_feat'] = copy.deepcopy(video_feat) + results['video_label'] = copy.deepcopy(label) + results['video_boundary'] = copy.deepcopy(boundary) + + results = self.pipeline(results) + return results['video_feat'], results['video_label'], results['video_boundary'] + + def prepare_test(self, idx): + """TEST: Prepare the data for test given the index.""" + results = {} + video_name = self.info[idx] + # load video feature + file_name = video_name.split('.')[0] + ".npy" + feat_file_path = os.path.join(self.feature_path, file_name) + #TODO: check path + video_feat = np.load(feat_file_path) + + # load label + file_name = video_name.split('.')[0] + ".npy" + label_file_path = os.path.join(self.label_path, file_name) + label = np.load(label_file_path).astype(np.int64) + + # load boundary + file_name = video_name.split('.')[0] + ".npy" + boundary_file_path = os.path.join(self.boundary_path, file_name) + boundary = np.expand_dims(np.load(boundary_file_path),axis=0).astype(np.float32) + + results['video_feat'] = copy.deepcopy(video_feat) + results['video_label'] = copy.deepcopy(label) + results['video_boundary'] = copy.deepcopy(boundary) + + results = self.pipeline(results) + return results['video_feat'], results['video_label'], results['video_boundary'] diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/ava_dataset.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/ava_dataset.py new file mode 100644 index 0000000..744e15b --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/ava_dataset.py @@ -0,0 +1,249 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import random +import numpy as np +import sys +import os +import pickle +from datetime import datetime +from ...metrics.ava_utils import ava_evaluate_results +from ..registry import DATASETS +from .base import BaseDataset +from collections import defaultdict + + +@DATASETS.register() +class AVADataset(BaseDataset): + """AVA dataset for spatial temporal detection. + the dataset loads raw frames, bounding boxes, proposals and applies + transformations to return the frame tensors and other information. + """ + + _FPS = 30 + + def __init__(self, + pipeline, + file_path=None, + exclude_file=None, + label_file=None, + suffix='{:05}.jpg', + proposal_file=None, + person_det_score_thr=0.9, + num_classes=81, + data_prefix=None, + test_mode=False, + num_max_proposals=1000, + timestamp_start=900, + timestamp_end=1800): + self.custom_classes = None + self.exclude_file = exclude_file + self.label_file = label_file + self.proposal_file = proposal_file + assert 0 <= person_det_score_thr <= 1, ( + 'The value of ' + 'person_det_score_thr should in [0, 1]. ') + self.person_det_score_thr = person_det_score_thr + self.num_classes = num_classes + self.suffix = suffix + self.num_max_proposals = num_max_proposals + self.timestamp_start = timestamp_start + self.timestamp_end = timestamp_end + super().__init__( + file_path, + pipeline, + data_prefix, + test_mode, + ) + if self.proposal_file is not None: + self.proposals = self._load(self.proposal_file) + else: + self.proposals = None + if not test_mode: + valid_indexes = self.filter_exclude_file() + self.info = self.info = [self.info[i] for i in valid_indexes] + + def _load(self, path): + f = open(path, 'rb') + res = pickle.load(f) + f.close() + return res + + def parse_img_record(self, img_records): + bboxes, labels, entity_ids = [], [], [] + while len(img_records) > 0: + img_record = img_records[0] + num_img_records = len(img_records) + selected_records = list( + filter( + lambda x: np.array_equal(x['entity_box'], img_record[ + 'entity_box']), img_records)) + num_selected_records = len(selected_records) + img_records = list( + filter( + lambda x: not np.array_equal(x['entity_box'], img_record[ + 'entity_box']), img_records)) + assert len(img_records) + num_selected_records == num_img_records + + bboxes.append(img_record['entity_box']) + valid_labels = np.array([ + selected_record['label'] for selected_record in selected_records + ]) + + label = np.zeros(self.num_classes, dtype=np.float32) + label[valid_labels] = 1. + + labels.append(label) + entity_ids.append(img_record['entity_id']) + + bboxes = np.stack(bboxes) + labels = np.stack(labels) + entity_ids = np.stack(entity_ids) + return bboxes, labels, entity_ids + + def filter_exclude_file(self): + valid_indexes = [] + if self.exclude_file is None: + valid_indexes = list(range(len(self.info))) + else: + exclude_video_infos = [ + x.strip().split(',') for x in open(self.exclude_file) + ] + for i, video_info in enumerate(self.info): + valid_indexes.append(i) + for video_id, timestamp in exclude_video_infos: + if (video_info['video_id'] == video_id + and video_info['timestamp'] == int(timestamp)): + valid_indexes.pop() + break + return valid_indexes + + def load_file(self): + """Load index file to get video information.""" + info = [] + records_dict_by_img = defaultdict(list) + with open(self.file_path, 'r') as fin: + for line in fin: + line_split = line.strip().split(',') + + video_id = line_split[0] + timestamp = int(line_split[1]) + img_key = f'{video_id},{timestamp:04d}' + + entity_box = np.array(list(map(float, line_split[2:6]))) + label = int(line_split[6]) + entity_id = int(line_split[7]) + shot_info = (0, (self.timestamp_end - self.timestamp_start) * + self._FPS) + + video_info = dict(video_id=video_id, + timestamp=timestamp, + entity_box=entity_box, + label=label, + entity_id=entity_id, + shot_info=shot_info) + records_dict_by_img[img_key].append(video_info) + + for img_key in records_dict_by_img: + video_id, timestamp = img_key.split(',') + bboxes, labels, entity_ids = self.parse_img_record( + records_dict_by_img[img_key]) + ann = dict(gt_bboxes=bboxes, + gt_labels=labels, + entity_ids=entity_ids) + frame_dir = video_id + if self.data_prefix is not None: + frame_dir = osp.join(self.data_prefix, frame_dir) + video_info = dict(frame_dir=frame_dir, + video_id=video_id, + timestamp=int(timestamp), + img_key=img_key, + shot_info=shot_info, + fps=self._FPS, + ann=ann) + info.append(video_info) + + return info + + def prepare_train(self, idx): + results = copy.deepcopy(self.info[idx]) + img_key = results['img_key'] + + results['suffix'] = self.suffix + results['timestamp_start'] = self.timestamp_start + results['timestamp_end'] = self.timestamp_end + + if self.proposals is not None: + if img_key not in self.proposals: + results['proposals'] = np.array([[0, 0, 1, 1]]) + results['scores'] = np.array([1]) + else: + proposals = self.proposals[img_key] + assert proposals.shape[-1] in [4, 5] + if proposals.shape[-1] == 5: + thr = min(self.person_det_score_thr, max(proposals[:, 4])) + positive_inds = (proposals[:, 4] >= thr) + proposals = proposals[positive_inds] + proposals = proposals[:self.num_max_proposals] + results['proposals'] = proposals[:, :4] + results['scores'] = proposals[:, 4] + else: + proposals = proposals[:self.num_max_proposals] + results['proposals'] = proposals + + ann = results.pop('ann') + results['gt_bboxes'] = ann['gt_bboxes'] + results['gt_labels'] = ann['gt_labels'] + results['entity_ids'] = ann['entity_ids'] + + #ret = self.pipeline(results, "") + ret = self.pipeline(results) + #padding for dataloader + len_proposals = ret['proposals'].shape[0] + len_gt_bboxes = ret['gt_bboxes'].shape[0] + len_gt_labels = ret['gt_labels'].shape[0] + len_scores = ret['scores'].shape[0] + len_entity_ids = ret['entity_ids'].shape[0] + padding_len = 128 + ret['proposals'] = self.my_padding_2d(ret['proposals'], padding_len) + ret['gt_bboxes'] = self.my_padding_2d(ret['gt_bboxes'], padding_len) + ret['gt_labels'] = self.my_padding_2d(ret['gt_labels'], padding_len) + ret['scores'] = self.my_padding_1d(ret['scores'], padding_len) + ret['entity_ids'] = self.my_padding_1d(ret['entity_ids'], padding_len) + return ret['imgs'][0], ret['imgs'][1], ret['proposals'], ret[ + 'gt_bboxes'], ret['gt_labels'], ret['scores'], ret[ + 'entity_ids'], np.array( + ret['img_shape'], dtype=int + ), idx, len_proposals, len_gt_bboxes, len_gt_labels, len_scores, len_entity_ids + + def my_padding_2d(self, feat, max_len): + feat_add = np.zeros((max_len - feat.shape[0], feat.shape[1]), + dtype=np.float32) + feat_pad = np.concatenate((feat, feat_add), axis=0) + return feat_pad + + def my_padding_1d(self, feat, max_len): + feat_add = np.zeros((max_len - feat.shape[0]), dtype=np.float32) + feat_pad = np.concatenate((feat, feat_add), axis=0) + return feat_pad + + def prepare_test(self, idx): + return self.prepare_train(idx) + + def evaluate(self, results): + return ava_evaluate_results(self.info, len(self), results, + self.custom_classes, self.label_file, + self.file_path, self.exclude_file) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/base.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/base.py new file mode 100644 index 0000000..2549dc4 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/base.py @@ -0,0 +1,80 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import numpy as np +from abc import ABC, abstractmethod + +import paddle +from paddle.io import Dataset + + +class BaseDataset(Dataset, ABC): + """Base class for datasets + + All datasets should subclass it. + All subclass should overwrite: + + - Method: `load_file`, load info from index file. + - Method: `prepare_train`, providing train data. + - Method: `prepare_test`, providing test data. + + Args: + file_path (str): index file path. + pipeline (Sequence XXX) + data_prefix (str): directory path of the data. Default: None. + test_mode (bool): whether to build test dataset. Default: False. + + """ + def __init__(self, file_path, pipeline, data_prefix=None, test_mode=False): + super().__init__() + self.file_path = file_path + self.data_prefix = osp.realpath(data_prefix) if \ + data_prefix is not None and osp.isdir(data_prefix) else data_prefix + self.test_mode = test_mode + self.pipeline = pipeline + self.info = self.load_file() + + @abstractmethod + def load_file(self): + """load the video information from the index file path.""" + pass + + def prepare_train(self, idx): + """TRAIN & VALID. Prepare the data for training/valid given the index.""" + #Note: For now, paddle.io.DataLoader cannot support dict type retval, so convert to list here + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + #unsqueeze label to list + return results['imgs'], np.array([results['labels']]) + + def prepare_test(self, idx): + """TEST: Prepare the data for test given the index.""" + #Note: For now, paddle.io.DataLoader cannot support dict type retval, so convert to list here + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + #unsqueeze label to list + return results['imgs'], np.array([results['labels']]) + + def __len__(self): + """get the size of the dataset.""" + return len(self.info) + + def __getitem__(self, idx): + """ Get the sample for either training or testing given index""" + if self.test_mode: + return self.prepare_test(idx) + else: + return self.prepare_train(idx) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/bmn_dataset.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/bmn_dataset.py new file mode 100644 index 0000000..44c7651 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/bmn_dataset.py @@ -0,0 +1,72 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 copy +import json + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class BMNDataset(BaseDataset): + """Video dataset for action localization. + """ + def __init__( + self, + file_path, + pipeline, + subset, + **kwargs, + ): + self.subset = subset + super().__init__(file_path, pipeline, **kwargs) + + def load_file(self): + """Load index file to get video information.""" + info = [] + annos = json.load(open(self.file_path)) + for video_name in annos.keys(): + video_subset = annos[video_name]["subset"] + if self.subset in video_subset: + info.append( + dict( + video_name=video_name, + video_info=annos[video_name], + )) + #sort by video_name + sort_f = lambda elem: elem['video_name'] + info.sort(key=sort_f) + #add video_idx to info + for idx, elem in enumerate(info): + info[idx]['video_idx'] = idx + logger.info("{} subset video numbers: {}".format( + self.subset, len(info))) + return info + + def prepare_train(self, idx): + """TRAIN & VALID: Prepare data for training/valid given the index.""" + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + return results['video_feat'], results['gt_iou_map'], results['gt_start'],\ + results['gt_end'] + + def prepare_test(self, idx): + """TEST: Prepare the data for test given the index.""" + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + return results['video_feat'], results['gt_iou_map'], results['gt_start'], \ + results['gt_end'], results['video_idx'] diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/davis_dataset.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/davis_dataset.py new file mode 100644 index 0000000..20a2759 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/davis_dataset.py @@ -0,0 +1,189 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 copy +import random +import numpy as np +import shutil +from PIL import Image +import cv2 +from paddle.io import Dataset + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +class VOS_Test(Dataset): + """process frames in each video + """ + def __init__(self, + image_root, + label_root, + seq_name, + images, + labels, + pipeline=None, + rgb=False, + resolution=None): + self.image_root = image_root + self.label_root = label_root + self.seq_name = seq_name + self.images = images # image file list + self.labels = labels + self.obj_num = 1 + self.num_frame = len(self.images) + self.pipeline = pipeline + self.rgb = rgb + self.resolution = resolution + + self.obj_nums = [] + temp_obj_num = 0 + for img_name in self.images: + self.obj_nums.append(temp_obj_num) + current_label_name = img_name.split('.')[0] + '.png' + if current_label_name in self.labels: + current_label = self.read_label(current_label_name) + if temp_obj_num < np.unique( + current_label)[-1]: #get object number from label_id + temp_obj_num = np.unique(current_label)[-1] + + def __len__(self): + return len(self.images) + + def read_image(self, idx): + img_name = self.images[idx] + img_path = os.path.join(self.image_root, self.seq_name, img_name) + img = cv2.imread(img_path) + img = np.array(img, dtype=np.float32) + if self.rgb: + img = img[:, :, [2, 1, 0]] + return img + + def read_label(self, label_name): + label_path = os.path.join(self.label_root, self.seq_name, label_name) + label = Image.open(label_path) + label = np.array(label, dtype=np.uint8) + return label + + def __getitem__(self, idx): + img_name = self.images[idx] + current_img = self.read_image(idx) + current_img = np.array(current_img) + height, width, channels = current_img.shape + if self.resolution is not None: + width = int(np.ceil(float(width) * self.resolution / float(height))) + height = int(self.resolution) + + current_label_name = img_name.split('.')[0] + '.png' + obj_num = self.obj_nums[idx] + + if current_label_name in self.labels: + current_label = self.read_label(current_label_name) + current_label = np.array(current_label) + sample = { + 'current_img': current_img, + 'current_label': current_label + } + else: + sample = { + 'current_img': current_img + } #only the first frame contains label + + sample['meta'] = { + 'seq_name': self.seq_name, + 'frame_num': self.num_frame, + 'obj_num': obj_num, + 'current_name': img_name, + 'height': height, + 'width': width, + 'flip': False + } + if self.pipeline is not None: + sample = self.pipeline(sample) + for s in sample: + s['current_img'] = np.array(s['current_img']) + if 'current_label' in s.keys(): + s['current_label'] = s['current_label'] + return sample + + +@DATASETS.register() +class DavisDataset(BaseDataset): + """Davis 2017 dataset. + """ + def __init__( + self, + file_path, + result_root, + pipeline, + data_prefix=None, + test_mode=False, + year=2017, + rgb=False, + resolution='480p', + ): + self.rgb = rgb + self.result_root = result_root + self.resolution = resolution + self.year = year + self.spt = 'val' if test_mode else 'train' + super().__init__(file_path, pipeline, data_prefix, test_mode) + + def load_file(self): + self.image_root = os.path.join(self.file_path, 'JPEGImages', + self.resolution) + self.label_root = os.path.join(self.file_path, 'Annotations', + self.resolution) + seq_names = [] + with open( + os.path.join(self.file_path, 'ImageSets', str(self.year), + self.spt + '.txt')) as f: + seqs_tmp = f.readlines() + seqs_tmp = list(map(lambda elem: elem.strip(), seqs_tmp)) + seq_names.extend(seqs_tmp) + self.info = list(np.unique(seq_names)) + return self.info + + def prepare_test(self, idx): + seq_name = self.info[idx] #video name + images = list( + np.sort(os.listdir(os.path.join(self.image_root, seq_name)))) + labels = [images[0].replace('jpg', 'png')] #we have first frame target + + # copy first frame target + if not os.path.isfile( + os.path.join(self.result_root, seq_name, labels[0])): + if not os.path.exists(os.path.join(self.result_root, seq_name)): + os.makedirs(os.path.join(self.result_root, seq_name)) + source_label_path = os.path.join(self.label_root, seq_name, + labels[0]) + result_label_path = os.path.join(self.result_root, seq_name, + labels[0]) + + shutil.copy(source_label_path, result_label_path) + + seq_dataset = VOS_Test(self.image_root, + self.label_root, + seq_name, + images, + labels, + self.pipeline, + rgb=self.rgb, + resolution=480) + return seq_dataset diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/feature.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/feature.py new file mode 100644 index 0000000..df5e33e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/feature.py @@ -0,0 +1,80 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 copy +import os.path as osp + +from ..registry import DATASETS +from .base import BaseDataset + + +@DATASETS.register() +class FeatureDataset(BaseDataset): + """Feature dataset for action recognition + Example:(TODO) + Args:(TODO) + """ + def __init__( + self, + file_path, + pipeline, + data_prefix=None, + test_mode=False, + suffix=None, + ): + self.suffix = suffix + super().__init__(file_path, pipeline, data_prefix, test_mode) + + def load_file(self): + """Load index file to get video information.""" + info = [] + with open(self.file_path, 'r') as fin: + for line in fin: + filename = line.strip().split()[0] + if self.data_prefix is not None: + filename = osp.join(self.data_prefix, filename) + if self.suffix is not None: + filename = filename + self.suffix + + info.append(dict(filename=filename)) + return info + + def prepare_train(self, idx): + """TRAIN & VALID. Prepare the data for training/valid given the index.""" + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + + if 'iou_norm' in results: + return results['rgb_data'], results['rgb_len'], results[ + 'rgb_mask'], results['audio_data'], results[ + 'audio_len'], results['audio_mask'], results[ + 'labels'], results['iou_norm'] + else: + return results['rgb_data'], results['rgb_len'], results[ + 'rgb_mask'], results['audio_data'], results[ + 'audio_len'], results['audio_mask'], results['labels'] + + def prepare_test(self, idx): + """TEST. Prepare the data for testing given the index.""" + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + + if 'iou_norm' in results: + return results['rgb_data'], results['rgb_len'], results[ + 'rgb_mask'], results['audio_data'], results[ + 'audio_len'], results['audio_mask'], results[ + 'labels'], results['iou_norm'] + else: + return results['rgb_data'], results['rgb_len'], results[ + 'rgb_mask'], results['audio_data'], results[ + 'audio_len'], results['audio_mask'], results['labels'] diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/frame.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/frame.py new file mode 100644 index 0000000..b02f526 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/frame.py @@ -0,0 +1,177 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import random +import numpy as np + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class FrameDataset(BaseDataset): + """Rawframe dataset for action recognition. + The dataset loads raw frames from frame files, and apply specified transform operatation them. + The indecx file is a text file with multiple lines, and each line indicates the directory of frames of a video, toatl frames of the video, and its label, which split with a whitespace. + Example of an index file: + + .. code-block:: txt + + file_path-1 150 1 + file_path-2 160 1 + file_path-3 170 2 + file_path-4 180 2 + + Args: + file_path (str): Path to the index file. + pipeline(XXX): + data_prefix (str): directory path of the data. Default: None. + test_mode (bool): Whether to bulid the test dataset. Default: False. + suffix (str): suffix of file. Default: 'img_{:05}.jpg'. + + """ + def __init__(self, + file_path, + pipeline, + num_retries=5, + data_prefix=None, + test_mode=False, + suffix='img_{:05}.jpg'): + self.num_retries = num_retries + self.suffix = suffix + super().__init__(file_path, pipeline, data_prefix, test_mode) + + def load_file(self): + """Load index file to get video information.""" + info = [] + with open(self.file_path, 'r') as fin: + for line in fin: + line_split = line.strip().split() + frame_dir, frames_len, labels = line_split + if self.data_prefix is not None: + frame_dir = osp.join(self.data_prefix, frame_dir) + info.append( + dict(frame_dir=frame_dir, + suffix=self.suffix, + frames_len=frames_len, + labels=int(labels))) + return info + + def prepare_train(self, idx): + """Prepare the frames for training/valid given index. """ + #Try to catch Exception caused by reading missing frames files + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['frame_dir'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return results['imgs'], np.array([results['labels']]) + + def prepare_test(self, idx): + """Prepare the frames for test given index. """ + #Try to catch Exception caused by reading missing frames files + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['frame_dir'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return results['imgs'], np.array([results['labels']]) + + +@DATASETS.register() +class FrameDataset_Sport(BaseDataset): + """Video dataset for action recognition + The dataset loads raw videos and apply specified transforms on them. + The index file is a file with multiple lines, and each line indicates + a sample video with the filepath and label, which are split with a whitesapce. + Example of a inde file: + .. code-block:: txt + path/000.mp4 1 + path/001.mp4 1 + path/002.mp4 2 + path/003.mp4 2 + Args: + file_path(str): Path to the index file. + pipeline(XXX): A sequence of data transforms. + **kwargs: Keyword arguments for ```BaseDataset```. + """ + def __init__(self, file_path, pipeline, num_retries=5, suffix='', **kwargs): + self.num_retries = num_retries + self.suffix = suffix + super().__init__(file_path, pipeline, **kwargs) + + def load_file(self): + """Load index file to get video information.""" + info = [] + with open(self.file_path, 'r') as fin: + for line in fin: + line_split = line.strip().split() + frame_dir = line_split[0] + if self.data_prefix is not None: + frame_dir = osp.join(self.data_prefix, frame_dir) + info.append(dict(frame_dir=frame_dir, suffix=self.suffix)) + return info + + def prepare_train(self, idx): + """TRAIN & VALID. Prepare the data for training/valid given the index.""" + #Try to catch Exception caused by reading corrupted video file + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['filename'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return results['imgs'], np.array([results['labels']]) + + def prepare_test(self, idx): + """TEST. Prepare the data for test given the index.""" + #Try to catch Exception caused by reading corrupted video file + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['filename'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return results['imgs'], np.array([results['labels']]) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/ms_tcn_dataset.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/ms_tcn_dataset.py new file mode 100644 index 0000000..56e3b7b --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/ms_tcn_dataset.py @@ -0,0 +1,110 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 copy + +import os +import numpy as np + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class MSTCNDataset(BaseDataset): + """Video dataset for action segmentation. + """ + + def __init__( + self, + file_path, + pipeline, + feature_path, + gt_path, + actions_map_file_path, + **kwargs, + ): + super().__init__(file_path, pipeline, **kwargs) + self.gt_path = gt_path + self.actions_map_file_path = actions_map_file_path + self.feature_path = feature_path + + # actions dict generate + file_ptr = open(self.actions_map_file_path, 'r') + actions = file_ptr.read().split('\n')[:-1] + file_ptr.close() + self.actions_dict = dict() + for a in actions: + self.actions_dict[a.split()[1]] = int(a.split()[0]) + + self.num_classes = len(self.actions_dict.keys()) + + def load_file(self): + """Load index file to get video information.""" + file_ptr = open(self.file_path, 'r') + info = file_ptr.read().split('\n')[:-1] + file_ptr.close() + return info + + def prepare_train(self, idx): + """TRAIN & VALID: Prepare data for training/valid given the index.""" + results = {} + video_name = self.info[idx] + # load video feature + file_name = video_name.split('.')[0] + ".npy" + feat_file_path = os.path.join(self.feature_path, file_name) + #TODO: check path + video_feat = np.load(feat_file_path) + + # load label + target_file_path = os.path.join(self.gt_path, video_name) + file_ptr = open(target_file_path, 'r') + content = file_ptr.read().split('\n')[:-1] + classes = np.zeros(min(np.shape(video_feat)[1], len(content)), dtype='int64') + for i in range(len(classes)): + classes[i] = self.actions_dict[content[i]] + # classes = classes * (-100) + + results['video_feat'] = copy.deepcopy(video_feat) + results['video_gt'] = copy.deepcopy(classes) + + results = self.pipeline(results) + return results['video_feat'], results['video_gt'] + + def prepare_test(self, idx): + """TEST: Prepare the data for test given the index.""" + results = {} + video_name = self.info[idx] + # load video feature + file_name = video_name.split('.')[0] + ".npy" + feat_file_path = os.path.join(self.feature_path, file_name) + #TODO: check path + video_feat = np.load(feat_file_path) + + # load label + target_file_path = os.path.join(self.gt_path, video_name) + file_ptr = open(target_file_path, 'r') + content = file_ptr.read().split('\n')[:-1] + classes = np.zeros(min(np.shape(video_feat)[1], len(content))) + for i in range(len(classes)): + classes[i] = self.actions_dict[content[i]] + # classes = classes * (-100) + + results['video_feat'] = copy.deepcopy(video_feat) + results['video_gt'] = copy.deepcopy(classes) + + results = self.pipeline(results) + return results['video_feat'], results['video_gt'] diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/msrvtt.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/msrvtt.py new file mode 100644 index 0000000..0e5294f --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/msrvtt.py @@ -0,0 +1,220 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import random +import numpy as np +try: + import lmdb +except ImportError as e: + print( + f"Warning! {e}, [lmdb] package and it's dependencies is required for ActBERT." + ) +import pickle +try: + from paddlenlp.transformers import BertTokenizer +except ImportError as e: + print( + f"Warning! {e}, [paddlenlp] package and it's dependencies is required for ActBERT." + ) +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class MSRVTTDataset(BaseDataset): + """MSR-VTT dataset for text-video clip retrieval. + """ + def __init__( + self, + file_path, + pipeline, + features_path, + bert_model="bert-base-uncased", + padding_index=0, + max_seq_length=36, + max_region_num=36, + max_action_num=5, + vision_feature_dim=2048, + action_feature_dim=2048, + spatials_dim=5, + data_prefix=None, + test_mode=False, + ): + self.features_path = features_path + self.bert_model = bert_model + self.padding_index = padding_index + self.max_seq_length = max_seq_length + self.max_region_num = max_region_num + self._max_action_num = max_action_num + self.vision_feature_dim = vision_feature_dim + self.action_feature_dim = action_feature_dim + self.spatials_dim = spatials_dim + self._tokenizer = BertTokenizer.from_pretrained(bert_model, + do_lower_case=True) + super().__init__(file_path, pipeline, data_prefix, test_mode) + self.tokenize() + self.gen_feature() + + def load_file(self): + """Load index file to get video information.""" + with open(self.file_path) as fin: + self.image_entries = [] + self.caption_entries = [] + for line in fin.readlines(): + line = line.strip() + vid_id = line.split(',')[0] + self.image_entries.append(vid_id) + self.caption_entries.append({ + "caption": line.split(',')[1], + "vid_id": vid_id + }) + self.env = lmdb.open(self.features_path) + + def tokenize(self): + for entry in self.caption_entries: + tokens = [] + tokens.append("[CLS]") + for token in self._tokenizer.tokenize(entry["caption"]): + tokens.append(token) + tokens.append("[SEP]") + tokens = self._tokenizer.convert_tokens_to_ids(tokens) + + segment_ids = [0] * len(tokens) + input_mask = [1] * len(tokens) + + if len(tokens) < self.max_seq_length: + padding = [self.padding_index + ] * (self.max_seq_length - len(tokens)) + tokens = tokens + padding + input_mask += padding + segment_ids += padding + + entry["token"] = np.array(tokens).astype('int64') + entry["input_mask"] = np.array(input_mask) + entry["segment_ids"] = np.array(segment_ids).astype('int64') + + def get_image_feature(self, video_id): + video_id = str(video_id).encode() + with self.env.begin(write=False) as txn: + item = pickle.loads(txn.get(video_id)) + video_id = item["video_id"] + image_h = int(item["image_h"]) + image_w = int(item["image_w"]) + + features = item["features"].reshape(-1, self.vision_feature_dim) + boxes = item["boxes"].reshape(-1, 4) + + num_boxes = features.shape[0] + g_feat = np.sum(features, axis=0) / num_boxes + num_boxes = num_boxes + 1 + features = np.concatenate( + [np.expand_dims(g_feat, axis=0), features], axis=0) + + action_features = item["action_features"].reshape( + -1, self.action_feature_dim) + + image_location = np.zeros((boxes.shape[0], self.spatials_dim), + dtype=np.float32) + image_location[:, :4] = boxes + image_location[:, + 4] = ((image_location[:, 3] - image_location[:, 1]) * + (image_location[:, 2] - image_location[:, 0]) / + (float(image_w) * float(image_h))) + + image_location[:, 0] = image_location[:, 0] / float(image_w) + image_location[:, 1] = image_location[:, 1] / float(image_h) + image_location[:, 2] = image_location[:, 2] / float(image_w) + image_location[:, 3] = image_location[:, 3] / float(image_h) + + g_location = np.array([0, 0, 1, 1, 1]) + image_location = np.concatenate( + [np.expand_dims(g_location, axis=0), image_location], axis=0) + return features, num_boxes, image_location, action_features + + def gen_feature(self): + num_inst = len(self.image_entries) #1000 + self.features_all = np.zeros( + (num_inst, self.max_region_num, self.vision_feature_dim)) + self.action_features_all = np.zeros( + (num_inst, self._max_action_num, self.action_feature_dim)) + self.spatials_all = np.zeros( + (num_inst, self.max_region_num, self.spatials_dim)) + self.image_mask_all = np.zeros((num_inst, self.max_region_num)) + self.action_mask_all = np.zeros((num_inst, self._max_action_num)) + + for i, image_id in enumerate(self.image_entries): + features, num_boxes, boxes, action_features = self.get_image_feature( + image_id) + + mix_num_boxes = min(int(num_boxes), self.max_region_num) + mix_boxes_pad = np.zeros((self.max_region_num, self.spatials_dim)) + mix_features_pad = np.zeros( + (self.max_region_num, self.vision_feature_dim)) + + image_mask = [1] * (int(mix_num_boxes)) + while len(image_mask) < self.max_region_num: + image_mask.append(0) + action_mask = [1] * (self._max_action_num) + while len(action_mask) < self._max_action_num: + action_mask.append(0) + + mix_boxes_pad[:mix_num_boxes] = boxes[:mix_num_boxes] + mix_features_pad[:mix_num_boxes] = features[:mix_num_boxes] + + self.features_all[i] = mix_features_pad + x = action_features.shape[0] + self.action_features_all[i][:x] = action_features[:] + self.image_mask_all[i] = np.array(image_mask) + self.action_mask_all[i] = np.array(action_mask) + self.spatials_all[i] = mix_boxes_pad + + self.features_all = self.features_all.astype("float32") + self.action_features_all = self.action_features_all.astype("float32") + self.image_mask_all = self.image_mask_all.astype("int64") + self.action_mask_all = self.action_mask_all.astype("int64") + self.spatials_all = self.spatials_all.astype("float32") + + def prepare_train(self, idx): + pass + + def prepare_test(self, idx): + entry = self.caption_entries[idx] + caption = entry["token"] + input_mask = entry["input_mask"] + segment_ids = entry["segment_ids"] + + target_all = np.zeros(1000) + for i, image_id in enumerate(self.image_entries): + if image_id == entry["vid_id"]: + target_all[i] = 1 + + return ( + caption, + self.action_features_all, + self.features_all, + self.spatials_all, + segment_ids, + input_mask, + self.image_mask_all, + self.action_mask_all, + target_all, + ) + + def __len__(self): + return len(self.caption_entries) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/oxford.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/oxford.py new file mode 100644 index 0000000..a9e65c6 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/oxford.py @@ -0,0 +1,62 @@ +# Copyright Niantic 2019. Patent Pending. All rights reserved. +# +# This software is licensed under the terms of the Monodepth2 licence +# which allows for non-commercial use only, the full terms of which are made +# available in the LICENSE file. + +from __future__ import absolute_import, division, print_function + +import copy +from os import path as osp + +from PIL import Image + +from ..registry import DATASETS +from .base import BaseDataset + + +def pil_loader(path): + # open path as file to avoid ResourceWarning + # (https://github.com/python-pillow/Pillow/issues/835) + with open(path, 'rb') as f: + with Image.open(f) as img: + return img.convert('RGB') + + +@DATASETS.register() +class MonoDataset(BaseDataset): + def __init__(self, + file_path, + data_prefix, + pipeline, + num_retries=0, + suffix='.png', + **kwargs): + self.num_retries = num_retries + self.suffix = suffix + super().__init__(file_path, pipeline, data_prefix, **kwargs) + + def load_file(self): + info = [] + with open(self.file_path, 'r') as f: + for line in f: + filename = line.strip() + self.suffix + folder = osp.dirname(filename) + frame_index = line.strip().split('/')[1] + info.append( + dict(data_path=self.data_prefix, + filename=filename, + folder=folder, + frame_index=int(frame_index))) + return info + + def prepare_train(self, idx): + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + results['imgs']['idx'] = idx + return results['imgs'], results['day_or_night'] + + def prepare_test(self, idx): + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + return results['imgs'], results['day_or_night'] diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/skeleton.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/skeleton.py new file mode 100644 index 0000000..30a3f3e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/skeleton.py @@ -0,0 +1,78 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import random +import numpy as np +import pickle + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class SkeletonDataset(BaseDataset): + """ + Skeleton dataset for action recognition. + The dataset loads skeleton feature, and apply norm operatations. + Args: + file_path (str): Path to the index file. + pipeline(obj): Define the pipeline of data preprocessing. + data_prefix (str): directory path of the data. Default: None. + test_mode (bool): Whether to bulid the test dataset. Default: False. + """ + def __init__(self, file_path, pipeline, label_path=None, test_mode=False): + self.label_path = label_path + super().__init__(file_path, pipeline, test_mode=test_mode) + + def load_file(self): + """Load feature file to get skeleton information.""" + logger.info("Loading data, it will take some moment...") + self.data = np.load(self.file_path) + if self.label_path: + if self.label_path.endswith('npy'): + self.label = np.load(self.label_path) + elif self.label_path.endswith('pkl'): + with open(self.label_path, 'rb') as f: + sample_name, self.label = pickle.load(f) + else: + logger.info( + "Label path not provided when test_mode={}, here just output predictions." + .format(self.test_mode)) + logger.info("Data Loaded!") + return self.data # used for __len__ + + def prepare_train(self, idx): + """Prepare the feature for training/valid given index. """ + results = dict() + results['data'] = copy.deepcopy(self.data[idx]) + results['label'] = copy.deepcopy(self.label[idx]) + results = self.pipeline(results) + return results['data'], results['label'] + + def prepare_test(self, idx): + """Prepare the feature for test given index. """ + results = dict() + results['data'] = copy.deepcopy(self.data[idx]) + if self.label_path: + results['label'] = copy.deepcopy(self.label[idx]) + results = self.pipeline(results) + return results['data'], results['label'] + else: + results = self.pipeline(results) + return [results['data']] diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/slowfast_video.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/slowfast_video.py new file mode 100644 index 0000000..1adf89c --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/slowfast_video.py @@ -0,0 +1,143 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import random +import numpy as np + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + +@DATASETS.register() +class SFVideoDataset(BaseDataset): + """Video dataset for action recognition + The dataset loads raw videos and apply specified transforms on them. + + The index file is a file with multiple lines, and each line indicates + a sample video with the filepath and label, which are split with a whitesapce. + Example of a inde file: + + .. code-block:: txt + + path/000.mp4 1 + path/001.mp4 1 + path/002.mp4 2 + path/003.mp4 2 + + Args: + file_path(str): Path to the index file. + pipeline(XXX): A sequence of data transforms. + num_ensemble_views(int): temporal segment when multi-crop test + num_spatial_crops(int): spatial crop number when multi-crop test + **kwargs: Keyword arguments for ```BaseDataset```. + + """ + def __init__( + self, + file_path, + pipeline, + num_ensemble_views=1, + num_spatial_crops=1, + num_retries=5, + num_samples_precise_bn=None, + **kwargs, + ): + self.num_ensemble_views = num_ensemble_views + self.num_spatial_crops = num_spatial_crops + self.num_retries = num_retries + self.num_samples_precise_bn = num_samples_precise_bn + super().__init__(file_path, pipeline, **kwargs) + #set random seed + random.seed(0) + np.random.seed(0) + + def load_file(self): + """Load index file to get video information.""" + info = [] + with open(self.file_path, 'r') as fin: + for line in fin: + line_split = line.strip().split() + filename, labels = line_split + if self.data_prefix is not None: + filename = osp.join(self.data_prefix, filename) + for tidx in range(self.num_ensemble_views): + for sidx in range(self.num_spatial_crops): + info.append( + dict( + filename=filename, + labels=int(labels), + temporal_sample_index=tidx, + spatial_sample_index=sidx, + temporal_num_clips=self.num_ensemble_views, + spatial_num_clips=self.num_spatial_crops, + )) + return info + + def prepare_train(self, idx): + """TRAIN & VALID. Prepare the data for training given the index.""" + #Try to catch Exception caused by reading corrupted video file + short_cycle = False + if isinstance(idx, tuple): + idx, short_cycle_idx = idx + short_cycle = True + for ir in range(self.num_retries): + try: + #Multi-grid short cycle + if short_cycle: + results = copy.deepcopy(self.info[idx]) + results['short_cycle_idx'] = short_cycle_idx + else: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['filename'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + + return results['imgs'][0], results['imgs'][1], np.array( + [results['labels']]) + + def prepare_test(self, idx): + """TEST. Prepare the data for test given the index.""" + #Try to catch Exception caused by reading corrupted video file + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['filename'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return results['imgs'][0], results['imgs'][1], np.array( + [results['labels']]), np.array([idx]) + + def __len__(self): + """get the size of the dataset.""" + if self.num_samples_precise_bn is None: + return len(self.info) + else: + random.shuffle(self.info) + return min(self.num_samples_precise_bn, len(self.info)) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/ucf101_skeleton.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/ucf101_skeleton.py new file mode 100644 index 0000000..8177933 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/ucf101_skeleton.py @@ -0,0 +1,89 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import random +import numpy as np +import pickle + +import paddle +from paddle.io import Dataset + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class UCF101SkeletonDataset(BaseDataset): + """ + Skeleton dataset for action recognition. + The dataset loads skeleton feature, and apply norm operatations. + Args: + file_path (str): Path to the index file. + pipeline(obj): Define the pipeline of data preprocessing. + test_mode (bool): Whether to bulid the test dataset. Default: False. + """ + + def __init__(self, + file_path, + pipeline, + split, + repeat_times, + test_mode=False): + self.split = split + self.repeat_times = repeat_times + super().__init__(file_path, pipeline, test_mode=test_mode) + self._ori_len = len(self.info) + self.start_index = 0 + self.modality = "Pose" + + def load_file(self): + """Load annotation file to get video information.""" + assert self.file_path.endswith('.pkl') + return self.load_pkl_annotations() + + def load_pkl_annotations(self): + with open(self.file_path, "rb") as f: + data = pickle.load(f) + + if self.split: + split, data = data['split'], data['annotations'] + identifier = 'filename' if 'filename' in data[0] else 'frame_dir' + data = [x for x in data if x[identifier] in split[self.split]] + + return data + + def prepare_train(self, idx): + """Prepare the frames for training given the index.""" + results = copy.deepcopy(self.info[idx % self._ori_len]) + results['modality'] = self.modality + results['start_index'] = self.start_index + + return self.pipeline(results) + + def prepare_test(self, idx): + """Prepare the frames for testing given the index.""" + results = copy.deepcopy(self.info[idx % self._ori_len]) + results['modality'] = self.modality + results['start_index'] = self.start_index + + return self.pipeline(results) + + def __len__(self): + """get the size of the dataset.""" + return len(self.info) * self.repeat_times diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/ucf24_dataset.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/ucf24_dataset.py new file mode 100644 index 0000000..ad2e84e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/ucf24_dataset.py @@ -0,0 +1,76 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 copy +import numpy as np + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class UCF24Dataset(BaseDataset): + """Dataset for YOWO + The dataset loads raw videos and apply specified transforms on them. + The index file is a file with multiple lines, and each line indicates + a sample video with the filepath and label, which are split with a whitesapce. + Example of a inde file: + .. code-block:: txt + + Args: + file_path(str): Path to the index file. + pipeline(XXX): A sequence of data transforms. + **kwargs: Keyword arguments for ```BaseDataset```. + """ + + def __init__(self, file_path, pipeline, num_retries=5, **kwargs): + self.num_retries = num_retries + super().__init__(file_path, pipeline, **kwargs) + + def load_file(self): + """Load index file to get video information.""" + info = [] + with open(self.file_path, 'r') as fin: + lines = fin.readlines() + for line in lines: + line = line.strip() # 'data/ucf24/labels/class_name/video_name/key_frame.txt' + filename = line.replace('txt', 'jpg').replace( + 'labels', 'rgb-images') # key frame path + + info.append(dict(filename=filename)) + return info + + def prepare_train(self, idx): + """TRAIN & VALID. Prepare the data for training/valid given the index.""" + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + im_path = results['filename'] + im_path = im_path.replace('jpg', 'txt') + im_split = im_path.split('/') + frame_index = im_split[3] + '_' + im_split[4] + '_' + im_split[5] + return results['imgs'], np.array([results['labels']]), frame_index + + def prepare_test(self, idx): + """TEST. Prepare the data for test given the index.""" + # Try to catch Exception caused by reading corrupted video file + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + im_path = results['filename'] + im_path = im_path.replace('jpg', 'txt') + im_split = im_path.split('/') + frame_index = im_split[3] + '_' + im_split[4] + '_' + im_split[5] + return results['imgs'], np.array([results['labels']]), frame_index diff --git a/Bank_second_part/detect_process/paddlevideo/loader/dataset/video.py b/Bank_second_part/detect_process/paddlevideo/loader/dataset/video.py new file mode 100644 index 0000000..f2d8f89 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/dataset/video.py @@ -0,0 +1,95 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import copy +import random +import numpy as np + +from ..registry import DATASETS +from .base import BaseDataset +from ...utils import get_logger + +logger = get_logger("paddlevideo") + + +@DATASETS.register() +class VideoDataset(BaseDataset): + """Video dataset for action recognition + The dataset loads raw videos and apply specified transforms on them. + The index file is a file with multiple lines, and each line indicates + a sample video with the filepath and label, which are split with a whitesapce. + Example of a inde file: + .. code-block:: txt + path/000.mp4 1 + path/001.mp4 1 + path/002.mp4 2 + path/003.mp4 2 + Args: + file_path(str): Path to the index file. + pipeline(XXX): A sequence of data transforms. + **kwargs: Keyword arguments for ```BaseDataset```. + """ + def __init__(self, file_path, pipeline, num_retries=5, suffix='', **kwargs): + self.num_retries = num_retries + self.suffix = suffix + super().__init__(file_path, pipeline, **kwargs) + + def load_file(self): + """Load index file to get video information.""" + info = [] + with open(self.file_path, 'r') as fin: + for line in fin: + line_split = line.strip().split() + filename, labels = line_split + #TODO(hj): Required suffix format: may mp4/avi/wmv + filename = filename + self.suffix + if self.data_prefix is not None: + filename = osp.join(self.data_prefix, filename) + info.append(dict(filename=filename, labels=int(labels))) + return info + + def prepare_train(self, idx): + """TRAIN & VALID. Prepare the data for training/valid given the index.""" + #Try to catch Exception caused by reading corrupted video file + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['filename'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return results['imgs'], np.array([results['labels']]) + + def prepare_test(self, idx): + """TEST. Prepare the data for test given the index.""" + #Try to catch Exception caused by reading corrupted video file + for ir in range(self.num_retries): + try: + results = copy.deepcopy(self.info[idx]) + results = self.pipeline(results) + except Exception as e: + #logger.info(e) + if ir < self.num_retries - 1: + logger.info( + "Error when loading {}, have {} trys, will try again". + format(results['filename'], ir)) + idx = random.randint(0, len(self.info) - 1) + continue + return results['imgs'], np.array([results['labels']]) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__init__.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__init__.py new file mode 100644 index 0000000..6e6afdc --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__init__.py @@ -0,0 +1,56 @@ +# 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. + +from .anet_pipeline import GetMatchMap, GetVideoLabel, LoadFeat +from .augmentations import (CenterCrop, ColorJitter, GroupRandomFlip, + GroupResize, Image2Array, JitterScale, MultiCrop, + Normalization, PackOutput, RandomCrop, RandomFlip, + RandomResizedCrop, Scale, TenCrop, ToArray, + UniformCrop, RandomGamma, MultiCenterCrop, + RandomBrightness, RandomHue, RandomSaturation, YowoAug) +from .augmentations_ava import * +from .compose import Compose +from .decode import FeatureDecoder, FrameDecoder, VideoDecoder, ActionFeatureDecoder +from .decode_image import ImageDecoder +from .decode_sampler import DecodeSampler +from .mix import Cutmix, Mixup, VideoMix +from .multimodal import FeaturePadding, RandomCap, RandomMask, Tokenize +from .sample import Sampler, SamplerPkl +from .sample_ava import * +from .segmentation import MultiNorm, MultiRestrictSize +from .skeleton_pipeline import AutoPadding, Iden, SkeletonNorm +from .skeleton_pipeline import SketeonCropSample, SketeonModalityTransform, RandomRotation +from .skeleton_pipeline import (UniformSampleFrames, PoseDecode, PoseCompact, + RandomResizedCrop_V2, Flip_V2, CenterCrop_V2, + GeneratePoseTarget, FormatShape, Collect) +from .decode_sampler_MRI import SFMRI_DecodeSampler +from .segmentation_pipline import SegmentationSampler +from .sample_ucf24 import SamplerUCF24 + +__all__ = [ + 'ImageDecoder', 'RandomMask', 'UniformCrop', 'SkeletonNorm', 'Tokenize', + 'Sampler', 'FeatureDecoder', 'DecodeSampler', 'TenCrop', 'Compose', + 'AutoPadding', 'Normalization', 'Mixup', 'Image2Array', 'Scale', + 'GroupResize', 'VideoDecoder', 'FrameDecoder', 'PackOutput', + 'ActionFeatureDecoder', 'GetVideoLabel', 'Cutmix', 'CenterCrop', + 'RandomCrop', 'LoadFeat', 'RandomCap', 'JitterScale', 'Iden', 'VideoMix', + 'ColorJitter', 'RandomFlip', 'ToArray', 'FeaturePadding', 'GetMatchMap', + 'GroupRandomFlip', 'MultiCrop', 'SFMRI_DecodeSampler', 'MultiRestrictSize', + 'MultiNorm', 'RandomResizedCrop', 'SamplerPkl', 'SegmentationSampler', + 'SketeonCropSample', 'SketeonModalityTransform', 'RandomRotation', + 'RandomGamma', 'MultiCenterCrop', 'RandomBrightness', 'RandomHue', + 'RandomSaturation', 'UniformSampleFrames', 'PoseDecode', 'PoseCompact', + 'Resize', 'RandomResizedCrop_V2', 'Flip_V2', 'GeneratePoseTarget', + 'FormatShape', 'Collect', 'RandomSaturation', 'SamplerUCF24', 'YowoAug' +] diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..303f5681a3c4d6d95b242812b08a8263e520daa8 GIT binary patch literal 2327 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/augmentations.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/augmentations.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d785703dca3283bacbada9c06d75be711ecf93ec GIT binary patch literal 39673 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/augmentations_ava.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/augmentations_ava.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ce471b7bcb6b57b8ccaa25ca3840398aeaa1b669 GIT binary patch literal 21444 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/decode_sampler_MRI.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/decode_sampler_MRI.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..17917fad8950bf2fba8e7c68d0952648dd0107e5 GIT binary patch literal 4924 zcmb7I-)|g89p9P#dFS)Raoog7ir7MFd(fKHf)?CRrEQYRq76~g5^+tmz1+;5*SXs} z&#sf$+LJ0=h$Ga>ydWfmWIqN8@h9-Y1CMgMI1p^5qL}EMK~CrAaeRJ|-IH@WqP&(jeQ^Idn2hJbwjr z7uE-?ZjoLe7rS6ClbePJHUAg$?Tg$_`eLIK%Q0arJF=Nzu2!<-UtN(2v?2X+ypLu+7vZQugnk(5 zdN&lJBmLVeGH=Hu9HIgJiBu4Q{48&ww-}JfIPpoSeEzp&vaX^D`{Y^$p}4c8CkPQR zceH^DwZEQI6-03?1FfyhjzHrW(LO@d+{^-XOF581kyOefP$EE!TulMo zH`FwWPv4PC*IsQzH-lE#k#Sx#*DSu zlz#!8vrqRFyydhxW;M@ZZg|VOl$CT81R_*5{@@=FN*x8rtgzdT;YuqGlbhMm*JbjG zQjLv^s@K)KRaSZni#D&C&0C9^qhuUz%FJo>X>Y2P6OdwvaNklm@#MFn@phT+? zpPQC;kM0>*U60)}(_9LYvN9nBA|jXKMU2^DYtDf&?!M&H6Jz!z#~2r5{E__8#|L%4 z{@$Q0_+W}GzQf`k?ZB(EH=(C`FUf7FF=RzhO{L|O&l%u46`e^DF`BY-0RLoKM(-07 zoPJ7_^MqU^!an4kH$>sWA5vNXw&-qMawe6kMtRH`WNkR2lN@yR;fqx`1b)GpRbR-uMb}% zoqqSo%BWyv{2YAwO>2j%H?YR$l2L@}*w|tzc5I6I)g#*KdKVE#KE%q=YjRAltps{= zpPsa00{DX7jqVmZ5pa6OHO%-}&V9T`5p}WR5B3$D=yZv0VAOHVA9A*snE6oe5d{vE z1v`o=Kf#VzIf-V z9ot;p&lnHpkCYh}hZB;+B_v}}8_6az$jQ8jsFY5v#+fJK#_3s+)Dki)j~OcDz{Udt zSt(8$Dxpj)b8$3M<-s|0G^uy=&{0Im!ZCcG_yBEeyVolNma=Uu>1}qx*fx&insLJT zC12xLjQdPI0Wy6g-sc%#IHSIT_I*>)X!SLKtdsWUXp3Xf)VDyD z5ILn<4=7)%@ytXvnb{)Q=*urPovINhJv(I#n)wzgpHK=3h578z8GbpA&ppak5iN%h*i z`X1GZrOwDR9`!SCl+0&VvlI4_8OG$p%!V2-d?&Lgh}2hU$T*!R*JNh5aR>P%Zo9oM zl0=jkk=dxUkzXb~Jy2f;=84?vB8d$9oeh}2r$D$VRWHu$1|_VuX`P3v)1a(ZChYb6 zf!3lrNrIdrs#34jie*B%=zg`8mGdh~&szMx5tjD>pHWqfs2o2TZev&8Bp0zLs+ ziRzmK76|C<6?ck!QN0ONJd2H>;?A;J~Xed6hZCd2^nf!b>@Al@oM8 zS;aexY}XoAc?DECw9q??Q5c7p<8}UHSr#(l8CKzy&ni}4S{8U9H>NC^c+q?g2Sri0 z_#A51aMt|aG*#0x%R2M6hL~~afSWb6hMq;zjWNz}2HfVT58R#MoOzthXjv=V`>bkJ zAz}HmIeV_q^z&|3x#2F=tc!SXLxe3O{9g!ytQ^oSeZ52VN)W8AH#$X+8w8@)3<7n8 zT%d#QGS&3%Fa~;`peq_t#IpdNVR2q1LvmLB)T>sGDeA8s&3G?X=TXgU>`(m-^#iJ# z_@kj{E6+;%|8Ep6_iSpp+edU>P^zaghE>p4h-!75`aC7uv=}xNodBbzRGHJev5G$m pddkCO&AhX@!Y|WN68ivN6?Y)`k;Ai95}M5nz4tl1QQ;0O{$En>gvI~> literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/mix.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/mix.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0d47a42d2a4e025b4d97699f5fe66daf8a6ffba0 GIT binary patch literal 3369 zcmb_eOK;>v5bkb2$1@2Fglv}QusqFUS;7HW5F2)Rh!sRgD{&ZtjAzT-3vyQ}J}8qCdk4DDCz zTlw`oW53g2wpkdgpr@aMNG5sAT3iZg#G+@k49+5B&)jG4GigfeHj`Fl?HaqhWl!a{ zbRc&sxigi!vIcprlDm@MWWINZzp&Lq0qXOj_VEWFzx&|_tMA_IkbJfo7_6YD7eON0 z6Ke^{TZVL{AarsnYa>%Hj8+O@EMD_HNwQChN>m)8uz64b_zELy8Uhz1P@`=KV1-y+uS_z#AsgM+NFuYiIbC}jZP;|zX!=! zhLe7e6R(M}7#o?`Gjg%d$3k-kI3qK2zRSmECbq0SJ2xS-H1FhW%cZ_A#x^8IZg241 zTwvg9l7A=0PHyL7fo|1aV!6nz3v7X%XIP#7D{=!5WVy3z?viI2t8{%b+exBBj_vtg zVaDAwD~wS$DMUZP-6|FC6h<8N3tNSKIp`I2I7n}pg;{sdFU)q7h5F75NBhMq%f71` zSgf$xVb<9!%x-TZE$ldKM{!z+c3K!+xs4^m9{v{gQf;b|AlMjPb|;MEAZTKg-Uo7y zdw5*l;P>%GzJz{!?WHOXq9`g4Y?|JO%LGB;1wn5hhcWSuAoyY!#?==m2;`s>1nM5l zQBM*ff0-e)6J>%dpr>R=mzlz|8kUxJAUM&;!B^1J=Ri(`o_9L*q>B)=Wep~%7xwjG z1~(gBYnIG30RMaZ=_@$lfwQrv$Q6}Cq(-DprCZ`x>;Y z+|6ytA7o1aQ)n1tPfKgLGnJZ<)@OCkPjnlzx>`!QbGet-^F}_mZo&fAsNN*c4%+R( zc2m)f9nv`~5c=b)(xG9iMF@d0Uns;!x1XsCGGyFbe>yEsL11%GYKgI@{VQKtR4@2ZPv>&KPNRd*WdW=Yu$m2xFH53_9y+-79B3Fn!LFBHWBz(Gop3=`N zEEF0G#cO;4m}not@M0!hD^OHVVS?|dXYf+b67h);M3u-#+y8g?dmdk3Ku|1;RCP?kipy2 zI)nzz&gNi{M$Pj3v|xemFbU2oTh<4vslPVE;l@)ss>*5B97mo zoH1#{)4g0rPg@{oRz9fEPz^1h8Uk2W)sUfOk3t5}o2`(@mk|jp5E-($=1i)ZeE2hE zsnOHN71PXJovNE=^=2;VwB9qP*3*}BO3}B9`pge?mMkp2w04-nF2DL_85-BH*;ak# z*R4i1U9W$43{YZ<&^72yim$Q+BWeo|AUL{r;zP$NOJLHZ5kIvDMHP|_-{boXRh77f zxC3?}eeI(*0*5+`IG?ZjR*40K_=+~J-XTI}^~Fr2pAokSbW%#ZI&Q^@9ad558|rOZ zj*_YNA@wwI$BSuBr{@)XSVKQ9NSsDpk(6rr{;-$qlxfOU(FO`RwWH{~MKz36VGr6{ nQ76;p(RR_Z&-z*6zFAgJZ&ChB&w;q}4PhI=oAc-|E%JW=0af$< literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/multimodal.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/multimodal.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fcf9da5d858adf2a25f901b274925fe493d76da8 GIT binary patch literal 8511 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/sample.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/sample.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b90beebc6468214161098f409d53bd565e132463 GIT binary patch literal 8513 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 ol#7Nar6w+0^hB76R z!<-rV!cyBda*zNECk0w;TWkWz+bvL|KratPfwn+zk9|pj0tHT=ioVou1@cfN+r<68 zGbBY)N=VF^GiT2Izn<@(FrUwA_6+$izTVKvyc-R@ zX_O6J^G)Asm`$r}AZBUEX1<(n7RrTwo9Xg2>e!9x zX0cps&Xi}Gv*p?TySeh5pDxb_#b73w^_`E*@Dcy;&{kGIg=(tq1oFJmM+y>cv;jUAnk>?n=p!>E*L4F9)$F3*K53 z3$GeCgZNtLmrR+v`10j*%P&+`Ub*zjWm)V$UAVmb=9QJ@OXr3qKUiIPae4K^xfi5a zy?z1>Q`N8$3Yl3K-mR$WH3FIGw5r#<)_UMqIj7N|iH9?|qE#e;R@Qy3Z1{TF%ozBa z_*)s%pY>C|eOoVEe%g0#YoMCi&9a^BBB+=53n+K|X}^ej#-G6s%*ospui0({=Y`h{ zqV6NflUq}dxP?tOz81LG>wXX}x%a^}+IeX;!mwR+kRSY*=jN^8icTTv={>EY^$etX z&qQkUETm>Hh1BZVNK?HuQsg#LzJ6Vcj(%Tz2W!KujMb7Mis(g7iJ%>Lai!r!aVagG zYNOt+G=i2as2Nu3tvC?Zy@t%RI?W2-Mshk1n(a_{jmkzn#%r02Z`7+nB~lBO#jq1s z!dhi5?6mw!*p6i;4x+fy4E>T#v=%ji7f9@vhp@BU}??n9##TN>1_a{C9rG%_|WMUGF9!6x(4=d~>Zq%jsC z+6P%;9M-nXp6MH#mN*uhJ0Q}AaTg>*O{-_c=0*B$GfZSLy*HXOweSNr2z$@oXKEgP*fBV*h1+Mo^k%yOKXj@*==x??1L zmF%v2A&6a4+zo5BD2OAs-f|(INJ+{iS4?B!f*gBK2U+XgU>$k<{^xrrNcr)tc2LSq zkXjn8wzNG#QIs}re%O?0-oa|pYImO$9rMO?P-Jg}yU|7#&v(5(mfJI*g=^#i(P&Ofm9?!)8!GtuK1ACZSFT#Aq0K?bzg zhmT^2`3BS~XlatVzP_M=E1rq19f0y@=>4iR`=0;DGwPQC48UO+8OaE=3ScFrL#=cAcS!u*^l9+SVRJXM&t-l zVhLqkPF2HJ)r*4`E^!PcC0h|#aKpuuOpY`87Lz3=)CeQwnoh_??V?oE_whQSLdh8i z^c<))pU^0w%h7%4GHg0V7Fq;eiY%Nw$s({_J9$9d=<5;0%n!z zWzdTiPy3l|{T+;u-cll)aJnPxFN`x8Gpy zaU{~D!B2}Iy5>PXX@Q}LLtp$7bNXvC`?}ZY1m}bZg*d@hN`xtA5PPMO*|^h)Bk>)+ zR&09`xpEQxCDZKd-Et=KY5`Xem8Uwb;e&MOfv~*nw1OL|g7_{wn-F=}Z}@YKN~MCA z(HSHTIDb~RbmKu57qs$&tU-I8Mb0sbxEF9a_|GbR;1~`{Sk6D>Wzya!{a0z&20z+< z`U*-^sAa$)u=YQNl}FCNT?q#6wB#1lP)2chTJ0BOfz-(Zo%F(@tcftWX-JM3+h!1wUJ9m7HgXo5x{v7=b zJ+afD>!nggX0V;u`KVH%XVij^TB(e1%U3#QMnZQ7?xU!{Yu|@V>Q!Y6n-#f8xYaO~ zhV`XoT3=X}^?z2%`h{g%pId3?Gt1dShNS%}Y=ZJLn4CYa{IH6(97R2)SQ8biz715xLo+bhdI@7$Z;dGQj-tto_Z~HcwAT4Ll!dbZz z!>?Ws&U)3&pyhWTU+$lXU{gROIAU&;)Nt35D$$ZVrqju&WLz@pr}Ql7@88o`)k^OT zs76=1?Zwwd*00!UQ9 zq}$Ti9+FTFE=4sC8^gwI>sxwEd!%n0ALi+E>=<|90R9j(wea6Ib**P!(Y~!khi>RP z$gXQ|;$j(2c+wDS_e^O*IHeV~q2VnNc>X;r@h`4m6sgzB86569L1nE|8`(o82i)AB z;QEvT;lQ1Ox`g}|zXW54; z@5>Hf&k1j!&)>xrag)gjj*+tkOZO0-6F-A%4;bJZfmMg-;&=}T2S9)wqydk>8MzHo zl^s0IC`f=$nLa3x?SleSz5}An%ItYa-b$k$wBqimWp_Pj1vp2$lt;RaD0bt}^{PDD zs#106^6Rx)Ao#K`^>8dKveg(9nV2=trBrMYMTQW;hIU;S^D&sHM{8xMlZ3Wo-h~?a zsrE6PGP*WvQIBG2Z3ed@neM-mcCrftFZdcO+M72# zu^vrw4At{JT04+(`XhOkA27$>Y4 z4xrj2fMxICj0D#fZfbNC?+m;{DfTaUXZMUajdmrx!yD|g^)XIs*jY1rR#CyZuE8D7 zC>o@aR)lWg9P6i)iZ0o!-ER>H>TiTgJLX2$!cN0?*8l=cNYg$ zM{6Z^Vpzu+)af1@kPSU`)`sR}ujcK(!J1x!%HozQf^|>{%;&ovN+;FWaTmyoy9h71 z8k~Mjbb>{j8j-ZPV?r@ZO3i12U*t?>u$TcO{v|2D zh$L(9Fz>)|G!zf<4u9oA0e6RYt9x{mpC&t69b+t>sd!N!BcADaVDIRn@IFNBedzJ` zb>FxH?M;mIJ?%aHJ)>qSrQ+};0)b0)7cciW9(z8ZAvD9tB;3_|x`@&Hn4?PD&#?)u zsgrPjObuh|9J80;f8shSpo0!>CA~b=9|O){bk7t5rK)ccF}G{HGs8Xn7rcllK1I6F zOCuAT+?=ITjSwz%^!(DWvABVTrBpJG8iI67M!dzG8u2D`$}cHS_W93vrH;Lh#qo=V zWp$5y%^b!QC2c!tvx4hW`UX^!$;tjo;=KSJt)o2gFZOX_)Qf**bM}?fyM>Xl_j8a2 z!-?Nuw{(yOLn!ZMzajYI-&mWfX-u6B9H^2meDV~{(odq1Qxc;*VL&c) zBolyL5nps!;p@$36;*zQD>{IL<`W+LgREsZIo+7a=}tap3fAE@_T#e8;EJ9{GUi3i zDF2CQI${)l2Ie${T-KkWVfAx<{O67t7lJAP$nKMuaLjgr z9J;hZNc$b$1EkZCx{YNrH&k}4-P_>qB0LS-{)P?RkkgVlYoN5!NaOz37o zA%z1CB8zHhDCR+l*g!9Gss@Wr$OTrh)c3f46EDPXF=3Sn?WCylA1GHYN&-h`_3pv( zB@Zo`m_k))uC0qP%|oYn2uptxx}az7X!IEY3+iwLa&QEc$$~~Qfv9{pHg;g<6#8Oq zz^C0ziD!Ej;sq%<0{thrI5rTVBu&>$AU@VuneAIZf=u8d&|N)!!}gs`Q+O(uLGEHt z-vK^@QS{b=%4d;J#m-K~cY3J}Q2nmS!|=uwAj;HE?k>j0__;fXmtm%P%=AYiGd2AJ zdhP9*h3!wjYjS>x7DdY=ZtK+2n61N z*>?1!IuQBK6uOf#zTnZFD1G6CXQ%01;|tfz|eDI6Xl5um8&=Dt5vwcky3FITbigu!2 z6%fs}AuKa-`lUqH~V$2p3RO1}gPQOKs1wTb$(9l%46HddCq=T3s&cZ5Ch2sg(+5Q1V z105*uIyDCM7Bs_?iV~_s;kgzO+Z~5THBc{=)O|tw^~bhs;KjtE?KrcOg+p%cO!e%$ zI%*N7({`L5LnuVBb3KQ43K%nx?45isa~CJ>x1RyMfhSY*`Du(_fEPFQE-~>0JKkGL z92scxA?>QMmED@cOs9KOy)3VFBIh~3&_k?N{2po*u>O26-^~ zonaO{54C^+G3wZg6x5CY${@14G;AU>3C8T#g|s7xN&V)kI7!Z>W|ek=Ju3~Hh?TCG zTv}lANU301Kp1ho-U3vgsJRUJzn@)?D{E`v%^;E)M4j7V1ZTE1D}I{;RGBEtu8ew( zj~_Boa+{9c?gRk>nA9QC45PNRHo|&K+FT4mWOrF^du_lozW5!sqe@gDyG*Mn+S4aW z#RRcA!@3!)5vQY2+!BApnt#mX=Sa%^J*fLP#TE6;6)0sQGu4hrLJ(5FCiNRKr@o1( z)bOnZApJjK_55&^6>4)HtS97NoJASFGU;pK40J6--Zlz|jOL6SP<7n(f(eHZ(Kjdq zlM&M-W;)-$zXMHe9}8REzYAecw`s2 zKIJd(x@8wxHm>UwO1#1~)5H!SYzGkbKI<3&*2b>02``_XnsOCNnSC8}dY$4AnUERO zCVw?H{UcQQcU+OezBts8;>OHN7XdGayOxaZ5 zwP<_4Yk3doNI4CSk(1L&bZhzbW#xY-GP4&=86J9hPKdQ_Pz?Sw)M|3{9DI7BtB@zW zs1zV1I2_!8fs;IoeDYn$0&+N@Dncou(Dtahmq-sf9tVu>!oj74|p~jDsQ6my0&>S@@gEdEUzI!pef|J!?TjY&NC#3cH8TSzx)R5DZiM4$i|~CwW-PJ0`8J z+R-$@DlBYkvM`I&!ercMzZ7jn}S9 zvxcviGI1RrV#NrG<3pxF79lL`qxd^4OxcWtaE#WfuN#uR-KE_;UVvk%Yr!%ubCe50zsR7WaleXv4iebaH%h0umIkhU-OuWG4922E}QzPnkcT*|w;;VG<+guf$#eoiH7|}r( zalch0iWs`rM1%7sXHxGfm8*82CQWHu95#|bXfl4n+u!5;}#UrVf?{zF|tKV`L)jMm?12Fj`_5PFgA$_ou99 zdTUidNlPMJ97;Lyf;12mL(xJ~F7&KLZR%B37ty&kf5b+Fjr+l1ED56vO1+N zlvnSZN13w(8>@RE_xn_gnRAJhFrl{L*AJG3F D%gq~$ literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/sample_ucf24.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/sample_ucf24.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0cf5b4f4065c5d1faec1640e912a99eb0220d115 GIT binary patch literal 1993 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/segmentation_pipline.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/segmentation_pipline.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..00d87e427416500279b7a2465632711eaddd74f0 GIT binary patch literal 971 zcmZ`%OKTKC5bnp!?Cj>jVn9?PdfiJ9j}j!PK?1S__aF=_&A45Ov*~%Hdsc`{PDxJw ziR9?N@!VHW`xiV}HDhpv*h4+Kx*lIuO}Vi#V0eCn-}EwI>?d7TPl%U2B=;VfW||w8 zbdo2$y^BP)GDw0}hDoS}mL|%3NsqHWgWh#~!`?C-=VPJQ-#TG?_2&b8KQm1=F^OQxZmnlja3r&U&g$qI~cD-ac$$+}aW`B_Z zxxA7O8NLSBVIyxi&O_|7)1Z655`Vpp#GQV$Ofg<^tcVK;vl?>erGdhS?sHl}J3JrE zN@`I9RHTgpOIUr+f?Jpx15V(~2Rg0OcFG-#$pyzUON~+LDc;;BvLWB(L;N0yArJmL zqAqAW3MoU8=Ae`xD3zCbVMt$B>U5Es?#1>ouiYX>OI~4w!P0CWAvppavskXn);3zR z1jvih`LI~z*rF&ZAKA3fW$vTyKk%`I WlE&-qQT2^j#GJl$E_f8)=f44lc<3Pj literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/skeleton_pipeline.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/__pycache__/skeleton_pipeline.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e4ddc3473935d5c41df28b12da23b1714c5fcb5a GIT binary patch literal 46357 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 t@q0JF2M9j;9sIr#%bUxEIePXTmAgwbg%bBJPH= self.target_size) and (h >= self.target_size), \ + "image width({}) and height({}) should be larger than crop size".format( + w, h, self.target_size) + + crop_images = [] + if 'backend' in results and results['backend'] == 'pyav': + x1 = np.random.randint(0, w - tw) + y1 = np.random.randint(0, h - th) + crop_images = imgs[:, :, y1:y1 + th, x1:x1 + tw] # [C, T, th, tw] + else: + x1 = random.randint(0, w - tw) + y1 = random.randint(0, h - th) + for img in imgs: + if w == tw and h == th: + crop_images.append(img) + else: + crop_images.append(img.crop((x1, y1, x1 + tw, y1 + th))) + results['imgs'] = crop_images + return results + + +@PIPELINES.register() +class RandomResizedCrop(RandomCrop): + def __init__(self, + area_range=(0.08, 1.0), + aspect_ratio_range=(3 / 4, 4 / 3), + target_size=224, + backend='cv2'): + + self.area_range = area_range + self.aspect_ratio_range = aspect_ratio_range + self.target_size = target_size + self.backend = backend + + @staticmethod + def get_crop_bbox(img_shape, + area_range, + aspect_ratio_range, + max_attempts=10): + + assert 0 < area_range[0] <= area_range[1] <= 1 + assert 0 < aspect_ratio_range[0] <= aspect_ratio_range[1] + + img_h, img_w = img_shape + area = img_h * img_w + + min_ar, max_ar = aspect_ratio_range + aspect_ratios = np.exp( + np.random.uniform(np.log(min_ar), np.log(max_ar), + size=max_attempts)) + target_areas = np.random.uniform(*area_range, size=max_attempts) * area + candidate_crop_w = np.round(np.sqrt(target_areas * + aspect_ratios)).astype(np.int32) + candidate_crop_h = np.round(np.sqrt(target_areas / + aspect_ratios)).astype(np.int32) + + for i in range(max_attempts): + crop_w = candidate_crop_w[i] + crop_h = candidate_crop_h[i] + if crop_h <= img_h and crop_w <= img_w: + x_offset = random.randint(0, img_w - crop_w) + y_offset = random.randint(0, img_h - crop_h) + return x_offset, y_offset, x_offset + crop_w, y_offset + crop_h + + # Fallback + crop_size = min(img_h, img_w) + x_offset = (img_w - crop_size) // 2 + y_offset = (img_h - crop_size) // 2 + return x_offset, y_offset, x_offset + crop_size, y_offset + crop_size + + def __call__(self, results): + imgs = results['imgs'] + if self.backend == 'pillow': + img_w, img_h = imgs[0].size + elif self.backend == 'cv2': + img_h, img_w, _ = imgs[0].shape + elif self.backend == 'pyav': + img_h, img_w = imgs.shape[2:] # [cthw] + else: + raise NotImplementedError + + left, top, right, bottom = self.get_crop_bbox( + (img_h, img_w), self.area_range, self.aspect_ratio_range) + + if self.backend == 'pillow': + img_w, img_h = imgs[0].size + imgs = [img.crop(left, top, right, bottom) for img in imgs] + elif self.backend == 'cv2': + img_h, img_w, _ = imgs[0].shape + imgs = [img[top:bottom, left:right] for img in imgs] + elif self.backend == 'pyav': + img_h, img_w = imgs.shape[2:] # [cthw] + imgs = imgs[:, :, top:bottom, left:right] + else: + raise NotImplementedError + results['imgs'] = imgs + return results + + +@PIPELINES.register() +class CenterCrop(object): + """ + Center crop images. + Args: + target_size(int): Center crop a square with the target_size from an image. + do_round(bool): Whether to round up the coordinates of the upper left corner of the cropping area. default: True + """ + def __init__(self, target_size, do_round=True, backend='pillow'): + self.target_size = target_size + self.do_round = do_round + self.backend = backend + + def __call__(self, results): + """ + Performs Center crop operations. + Args: + imgs: List where each item is a PIL.Image. + For example, [PIL.Image0, PIL.Image1, PIL.Image2, ...] + return: + ccrop_imgs: List where each item is a PIL.Image after Center crop. + """ + imgs = results['imgs'] + ccrop_imgs = [] + th, tw = self.target_size, self.target_size + if isinstance(imgs, paddle.Tensor): + h, w = imgs.shape[-2:] + x1 = int(round((w - tw) / 2.0)) if self.do_round else (w - tw) // 2 + y1 = int(round((h - th) / 2.0)) if self.do_round else (h - th) // 2 + ccrop_imgs = imgs[:, :, y1:y1 + th, x1:x1 + tw] + else: + for img in imgs: + if self.backend == 'pillow': + w, h = img.size + elif self.backend == 'cv2': + h, w, _ = img.shape + else: + raise NotImplementedError + assert (w >= self.target_size) and (h >= self.target_size), \ + "image width({}) and height({}) should be larger than crop size".format( + w, h, self.target_size) + x1 = int(round( + (w - tw) / 2.0)) if self.do_round else (w - tw) // 2 + y1 = int(round( + (h - th) / 2.0)) if self.do_round else (h - th) // 2 + if self.backend == 'cv2': + ccrop_imgs.append(img[y1:y1 + th, x1:x1 + tw]) + elif self.backend == 'pillow': + ccrop_imgs.append(img.crop((x1, y1, x1 + tw, y1 + th))) + results['imgs'] = ccrop_imgs + return results + + +@PIPELINES.register() +class MultiScaleCrop(object): + """ + Random crop images in with multiscale sizes + Args: + target_size(int): Random crop a square with the target_size from an image. + scales(int): List of candidate cropping scales. + max_distort(int): Maximum allowable deformation combination distance. + fix_crop(int): Whether to fix the cutting start point. + allow_duplication(int): Whether to allow duplicate candidate crop starting points. + more_fix_crop(int): Whether to allow more cutting starting points. + """ + def __init__( + self, + target_size, # NOTE: named target size now, but still pass short size in it! + scales=None, + max_distort=1, + fix_crop=True, + allow_duplication=False, + more_fix_crop=True, + backend='pillow'): + + self.target_size = target_size + self.scales = scales if scales else [1, .875, .75, .66] + self.max_distort = max_distort + self.fix_crop = fix_crop + self.allow_duplication = allow_duplication + self.more_fix_crop = more_fix_crop + assert backend in [ + 'pillow', 'cv2' + ], f"MultiScaleCrop's backend must be pillow or cv2, but get {backend}" + self.backend = backend + + def __call__(self, results): + """ + Performs MultiScaleCrop operations. + Args: + imgs: List where wach item is a PIL.Image. + XXX: + results: + + """ + imgs = results['imgs'] + + input_size = [self.target_size, self.target_size] + + im_size = imgs[0].size + + # get random crop offset + def _sample_crop_size(im_size): + image_w, image_h = im_size[0], im_size[1] + + base_size = min(image_w, image_h) + crop_sizes = [int(base_size * x) for x in self.scales] + crop_h = [ + input_size[1] if abs(x - input_size[1]) < 3 else x + for x in crop_sizes + ] + crop_w = [ + input_size[0] if abs(x - input_size[0]) < 3 else x + for x in crop_sizes + ] + + pairs = [] + for i, h in enumerate(crop_h): + for j, w in enumerate(crop_w): + if abs(i - j) <= self.max_distort: + pairs.append((w, h)) + crop_pair = random.choice(pairs) + if not self.fix_crop: + w_offset = random.randint(0, image_w - crop_pair[0]) + h_offset = random.randint(0, image_h - crop_pair[1]) + else: + w_step = (image_w - crop_pair[0]) / 4 + h_step = (image_h - crop_pair[1]) / 4 + + ret = list() + ret.append((0, 0)) # upper left + if self.allow_duplication or w_step != 0: + ret.append((4 * w_step, 0)) # upper right + if self.allow_duplication or h_step != 0: + ret.append((0, 4 * h_step)) # lower left + if self.allow_duplication or (h_step != 0 and w_step != 0): + ret.append((4 * w_step, 4 * h_step)) # lower right + if self.allow_duplication or (h_step != 0 or w_step != 0): + ret.append((2 * w_step, 2 * h_step)) # center + + if self.more_fix_crop: + ret.append((0, 2 * h_step)) # center left + ret.append((4 * w_step, 2 * h_step)) # center right + ret.append((2 * w_step, 4 * h_step)) # lower center + ret.append((2 * w_step, 0 * h_step)) # upper center + + ret.append((1 * w_step, 1 * h_step)) # upper left quarter + ret.append((3 * w_step, 1 * h_step)) # upper right quarter + ret.append((1 * w_step, 3 * h_step)) # lower left quarter + ret.append((3 * w_step, 3 * h_step)) # lower righ quarter + + w_offset, h_offset = random.choice(ret) + + return crop_pair[0], crop_pair[1], w_offset, h_offset + + crop_w, crop_h, offset_w, offset_h = _sample_crop_size(im_size) + crop_img_group = [ + img.crop((offset_w, offset_h, offset_w + crop_w, offset_h + crop_h)) + for img in imgs + ] + if self.backend == 'pillow': + ret_img_group = [ + img.resize((input_size[0], input_size[1]), Image.BILINEAR) + for img in crop_img_group + ] + else: + ret_img_group = [ + Image.fromarray( + cv2.resize(np.asarray(img), + dsize=(input_size[0], input_size[1]), + interpolation=cv2.INTER_LINEAR)) + for img in crop_img_group + ] + results['imgs'] = ret_img_group + return results + + +@PIPELINES.register() +class RandomFlip(object): + """ + Random Flip images. + Args: + p(float): Random flip images with the probability p. + """ + def __init__(self, p=0.5): + self.p = p + + def __call__(self, results): + """ + Performs random flip operations. + Args: + imgs: List where each item is a PIL.Image. + For example, [PIL.Image0, PIL.Image1, PIL.Image2, ...] + return: + flip_imgs: List where each item is a PIL.Image after random flip. + """ + imgs = results['imgs'] + v = random.random() + if v < self.p: + if isinstance(imgs, paddle.Tensor): + results['imgs'] = paddle.flip(imgs, axis=[3]) + elif isinstance(imgs[0], np.ndarray): + results['imgs'] = [cv2.flip(img, 1, img) for img in imgs + ] # [[h,w,c], [h,w,c], ..., [h,w,c]] + else: + results['imgs'] = [ + img.transpose(Image.FLIP_LEFT_RIGHT) for img in imgs + ] + else: + results['imgs'] = imgs + return results + + +@PIPELINES.register() +class RandomBrightness(object): + """ + Random Brightness images. + Args: + p(float): Random brightness images with the probability p. + """ + def __init__(self, p=0.1, brightness=1): + self.p = p + self.brightness = brightness + + def __call__(self, results): + """ + Performs random brightness operations. + Args: + imgs: List where each item is a PIL.Image. + For example, [PIL.Image0, PIL.Image1, PIL.Image2, ...] + return: + brightness_imgs: List where each item is a PIL.Image after random brightness. + """ + imgs = results['imgs'] + v = random.random() + + if v < self.p: + transform = ColorJitter(brightness=self.brightness) + results['imgs'] = [transform(img) for img in imgs] + else: + results['imgs'] = imgs + return results + + +@PIPELINES.register() +class RandomSaturation(object): + """ + Random Saturation images. + Args: + p(float): Random saturation images with the probability p. + """ + def __init__(self, p=0.1, saturation=2): + self.p = p + self.saturation = saturation + + def __call__(self, results): + """ + Performs random saturation operations. + Args: + imgs: List where each item is a PIL.Image. + For example, [PIL.Image0, PIL.Image1, PIL.Image2, ...] + return: + saturation_imgs: List where each item is a PIL.Image after random saturation. + """ + imgs = results['imgs'] + v = random.random() + + if v < self.p: + transform = ColorJitter(saturation=self.saturation) + results['imgs'] = [transform(img) for img in imgs] + else: + results['imgs'] = imgs + return results + + +@PIPELINES.register() +class RandomHue(object): + """ + Random Hue images. + Args: + p(float): Random hue images with the probability p. + """ + def __init__(self, p=0.1, hue=0.5): + self.p = p + self.hue = hue + + def __call__(self, results): + """ + Performs random hue operations. + Args: + imgs: List where each item is a PIL.Image. + For example, [PIL.Image0, PIL.Image1, PIL.Image2, ...] + return: + hue_imgs: List where each item is a PIL.Image after random hue. + """ + imgs = results['imgs'] + v = random.random() + + if v < self.p: + transform = ColorJitter(hue=self.hue) + results['imgs'] = [transform(img) for img in imgs] + else: + results['imgs'] = imgs + return results + + +@PIPELINES.register() +class RandomGamma(object): + """ + Random Gamma images. + Args: + p(float): Random gamma images with the probability p. + gamma (float): Non negative real number, same as `\\gamma` in the equation. + gamma larger than 1 make the shadows darker, + while gamma smaller than 1 make dark regions lighter. + """ + def __init__(self, p=0.1, gamma=0.2): + self.p = p + self.value = [1 - gamma, 1 + gamma] + self.value[0] = max(self.value[0], 0) + + def _adust_gamma(self, img, gamma, gain=1.0): + flag = False + if isinstance(img, np.ndarray): + flag = True + img = Image.fromarray(img) + input_mode = img.mode + img = img.convert("RGB") + gamma_map = [ + int((255 + 1 - 1e-3) * gain * pow(ele / 255.0, gamma)) + for ele in range(256) + ] * 3 + img = img.point( + gamma_map) # use PIL's point-function to accelerate this part + img = img.convert(input_mode) + if flag: + img = np.array(img) + return img + + def __call__(self, results): + """ + Performs random gamma operations. + Args: + imgs: List where each item is a PIL.Image. + For example, [PIL.Image0, PIL.Image1, PIL.Image2, ...] + return: + gamma_imgs: List where each item is a PIL.Image after random gamma. + """ + imgs = results['imgs'] + v = random.random() + + if v < self.p: + gamma = random.uniform(self.value[0], self.value[1]) + results['imgs'] = [self._adust_gamma(img, gamma) for img in imgs] + else: + results['imgs'] = imgs + return results + + +@PIPELINES.register() +class Image2Array(object): + """ + transfer PIL.Image to Numpy array and transpose dimensions from 'dhwc' to 'dchw'. + Args: + transpose: whether to transpose or not, default True, False for slowfast. + """ + def __init__(self, transpose=True, data_format='tchw'): + assert data_format in [ + 'tchw', 'cthw' + ], f"Target format must in ['tchw', 'cthw'], but got {data_format}" + self.transpose = transpose + self.data_format = data_format + + def __call__(self, results): + """ + Performs Image to NumpyArray operations. + Args: + imgs: List where each item is a PIL.Image. + For example, [PIL.Image0, PIL.Image1, PIL.Image2, ...] + return: + np_imgs: Numpy array. + """ + imgs = results['imgs'] + if 'backend' in results and results[ + 'backend'] == 'pyav': # [T,H,W,C] in [0, 1] + if self.transpose: + if self.data_format == 'tchw': + t_imgs = imgs.transpose((0, 3, 1, 2)) # tchw + else: + t_imgs = imgs.transpose((3, 0, 1, 2)) # cthw + results['imgs'] = t_imgs + else: + t_imgs = np.stack(imgs).astype('float32') + if self.transpose: + if self.data_format == 'tchw': + t_imgs = t_imgs.transpose(0, 3, 1, 2) # tchw + else: + t_imgs = t_imgs.transpose(3, 0, 1, 2) # cthw + results['imgs'] = t_imgs + return results + + +@PIPELINES.register() +class Normalization(object): + """ + Normalization. + Args: + mean(Sequence[float]): mean values of different channels. + std(Sequence[float]): std values of different channels. + tensor_shape(list): size of mean, default [3,1,1]. For slowfast, [1,1,1,3] + """ + def __init__(self, mean, std, tensor_shape=[3, 1, 1], inplace=False): + if not isinstance(mean, Sequence): + raise TypeError( + f'Mean must be list, tuple or np.ndarray, but got {type(mean)}') + if not isinstance(std, Sequence): + raise TypeError( + f'Std must be list, tuple or np.ndarray, but got {type(std)}') + + self.inplace = inplace + if not inplace: + self.mean = np.array(mean).reshape(tensor_shape).astype(np.float32) + self.std = np.array(std).reshape(tensor_shape).astype(np.float32) + else: + self.mean = np.array(mean, dtype=np.float32) + self.std = np.array(std, dtype=np.float32) + + def __call__(self, results): + """ + Performs normalization operations. + Args: + imgs: Numpy array. + return: + np_imgs: Numpy array after normalization. + """ + if self.inplace: + n = len(results['imgs']) + h, w, c = results['imgs'][0].shape + norm_imgs = np.empty((n, h, w, c), dtype=np.float32) + for i, img in enumerate(results['imgs']): + norm_imgs[i] = img + + for img in norm_imgs: # [n,h,w,c] + mean = np.float64(self.mean.reshape(1, -1)) # [1, 3] + stdinv = 1 / np.float64(self.std.reshape(1, -1)) # [1, 3] + cv2.subtract(img, mean, img) + cv2.multiply(img, stdinv, img) + else: + imgs = results['imgs'] + norm_imgs = imgs / 255.0 + norm_imgs -= self.mean + norm_imgs /= self.std + if 'backend' in results and results['backend'] == 'pyav': + norm_imgs = paddle.to_tensor(norm_imgs, dtype=paddle.float32) + results['imgs'] = norm_imgs + return results + + +@PIPELINES.register() +class JitterScale(object): + """ + Scale image, while the target short size is randomly select between min_size and max_size. + Args: + min_size: Lower bound for random sampler. + max_size: Higher bound for random sampler. + """ + def __init__(self, + min_size, + max_size, + short_cycle_factors=[0.5, 0.7071], + default_min_size=256): + self.default_min_size = default_min_size + self.orig_min_size = self.min_size = min_size + self.max_size = max_size + self.short_cycle_factors = short_cycle_factors + + def __call__(self, results): + """ + Performs jitter resize operations. + Args: + imgs (Sequence[PIL.Image]): List where each item is a PIL.Image. + For example, [PIL.Image0, PIL.Image1, PIL.Image2, ...] + return: + resized_imgs: List where each item is a PIL.Image after scaling. + """ + short_cycle_idx = results.get('short_cycle_idx') + if short_cycle_idx in [0, 1]: + self.min_size = int( + round(self.short_cycle_factors[short_cycle_idx] * + self.default_min_size)) + else: + self.min_size = self.orig_min_size + + imgs = results['imgs'] + size = int(round(np.random.uniform(self.min_size, self.max_size))) + assert (len(imgs) >= 1), \ + "len(imgs):{} should be larger than 1".format(len(imgs)) + + if 'backend' in results and results['backend'] == 'pyav': + height, width = imgs.shape[2:] + else: + width, height = imgs[0].size + if (width <= height and width == size) or (height <= width + and height == size): + return results + + new_width = size + new_height = size + if width < height: + new_height = int(math.floor((float(height) / width) * size)) + else: + new_width = int(math.floor((float(width) / height) * size)) + + if 'backend' in results and results['backend'] == 'pyav': + frames_resize = F.interpolate(imgs, + size=(new_height, new_width), + mode="bilinear", + align_corners=False) # [c,t,h,w] + else: + frames_resize = [] + for j in range(len(imgs)): + img = imgs[j] + scale_img = img.resize((new_width, new_height), Image.BILINEAR) + frames_resize.append(scale_img) + + results['imgs'] = frames_resize + return results + + +@PIPELINES.register() +class MultiCenterCrop(object): + """ + center crop, left center crop right center crop + Args: + target_size(int): Random crop a square with the target_size from an image. + """ + def __init__(self, target_size): + self.target_size = target_size + + def __call__(self, results): + """ + Performs random crop operations. + Args: + imgs: List where each item is a PIL.Image. + For example, [PIL.Image0, PIL.Image1, PIL.Image2, ...] + return: + crop_imgs: List where each item is a PIL.Image after random crop. + """ + imgs = results['imgs'] + if 'backend' in results and results['backend'] == 'pyav': # [c,t,h,w] + h, w = imgs.shape[2:] + else: + w, h = imgs[0].size + th, tw = self.target_size, self.target_size + + assert (w >= self.target_size) and (h >= self.target_size), \ + "image width({}) and height({}) should be larger than crop size".format( + w, h, self.target_size) + + crop_images = [] + #just for tensor + crop_imgs_center = [] + crop_imgs_left = [] + crop_imgs_right = [] + if 'backend' in results and results['backend'] == 'pyav': + #center_corp + x1 = 0 + if w > self.target_size: + x1 = int((w - self.target_size) / 2.0) + y1 = 0 + if h > self.target_size: + y1 = int((h - self.target_size) / 2.0) + crop_imgs_center = imgs[:, :, y1:y1 + th, + x1:x1 + tw].numpy() # [C, T, th, tw] + #left_crop + x1 = 0 + y1 = 0 + if h > self.target_size: + y1 = int((h - self.target_size) / 2.0) + crop_imgs_left = imgs[:, :, y1:y1 + th, x1:x1 + tw].numpy() + #right_crop + x1 = 0 + y1 = 0 + if w > self.target_size: + x1 = w - self.target_size + if h > self.target_size: + y1 = int((h - self.target_size) / 2.0) + crop_imgs_right = imgs[:, :, y1:y1 + th, x1:x1 + tw].numpy() + crop_imgs = np.concatenate( + (crop_imgs_center, crop_imgs_left, crop_imgs_right), axis=1) + crop_images = paddle.to_tensor(crop_imgs) + + else: + x1 = 0 + if w > self.target_size: + x1 = random.randint(0, w - tw) + y1 = 0 + if h > self.target_size: + y1 = random.randint(0, h - th) + for img in imgs: + if w == tw and h == th: + crop_images.append(img) + else: + crop_images.append(img.crop((x1, y1, x1 + tw, y1 + th))) + results['imgs'] = crop_images + return results + + +@PIPELINES.register() +class MultiCrop(object): + """ + Random crop image. + This operation can perform multi-crop during multi-clip test, as in slowfast model. + Args: + target_size(int): Random crop a square with the target_size from an image. + """ + def __init__(self, + target_size, + default_crop_size=224, + short_cycle_factors=[0.5, 0.7071], + test_mode=False): + self.orig_target_size = self.target_size = target_size + self.short_cycle_factors = short_cycle_factors + self.default_crop_size = default_crop_size + self.test_mode = test_mode + + def __call__(self, results): + """ + Performs random crop operations. + Args: + imgs: List where each item is a PIL.Image. + For example, [PIL.Image0, PIL.Image1, PIL.Image2, ...] + return: + crop_imgs: List where each item is a PIL.Image after random crop. + """ + imgs = results['imgs'] + spatial_sample_index = results['spatial_sample_index'] + spatial_num_clips = results['spatial_num_clips'] + + short_cycle_idx = results.get('short_cycle_idx') + if short_cycle_idx in [0, 1]: + self.target_size = int( + round(self.short_cycle_factors[short_cycle_idx] * + self.default_crop_size)) + else: + self.target_size = self.orig_target_size # use saved value before call + + w, h = imgs[0].size + if w == self.target_size and h == self.target_size: + return results + + assert (w >= self.target_size) and (h >= self.target_size), \ + "image width({}) and height({}) should be larger than crop size({},{})".format(w, h, self.target_size, self.target_size) + frames_crop = [] + if not self.test_mode: + x_offset = random.randint(0, w - self.target_size) + y_offset = random.randint(0, h - self.target_size) + else: # multi-crop + x_gap = int( + math.ceil((w - self.target_size) / (spatial_num_clips - 1))) + y_gap = int( + math.ceil((h - self.target_size) / (spatial_num_clips - 1))) + if h > w: + x_offset = int(math.ceil((w - self.target_size) / 2)) + if spatial_sample_index == 0: + y_offset = 0 + elif spatial_sample_index == spatial_num_clips - 1: + y_offset = h - self.target_size + else: + y_offset = y_gap * spatial_sample_index + else: + y_offset = int(math.ceil((h - self.target_size) / 2)) + if spatial_sample_index == 0: + x_offset = 0 + elif spatial_sample_index == spatial_num_clips - 1: + x_offset = w - self.target_size + else: + x_offset = x_gap * spatial_sample_index + + for img in imgs: + nimg = img.crop((x_offset, y_offset, x_offset + self.target_size, + y_offset + self.target_size)) + frames_crop.append(nimg) + results['imgs'] = frames_crop + return results + + +@PIPELINES.register() +class PackOutput(object): + """ + In slowfast model, we want to get slow pathway from fast pathway based on + alpha factor. + Args: + alpha(int): temporal length of fast/slow + """ + def __init__(self, alpha): + self.alpha = alpha + + def __call__(self, results): + fast_pathway = results['imgs'] + + # sample num points between start and end + slow_idx_start = 0 + slow_idx_end = fast_pathway.shape[0] - 1 + slow_idx_num = fast_pathway.shape[0] // self.alpha + slow_idxs_select = np.linspace(slow_idx_start, slow_idx_end, + slow_idx_num).astype("int64") + slow_pathway = fast_pathway[slow_idxs_select] + + # T H W C -> C T H W. + slow_pathway = slow_pathway.transpose(3, 0, 1, 2) + fast_pathway = fast_pathway.transpose(3, 0, 1, 2) + + # slow + fast + frames_list = [slow_pathway, fast_pathway] + results['imgs'] = frames_list + return results + + +@PIPELINES.register() +class GroupFullResSample(object): + def __init__(self, crop_size, flip=False): + self.crop_size = crop_size if not isinstance(crop_size, int) else ( + crop_size, crop_size) + self.flip = flip + + def __call__(self, results): + img_group = results['imgs'] + + image_w, image_h = img_group[0].size + crop_w, crop_h = self.crop_size + + w_step = (image_w - crop_w) // 4 + h_step = (image_h - crop_h) // 4 + + offsets = list() + offsets.append((0 * w_step, 2 * h_step)) # left + offsets.append((4 * w_step, 2 * h_step)) # right + offsets.append((2 * w_step, 2 * h_step)) # center + + oversample_group = list() + for o_w, o_h in offsets: + normal_group = list() + flip_group = list() + for i, img in enumerate(img_group): + crop = img.crop((o_w, o_h, o_w + crop_w, o_h + crop_h)) + normal_group.append(crop) + if self.flip: + flip_crop = crop.copy().transpose(Image.FLIP_LEFT_RIGHT) + flip_group.append(flip_crop) + + oversample_group.extend(normal_group) + if self.flip: + oversample_group.extend(flip_group) + + results['imgs'] = oversample_group + return results + + +@PIPELINES.register() +class TenCrop: + """ + Crop out 5 regions (4 corner points + 1 center point) from the picture, + and then flip the cropping result to get 10 cropped images, which can make the prediction result more robust. + Args: + target_size(int | tuple[int]): (w, h) of target size for crop. + """ + def __init__(self, target_size): + self.target_size = (target_size, target_size) + + def __call__(self, results): + imgs = results['imgs'] + img_w, img_h = imgs[0].size + crop_w, crop_h = self.target_size + w_step = (img_w - crop_w) // 4 + h_step = (img_h - crop_h) // 4 + offsets = [ + (0, 0), + (4 * w_step, 0), + (0, 4 * h_step), + (4 * w_step, 4 * h_step), + (2 * w_step, 2 * h_step), + ] + img_crops = list() + for x_offset, y_offset in offsets: + crop = [ + img.crop( + (x_offset, y_offset, x_offset + crop_w, y_offset + crop_h)) + for img in imgs + ] + crop_fliped = [ + timg.transpose(Image.FLIP_LEFT_RIGHT) for timg in crop + ] + img_crops.extend(crop) + img_crops.extend(crop_fliped) + + results['imgs'] = img_crops + return results + + +@PIPELINES.register() +class UniformCrop: + """ + Perform uniform spatial sampling on the images, + select the two ends of the long side and the middle position (left middle right or top middle bottom) 3 regions. + Args: + target_size(int | tuple[int]): (w, h) of target size for crop. + """ + def __init__(self, target_size, backend='cv2'): + if isinstance(target_size, tuple): + self.target_size = target_size + elif isinstance(target_size, int): + self.target_size = (target_size, target_size) + else: + raise TypeError( + f'target_size must be int or tuple[int], but got {type(target_size)}' + ) + self.backend = backend + + def __call__(self, results): + + imgs = results['imgs'] + if 'backend' in results and results['backend'] == 'pyav': # [c,t,h,w] + img_h, img_w = imgs.shape[2:] + elif self.backend == 'pillow': + img_w, img_h = imgs[0].size + else: + img_h, img_w = imgs[0].shape[:2] + + crop_w, crop_h = self.target_size + if crop_h == img_h: + w_step = (img_w - crop_w) // 2 + offsets = [ + (0, 0), + (w_step * 2, 0), + (w_step, 0), + ] + elif crop_w == img_w: + h_step = (img_h - crop_h) // 2 + offsets = [ + (0, 0), + (0, h_step * 2), + (0, h_step), + ] + else: + raise ValueError( + f"img_w({img_w}) == crop_w({crop_w}) or img_h({img_h}) == crop_h({crop_h})" + ) + img_crops = [] + if 'backend' in results and results['backend'] == 'pyav': # [c,t,h,w] + for x_offset, y_offset in offsets: + crop = imgs[:, :, y_offset:y_offset + crop_h, + x_offset:x_offset + crop_w] + img_crops.append(crop) + img_crops = paddle.concat(img_crops, axis=1) + else: + if self.backend == 'pillow': + for x_offset, y_offset in offsets: + crop = [ + img.crop((x_offset, y_offset, x_offset + crop_w, + y_offset + crop_h)) for img in imgs + ] + img_crops.extend(crop) + else: + for x_offset, y_offset in offsets: + crop = [ + img[y_offset:y_offset + crop_h, + x_offset:x_offset + crop_w] for img in imgs + ] + img_crops.extend(crop) + results['imgs'] = img_crops + return results + + +@PIPELINES.register() +class GroupResize(object): + def __init__(self, height, width, scale, K, mode='train'): + self.height = height + self.width = width + self.scale = scale + self.resize = {} + self.K = np.array(K, dtype=np.float32) + self.mode = mode + for i in range(self.scale): + s = 2**i + self.resize[i] = paddle.vision.transforms.Resize( + (self.height // s, self.width // s), interpolation='lanczos') + + def __call__(self, results): + if self.mode == 'infer': + imgs = results['imgs'] + for k in list(imgs): # ("color", 0, -1) + if "color" in k or "color_n" in k: + n, im, _ = k + for i in range(self.scale): + imgs[(n, im, i)] = self.resize[i](imgs[(n, im, i - 1)]) + else: + imgs = results['imgs'] + for scale in range(self.scale): + K = self.K.copy() + + K[0, :] *= self.width // (2**scale) + K[1, :] *= self.height // (2**scale) + + inv_K = np.linalg.pinv(K) + imgs[("K", scale)] = K + imgs[("inv_K", scale)] = inv_K + + for k in list(imgs): + if "color" in k or "color_n" in k: + n, im, i = k + for i in range(self.scale): + imgs[(n, im, i)] = self.resize[i](imgs[(n, im, i - 1)]) + + results['imgs'] = imgs + return results + + +@PIPELINES.register() +class ColorJitter(object): + """Randomly change the brightness, contrast, saturation and hue of an image. + """ + def __init__(self, + brightness=0, + contrast=0, + saturation=0, + hue=0, + mode='train', + p=0.5, + keys=None): + self.mode = mode + self.colorjitter = paddle.vision.transforms.ColorJitter( + brightness, contrast, saturation, hue) + self.p = p + + def __call__(self, results): + """ + Args: + results (PIL Image): Input image. + + Returns: + PIL Image: Color jittered image. + """ + + do_color_aug = random.random() > self.p + imgs = results['imgs'] + for k in list(imgs): + f = imgs[k] + if "color" in k or "color_n" in k: + n, im, i = k + imgs[(n, im, i)] = f + if do_color_aug: + imgs[(n + "_aug", im, i)] = self.colorjitter(f) + else: + imgs[(n + "_aug", im, i)] = f + if self.mode == "train": + for i in results['frame_idxs']: + del imgs[("color", i, -1)] + del imgs[("color_aug", i, -1)] + del imgs[("color_n", i, -1)] + del imgs[("color_n_aug", i, -1)] + else: + for i in results['frame_idxs']: + del imgs[("color", i, -1)] + del imgs[("color_aug", i, -1)] + + results['img'] = imgs + return results + + +@PIPELINES.register() +class GroupRandomFlip(object): + def __init__(self, p=0.5): + self.p = p + + def __call__(self, results): + + imgs = results['imgs'] + do_flip = random.random() > self.p + if do_flip: + for k in list(imgs): + if "color" in k or "color_n" in k: + n, im, i = k + imgs[(n, im, + i)] = imgs[(n, im, + i)].transpose(Image.FLIP_LEFT_RIGHT) + if "depth_gt" in imgs: + imgs['depth_gt'] = np.array(np.fliplr(imgs['depth_gt'])) + + results['imgs'] = imgs + return results + + +@PIPELINES.register() +class ToArray(object): + def __init__(self): + pass + + def __call__(self, results): + imgs = results['imgs'] + for k in list(imgs): + if "color" in k or "color_n" in k or "color_aug" in k or "color_n_aug" in k: + n, im, i = k + imgs[(n, im, + i)] = np.array(imgs[(n, im, i)]).astype('float32') / 255.0 + imgs[(n, im, i)] = imgs[(n, im, i)].transpose((2, 0, 1)) + if "depth_gt" in imgs: + imgs['depth_gt'] = np.array(imgs['depth_gt']).astype('float32') + + results['imgs'] = imgs + return results + + +@PIPELINES.register() +class YowoAug(object): + def __init__(self, target_size=224, jitter=0.2, hue=0.1, saturation=1.5, exposure=1.5, valid_mode=False): + self.shape = (target_size, target_size) + self.jitter = jitter + self.hue = hue + self.saturation = saturation + self.exposure = exposure + self.valid_mode = valid_mode + + def _rand_scale(self, s): + scale = random.uniform(1, s) + if (random.randint(1, 10000) % 2): + return scale + return 1. / scale + + def _distort_image(self, im, hue, sat, val): + im = im.convert('HSV') + cs = list(im.split()) + cs[1] = cs[1].point(lambda i: i * sat) + cs[2] = cs[2].point(lambda i: i * val) + + def _change_hue(x): + x += hue * 255 + if x > 255: + x -= 255 + if x < 0: + x += 255 + return x + + cs[0] = cs[0].point(_change_hue) + im = Image.merge(im.mode, tuple(cs)) + + im = im.convert('RGB') + # constrain_image(im) + return im + + def _random_distort_image(self, im, dhue, dsat, dexp): + res = self._distort_image(im, dhue, dsat, dexp) + return res + + def _read_truths_args(self, lab_path, min_box_scale): + truths = np.loadtxt(lab_path) + truths = np.reshape(truths, (truths.size // 5, 5)) + new_truths = [] + for i in range(truths.shape[0]): + cx = (truths[i][1] + truths[i][3]) / (2 * 320) + cy = (truths[i][2] + truths[i][4]) / (2 * 240) + imgw = (truths[i][3] - truths[i][1]) / 320 + imgh = (truths[i][4] - truths[i][2]) / 240 + truths[i][0] = truths[i][0] - 1 + truths[i][1] = cx + truths[i][2] = cy + truths[i][3] = imgw + truths[i][4] = imgh + + if truths[i][3] < min_box_scale: + continue + new_truths.append([truths[i][0], truths[i][1], truths[i][2], truths[i][3], truths[i][4]]) + return np.array(new_truths) + + def _fill_truth_detection(self, labpath, flip, dx, dy, sx, sy): + max_boxes = 50 + label = np.zeros((max_boxes, 5)) + bs = np.loadtxt(labpath) + bs = np.reshape(bs, (-1, 5)) + + for i in range(bs.shape[0]): + cx = (bs[i][1] + bs[i][3]) / (2 * 320) + cy = (bs[i][2] + bs[i][4]) / (2 * 240) + imgw = (bs[i][3] - bs[i][1]) / 320 + imgh = (bs[i][4] - bs[i][2]) / 240 + bs[i][0] = bs[i][0] - 1 + bs[i][1] = cx + bs[i][2] = cy + bs[i][3] = imgw + bs[i][4] = imgh + + cc = 0 + for i in range(bs.shape[0]): + x1 = bs[i][1] - bs[i][3] / 2 + y1 = bs[i][2] - bs[i][4] / 2 + x2 = bs[i][1] + bs[i][3] / 2 + y2 = bs[i][2] + bs[i][4] / 2 + + x1 = min(0.999, max(0, x1 * sx - dx)) + y1 = min(0.999, max(0, y1 * sy - dy)) + x2 = min(0.999, max(0, x2 * sx - dx)) + y2 = min(0.999, max(0, y2 * sy - dy)) + + bs[i][1] = (x1 + x2) / 2 + bs[i][2] = (y1 + y2) / 2 + bs[i][3] = (x2 - x1) + bs[i][4] = (y2 - y1) + + if flip: + bs[i][1] = 0.999 - bs[i][1] + + if bs[i][3] < 0.001 or bs[i][4] < 0.001: + continue + label[cc] = bs[i] + cc += 1 + if cc >= 50: + break + + label = np.reshape(label, (-1)) + return label + + def __call__(self, results): + clip = results['imgs'] + frame_num = len(clip) + oh = clip[0].height + ow = clip[0].width + labpath = results['filename'].replace('jpg', 'txt').replace('rgb-images', 'labels') + if not self.valid_mode: + dw = int(ow * self.jitter) + dh = int(oh * self.jitter) + + pleft = random.randint(-dw, dw) + pright = random.randint(-dw, dw) + ptop = random.randint(-dh, dh) + pbot = random.randint(-dh, dh) + + swidth = ow - pleft - pright + sheight = oh - ptop - pbot + + sx = float(swidth) / ow + sy = float(sheight) / oh + + dx = (float(pleft) / ow) / sx + dy = (float(ptop) / oh) / sy + + flip = random.randint(1, 10000) % 2 + + dhue = random.uniform(-self.hue, self.hue) + dsat = self._rand_scale(self.saturation) + dexp = self._rand_scale(self.exposure) + + # Augment + cropped = [img.crop((pleft, ptop, pleft + swidth - 1, ptop + sheight - 1)) for img in clip] + + sized = [img.resize(self.shape) for img in cropped] + + if flip: + sized = [img.transpose(Image.FLIP_LEFT_RIGHT) for img in sized] + + clip = [self._random_distort_image(img, dhue, dsat, dexp) for img in sized] + + label = self._fill_truth_detection(labpath, flip, dx, dy, 1. / sx, 1. / sy) + + else: + label = np.zeros([50 * 5]) + tmp = self._read_truths_args(labpath, 8.0 / clip[0].width).astype('float32') + tmp = np.reshape(tmp, [-1]) + tsz = tmp.size + if tsz > 50 * 5: + label = tmp[0:50 * 5] + elif tsz > 0: + label[0:tsz] = tmp + clip = [img.resize(self.shape) for img in clip] + + clip = [np.asarray(img).astype('float32') / 255.0 for img in clip] + clip = np.concatenate(clip, 0).reshape([frame_num, 224, 224, 3]) + clip = np.transpose(clip, [3, 0, 1, 2]) + results['imgs'] = clip + results['labels'] = label + return results diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/augmentations_ava.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/augmentations_ava.py new file mode 100644 index 0000000..4f0c43d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/augmentations_ava.py @@ -0,0 +1,749 @@ +# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 random +import numpy as np +import math +from PIL import Image +from ..registry import PIPELINES +from collections.abc import Sequence +import cv2 + +pillow_interp_codes = { + 'nearest': Image.NEAREST, + 'bilinear': Image.BILINEAR, + 'bicubic': Image.BICUBIC, + 'box': Image.BOX, + 'lanczos': Image.LANCZOS, + 'hamming': Image.HAMMING +} + +cv2_interp_codes = { + 'nearest': cv2.INTER_NEAREST, + 'bilinear': cv2.INTER_LINEAR, + 'bicubic': cv2.INTER_CUBIC, + 'area': cv2.INTER_AREA, + 'lanczos': cv2.INTER_LANCZOS4 +} + + +def _init_lazy_if_proper(results, lazy): + """Initialize lazy operation properly. + + Make sure that a lazy operation is properly initialized, + and avoid a non-lazy operation accidentally getting mixed in. + + Required keys in results are "imgs" if "img_shape" not in results, + otherwise, Required keys in results are "img_shape", add or modified keys + are "img_shape", "lazy". + Add or modified keys in "lazy" are "original_shape", "crop_bbox", "flip", + "flip_direction", "interpolation". + + Args: + results (dict): A dict stores data pipeline result. + lazy (bool): Determine whether to apply lazy operation. Default: False. + """ + + if 'img_shape' not in results: + results['img_shape'] = results['imgs'][0].shape[:2] + if lazy: + if 'lazy' not in results: + img_h, img_w = results['img_shape'] + lazyop = dict() + lazyop['original_shape'] = results['img_shape'] + lazyop['crop_bbox'] = np.array([0, 0, img_w, img_h], + dtype=np.float32) + lazyop['flip'] = False + lazyop['flip_direction'] = None + lazyop['interpolation'] = None + results['lazy'] = lazyop + else: + assert 'lazy' not in results, 'Use Fuse after lazy operations' + + +def _scale_size(size, scale): + """Rescale a size by a ratio. + + Args: + size (tuple[int]): (w, h). + scale (float): Scaling factor. + + Returns: + tuple[int]: scaled size. + """ + w, h = size + return int(w * float(scale) + 0.5), int(h * float(scale) + 0.5) + + +def rescale_size(old_size, scale, return_scale=False): + """Calculate the new size to be rescaled to. + + Args: + old_size (tuple[int]): The old size (w, h) of image. + scale (float | tuple[int]): The scaling factor or maximum size. + If it is a float number, then the image will be rescaled by this + factor, else if it is a tuple of 2 integers, then the image will + be rescaled as large as possible within the scale. + return_scale (bool): Whether to return the scaling factor besides the + rescaled image size. + + Returns: + tuple[int]: The new rescaled image size. + """ + w, h = old_size + if isinstance(scale, (float, int)): + if scale <= 0: + raise ValueError(f'Invalid scale {scale}, must be positive.') + scale_factor = scale + elif isinstance(scale, tuple): + max_long_edge = max(scale) + max_short_edge = min(scale) + scale_factor = min(max_long_edge / max(h, w), + max_short_edge / min(h, w)) + else: + raise TypeError( + f'Scale must be a number or tuple of int, but got {type(scale)}') + + new_size = _scale_size((w, h), scale_factor) + + if return_scale: + return new_size, scale_factor + else: + return new_size + + +def imresize(img, + size, + return_scale=False, + interpolation='bilinear', + out=None, + backend=None): + """Resize image to a given size. """ + h, w = img.shape[:2] + if backend is None: + backend = 'cv2' + if backend not in ['cv2', 'pillow']: + raise ValueError(f'backend: {backend} is not supported for resize.' + f"Supported backends are 'cv2', 'pillow'") + + if backend == 'pillow': + assert img.dtype == np.uint8, 'Pillow backend only support uint8 type' + pil_image = Image.fromarray(img) + pil_image = pil_image.resize(size, pillow_interp_codes[interpolation]) + resized_img = np.array(pil_image) + else: + resized_img = cv2.resize( + img, size, dst=out, interpolation=cv2_interp_codes[interpolation]) + if not return_scale: + return resized_img + else: + w_scale = size[0] / w + h_scale = size[1] / h + return resized_img, w_scale, h_scale + + +@PIPELINES.register() +class EntityBoxRescale: + """Rescale the entity box and proposals according to the image shape. + + Required keys are "proposals", "gt_bboxes", added or modified keys are + "gt_bboxes". If original "proposals" is not None, "proposals" and + will be added or modified. + + Args: + scale_factor (np.ndarray): The scale factor used entity_box rescaling. + """ + + def __init__(self, scale_factor): + self.scale_factor = scale_factor + + def __call__(self, results): + scale_factor = np.concatenate([self.scale_factor, self.scale_factor]) + + if 'gt_bboxes' in results: + gt_bboxes = results['gt_bboxes'] + results['gt_bboxes'] = gt_bboxes * scale_factor + + if 'proposals' in results: + proposals = results['proposals'] + if proposals is not None: + assert proposals.shape[1] == 4, ( + 'proposals shape should be in ' + f'(n, 4), but got {proposals.shape}') + results['proposals'] = proposals * scale_factor + + return results + + def __repr__(self): + return f'{self.__class__.__name__}(scale_factor={self.scale_factor})' + + +@PIPELINES.register() +class EntityBoxCrop: + """Crop the entity boxes and proposals according to the cropped images. + + Required keys are "proposals", "gt_bboxes", added or modified keys are + "gt_bboxes". If original "proposals" is not None, "proposals" will be + modified. + + Args: + crop_bbox(np.ndarray | None): The bbox used to crop the original image. + """ + + def __init__(self, crop_bbox): + self.crop_bbox = crop_bbox + + def __call__(self, results): + proposals = results['proposals'] + gt_bboxes = results['gt_bboxes'] + + if self.crop_bbox is None: + return results + + x1, y1, x2, y2 = self.crop_bbox + img_w, img_h = x2 - x1, y2 - y1 + + assert gt_bboxes.shape[-1] == 4 + gt_bboxes_ = gt_bboxes.copy() + gt_bboxes_[..., 0::2] = np.clip(gt_bboxes[..., 0::2] - x1, 0, img_w - 1) + gt_bboxes_[..., 1::2] = np.clip(gt_bboxes[..., 1::2] - y1, 0, img_h - 1) + results['gt_bboxes'] = gt_bboxes_ + + if proposals is not None: + assert proposals.shape[-1] == 4 + proposals_ = proposals.copy() + proposals_[..., 0::2] = np.clip(proposals[..., 0::2] - x1, 0, + img_w - 1) + proposals_[..., 1::2] = np.clip(proposals[..., 1::2] - y1, 0, + img_h - 1) + results['proposals'] = proposals_ + return results + + def __repr__(self): + return f'{self.__class__.__name__}(crop_bbox={self.crop_bbox})' + + +@PIPELINES.register() +class EntityBoxFlip: + """Flip the entity boxes and proposals with a probability. + + Reverse the order of elements in the given bounding boxes and proposals + with a specific direction. The shape of them are preserved, but the + elements are reordered. Only the horizontal flip is supported (seems + vertical flipping makes no sense). Required keys are "proposals", + "gt_bboxes", added or modified keys are "gt_bboxes". If "proposals" + is not None, it will also be modified. + + Args: + img_shape (tuple[int]): The img shape. + """ + + def __init__(self, img_shape): + self.img_shape = img_shape + + def __call__(self, results): + proposals = results['proposals'] + gt_bboxes = results['gt_bboxes'] + img_h, img_w = self.img_shape + + assert gt_bboxes.shape[-1] == 4 + gt_bboxes_ = gt_bboxes.copy() + gt_bboxes_[..., 0::4] = img_w - gt_bboxes[..., 2::4] - 1 + gt_bboxes_[..., 2::4] = img_w - gt_bboxes[..., 0::4] - 1 + if proposals is not None: + assert proposals.shape[-1] == 4 + proposals_ = proposals.copy() + proposals_[..., 0::4] = img_w - proposals[..., 2::4] - 1 + proposals_[..., 2::4] = img_w - proposals[..., 0::4] - 1 + else: + proposals_ = None + + results['proposals'] = proposals_ + results['gt_bboxes'] = gt_bboxes_ + + return results + + def __repr__(self): + repr_str = f'{self.__class__.__name__}(img_shape={self.img_shape})' + return repr_str + + +@PIPELINES.register() +class Resize: + """Resize images to a specific size. + + Required keys are "imgs", "img_shape", "modality", added or modified + keys are "imgs", "img_shape", "keep_ratio", "scale_factor", "lazy", + "resize_size". Required keys in "lazy" is None, added or modified key is + "interpolation". + + Args: + scale (float | Tuple[int]): If keep_ratio is True, it serves as scaling + factor or maximum size: + If it is a float number, the image will be rescaled by this + factor, else if it is a tuple of 2 integers, the image will + be rescaled as large as possible within the scale. + Otherwise, it serves as (w, h) of output size. + keep_ratio (bool): If set to True, Images will be resized without + changing the aspect ratio. Otherwise, it will resize images to a + given size. Default: True. + interpolation (str): Algorithm used for interpolation: + "nearest" | "bilinear". Default: "bilinear". + lazy (bool): Determine whether to apply lazy operation. Default: False. + """ + + def __init__(self, + scale, + keep_ratio=True, + interpolation='bilinear', + lazy=False): + if isinstance(scale, str): + scale = eval(scale) + if isinstance(scale, float): + if scale <= 0: + raise ValueError(f'Invalid scale {scale}, must be positive.') + elif isinstance(scale, tuple): + max_long_edge = max(scale) + max_short_edge = min(scale) + if max_short_edge == -1: + # assign np.inf to long edge for rescaling short edge later. + scale = (np.inf, max_long_edge) + else: + raise TypeError( + f'Scale must be float or tuple of int, but got {type(scale)}') + self.scale = scale + self.keep_ratio = keep_ratio + self.interpolation = interpolation + self.lazy = lazy + + def __call__(self, results): + """Performs the Resize augmentation. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + + _init_lazy_if_proper(results, self.lazy) + + if 'scale_factor' not in results: + results['scale_factor'] = np.array([1, 1], dtype=np.float32) + img_h, img_w = results['img_shape'] + + if self.keep_ratio: + new_w, new_h = rescale_size((img_w, img_h), self.scale) + else: + new_w, new_h = self.scale + + self.scale_factor = np.array([new_w / img_w, new_h / img_h], + dtype=np.float32) + results['img_shape'] = (new_h, new_w) + results['keep_ratio'] = self.keep_ratio + results['scale_factor'] = results['scale_factor'] * self.scale_factor + + if not self.lazy: + if 'imgs' in results: + results['imgs'] = [ + imresize( + img, (new_w, new_h), interpolation=self.interpolation) + for img in results['imgs'] + ] + if 'keypoint' in results: + results['keypoint'] = results['keypoint'] * self.scale_factor + else: + lazyop = results['lazy'] + if lazyop['flip']: + raise NotImplementedError('Put Flip at last for now') + lazyop['interpolation'] = self.interpolation + + #if 'gt_bboxes' in results: + assert not self.lazy + entity_box_rescale = EntityBoxRescale(self.scale_factor) + results = entity_box_rescale(results) + + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(' + f'scale={self.scale}, keep_ratio={self.keep_ratio}, ' + f'interpolation={self.interpolation}, ' + f'lazy={self.lazy})') + return repr_str + + +@PIPELINES.register() +class RandomRescale: + """Randomly resize images so that the short_edge is resized to a specific + size in a given range. The scale ratio is unchanged after resizing. + """ + + def __init__(self, scale_range, interpolation='bilinear'): + scale_range = eval(scale_range) + self.scale_range = scale_range + + assert len(scale_range) == 2 + assert scale_range[0] < scale_range[1] + assert np.all([x > 0 for x in scale_range]) + + self.keep_ratio = True + self.interpolation = interpolation + + def __call__(self, results): + """Performs the Resize augmentation. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + short_edge = np.random.randint(self.scale_range[0], + self.scale_range[1] + 1) + resize = Resize((-1, short_edge), + keep_ratio=True, + interpolation=self.interpolation, + lazy=False) + results = resize(results) + + results['short_edge'] = short_edge + return results + + def __repr__(self): + scale_range = self.scale_range + repr_str = (f'{self.__class__.__name__}(' + f'scale_range=({scale_range[0]}, {scale_range[1]}), ' + f'interpolation={self.interpolation})') + return repr_str + + +@PIPELINES.register() +class Rescale: + """resize images so that the short_edge is resized to a specific + size in a given range. The scale ratio is unchanged after resizing. + + Required keys are "imgs", "img_shape", "modality", added or modified + keys are "imgs", "img_shape", "keep_ratio", "scale_factor", "resize_size", + "short_edge". + + Args: + scale_range (tuple[int]): The range of short edge length. A closed + interval. + interpolation (str): Algorithm used for interpolation: + "nearest" | "bilinear". Default: "bilinear". + """ + + def __init__(self, scale_range, interpolation='bilinear'): + scale_range = eval(scale_range) + self.scale_range = scale_range + + self.keep_ratio = True + self.interpolation = interpolation + + def __call__(self, results): + """Performs the Resize augmentation. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + resize = Resize( + self.scale_range, + keep_ratio=True, + interpolation=self.interpolation, + lazy=False) + results = resize(results) + return results + + def __repr__(self): + scale_range = self.scale_range + repr_str = (f'{self.__class__.__name__}(' + f'scale_range=({scale_range[0]}, {scale_range[1]}), ' + f'interpolation={self.interpolation})') + return repr_str + + +@PIPELINES.register() +class RandomCrop_v2: + """Vanilla square random crop that specifics the output size. + + Required keys in results are "imgs" and "img_shape", added or + modified keys are "imgs", "lazy"; Required keys in "lazy" are "flip", + "crop_bbox", added or modified key is "crop_bbox". + + Args: + size (int): The output size of the images. + lazy (bool): Determine whether to apply lazy operation. Default: False. + """ + + def __init__(self, size, lazy=False): + if not isinstance(size, int): + raise TypeError(f'Size must be an int, but got {type(size)}') + self.size = size + self.lazy = lazy + + def __call__(self, results): + """Performs the RandomCrop augmentation. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + _init_lazy_if_proper(results, self.lazy) + + img_h, img_w = results['img_shape'] + assert self.size <= img_h and self.size <= img_w + + y_offset = 0 + x_offset = 0 + if img_h > self.size: + y_offset = int(np.random.randint(0, img_h - self.size)) + if img_w > self.size: + x_offset = int(np.random.randint(0, img_w - self.size)) + if 'crop_quadruple' not in results: + results['crop_quadruple'] = np.array( + [0, 0, 1, 1], # x, y, w, h + dtype=np.float32) + + x_ratio, y_ratio = x_offset / img_w, y_offset / img_h + w_ratio, h_ratio = self.size / img_w, self.size / img_h + + old_crop_quadruple = results['crop_quadruple'] + old_x_ratio, old_y_ratio = old_crop_quadruple[0], old_crop_quadruple[1] + old_w_ratio, old_h_ratio = old_crop_quadruple[2], old_crop_quadruple[3] + new_crop_quadruple = [ + old_x_ratio + x_ratio * old_w_ratio, + old_y_ratio + y_ratio * old_h_ratio, w_ratio * old_w_ratio, + h_ratio * old_x_ratio + ] + results['crop_quadruple'] = np.array( + new_crop_quadruple, dtype=np.float32) + + new_h, new_w = self.size, self.size + + results['crop_bbox'] = np.array( + [x_offset, y_offset, x_offset + new_w, y_offset + new_h]) + results['img_shape'] = (new_h, new_w) + + if not self.lazy: + results['imgs'] = [ + img[y_offset:y_offset + new_h, x_offset:x_offset + new_w] + for img in results['imgs'] + ] + else: + lazyop = results['lazy'] + if lazyop['flip']: + raise NotImplementedError('Put Flip at last for now') + + # record crop_bbox in lazyop dict to ensure only crop once in Fuse + lazy_left, lazy_top, lazy_right, lazy_bottom = lazyop['crop_bbox'] + left = x_offset * (lazy_right - lazy_left) / img_w + right = (x_offset + new_w) * (lazy_right - lazy_left) / img_w + top = y_offset * (lazy_bottom - lazy_top) / img_h + bottom = (y_offset + new_h) * (lazy_bottom - lazy_top) / img_h + lazyop['crop_bbox'] = np.array( + [(lazy_left + left), (lazy_top + top), (lazy_left + right), + (lazy_top + bottom)], + dtype=np.float32) + + # Process entity boxes + if 'gt_bboxes' in results: + assert not self.lazy + entity_box_crop = EntityBoxCrop(results['crop_bbox']) + results = entity_box_crop(results) + + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(size={self.size}, ' + f'lazy={self.lazy})') + return repr_str + + +def imflip_(img, direction='horizontal'): + """Inplace flip an image horizontally or vertically. + + Args: + img (ndarray): Image to be flipped. + direction (str): The flip direction, either "horizontal" or + "vertical" or "diagonal". + + Returns: + ndarray: The flipped image (inplace). + """ + assert direction in ['horizontal', 'vertical', 'diagonal'] + if direction == 'horizontal': + return cv2.flip(img, 1, img) + elif direction == 'vertical': + return cv2.flip(img, 0, img) + else: + return cv2.flip(img, -1, img) + + +def iminvert(img): + """Invert (negate) an image. + + Args: + img (ndarray): Image to be inverted. + + Returns: + ndarray: The inverted image. + """ + return np.full_like(img, 255) - img + + +@PIPELINES.register() +class Flip: + """Flip the input images with a probability. + + Reverse the order of elements in the given imgs with a specific direction. + The shape of the imgs is preserved, but the elements are reordered. + Required keys are "imgs", "img_shape", "modality", added or modified + keys are "imgs", "lazy" and "flip_direction". Required keys in "lazy" is + None, added or modified key are "flip" and "flip_direction". The Flip + augmentation should be placed after any cropping / reshaping augmentations, + to make sure crop_quadruple is calculated properly. + + Args: + flip_ratio (float): Probability of implementing flip. Default: 0.5. + direction (str): Flip imgs horizontally or vertically. Options are + "horizontal" | "vertical". Default: "horizontal". + lazy (bool): Determine whether to apply lazy operation. Default: False. + """ + _directions = ['horizontal', 'vertical'] + + def __init__(self, flip_ratio=0.5, direction='horizontal', lazy=False): + if direction not in self._directions: + raise ValueError(f'Direction {direction} is not supported. ' + f'Currently support ones are {self._directions}') + self.flip_ratio = flip_ratio + self.direction = direction + self.lazy = lazy + + def __call__(self, results): + """Performs the Flip augmentation. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + _init_lazy_if_proper(results, self.lazy) + flip = np.random.rand() < self.flip_ratio + + results['flip'] = flip + results['flip_direction'] = self.direction + + if not self.lazy: + if flip: + for i, img in enumerate(results['imgs']): + imflip_(img, self.direction) + lt = len(results['imgs']) + else: + results['imgs'] = list(results['imgs']) + else: + lazyop = results['lazy'] + if lazyop['flip']: + raise NotImplementedError('Use one Flip please') + lazyop['flip'] = flip + lazyop['flip_direction'] = self.direction + + if 'gt_bboxes' in results and flip: + assert not self.lazy and self.direction == 'horizontal' + entity_box_flip = EntityBoxFlip(results['img_shape']) + results = entity_box_flip(results) + + return results + + def __repr__(self): + repr_str = ( + f'{self.__class__.__name__}(' + f'flip_ratio={self.flip_ratio}, direction={self.direction}, ' + f'lazy={self.lazy})') + return repr_str + + +def imnormalize_(img, mean, std, to_rgb=True): + """Inplace normalize an image with mean and std. + + Args: + img (ndarray): Image to be normalized. + mean (ndarray): The mean to be used for normalize. + std (ndarray): The std to be used for normalize. + to_rgb (bool): Whether to convert to rgb. + + Returns: + ndarray: The normalized image. + """ + # cv2 inplace normalization does not accept uint8 + assert img.dtype != np.uint8 + mean = np.float64(mean.reshape(1, -1)) + stdinv = 1 / np.float64(std.reshape(1, -1)) + if to_rgb: + cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img) # inplace + cv2.subtract(img, mean, img) # inplace + cv2.multiply(img, stdinv, img) # inplace + return img + + +@PIPELINES.register() +class Normalize: + """Normalize images with the given mean and std value. + + Required keys are "imgs", "img_shape", "modality", added or modified + keys are "imgs" and "img_norm_cfg". If modality is 'Flow', additional + keys "scale_factor" is required + + Args: + mean (Sequence[float]): Mean values of different channels. + std (Sequence[float]): Std values of different channels. + to_bgr (bool): Whether to convert channels from RGB to BGR. + Default: False. + adjust_magnitude (bool): Indicate whether to adjust the flow magnitude + on 'scale_factor' when modality is 'Flow'. Default: False. + """ + + def __init__(self, mean, std, to_bgr=False, adjust_magnitude=False): + if not isinstance(mean, Sequence): + raise TypeError( + f'Mean must be list, tuple or np.ndarray, but got {type(mean)}') + + if not isinstance(std, Sequence): + raise TypeError( + f'Std must be list, tuple or np.ndarray, but got {type(std)}') + + self.mean = np.array(mean, dtype=np.float32) + self.std = np.array(std, dtype=np.float32) + self.to_bgr = to_bgr + self.adjust_magnitude = adjust_magnitude + + def __call__(self, results): + n = len(results['imgs']) + h, w, c = results['imgs'][0].shape + imgs = np.empty((n, h, w, c), dtype=np.float32) + for i, img in enumerate(results['imgs']): + imgs[i] = img + + for img in imgs: + imnormalize_(img, self.mean, self.std, self.to_bgr) + + results['imgs'] = imgs + results['img_norm_cfg'] = dict( + mean=self.mean, std=self.std, to_bgr=self.to_bgr) + + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(' + f'mean={self.mean}, ' + f'std={self.std}, ' + f'to_bgr={self.to_bgr}, ' + f'adjust_magnitude={self.adjust_magnitude})') + return repr_str diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/compose.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/compose.py new file mode 100644 index 0000000..76eb4ed --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/compose.py @@ -0,0 +1,76 @@ +# 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. + +from collections.abc import Sequence +from ..registry import PIPELINES +import traceback +from ...utils import build +from ...utils import get_logger + + +@PIPELINES.register() +class Compose(object): + """ + Composes several pipelines(include decode func, sample func, and transforms) together. + + Note: To deal with ```list``` type cfg temporaray, like: + + transform: + - Crop: # A list + attribute: 10 + - Resize: # A list + attribute: 20 + + every key of list will pass as the key name to build a module. + XXX: will be improved in the future. + + Args: + pipelines (list): List of transforms to compose. + Returns: + A compose object which is callable, __call__ for this Compose + object will call each given :attr:`transforms` sequencely. + """ + def __init__(self, pipelines): + #assert isinstance(pipelines, Sequence) + self.pipelines = [] + for p in pipelines.values(): + if isinstance(p, dict): + p = build(p, PIPELINES) + self.pipelines.append(p) + elif isinstance(p, list): + for t in p: + #XXX: to deal with old format cfg, ugly code here! + temp_dict = dict(name=list(t.keys())[0]) + for all_sub_t in t.values(): + if all_sub_t is not None: + temp_dict.update(all_sub_t) + + t = build(temp_dict, PIPELINES) + self.pipelines.append(t) + elif callable(p): + self.pipelines.append(p) + else: + raise TypeError(f'pipelines must be callable or a dict,' + f'but got {type(p)}') + def __call__(self, data): + for p in self.pipelines: + try: + data = p(data) + except Exception as e: + stack_info = traceback.format_exc() + logger = get_logger("paddlevideo") + logger.info("fail to perform transform [{}] with error: " + "{} and stack:\n{}".format(p, e, str(stack_info))) + raise e + return data diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode.py new file mode 100644 index 0000000..2611272 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode.py @@ -0,0 +1,348 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +try: + import av +except ImportError as e: + print( + f"Warning! {e}, [av] package and it's dependencies is required for TimeSformer and other models." + ) +import cv2 +import pickle +import decord as de +import math +import random +from ..registry import PIPELINES + + +def get_start_end_idx(video_size, clip_size, clip_idx, num_clips): + delta = max(video_size - clip_size, 0) + if clip_idx == -1: # here + # Random temporal sampling. + start_idx = random.uniform(0, delta) + else: # ignore + # Uniformly sample the clip with the given index. + start_idx = delta * clip_idx / num_clips + end_idx = start_idx + clip_size - 1 + return start_idx, end_idx + + +@PIPELINES.register() +class VideoDecoder(object): + """ + Decode mp4 file to frames. + Args: + filepath: the file path of mp4 file + """ + def __init__(self, + backend='cv2', + mode='train', + sampling_rate=32, + num_seg=8, + num_clips=1, + target_fps=30): + + self.backend = backend + # params below only for TimeSformer + self.mode = mode + self.sampling_rate = sampling_rate + self.num_seg = num_seg + self.num_clips = num_clips + self.target_fps = target_fps + + def __call__(self, results): + """ + Perform mp4 decode operations. + return: + List where each item is a numpy array after decoder. + """ + file_path = results['filename'] + results['format'] = 'video' + results['backend'] = self.backend + + if self.backend == 'cv2': + cap = cv2.VideoCapture(file_path) + videolen = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) + sampledFrames = [] + for i in range(videolen): + ret, frame = cap.read() + # maybe first frame is empty + if ret == False: + continue + img = frame[:, :, ::-1] + sampledFrames.append(img) + results['frames'] = sampledFrames + results['frames_len'] = len(sampledFrames) + + elif self.backend == 'decord': + container = de.VideoReader(file_path) + frames_len = len(container) + results['frames'] = container + results['frames_len'] = frames_len + + elif self.backend == 'pyav': # for TimeSformer + if self.mode in ["train", "valid"]: + clip_idx = -1 + elif self.mode in ["test"]: + clip_idx = 0 + else: + raise NotImplementedError + + container = av.open(file_path) + + num_clips = 1 # always be 1 + + # decode process + fps = float(container.streams.video[0].average_rate) + + frames_length = container.streams.video[0].frames + duration = container.streams.video[0].duration + + if duration is None: + # If failed to fetch the decoding information, decode the entire video. + decode_all_video = True + video_start_pts, video_end_pts = 0, math.inf + else: + decode_all_video = False + start_idx, end_idx = get_start_end_idx( + frames_length, + self.sampling_rate * self.num_seg / self.target_fps * fps, + clip_idx, num_clips) + timebase = duration / frames_length + video_start_pts = int(start_idx * timebase) + video_end_pts = int(end_idx * timebase) + + frames = None + # If video stream was found, fetch video frames from the video. + if container.streams.video: + margin = 1024 + seek_offset = max(video_start_pts - margin, 0) + + container.seek(seek_offset, + any_frame=False, + backward=True, + stream=container.streams.video[0]) + tmp_frames = {} + buffer_count = 0 + max_pts = 0 + for frame in container.decode(**{"video": 0}): + max_pts = max(max_pts, frame.pts) + if frame.pts < video_start_pts: + continue + if frame.pts <= video_end_pts: + tmp_frames[frame.pts] = frame + else: + buffer_count += 1 + tmp_frames[frame.pts] = frame + if buffer_count >= 0: + break + video_frames = [tmp_frames[pts] for pts in sorted(tmp_frames)] + + container.close() + + frames = [frame.to_rgb().to_ndarray() for frame in video_frames] + clip_sz = self.sampling_rate * self.num_seg / self.target_fps * fps + + start_idx, end_idx = get_start_end_idx( + len(frames), # frame_len + clip_sz, + clip_idx if decode_all_video else + 0, # If decode all video, -1 in train and valid, 0 in test; + # else, always 0 in train, valid and test, as we has selected clip size frames when decode. + 1) + results['frames'] = frames + results['frames_len'] = len(frames) + results['start_idx'] = start_idx + results['end_idx'] = end_idx + else: + raise NotImplementedError + # pass + return results + + +@PIPELINES.register() +class FrameDecoder(object): + """just parse results + """ + def __init__(self): + pass + + def __call__(self, results): + results['format'] = 'frame' + return results + + +@PIPELINES.register() +class MRIDecoder(object): + """just parse results + """ + def __init__(self): + pass + + def __call__(self, results): + results['format'] = 'MRI' + return results + + +@PIPELINES.register() +class FeatureDecoder(object): + """ + Perform feature decode operations.e.g.youtube8m + """ + def __init__(self, num_classes, max_len=512, has_label=True): + self.max_len = max_len + self.num_classes = num_classes + self.has_label = has_label + + def __call__(self, results): + """ + Perform feature decode operations. + return: + List where each item is a numpy array after decoder. + """ + #1. load pkl + #2. parse to rgb/audio/ + #3. padding + + filepath = results['filename'] + data = pickle.load(open(filepath, 'rb'), encoding='bytes') + + record = data + nframes = record['nframes'] if 'nframes' in record else record[ + b'nframes'] + rgb = record['feature'].astype( + float) if 'feature' in record else record[b'feature'].astype(float) + audio = record['audio'].astype( + float) if 'audio' in record else record[b'audio'].astype(float) + if self.has_label: + label = record['label'] if 'label' in record else record[b'label'] + one_hot_label = self.make_one_hot(label, self.num_classes) + + rgb = rgb[0:nframes, :] + audio = audio[0:nframes, :] + + rgb = self.dequantize(rgb, + max_quantized_value=2., + min_quantized_value=-2.) + audio = self.dequantize(audio, + max_quantized_value=2, + min_quantized_value=-2) + + if self.has_label: + results['labels'] = one_hot_label.astype("float32") + + feat_pad_list = [] + feat_len_list = [] + mask_list = [] + vitem = [rgb, audio] + for vi in range(2): #rgb and audio + if vi == 0: + prefix = "rgb_" + else: + prefix = "audio_" + feat = vitem[vi] + results[prefix + 'len'] = feat.shape[0] + #feat pad step 1. padding + feat_add = np.zeros((self.max_len - feat.shape[0], feat.shape[1]), + dtype=np.float32) + feat_pad = np.concatenate((feat, feat_add), axis=0) + results[prefix + 'data'] = feat_pad.astype("float32") + #feat pad step 2. mask + feat_mask_origin = np.ones(feat.shape, dtype=np.float32) + feat_mask_add = feat_add + feat_mask = np.concatenate((feat_mask_origin, feat_mask_add), + axis=0) + results[prefix + 'mask'] = feat_mask.astype("float32") + + return results + + def dequantize(self, + feat_vector, + max_quantized_value=2., + min_quantized_value=-2.): + """ + Dequantize the feature from the byte format to the float format + """ + + assert max_quantized_value > min_quantized_value + quantized_range = max_quantized_value - min_quantized_value + scalar = quantized_range / 255.0 + bias = (quantized_range / 512.0) + min_quantized_value + + return feat_vector * scalar + bias + + def make_one_hot(self, label, dim=3862): + one_hot_label = np.zeros(dim) + one_hot_label = one_hot_label.astype(float) + for ind in label: + one_hot_label[int(ind)] = 1 + return one_hot_label + + +@PIPELINES.register() +class ActionFeatureDecoder(object): + """ + Perform feature decode operations on footballaction + """ + def __init__(self, num_classes, max_len=512, has_label=True): + self.max_len = max_len + self.num_classes = num_classes + self.has_label = has_label + + def __call__(self, results): + """ + Perform feature decode operations. + return: + List where each item is a numpy array after decoder. + """ + #1. load pkl + #2. parse to rgb/audio/ + #3. padding + + filepath = results['filename'] + data = pickle.load(open(filepath, 'rb'), encoding='bytes') + + pkl_data = data + rgb = pkl_data['image_feature'].astype(float) + audio = pkl_data['audio_feature'].astype(float) + label_id_info = pkl_data['label_info'] + label_cls = [label_id_info['label']] + label_one = int(label_cls[0]) + if len(label_cls) > 1: + label_index = random.randint(0, 1) + label_one = int(label_cls[label_index]) + iou_norm = float(label_id_info['norm_iou']) + results['labels'] = np.array([label_one]) + results['iou_norm'] = float(iou_norm) + + vitem = [rgb, audio] + for vi in range(2): #rgb and audio + if vi == 0: + prefix = "rgb_" + else: + prefix = "audio_" + feat = vitem[vi] + results[prefix + 'len'] = feat.shape[0] + #feat pad step 1. padding + feat_add = np.zeros((self.max_len - feat.shape[0], feat.shape[1]), + dtype=np.float32) + feat_pad = np.concatenate((feat, feat_add), axis=0) + results[prefix + 'data'] = feat_pad.astype("float32") + #feat pad step 2. mask + feat_mask_origin = np.ones(feat.shape, dtype=np.float32) + feat_mask = np.concatenate((feat_mask_origin, feat_add), axis=0) + results[prefix + 'mask'] = feat_mask.astype("float32") + + return results diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_image.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_image.py new file mode 100644 index 0000000..64a7e2f --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_image.py @@ -0,0 +1,206 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +import PIL.Image as pil + +try: + import skimage.transform +except ImportError as e: + print( + f"Warning! {e}, [scikit-image] package and it's dependencies is required for ADDS." + ) +from PIL import Image + +from ..registry import PIPELINES + + +@PIPELINES.register() +class ImageDecoder(object): + """Decode Image + """ + def __init__(self, + dataset, + frame_idxs, + num_scales, + side_map, + full_res_shape, + img_ext, + backend='cv2'): + self.backend = backend + self.dataset = dataset + self.frame_idxs = frame_idxs + self.num_scales = num_scales + self.side_map = side_map + self.full_res_shape = full_res_shape + self.img_ext = img_ext + + def _pil_loader(self, path): + with open(path, 'rb') as f: + with Image.open(f) as img: + return img.convert('RGB') + + def get_color(self, folder, frame_index, side): + color = self._pil_loader( + self.get_image_path(self.dataset, folder, frame_index, side)) + return color + + def get_image_path(self, dataset, folder, frame_index, side): + if dataset == "kitti": + f_str = "{:010d}{}".format(frame_index, self.img_ext) + image_path = os.path.join(self.data_path, folder, f_str) + elif dataset == "kitti_odom": + f_str = "{:06d}{}".format(frame_index, self.img_ext) + image_path = os.path.join(self.data_path, + "sequences/{:02d}".format(int(folder)), + "image_{}".format(self.side_map[side]), + f_str) + elif dataset == "kitti_depth": + f_str = "{:010d}{}".format(frame_index, self.img_ext) + image_path = os.path.join( + self.data_path, folder, + "image_0{}/data".format(self.side_map[side]), f_str) + + return image_path + + def get_depth(self, dataset, folder, frame_index, side): + if dataset == "kitii_depth": + f_str = "{:010d}.png".format(frame_index) + depth_path = os.path.join( + self.data_path, folder, + "proj_depth/groundtruth/image_0{}".format(self.side_map[side]), + f_str) + + depth_gt = pil.open(depth_path) + depth_gt = depth_gt.resize(self.full_res_shape, pil.NEAREST) + depth_gt = np.array(depth_gt).astype(np.float32) / 256 + + else: + f_str = "{:010d}{}".format(frame_index, self.img_ext) + depth_path = os.path.join(self.data_path, folder + '_gt', f_str) + + img_file = Image.open(depth_path) + depth_png = np.array(img_file, dtype=int) + img_file.close() + # make sure we have a proper 16bit depth map here.. not 8bit! + assert np.max(depth_png) > 255, \ + "np.max(depth_png)={}, path={}".format(np.max(depth_png), depth_path) + + depth_gt = depth_png.astype(np.float) / 256. + + depth_gt = depth_gt[160:960 - 160, :] + + depth_gt = skimage.transform.resize(depth_gt, + self.full_res_shape[::-1], + order=0, + preserve_range=True, + mode='constant') + + return depth_gt + + def __call__(self, results): + """ + Perform mp4 decode operations. + return: + List where each item is a numpy array after decoder. + """ + if results.get('mode', None) == 'infer': + imgs = {} + imgs[("color", 0, + -1)] = Image.open(results["filename"]).convert("RGB") + results['imgs'] = imgs + return results + + self.data_path = results['data_path'] + results['backend'] = self.backend + + imgs = {} + + results['frame_idxs'] = self.frame_idxs + results['num_scales'] = self.num_scales + + file_name = results['filename'] + folder = results['folder'] + frame_index = results['frame_index'] + line = file_name.split('/') + istrain = folder.split('_')[1] + if 'mode' not in results: + results['mode'] = istrain + results['day_or_night'] = folder.split('_')[0] + + if istrain == "train": + if folder[0] == 'd': + folder2 = folder + '_fake_night' + flag = 0 + else: + folder2 = folder + '_fake_day' + tmp = folder + folder = folder2 + folder2 = tmp + flag = 1 + + if len(line) == 3: + side = line[2] + else: + side = None + + results['side'] = side + + for i in self.frame_idxs: + + if i == "s": + other_side = {"r": "l", "l": "r"}[side] + imgs[("color", i, + -1)] = self.get_color(folder, frame_index, other_side) + imgs[("color_n", i, + -1)] = self.get_color(folder2, frame_index, + other_side) + else: + imgs[("color", i, + -1)] = self.get_color(folder, frame_index + i, side) + imgs[("color_n", i, + -1)] = self.get_color(folder2, frame_index + i, side) + + istrain = folder.split('_')[1] + if istrain != 'train': + if flag: + depth_gt = self.get_depth(folder2, frame_index, side) + else: + depth_gt = self.get_depth(folder, frame_index, side) + imgs["depth_gt"] = np.expand_dims(depth_gt, 0) + elif istrain == 'val': + if len(line) == 3: + side = line[2] + else: + side = None + + for i in self.frame_idxs: + if i == "s": + other_side = {"r": "l", "l": "r"}[side] + imgs[("color", i, + -1)] = self.get_color(folder, frame_index, other_side) + else: + + imgs[("color", i, + -1)] = self.get_color(folder, frame_index + i, side) + + # adjusting intrinsics to match each scale in the pyramid + + depth_gt = self.get_depth(self.dataset, folder, frame_index, side) + imgs["depth_gt"] = np.expand_dims(depth_gt, 0) + results['imgs'] = imgs + + return results diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_sampler.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_sampler.py new file mode 100644 index 0000000..12a8f76 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_sampler.py @@ -0,0 +1,93 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 random +import numpy as np +from PIL import Image +import decord as de +from ..registry import PIPELINES + + +@PIPELINES.register() +class DecodeSampler(object): + """ + We use 'decord' for decode and sampling, which is faster than opencv. + This is used in slowfast model. + Args: + num_frames(int): the number of frames we want to sample. + sampling_rate(int): sampling rate for video data. + target_fps(int): desired fps, default 30 + test_mode(bool): whether test or train/valid. In slowfast, we use multicrop when test. + """ + def __init__(self, + num_frames, + sampling_rate, + default_sampling_rate=2, + target_fps=30, + test_mode=False): + self.num_frames = num_frames + self.orig_sampling_rate = self.sampling_rate = sampling_rate + self.default_sampling_rate = default_sampling_rate + self.target_fps = target_fps + self.test_mode = test_mode + + def get_start_end_idx(self, video_size, clip_size, clip_idx, + temporal_num_clips): + delta = max(video_size - clip_size, 0) + if not self.test_mode: + # Random temporal sampling. + start_idx = random.uniform(0, delta) + else: + # Uniformly sample the clip with the given index. + start_idx = delta * clip_idx / temporal_num_clips + end_idx = start_idx + clip_size - 1 + return start_idx, end_idx + + def __call__(self, results): + """ + Perform mp4 decode operations. + return: + List where each item is a numpy array after decoder. + """ + short_cycle_idx = results.get('short_cycle_idx') + if short_cycle_idx: + self.sampling_rate = random.randint(self.default_sampling_rate, + self.orig_sampling_rate) + + filepath = results['filename'] + temporal_sample_index = results['temporal_sample_index'] + temporal_num_clips = results['temporal_num_clips'] + + vr = de.VideoReader(filepath) + videolen = len(vr) + + # fps = vr.get_avg_fps() + clip_size = self.num_frames * self.sampling_rate * fps / self.target_fps + + start_idx, end_idx = self.get_start_end_idx(videolen, clip_size, + temporal_sample_index, + temporal_num_clips) + index = np.linspace(start_idx, end_idx, self.num_frames).astype("int64") + index = np.clip(index, 0, videolen) + + frames_select = vr.get_batch(index) #1 for buffer + + # dearray_to_img + np_frames = frames_select.asnumpy() + frames_select_list = [] + for i in range(np_frames.shape[0]): + imgbuf = np_frames[i] + frames_select_list.append(Image.fromarray(imgbuf, mode='RGB')) + results['imgs'] = frames_select_list + return results diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_sampler_MRI.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_sampler_MRI.py new file mode 100644 index 0000000..08d1dd0 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/decode_sampler_MRI.py @@ -0,0 +1,224 @@ +# 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 random + +import numpy as np +from PIL import Image +try: + import SimpleITK as sitk +except ImportError as e: + print( + f"Warning! {e}, [SimpleITK] package and it's dependencies is required for PP-Care." + ) +import cv2 + +from ..registry import PIPELINES + + +@PIPELINES.register() +class SFMRI_DecodeSampler(object): + """ + Sample frames id. + NOTE: Use PIL to read image here, has diff with CV2 + Args: + num_seg(int): number of segments. + seg_len(int): number of sampled frames in each segment. + valid_mode(bool): True or False. + select_left: Whether to select the frame to the left in the middle when the sampling interval is even in the test mode. + Returns: + frames_idx: the index of sampled #frames. + """ + def __init__(self, + num_seg, + seg_len, + valid_mode=False, + select_left=False, + dense_sample=False, + linspace_sample=False): + self.num_seg = num_seg + self.seg_len = seg_len + self.valid_mode = valid_mode + self.select_left = select_left + self.dense_sample = dense_sample + self.linspace_sample = linspace_sample + + def _get(self, frames_idx_s, frames_idx_f, results): + + frame_dir = results['frame_dir'] + imgs_s = [] + imgs_f = [] + MRI = sitk.GetArrayFromImage(sitk.ReadImage(frame_dir)) + for idx in frames_idx_s: + item = MRI[idx] + item = cv2.resize(item, (224, 224)) + imgs_s.append(item) + + for idx in frames_idx_f: + item = MRI[idx] + item = cv2.resize(item, (224, 224)) + imgs_f.append(item) + + results['imgs'] = [imgs_s, imgs_f] + return results + + def __call__(self, results): + """ + Args: + frames_len: length of frames. + return: + sampling id. + """ + frames_len = int(results['frames_len']) + average_dur1 = int(frames_len / self.num_seg[0]) + average_dur2 = int(frames_len / self.num_seg[1]) + frames_idx_s = [] + frames_idx_f = [] + if self.linspace_sample: + if 'start_idx' in results and 'end_idx' in results: + offsets_s = np.linspace(results['start_idx'], + results['end_idx'], self.num_seg[0]) + offsets_f = np.linspace(results['start_idx'], + results['end_idx'], self.num_seg[1]) + else: + offsets_s = np.linspace(0, frames_len - 1, self.num_seg[0]) + offsets_f = np.linspace(0, frames_len - 1, self.num_seg[1]) + offsets_s = np.clip(offsets_s, 0, frames_len - 1).astype(np.int64) + offsets_f = np.clip(offsets_f, 0, frames_len - 1).astype(np.int64) + + frames_idx_s = list(offsets_s) + frames_idx_f = list(offsets_f) + + return self._get(frames_idx_s, frames_idx_f, results) + + if not self.select_left: + if self.dense_sample: # For ppTSM + if not self.valid_mode: # train + sample_pos = max(1, 1 + frames_len - 64) + t_stride1 = 64 // self.num_seg[0] + t_stride2 = 64 // self.num_seg[1] + start_idx = 0 if sample_pos == 1 else np.random.randint( + 0, sample_pos - 1) + offsets_s = [(idx * t_stride1 + start_idx) % frames_len + 1 + for idx in range(self.num_seg[0])] + offsets_f = [(idx * t_stride2 + start_idx) % frames_len + 1 + for idx in range(self.num_seg[1])] + frames_idx_s = offsets_s + frames_idx_f = offsets_f + else: + sample_pos = max(1, 1 + frames_len - 64) + t_stride1 = 64 // self.num_seg[0] + t_stride2 = 64 // self.num_seg[1] + start_list = np.linspace(0, + sample_pos - 1, + num=10, + dtype=int) + offsets_s = [] + offsets_f = [] + for start_idx in start_list.tolist(): + offsets_s += [ + (idx * t_stride1 + start_idx) % frames_len + 1 + for idx in range(self.num_seg[0]) + ] + for start_idx in start_list.tolist(): + offsets_f += [ + (idx * t_stride2 + start_idx) % frames_len + 1 + for idx in range(self.num_seg[1]) + ] + frames_idx_s = offsets_s + frames_idx_f = offsets_f + else: + for i in range(self.num_seg[0]): + idx = 0 + if not self.valid_mode: + if average_dur1 >= self.seg_len: + idx = random.randint(0, average_dur1 - self.seg_len) + idx += i * average_dur1 + elif average_dur1 >= 1: + idx += i * average_dur1 + else: + idx = i + else: + if average_dur1 >= self.seg_len: + idx = (average_dur1 - 1) // 2 + idx += i * average_dur1 + elif average_dur1 >= 1: + idx += i * average_dur1 + else: + idx = i + for jj in range(idx, idx + self.seg_len): + frames_idx_s.append(jj) + + for i in range(self.num_seg[1]): + idx = 0 + if not self.valid_mode: + if average_dur2 >= self.seg_len: + idx = random.randint(0, average_dur2 - self.seg_len) + idx += i * average_dur2 + elif average_dur2 >= 1: + idx += i * average_dur2 + else: + idx = i + else: + if average_dur2 >= self.seg_len: + idx = (average_dur2 - 1) // 2 + idx += i * average_dur2 + elif average_dur2 >= 1: + idx += i * average_dur2 + else: + idx = i + for jj in range(idx, idx + self.seg_len): + frames_idx_f.append(jj) + + return self._get(frames_idx_s, frames_idx_f, results) + + else: # for TSM + if not self.valid_mode: + if average_dur2 > 0: + offsets_s = np.multiply(list(range( + self.num_seg[0])), average_dur1) + np.random.randint( + average_dur1, size=self.num_seg[0]) + + offsets_f = np.multiply(list(range( + self.num_seg[1])), average_dur2) + np.random.randint( + average_dur2, size=self.num_seg[1]) + elif frames_len > self.num_seg[1]: + offsets_s = np.sort( + np.random.randint(frames_len, size=self.num_seg[0])) + offsets_f = np.sort( + np.random.randint(frames_len, size=self.num_seg[1])) + else: + offsets_s = np.zeros(shape=(self.num_seg[0], )) + offsets_f = np.zeros(shape=(self.num_seg[1], )) + else: + if frames_len > self.num_seg[1]: + average_dur_float_s = frames_len / self.num_seg[0] + offsets_s = np.array([ + int(average_dur_float_s / 2.0 + average_dur_float_s * x) + for x in range(self.num_seg[0]) + ]) + average_dur_float_f = frames_len / self.num_seg[1] + offsets_f = np.array([ + int(average_dur_float_f / 2.0 + average_dur_float_f * x) + for x in range(self.num_seg[1]) + ]) + else: + offsets_s = np.zeros(shape=(self.num_seg[0], )) + offsets_f = np.zeros(shape=(self.num_seg[1], )) + + frames_idx_s = list(offsets_s) + frames_idx_f = list(offsets_f) + + return self._get(frames_idx_s, frames_idx_f, results) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/mix.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/mix.py new file mode 100644 index 0000000..ccc5f98 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/mix.py @@ -0,0 +1,116 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np + +from ..registry import PIPELINES + + +@PIPELINES.register() +class Mixup(object): + """ + Mixup operator. + Args: + alpha(float): alpha value. + """ + def __init__(self, alpha=0.2): + assert alpha > 0., \ + 'parameter alpha[%f] should > 0.0' % (alpha) + self.alpha = alpha + + def __call__(self, batch): + imgs, labels = list(zip(*batch)) + imgs = np.array(imgs) + labels = np.array(labels) + bs = len(batch) + idx = np.random.permutation(bs) + lam = np.random.beta(self.alpha, self.alpha) + lams = np.array([lam] * bs, dtype=np.float32) + imgs = lam * imgs + (1 - lam) * imgs[idx] + return list(zip(imgs, labels, labels[idx], lams)) + + +@PIPELINES.register() +class Cutmix(object): + """ Cutmix operator + Args: + alpha(float): alpha value. + """ + def __init__(self, alpha=0.2): + assert alpha > 0., \ + 'parameter alpha[%f] should > 0.0' % (alpha) + self.alpha = alpha + + def rand_bbox(self, size, lam): + """ rand_bbox """ + w = size[2] + h = size[3] + cut_rat = np.sqrt(1. - lam) + cut_w = np.int(w * cut_rat) + cut_h = np.int(h * cut_rat) + + # uniform + cx = np.random.randint(w) + cy = np.random.randint(h) + + bbx1 = np.clip(cx - cut_w // 2, 0, w) + bby1 = np.clip(cy - cut_h // 2, 0, h) + bbx2 = np.clip(cx + cut_w // 2, 0, w) + bby2 = np.clip(cy + cut_h // 2, 0, h) + + return bbx1, bby1, bbx2, bby2 + + def __call__(self, batch): + imgs, labels = list(zip(*batch)) + imgs = np.array(imgs) + labels = np.array(labels) + + bs = len(batch) + idx = np.random.permutation(bs) + lam = np.random.beta(self.alpha, self.alpha) + + bbx1, bby1, bbx2, bby2 = self.rand_bbox(imgs.shape, lam) + imgs[:, :, bbx1:bbx2, bby1:bby2] = imgs[idx, :, bbx1:bbx2, bby1:bby2] + lam = 1 - (float(bbx2 - bbx1) * (bby2 - bby1) / + (imgs.shape[-2] * imgs.shape[-1])) + lams = np.array([lam] * bs, dtype=np.float32) + + return list(zip(imgs, labels, labels[idx], lams)) + + +@PIPELINES.register() +class VideoMix(object): + """ + VideoMix operator. + Args: + cutmix_prob(float): prob choose cutmix + mixup_alpha(float): alpha for mixup aug + cutmix_alpha(float): alpha for cutmix aug + """ + def __init__(self, cutmix_prob=0.5, mixup_alpha=0.2, cutmix_alpha=1.0): + assert cutmix_prob > 0., \ + 'parameter cutmix_prob[%f] should > 0.0' % (cutmix_prob) + assert mixup_alpha > 0., \ + 'parameter mixup_alpha[%f] should > 0.0' % (mixup_alpha) + assert cutmix_alpha > 0., \ + 'parameter cutmix_alpha[%f] should > 0.0' % (cutmix_alpha) + self.cutmix_prob = cutmix_prob + self.mixup = Mixup(mixup_alpha) + self.cutmix = Cutmix(cutmix_alpha) + + def __call__(self, batch): + if np.random.random() < self.cutmix_prob: + return self.cutmix(batch) + else: + return self.mixup(batch) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/multimodal.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/multimodal.py new file mode 100644 index 0000000..39ced5d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/multimodal.py @@ -0,0 +1,380 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 random +import numpy as np +from PIL import Image +# import decord as de +import copy +import json +from ..registry import PIPELINES + +try: + from paddlenlp.transformers import BertTokenizer +except ImportError as e: + print( + f"Warning! {e}, [paddlenlp] package and it's dependencies is required for ActBERT." + ) + + +@PIPELINES.register() +class FeaturePadding(object): + """ + Padding feature to target shape. + """ + def __init__(self, max_region_num=36, max_action_num=5): + self.max_region_num = max_region_num + self.max_action_num = max_action_num + + def __call__(self, results): + """ + Padding feature. + """ + pack_feature = results['feature'] + tokenizer = results['tokenizer'] + image_feature_wp, image_target_wp, image_location_wp, \ + num_boxes, image_h, image_w, image_id, caption, \ + action_feature_wp, action_target_wp, num_actions = pack_feature + + image_feature = np.zeros((self.max_region_num, 2048), dtype=np.float32) + image_target = np.zeros((self.max_region_num, 1601), dtype=np.float32) + image_location = np.zeros((self.max_region_num, 5), dtype=np.float32) + + action_feature = np.zeros((self.max_action_num, 2048), dtype=np.float32) + action_target = np.zeros((self.max_action_num, ), dtype=np.int64) + + num_boxes = int(num_boxes) + image_feature[:num_boxes] = image_feature_wp + image_target[:num_boxes] = image_target_wp + image_location[:num_boxes, :4] = image_location_wp + + image_location[:, 4] = (image_location[:, 3] - image_location[:, 1]) * ( + image_location[:, 2] - image_location[:, 0]) / (float(image_w) * + float(image_h)) + + image_location[:, 0] = image_location[:, 0] / float(image_w) + image_location[:, 1] = image_location[:, 1] / float(image_h) + image_location[:, 2] = image_location[:, 2] / float(image_w) + image_location[:, 3] = image_location[:, 3] / float(image_h) + + image_feature = copy.deepcopy(image_feature) + image_target = copy.deepcopy(image_target) + + num_actions = int(num_actions) + action_feature[:num_actions] = action_feature_wp + action_target[:num_actions] = action_target_wp + action_feature = copy.deepcopy(action_feature) + action_target = copy.deepcopy(action_target) + + results = dict(image_feat=image_feature, + image_target=image_target, + caption=caption, + image_loc=image_location, + num_boxes=int(num_boxes), + action_feat=action_feature, + action_target=action_target, + num_actions=int(num_actions), + tokenizer=tokenizer) + return results + + +@PIPELINES.register() +class RandomCap(object): + def __init__(self, caption_path): + """ + Random Caption for NSP task + """ + self.caption_path = caption_path + + def select_caption(self, caption): + captions = caption.split('!') + rind = random.randint(0, len(captions) - 1) + caption = captions[rind] + return caption + + def get_random_caption(self, all_captions): + num_caps = len(all_captions) + rand_doc_idx = random.randint(0, num_caps - 1) + caption = all_captions[rand_doc_idx] + caption = self.select_caption(caption) + return caption + + def random_cap(self, caption, all_captions): + if random.random() > 0.5: + label = 0 + else: + caption = self.get_random_caption(all_captions) + label = 1 + return caption, label + + def __call__(self, results): + caption = results['caption'] + all_captions = list(json.load(open(self.caption_path, 'r'))) + caption = self.select_caption(caption) + caption, label = self.random_cap(caption, all_captions) + results['caption'] = caption + results['is_next'] = label + return results + + +@PIPELINES.register() +class Tokenize(object): + def __init__(self, ): + """ + Tokenize caption + """ + pass + + def __call__(self, results): + caption = results['caption'] + tokenizer = results['tokenizer'] + tokens_caption = tokenizer.tokenize(caption) + results['caption'] = tokens_caption + return results + + +@PIPELINES.register() +class RandomMask(object): + def __init__(self, + max_seq_length=36, + max_action_length=5, + max_region_length=36): + self.max_seq_length = max_seq_length + self.max_action_length = max_action_length + self.max_region_length = max_region_length + + def get_image_global_feature(self, image_feat, image_loc, image_mask): + g_image_feat = np.sum(image_feat, axis=0) / np.sum( + image_mask, axis=0, keepdims=True) + image_feat = np.concatenate( + [np.expand_dims(g_image_feat, axis=0), image_feat], + axis=0).astype("float32") + + g_image_loc = np.array([0, 0, 1, 1, 1]).astype("float32") + image_loc = np.concatenate( + [np.expand_dims(g_image_loc, axis=0), image_loc], axis=0) + + g_image_mask = np.array([1]) + image_mask = np.concatenate([g_image_mask, image_mask], axis=0) + + return image_feat, image_loc, image_mask + + def _truncate_seq_pair(self, tokens_b, max_length): + """Truncates a sequence pair in place to the maximum length. + This is a simple heuristic which will always truncate the longer sequence + one token at a time. This makes more sense than truncating an equal percent + of tokens from each, since if one sequence is very short then each token + that's truncated likely contains more information than a longer sequence. + """ + while True: + total_length = len(tokens_b) + if total_length <= max_length: + break + tokens_b.pop() + + def random_word(self, tokens, tokenizer): + """ + Masking some random tokens for Language Model task with probabilities as in the original BERT paper. + Args: + tokens: list of str, tokenized sentence. + tokenizer: Tokenizer, object used for tokenization (we need it's vocab here) + Return: + (list of str, list of int), masked tokens and related labels for LM prediction + """ + output_label = [] + + for i, token in enumerate(tokens): + prob = random.random() + # mask token with 15% probability + + if prob < 0.15: + prob /= 0.15 + + # 80% randomly change token to mask token + if prob < 0.8: + tokens[i] = "[MASK]" + + # 10% randomly change token to random token + elif prob < 0.9: + #tok = random.choice(list(tokenizer.vocab.items()))[0] + tok = tokenizer.vocab.idx_to_token[random.randint( + 0, + tokenizer.vocab_size, + )] + tokens[i] = tok + + # rest 10% randomly keep current token + # append current token to output (we will predict these later) + try: + output_label.append(tokenizer.vocab[token]) + except KeyError: + # For unknown words (should not occur with BPE vocab) + output_label.append(tokenizer.vocab["[UNK]"]) + print( + "Cannot find token '{}' in vocab. Using [UNK] insetad". + format(token)) + else: + # no masking token (will be ignored by loss function later) + output_label.append(-1) + + return tokens, output_label + + def random_region(self, image_feat, image_loc, num_boxes): + output_label = [] + + for i in range(num_boxes): + prob = random.random() + # mask token with 15% probability + if prob < 0.15: + prob /= 0.15 + + # 80% randomly change token to mask token + if prob < 0.9: + image_feat[i] = 0 + + # rest 20% randomly keep current token + # append current token to output (we will predict these later) + output_label.append(1) + else: + # no masking token (will be ignored by loss function later) + output_label.append(-1) + + return image_feat, image_loc, output_label + + def random_action(self, action_feat, action_target, num_actions): + output_label = [] + + for i in range(num_actions): + prob = random.random() + # mask token with 15% probability + if prob < 0.15: + prob /= 0.15 + + # 90% randomly change token to mask token + if prob < 0.9: + action_feat[i] = 0 + + # rest 10% randomly keep current token + # append current token to output (we will predict these later) + output_label.append(action_target[i]) + else: + # no masking token (will be ignored by loss function later) + output_label.append(-1) + + return action_feat, output_label + + def __call__(self, results): + caption = results['caption'] + tokenizer = results['tokenizer'] + image_feat = results['image_feat'] + image_loc = results['image_loc'] + num_boxes = results['num_boxes'] + action_feat = results['action_feat'] + action_target = results['action_target'] + num_actions = results['num_actions'] + is_next = results['is_next'] + image_target = results['image_target'] + + self._truncate_seq_pair(caption, self.max_seq_length - 2) + caption, caption_label = self.random_word(caption, tokenizer) + + image_feat, image_loc, image_label = self.random_region( + image_feat, image_loc, num_boxes) + action_feat, action_label = self.random_action(action_feat, + action_target, + num_actions) + + # concatenate lm labels and account for CLS, SEP, SEP + lm_label_ids = [-1] + caption_label + [-1] + + # The convention in BERT is: + # (a) For sequence pairs: + # tokens: [CLS] is this jack ##son ##ville ? [SEP] no it is not . [SEP] + # type_ids: 0 0 0 0 0 0 0 0 1 1 1 1 1 1 + # (b) For single sequences: + # tokens: [CLS] the dog is hairy . [SEP] + # type_ids: 0 0 0 0 0 0 0 + # + # Where "type_ids" are used to indicate whether this is the first + # sequence or the second sequence. The embedding vectors for `type=0` and + # `type=1` were learned during pre-training and are added to the wordpiece + # embedding vector (and position vector). This is not *strictly* necessary + # since the [SEP] token unambigiously separates the sequences, but it makes + # it easier for the model to learn the concept of sequences. + # + # For classification tasks, the first vector (corresponding to [CLS]) is + # used as as the "sentence vector". Note that this only makes sense because + # the entire model is fine-tuned. + + tokens = [] + segment_ids = [] + + tokens.append("[CLS]") + segment_ids.append(0) + + for token in caption: + tokens.append(token) + segment_ids.append(0) + tokens.append("[SEP]") + segment_ids.append(0) + input_ids = tokenizer.convert_tokens_to_ids(tokens) + + # The mask has 1 for real tokens and 0 for padding tokens. Only real tokens are attended to. + input_mask = [1] * (len(input_ids)) + image_mask = [1] * (num_boxes) + action_mask = [1] * (num_actions) + + # Zero-pad up to the visual sequence length. + while len(image_mask) < self.max_region_length: + image_mask.append(0) + image_label.append(-1) + while len(action_mask) < self.max_action_length: + action_mask.append(0) + action_label.append(-1) + + # Zero-pad up to the sequence length. + while len(input_ids) < self.max_seq_length: + input_ids.append(0) + input_mask.append(0) + segment_ids.append(0) + lm_label_ids.append(-1) + + assert len(input_ids) == self.max_seq_length + assert len(input_mask) == self.max_seq_length + assert len(segment_ids) == self.max_seq_length + assert len(lm_label_ids) == self.max_seq_length + assert len(image_mask) == self.max_region_length + assert len(image_label) == self.max_region_length + assert len(action_mask) == self.max_action_length + assert len(action_label) == self.max_action_length + + image_feat, image_loc, image_mask = self.get_image_global_feature( + image_feat, image_loc, np.array(image_mask)) + features = [ + np.array(input_ids), + action_feat, + image_feat, + image_loc, + np.array(segment_ids), + np.array(input_mask), + image_mask, + np.array(action_mask), + np.array(lm_label_ids), + np.array(action_label), + np.array(is_next), + np.array(image_label), + image_target, + ] + results['features'] = features + return results diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample.py new file mode 100644 index 0000000..0a1d068 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample.py @@ -0,0 +1,382 @@ +# 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 random + +import numpy as np +from PIL import Image +try: + import SimpleITK as sitk +except ImportError as e: + print( + f"Warning! {e}, [SimpleITK] package and it's dependencies is required for PP-Care." + ) +import cv2 + +from ..registry import PIPELINES + +try: + import cPickle as pickle + from cStringIO import StringIO +except ImportError: + import pickle + from io import BytesIO + + +@PIPELINES.register() +class Sampler(object): + """ + Sample frames id. + NOTE: Use PIL to read image here, has diff with CV2 + Args: + num_seg(int): number of segments. + seg_len(int): number of sampled frames in each segment. + valid_mode(bool): True or False. + select_left: Whether to select the frame to the left in the middle when the sampling interval is even in the test mode. + Returns: + frames_idx: the index of sampled #frames. + """ + def __init__(self, + num_seg, + seg_len, + frame_interval=None, + valid_mode=False, + select_left=False, + dense_sample=False, + linspace_sample=False, + use_pil=True): + self.num_seg = num_seg + self.seg_len = seg_len + self.frame_interval = frame_interval + self.valid_mode = valid_mode + self.select_left = select_left + self.dense_sample = dense_sample + self.linspace_sample = linspace_sample + self.use_pil = use_pil + + def _get(self, frames_idx, results): + data_format = results['format'] + + if data_format == "frame": + frame_dir = results['frame_dir'] + imgs = [] + for idx in frames_idx: + img = Image.open( + os.path.join(frame_dir, + results['suffix'].format(idx))).convert('RGB') + imgs.append(img) + + elif data_format == "MRI": + frame_dir = results['frame_dir'] + imgs = [] + MRI = sitk.GetArrayFromImage(sitk.ReadImage(frame_dir)) + for idx in frames_idx: + item = MRI[idx] + item = cv2.resize(item, (224, 224)) + imgs.append(item) + + elif data_format == "video": + if results['backend'] == 'cv2': + frames = np.array(results['frames']) + imgs = [] + for idx in frames_idx: + imgbuf = frames[idx] + img = Image.fromarray(imgbuf, mode='RGB') + imgs.append(img) + elif results['backend'] == 'decord': + container = results['frames'] + if self.use_pil: + frames_select = container.get_batch(frames_idx) + # dearray_to_img + np_frames = frames_select.asnumpy() + imgs = [] + for i in range(np_frames.shape[0]): + imgbuf = np_frames[i] + imgs.append(Image.fromarray(imgbuf, mode='RGB')) + else: + if frames_idx.ndim != 1: + frames_idx = np.squeeze(frames_idx) + frame_dict = { + idx: container[idx].asnumpy() + for idx in np.unique(frames_idx) + } + imgs = [frame_dict[idx] for idx in frames_idx] + elif results['backend'] == 'pyav': + imgs = [] + frames = np.array(results['frames']) + for idx in frames_idx: + if self.dense_sample: + idx = idx - 1 + imgbuf = frames[idx] + imgs.append(imgbuf) + imgs = np.stack(imgs) # thwc + else: + raise NotImplementedError + else: + raise NotImplementedError + results['imgs'] = imgs + return results + + def _get_train_clips(self, num_frames): + ori_seg_len = self.seg_len * self.frame_interval + avg_interval = (num_frames - ori_seg_len + 1) // self.num_seg + + if avg_interval > 0: + base_offsets = np.arange(self.num_seg) * avg_interval + clip_offsets = base_offsets + np.random.randint(avg_interval, + size=self.num_seg) + elif num_frames > max(self.num_seg, ori_seg_len): + clip_offsets = np.sort( + np.random.randint(num_frames - ori_seg_len + 1, + size=self.num_seg)) + elif avg_interval == 0: + ratio = (num_frames - ori_seg_len + 1.0) / self.num_seg + clip_offsets = np.around(np.arange(self.num_seg) * ratio) + else: + clip_offsets = np.zeros((self.num_seg, ), dtype=np.int) + return clip_offsets + + def _get_test_clips(self, num_frames): + ori_seg_len = self.seg_len * self.frame_interval + avg_interval = (num_frames - ori_seg_len + 1) / float(self.num_seg) + if num_frames > ori_seg_len - 1: + base_offsets = np.arange(self.num_seg) * avg_interval + clip_offsets = (base_offsets + avg_interval / 2.0).astype(np.int) + else: + clip_offsets = np.zeros((self.num_seg, ), dtype=np.int) + return clip_offsets + + def __call__(self, results): + """ + Args: + frames_len: length of frames. + return: + sampling id. + """ + frames_len = int(results['frames_len']) + frames_idx = [] + if self.frame_interval is not None: + assert isinstance(self.frame_interval, int) + if not self.valid_mode: + offsets = self._get_train_clips(frames_len) + else: + offsets = self._get_test_clips(frames_len) + + offsets = offsets[:, None] + np.arange( + self.seg_len)[None, :] * self.frame_interval + offsets = np.concatenate(offsets) + + offsets = offsets.reshape((-1, self.seg_len)) + offsets = np.mod(offsets, frames_len) + offsets = np.concatenate(offsets) + + if results['format'] == 'video': + frames_idx = offsets + elif results['format'] == 'frame': + frames_idx = list(offsets + 1) + else: + raise NotImplementedError + + return self._get(frames_idx, results) + + if self.linspace_sample: + if 'start_idx' in results and 'end_idx' in results: + offsets = np.linspace(results['start_idx'], results['end_idx'], + self.num_seg) + else: + offsets = np.linspace(0, frames_len - 1, self.num_seg) + offsets = np.clip(offsets, 0, frames_len - 1).astype(np.int64) + if results['format'] == 'video': + frames_idx = list(offsets) + frames_idx = [x % frames_len for x in frames_idx] + elif results['format'] == 'frame': + frames_idx = list(offsets + 1) + + elif results['format'] == 'MRI': + frames_idx = list(offsets) + + else: + raise NotImplementedError + return self._get(frames_idx, results) + + average_dur = int(frames_len / self.num_seg) + if not self.select_left: + if self.dense_sample: # For ppTSM + if not self.valid_mode: # train + sample_pos = max(1, 1 + frames_len - 64) + t_stride = 64 // self.num_seg + start_idx = 0 if sample_pos == 1 else np.random.randint( + 0, sample_pos - 1) + offsets = [(idx * t_stride + start_idx) % frames_len + 1 + for idx in range(self.num_seg)] + frames_idx = offsets + else: + sample_pos = max(1, 1 + frames_len - 64) + t_stride = 64 // self.num_seg + start_list = np.linspace(0, + sample_pos - 1, + num=10, + dtype=int) + offsets = [] + for start_idx in start_list.tolist(): + offsets += [ + (idx * t_stride + start_idx) % frames_len + 1 + for idx in range(self.num_seg) + ] + frames_idx = offsets + else: + for i in range(self.num_seg): + idx = 0 + if not self.valid_mode: + if average_dur >= self.seg_len: + idx = random.randint(0, average_dur - self.seg_len) + idx += i * average_dur + elif average_dur >= 1: + idx += i * average_dur + else: + idx = i + else: + if average_dur >= self.seg_len: + idx = (average_dur - 1) // 2 + idx += i * average_dur + elif average_dur >= 1: + idx += i * average_dur + else: + idx = i + for jj in range(idx, idx + self.seg_len): + if results['format'] == 'video': + frames_idx.append(int(jj % frames_len)) + elif results['format'] == 'frame': + frames_idx.append(jj + 1) + + elif results['format'] == 'MRI': + frames_idx.append(jj) + else: + raise NotImplementedError + return self._get(frames_idx, results) + + else: # for TSM + if not self.valid_mode: + if average_dur > 0: + offsets = np.multiply(list(range(self.num_seg)), + average_dur) + np.random.randint( + average_dur, size=self.num_seg) + elif frames_len > self.num_seg: + offsets = np.sort( + np.random.randint(frames_len, size=self.num_seg)) + else: + offsets = np.zeros(shape=(self.num_seg, )) + else: + if frames_len > self.num_seg: + average_dur_float = frames_len / self.num_seg + offsets = np.array([ + int(average_dur_float / 2.0 + average_dur_float * x) + for x in range(self.num_seg) + ]) + else: + offsets = np.zeros(shape=(self.num_seg, )) + + if results['format'] == 'video': + frames_idx = list(offsets) + frames_idx = [x % frames_len for x in frames_idx] + elif results['format'] == 'frame': + frames_idx = list(offsets + 1) + + elif results['format'] == 'MRI': + frames_idx = list(offsets) + + else: + raise NotImplementedError + + return self._get(frames_idx, results) + + +@PIPELINES.register() +class SamplerPkl(object): + """ + Sample frames id. + NOTE: Use PIL to read image here, has diff with CV2 + Args: + num_seg(int): number of segments. + seg_len(int): number of sampled frames in each segment. + mode(str): 'train', 'valid' + Returns: + frames_idx: the index of sampled #frames. + """ + def __init__(self, num_seg, seg_len, backend='pillow', valid_mode=False): + self.num_seg = num_seg + self.seg_len = seg_len + self.valid_mode = valid_mode + self.backend = backend + + def _get(self, buf): + if isinstance(buf, str): + img = Image.open(StringIO(buf)) + else: + img = Image.open(BytesIO(buf)) + img = img.convert('RGB') + if self.backend != 'pillow': + img = np.array(img) + return img + + def __call__(self, results): + """ + Args: + frames_len: length of frames. + return: + sampling id. + """ + filename = results['frame_dir'] + data_loaded = pickle.load(open(filename, 'rb'), encoding='bytes') + video_name, label, frames = data_loaded + if isinstance(label, dict): + label = label['动作类型'] + results['labels'] = label + elif len(label) == 1: + results['labels'] = int(label[0]) + else: + results['labels'] = int(label[0]) if random.random() < 0.5 else int( + label[1]) + results['frames_len'] = len(frames) + frames_len = results['frames_len'] + average_dur = int(int(frames_len) / self.num_seg) + imgs = [] + for i in range(self.num_seg): + idx = 0 + if not self.valid_mode: + if average_dur >= self.seg_len: + idx = random.randint(0, average_dur - self.seg_len) + idx += i * average_dur + elif average_dur >= 1: + idx += i * average_dur + else: + idx = i + else: + if average_dur >= self.seg_len: + idx = (average_dur - 1) // 2 + idx += i * average_dur + elif average_dur >= 1: + idx += i * average_dur + else: + idx = i + + for jj in range(idx, idx + self.seg_len): + imgbuf = frames[int(jj % results['frames_len'])] + img = self._get(imgbuf) + imgs.append(img) + results['backend'] = self.backend + results['imgs'] = imgs + + return results diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample_ava.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample_ava.py new file mode 100644 index 0000000..39e90a2 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample_ava.py @@ -0,0 +1,375 @@ +# Copyright (c) 2021 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 random +from PIL import Image +from ..registry import PIPELINES +import os +import numpy as np +import io +import os.path as osp +from abc import ABCMeta, abstractmethod +import cv2 +from cv2 import IMREAD_COLOR, IMREAD_GRAYSCALE, IMREAD_UNCHANGED +import inspect + +imread_backend = 'cv2' +imread_flags = { + 'color': IMREAD_COLOR, + 'grayscale': IMREAD_GRAYSCALE, + 'unchanged': IMREAD_UNCHANGED +} + + +@PIPELINES.register() +class SampleFrames: + """Sample frames from the video. """ + + def __init__(self, + clip_len, + frame_interval=1, + num_clips=1, + temporal_jitter=False, + twice_sample=False, + out_of_bound_opt='loop', + test_mode=False): + self.clip_len = clip_len + self.frame_interval = frame_interval + self.num_clips = num_clips + self.temporal_jitter = temporal_jitter + self.twice_sample = twice_sample + self.out_of_bound_opt = out_of_bound_opt + self.test_mode = test_mode + assert self.out_of_bound_opt in ['loop', 'repeat_last'] + + def _get_train_clips(self, num_frames): + """Get clip offsets in train mode. """ + ori_clip_len = self.clip_len * self.frame_interval + avg_interval = (num_frames - ori_clip_len + 1) // self.num_clips + if avg_interval > 0: + base_offsets = np.arange(self.num_clips) * avg_interval + clip_offsets = base_offsets + np.random.randint( + avg_interval, size=self.num_clips) + elif num_frames > max(self.num_clips, ori_clip_len): + clip_offsets = np.sort( + np.random.randint( + num_frames - ori_clip_len + 1, size=self.num_clips)) + elif avg_interval == 0: + ratio = (num_frames - ori_clip_len + 1.0) / self.num_clips + clip_offsets = np.around(np.arange(self.num_clips) * ratio) + else: + clip_offsets = np.zeros((self.num_clips, ), dtype=np.int) + return clip_offsets + + def _get_test_clips(self, num_frames): + """Get clip offsets in test mode. """ + ori_clip_len = self.clip_len * self.frame_interval + avg_interval = (num_frames - ori_clip_len + 1) / float(self.num_clips) + if num_frames > ori_clip_len - 1: + base_offsets = np.arange(self.num_clips) * avg_interval + clip_offsets = (base_offsets + avg_interval / 2.0).astype(np.int) + if self.twice_sample: + clip_offsets = np.concatenate([clip_offsets, base_offsets]) + else: + clip_offsets = np.zeros((self.num_clips, ), dtype=np.int) + return clip_offsets + + def _sample_clips(self, num_frames): + """Choose clip offsets for the video in a given mode. """ + if self.test_mode: + clip_offsets = self._get_test_clips(num_frames) + else: + clip_offsets = self._get_train_clips(num_frames) + return clip_offsets + + def __call__(self, results): + """Perform the SampleFrames loading. """ + total_frames = results['total_frames'] + clip_offsets = self._sample_clips(total_frames) + frame_inds = clip_offsets[:, None] + np.arange( + self.clip_len)[None, :] * self.frame_interval + frame_inds = np.concatenate(frame_inds) + if self.temporal_jitter: + perframe_offsets = np.random.randint( + self.frame_interval, size=len(frame_inds)) + frame_inds += perframe_offsets + frame_inds = frame_inds.reshape((-1, self.clip_len)) + if self.out_of_bound_opt == 'loop': + frame_inds = np.mod(frame_inds, total_frames) + elif self.out_of_bound_opt == 'repeat_last': + safe_inds = frame_inds < total_frames + unsafe_inds = 1 - safe_inds + last_ind = np.max(safe_inds * frame_inds, axis=1) + new_inds = (safe_inds * frame_inds + (unsafe_inds.T * last_ind).T) + frame_inds = new_inds + else: + raise ValueError('Illegal out_of_bound option.') + start_index = results['start_index'] + frame_inds = np.concatenate(frame_inds) + start_index + results['frame_inds'] = frame_inds.astype(np.int) + results['clip_len'] = self.clip_len + results['frame_interval'] = self.frame_interval + results['num_clips'] = self.num_clips + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(' + f'clip_len={self.clip_len}, ' + f'frame_interval={self.frame_interval}, ' + f'num_clips={self.num_clips}, ' + f'temporal_jitter={self.temporal_jitter}, ' + f'twice_sample={self.twice_sample}, ' + f'out_of_bound_opt={self.out_of_bound_opt}, ' + f'test_mode={self.test_mode})') + return repr_str + +class BaseStorageBackend(metaclass=ABCMeta): + """Abstract class of storage backends. """ + + @abstractmethod + def get(self, filepath): + pass + + @abstractmethod + def get_text(self, filepath): + pass + +class HardDiskBackend(BaseStorageBackend): + """Raw hard disks storage backend.""" + + def get(self, filepath): + filepath = str(filepath) + with open(filepath, 'rb') as f: + value_buf = f.read() + return value_buf + + def get_text(self, filepath): + filepath = str(filepath) + with open(filepath, 'r') as f: + value_buf = f.read() + return value_buf + +class FileClient: + """A general file client to access files in different backend. """ + + _backends = { + 'disk': HardDiskBackend, + } + + def __init__(self, backend='disk', **kwargs): + if backend not in self._backends: + raise ValueError( + f'Backend {backend} is not supported. Currently supported ones' + f' are {list(self._backends.keys())}') + self.backend = backend + self.client = self._backends[backend](**kwargs) + + @classmethod + def _register_backend(cls, name, backend, force=False): + if not isinstance(name, str): + raise TypeError('the backend name should be a string, ' + f'but got {type(name)}') + if not inspect.isclass(backend): + raise TypeError( + f'backend should be a class but got {type(backend)}') + if not issubclass(backend, BaseStorageBackend): + raise TypeError( + f'backend {backend} is not a subclass of BaseStorageBackend') + if not force and name in cls._backends: + raise KeyError( + f'{name} is already registered as a storage backend, ' + 'add "force=True" if you want to override it') + + cls._backends[name] = backend + + @classmethod + def register_backend(cls, name, backend=None, force=False): + """Register a backend to FileClient. """ + + if backend is not None: + cls._register_backend(name, backend, force=force) + return + + def _register(backend_cls): + cls._register_backend(name, backend_cls, force=force) + return backend_cls + + return _register + + def get(self, filepath): + return self.client.get(filepath) + + def get_text(self, filepath): + return self.client.get_text(filepath) + +@PIPELINES.register() +class RawFrameDecode: + """Load and decode frames with given indices. """ + + def __init__(self, io_backend='disk', decoding_backend='cv2', **kwargs): + self.io_backend = io_backend + self.decoding_backend = decoding_backend + self.kwargs = kwargs + self.file_client = None + + def _pillow2array(self,img, flag='color', channel_order='bgr'): + """Convert a pillow image to numpy array. """ + + channel_order = channel_order.lower() + if channel_order not in ['rgb', 'bgr']: + raise ValueError('channel order must be either "rgb" or "bgr"') + + if flag == 'unchanged': + array = np.array(img) + if array.ndim >= 3 and array.shape[2] >= 3: # color image + array[:, :, :3] = array[:, :, (2, 1, 0)] # RGB to BGR + else: + # If the image mode is not 'RGB', convert it to 'RGB' first. + if img.mode != 'RGB': + if img.mode != 'LA': + # Most formats except 'LA' can be directly converted to RGB + img = img.convert('RGB') + else: + # When the mode is 'LA', the default conversion will fill in + # the canvas with black, which sometimes shadows black objects + # in the foreground. + # + # Therefore, a random color (124, 117, 104) is used for canvas + img_rgba = img.convert('RGBA') + img = Image.new('RGB', img_rgba.size, (124, 117, 104)) + img.paste(img_rgba, mask=img_rgba.split()[3]) # 3 is alpha + if flag == 'color': + array = np.array(img) + if channel_order != 'rgb': + array = array[:, :, ::-1] # RGB to BGR + elif flag == 'grayscale': + img = img.convert('L') + array = np.array(img) + else: + raise ValueError( + 'flag must be "color", "grayscale" or "unchanged", ' + f'but got {flag}') + return array + + def _imfrombytes(self,content, flag='color', channel_order='bgr'):#, backend=None): + """Read an image from bytes. """ + + img_np = np.frombuffer(content, np.uint8) + flag = imread_flags[flag] if isinstance(flag, str) else flag + img = cv2.imdecode(img_np, flag) + if flag == IMREAD_COLOR and channel_order == 'rgb': + cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img) + return img + + def __call__(self, results): + """Perform the ``RawFrameDecode`` to pick frames given indices. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + # mmcv.use_backend(self.decoding_backend) + + directory = results['frame_dir'] + suffix = results['suffix'] + #modality = results['modality'] + + if self.file_client is None: + self.file_client = FileClient(self.io_backend, **self.kwargs) + + imgs = list() + + if results['frame_inds'].ndim != 1: + results['frame_inds'] = np.squeeze(results['frame_inds']) + + offset = results.get('offset', 0) + + for frame_idx in results['frame_inds']: + frame_idx += offset + filepath = osp.join(directory, suffix.format(frame_idx)) + img_bytes = self.file_client.get(filepath) #以二进制方式读取图片 + # Get frame with channel order RGB directly. + + cur_frame = self._imfrombytes(img_bytes, channel_order='rgb') + imgs.append(cur_frame) + + results['imgs'] = imgs + results['original_shape'] = imgs[0].shape[:2] + results['img_shape'] = imgs[0].shape[:2] + + # we resize the gt_bboxes and proposals to their real scale + h, w = results['img_shape'] + scale_factor = np.array([w, h, w, h]) + if 'gt_bboxes' in results: + gt_bboxes = results['gt_bboxes'] + gt_bboxes_new = (gt_bboxes * scale_factor).astype(np.float32) + results['gt_bboxes'] = gt_bboxes_new + if 'proposals' in results and results['proposals'] is not None: + proposals = results['proposals'] + proposals = (proposals * scale_factor).astype(np.float32) + results['proposals'] = proposals + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(' + f'io_backend={self.io_backend}, ' + f'decoding_backend={self.decoding_backend})') + return repr_str + +@PIPELINES.register() +class SampleAVAFrames(SampleFrames): + + def __init__(self, clip_len, frame_interval=2, test_mode=False): + + super().__init__(clip_len, frame_interval, test_mode=test_mode) + + def _get_clips(self, center_index, skip_offsets, shot_info): + start = center_index - (self.clip_len // 2) * self.frame_interval + end = center_index + ((self.clip_len + 1) // 2) * self.frame_interval + frame_inds = list(range(start, end, self.frame_interval)) + frame_inds = frame_inds + skip_offsets + frame_inds = np.clip(frame_inds, shot_info[0], shot_info[1] - 1) + + return frame_inds + + def __call__(self, results): + fps = results['fps'] + timestamp = results['timestamp'] + timestamp_start = results['timestamp_start'] + shot_info = results['shot_info'] + + #delta=(timestamp - timestamp_start) 为该帧距离15min视频开头有几秒 + #center_index=fps*delta为该帧距离15min视频开头有几帧 + #center_index+1是为了避免后续采样时出现负数? + #后续需要以center_index为中心前后采样视频帧片段 + center_index = fps * (timestamp - timestamp_start) + 1 + + skip_offsets = np.random.randint( + -self.frame_interval // 2, (self.frame_interval + 1) // 2, + size=self.clip_len) + frame_inds = self._get_clips(center_index, skip_offsets, shot_info) + + results['frame_inds'] = np.array(frame_inds, dtype=np.int) + results['clip_len'] = self.clip_len + results['frame_interval'] = self.frame_interval + results['num_clips'] = 1 + results['crop_quadruple'] = np.array([0, 0, 1, 1], dtype=np.float32) + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(' + f'clip_len={self.clip_len}, ' + f'frame_interval={self.frame_interval}, ' + f'test_mode={self.test_mode})') + return repr_str + diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample_ucf24.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample_ucf24.py new file mode 100644 index 0000000..7d9e904 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/sample_ucf24.py @@ -0,0 +1,69 @@ +# 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 random + +from PIL import Image + +from ..registry import PIPELINES + + +@PIPELINES.register() +class SamplerUCF24(object): + """ + Sample frames id. + NOTE: Use PIL to read image here, has diff with CV2 + Args: + num_frames(int): The amount of frames used in a video + frame_interval(int): Sampling rate + valid_mode(bool): True or False. + Returns: + frames_idx: the index of sampled #frames. + """ + def __init__(self, + num_frames=16, + frame_interval=1, + valid_mode=False): + self.num_frames = num_frames + self.frame_interval = frame_interval if valid_mode else random.randint(1, 2) + self.valid_mode = valid_mode + + def _get(self, frames_idxs, img_folder, results): + imgs = [] + for idx in frames_idxs: + img = Image.open( + os.path.join(img_folder, '{:05d}.jpg'.format(idx))).convert('RGB') + imgs.append(img) + results['imgs'] = imgs + return results + + def _make_clip(self, im_ind, max_num): + frame_idxs = [] + for i in reversed(range(self.num_frames)): + # make it as a loop + i_temp = im_ind - i * self.frame_interval + if i_temp < 1: + i_temp = 1 + elif i_temp > max_num: + i_temp = max_num + frame_idxs.append(i_temp) + return frame_idxs + + def __call__(self, results): + img_folder, key_frame = os.path.split(results['filename']) + frame_len = len(os.listdir(img_folder)) + key_idx = int(key_frame[0:5]) + frame_idxs = self._make_clip(key_idx, frame_len) + return self._get(frame_idxs, img_folder, results) diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/segmentation.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/segmentation.py new file mode 100644 index 0000000..2471442 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/segmentation.py @@ -0,0 +1,130 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +from PIL import Image +import copy +import cv2 +from ..registry import PIPELINES + + +@PIPELINES.register() +class MultiRestrictSize(object): + def __init__(self, + min_size=None, + max_size=800, + flip=False, + multi_scale=[1.3]): + self.min_size = min_size + self.max_size = max_size + self.multi_scale = multi_scale + self.flip = flip + assert ((min_size is None)) or ((max_size is None)) + + def __call__(self, sample): + samples = [] + image = sample['current_img'] + h, w = image.shape[:2] + for scale in self.multi_scale: + # Fixed range of scales + sc = None + # Align short edge + if not (self.min_size is None): + if h > w: + short_edge = w + else: + short_edge = h + if short_edge > self.min_size: + sc = float(self.min_size) / short_edge + else: + if h > w: + long_edge = h + else: + long_edge = w + if long_edge > self.max_size: + sc = float(self.max_size) / long_edge + + if sc is None: + new_h = h + new_w = w + else: + new_h = sc * h + new_w = sc * w + new_h = int(new_h * scale) + new_w = int(new_w * scale) + + if (new_h - 1) % 16 != 0: + new_h = int(np.around((new_h - 1) / 16.) * 16 + 1) + if (new_w - 1) % 16 != 0: + new_w = int(np.around((new_w - 1) / 16.) * 16 + 1) + + if new_h == h and new_w == w: + samples.append(sample) + else: + new_sample = {} + for elem in sample.keys(): + if 'meta' in elem: + new_sample[elem] = sample[elem] + continue + tmp = sample[elem] + if 'label' in elem: + new_sample[elem] = sample[elem] + continue + else: + flagval = cv2.INTER_CUBIC + tmp = cv2.resize(tmp, + dsize=(new_w, new_h), + interpolation=flagval) + new_sample[elem] = tmp + samples.append(new_sample) + + if self.flip: + now_sample = samples[-1] + new_sample = {} + for elem in now_sample.keys(): + if 'meta' in elem: + new_sample[elem] = now_sample[elem].copy() + new_sample[elem]['flip'] = True + continue + tmp = now_sample[elem] + tmp = tmp[:, ::-1].copy() + new_sample[elem] = tmp + samples.append(new_sample) + + return samples + + +@PIPELINES.register() +class MultiNorm(object): + def __call__(self, samples): + for idx in range(len(samples)): + sample = samples[idx] + for elem in sample.keys(): + if 'meta' in elem: + continue + tmp = sample[elem] + if tmp is None: + continue + + if tmp.ndim == 2: + tmp = tmp[:, :, np.newaxis] + else: + tmp = tmp / 255. + tmp -= (0.485, 0.456, 0.406) + tmp /= (0.229, 0.224, 0.225) + + tmp = tmp.transpose((2, 0, 1)) + samples[idx][elem] = tmp + + return samples diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/segmentation_pipline.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/segmentation_pipline.py new file mode 100644 index 0000000..dda6dee --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/segmentation_pipline.py @@ -0,0 +1,40 @@ +# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 copy + +import os +import numpy as np +import random +import paddle +from ..registry import PIPELINES +""" +pipeline ops for Action Segmentation Dataset. +""" + + +@PIPELINES.register() +class SegmentationSampler(object): + + def __init__(self, sample_rate): + self.sample_rate = sample_rate + + def __call__(self, results): + for key, data in results.items(): + if len(data.shape) == 1: + data = data[::self.sample_rate] + results[key] = copy.deepcopy(data) + else: + data = data[:, ::self.sample_rate] + results[key] = copy.deepcopy(data) + return results diff --git a/Bank_second_part/detect_process/paddlevideo/loader/pipelines/skeleton_pipeline.py b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/skeleton_pipeline.py new file mode 100644 index 0000000..d31c816 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/pipelines/skeleton_pipeline.py @@ -0,0 +1,1554 @@ +# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 collections +from itertools import repeat +import copy as cp +from collections import abc +import numpy as np +import paddle.nn.functional as F +import random +import paddle +from ..registry import PIPELINES +from .augmentations_ava import iminvert, imflip_ +"""pipeline ops for Activity Net. +""" + + +def _ntuple(n): + def parse(x): + if isinstance(x, collections.abc.Iterable): + return tuple(x) + return tuple(repeat(x, n)) + + return parse + + +_single = _ntuple(1) +_pair = _ntuple(2) +_triple = _ntuple(3) +_quadruple = _ntuple(4) + + +def _init_lazy_if_proper(results, lazy): + """Initialize lazy operation properly. + + Make sure that a lazy operation is properly initialized, + and avoid a non-lazy operation accidentally getting mixed in. + + Required keys in results are "imgs" if "img_shape" not in results, + otherwise, Required keys in results are "img_shape", add or modified keys + are "img_shape", "lazy". + Add or modified keys in "lazy" are "original_shape", "crop_bbox", "flip", + "flip_direction", "interpolation". + + Args: + results (dict): A dict stores data pipeline result. + lazy (bool): Determine whether to apply lazy operation. Default: False. + """ + + if 'img_shape' not in results: + results['img_shape'] = results['imgs'][0].shape[:2] + if lazy: + if 'lazy' not in results: + img_h, img_w = results['img_shape'] + lazyop = dict() + lazyop['original_shape'] = results['img_shape'] + lazyop['crop_bbox'] = np.array([0, 0, img_w, img_h], + dtype=np.float32) + lazyop['flip'] = False + lazyop['flip_direction'] = None + lazyop['interpolation'] = None + results['lazy'] = lazyop + else: + assert 'lazy' not in results, 'Use Fuse after lazy operations' + + +@PIPELINES.register() +class AutoPadding(object): + """ + Sample or Padding frame skeleton feature. + Args: + window_size: int, temporal size of skeleton feature. + random_pad: bool, whether do random padding when frame length < window size. Default: False. + """ + + def __init__(self, window_size, random_pad=False): + self.window_size = window_size + self.random_pad = random_pad + + def get_frame_num(self, data): + C, T, V, M = data.shape + for i in range(T - 1, -1, -1): + tmp = np.sum(data[:, i, :, :]) + if tmp > 0: + T = i + 1 + break + return T + + def __call__(self, results): + data = results['data'] + + C, T, V, M = data.shape + T = self.get_frame_num(data) + if T == self.window_size: + data_pad = data[:, :self.window_size, :, :] + elif T < self.window_size: + begin = random.randint( + 0, self.window_size - T) if self.random_pad else 0 + data_pad = np.zeros((C, self.window_size, V, M)) + data_pad[:, begin:begin + T, :, :] = data[:, :T, :, :] + else: + if self.random_pad: + index = np.random.choice( + T, self.window_size, replace=False).astype('int64') + else: + index = np.linspace(0, T, self.window_size).astype("int64") + data_pad = data[:, index, :, :] + + results['data'] = data_pad + return results + + +@PIPELINES.register() +class SkeletonNorm(object): + """ + Normalize skeleton feature. + Args: + aixs: dimensions of vertex coordinate. 2 for (x,y), 3 for (x,y,z). Default: 2. + """ + + def __init__(self, axis=2, squeeze=False): + self.axis = axis + self.squeeze = squeeze + + def __call__(self, results): + data = results['data'] + + # Centralization + data = data - data[:, :, 8:9, :] + data = data[:self.axis, :, :, :] # get (x,y) from (x,y, acc) + C, T, V, M = data.shape + if self.squeeze: + data = data.reshape((C, T, V)) # M = 1 + + results['data'] = data.astype('float32') + if 'label' in results: + label = results['label'] + results['label'] = np.expand_dims(label, 0).astype('int64') + return results + + +@PIPELINES.register() +class Iden(object): + """ + Wrapper Pipeline + """ + + def __init__(self, label_expand=True): + self.label_expand = label_expand + + def __call__(self, results): + data = results['data'] + results['data'] = data.astype('float32') + + if 'label' in results and self.label_expand: + label = results['label'] + results['label'] = np.expand_dims(label, 0).astype('int64') + return results + + +@PIPELINES.register() +class RandomRotation(object): + """ + Random rotation sketeton. + Args: + argument: bool, if rotation. + theta: float, rotation rate. + """ + + def __init__(self, argument, theta=0.3): + self.theta = theta + self.argument = argument + + def _rot(self, rot): + """ + rot: T,3 + """ + cos_r, sin_r = np.cos(rot), np.sin(rot) # T,3 + zeros = np.zeros((rot.shape[0], 1)) # T,1 + ones = np.ones((rot.shape[0], 1)) # T,1 + + r1 = np.stack((ones, zeros, zeros), axis=-1) # T,1,3 + rx2 = np.stack((zeros, cos_r[:, 0:1], sin_r[:, 0:1]), axis=-1) # T,1,3 + rx3 = np.stack((zeros, -sin_r[:, 0:1], cos_r[:, 0:1]), axis=-1) # T,1,3 + rx = np.concatenate((r1, rx2, rx3), axis=1) # T,3,3 + + ry1 = np.stack((cos_r[:, 1:2], zeros, -sin_r[:, 1:2]), axis=-1) + r2 = np.stack((zeros, ones, zeros), axis=-1) + ry3 = np.stack((sin_r[:, 1:2], zeros, cos_r[:, 1:2]), axis=-1) + ry = np.concatenate((ry1, r2, ry3), axis=1) + + rz1 = np.stack((cos_r[:, 2:3], sin_r[:, 2:3], zeros), axis=-1) + r3 = np.stack((zeros, zeros, ones), axis=-1) + rz2 = np.stack((-sin_r[:, 2:3], cos_r[:, 2:3], zeros), axis=-1) + rz = np.concatenate((rz1, rz2, r3), axis=1) + + rot = np.matmul(np.matmul(rz, ry), rx) + return rot + + def __call__(self, results): + # C,T,V,M + data = results['data'] + if self.argument: + C, T, V, M = data.shape + data_numpy = np.transpose(data, (1, 0, 2, 3)).conjugate().reshape( + T, C, V * M) # T,3,V*M + rot = np.random.uniform(-self.theta, self.theta, 3) + rot = np.stack( + [ + rot, + ] * T, axis=0) + rot = self._rot(rot) # T,3,3 + data_numpy = np.matmul(rot, data_numpy) + data_numpy = data_numpy.reshape(T, C, V, M) + data_numpy = np.transpose(data_numpy, (1, 0, 2, 3)) + data = data_numpy + results['data'] = data.astype(np.float32) + return results + + +@PIPELINES.register() +class SketeonCropSample(object): + """ + Sketeon Crop Sampler. + Args: + crop_model: str, crop model, support: ['center']. + p_interval: list, crop len + window_size: int, sample windows size. + """ + + def __init__(self, window_size, crop_model='center', p_interval=1): + assert crop_model in ['center'], "Don't support :" + crop_model + + self.crop_model = crop_model + self.window_size = window_size + self.p_interval = p_interval + + def __call__(self, results): + if self.crop_model == 'center': + # input: C,T,V,M + data = results['data'] + valid_frame_num = np.sum(data.sum(0).sum(-1).sum(-1) != 0) + + C, T, V, M = data.shape + begin = 0 + end = valid_frame_num + valid_size = end - begin + + #crop + if len(self.p_interval) == 1: + p = self.p_interval[0] + bias = int((1 - p) * valid_size / 2) + data = data[:, begin + bias:end - bias, :, :] # center_crop + cropped_length = data.shape[1] + else: + p = np.random.rand(1) * (self.p_interval[1] - self.p_interval[0] + ) + self.p_interval[0] + # constraint cropped_length lower bound as 64 + cropped_length = np.minimum( + np.maximum(int(np.floor(valid_size * p)), 64), valid_size) + bias = np.random.randint(0, valid_size - cropped_length + 1) + data = data[:, begin + bias:begin + bias + cropped_length, :, :] + + # resize + data = np.transpose(data, (0, 2, 3, 1)).conjugate().reshape( + C * V * M, cropped_length) + data = data[None, None, :, :] + # could perform both up sample and down sample + data_tensor = paddle.to_tensor(data) + data_tensor = F.interpolate( + data_tensor, + size=(C * V * M, self.window_size), + mode='bilinear', + align_corners=False).squeeze() + data = paddle.transpose( + paddle.reshape(data_tensor, (C, V, M, self.window_size)), + (0, 3, 1, 2)).numpy() + else: + raise NotImplementedError + results['data'] = data + return results + + +@PIPELINES.register() +class SketeonModalityTransform(object): + """ + Sketeon Crop Sampler. + Args: + crop_model: str, crop model, support: ['center']. + p_interval: list, crop len + window_size: int, sample windows size. + """ + + def __init__(self, bone, motion, joint=True, graph='ntu_rgb_d'): + + self.joint = joint + self.bone = bone + self.motion = motion + self.graph = graph + if self.graph == "ntu_rgb_d": + self.bone_pairs = ((1, 2), (2, 21), (3, 21), (4, 3), (5, 21), + (6, 5), (7, 6), (8, 7), (9, 21), (10, 9), + (11, 10), (12, 11), (13, 1), (14, 13), (15, 14), + (16, 15), (17, 1), (18, 17), (19, 18), (20, 19), + (22, 23), (21, 21), (23, 8), (24, 25), (25, 12)) + else: + raise NotImplementedError + + def __call__(self, results): + if self.joint: + return results + data_numpy = results['data'] + if self.bone: + bone_data_numpy = np.zeros_like(data_numpy) + for v1, v2 in self.bone_pairs: + bone_data_numpy[:, :, v1 - + 1] = data_numpy[:, :, v1 - + 1] - data_numpy[:, :, v2 - 1] + data_numpy = bone_data_numpy + if self.motion: + data_numpy[:, :-1] = data_numpy[:, 1:] - data_numpy[:, :-1] + data_numpy[:, -1] = 0 + results['data'] = data_numpy + return results + + +@PIPELINES.register() +class UniformSampleFrames: + """Uniformly sample frames from the video. + + To sample an n-frame clip from the video. UniformSampleFrames basically + divide the video into n segments of equal length and randomly sample one + frame from each segment. To make the testing results reproducible, a + random seed is set during testing, to make the sampling results + deterministic. + + Required keys are "total_frames", "start_index" , added or modified keys + are "frame_inds", "clip_len", "frame_interval" and "num_clips". + + Args: + clip_len (int): Frames of each sampled output clip. + num_clips (int): Number of clips to be sampled. Default: 1. + test_mode (bool): Store True when building test or validation dataset. + Default: False. + seed (int): The random seed used during test time. Default: 255. + """ + + def __init__(self, clip_len, num_clips=1, test_mode=False, seed=255): + + self.clip_len = clip_len + self.num_clips = num_clips + self.test_mode = test_mode + self.seed = seed + + def _get_train_clips(self, num_frames, clip_len): + """Uniformly sample indices for training clips. + + Args: + num_frames (int): The number of frames. + clip_len (int): The length of the clip. + """ + + assert self.num_clips == 1 + if num_frames < clip_len: + start = np.random.randint(0, num_frames) + inds = np.arange(start, start + clip_len) + elif clip_len <= num_frames < 2 * clip_len: + basic = np.arange(clip_len) + inds = np.random.choice( + clip_len + 1, num_frames - clip_len, replace=False) + offset = np.zeros(clip_len + 1, dtype=np.int64) + offset[inds] = 1 + offset = np.cumsum(offset) + inds = basic + offset[:-1] + else: + bids = np.array( + [i * num_frames // clip_len for i in range(clip_len + 1)]) + bsize = np.diff(bids) + bst = bids[:clip_len] + offset = np.random.randint(bsize) + inds = bst + offset + return inds + + def _get_test_clips(self, num_frames, clip_len): + """Uniformly sample indices for testing clips. + + Args: + num_frames (int): The number of frames. + clip_len (int): The length of the clip. + """ + + np.random.seed(self.seed) + if num_frames < clip_len: + # Then we use a simple strategy + if num_frames < self.num_clips: + start_inds = list(range(self.num_clips)) + else: + start_inds = [ + i * num_frames // self.num_clips + for i in range(self.num_clips) + ] + inds = np.concatenate( + [np.arange(i, i + clip_len) for i in start_inds]) + elif clip_len <= num_frames < clip_len * 2: + all_inds = [] + for i in range(self.num_clips): + basic = np.arange(clip_len) + inds = np.random.choice( + clip_len + 1, num_frames - clip_len, replace=False) + offset = np.zeros(clip_len + 1, dtype=np.int64) + offset[inds] = 1 + offset = np.cumsum(offset) + inds = basic + offset[:-1] + all_inds.append(inds) + inds = np.concatenate(all_inds) + else: + bids = np.array( + [i * num_frames // clip_len for i in range(clip_len + 1)]) + bsize = np.diff(bids) + bst = bids[:clip_len] + all_inds = [] + for i in range(self.num_clips): + offset = np.random.randint(bsize) + all_inds.append(bst + offset) + inds = np.concatenate(all_inds) + return inds + + def __call__(self, results): + num_frames = results['total_frames'] + + if self.test_mode: + inds = self._get_test_clips(num_frames, self.clip_len) + else: + inds = self._get_train_clips(num_frames, self.clip_len) + + inds = np.mod(inds, num_frames) + start_index = results['start_index'] + inds = inds + start_index + + results['frame_inds'] = inds.astype(np.int) + results['clip_len'] = self.clip_len + results['frame_interval'] = None + results['num_clips'] = self.num_clips + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(' + f'clip_len={self.clip_len}, ' + f'num_clips={self.num_clips}, ' + f'test_mode={self.test_mode}, ' + f'seed={self.seed})') + return repr_str + + +@PIPELINES.register() +class PoseDecode: + """Load and decode pose with given indices. + + Required keys are "keypoint", "frame_inds" (optional), "keypoint_score" + (optional), added or modified keys are "keypoint", "keypoint_score" (if + applicable). + """ + + @staticmethod + def _load_kp(kp, frame_inds): + """Load keypoints given frame indices. + + Args: + kp (np.ndarray): The keypoint coordinates. + frame_inds (np.ndarray): The frame indices. + """ + + return [x[frame_inds].astype(np.float32) for x in kp] + + @staticmethod + def _load_kpscore(kpscore, frame_inds): + """Load keypoint scores given frame indices. + + Args: + kpscore (np.ndarray): The confidence scores of keypoints. + frame_inds (np.ndarray): The frame indices. + """ + + return [x[frame_inds].astype(np.float32) for x in kpscore] + + def __call__(self, results): + + if 'frame_inds' not in results: + results['frame_inds'] = np.arange(results['total_frames']) + + if results['frame_inds'].ndim != 1: + results['frame_inds'] = np.squeeze(results['frame_inds']) + + offset = results.get('offset', 0) + frame_inds = results['frame_inds'] + offset + + if 'keypoint_score' in results: + kpscore = results['keypoint_score'] + results['keypoint_score'] = kpscore[:, frame_inds].astype( + np.float32) + + if 'keypoint' in results: + results['keypoint'] = results['keypoint'][:, frame_inds].astype( + np.float32) + + return results + + def __repr__(self): + repr_str = f'{self.__class__.__name__}()' + return repr_str + + +@PIPELINES.register() +class PoseCompact: + """Convert the coordinates of keypoints to make it more compact. + Specifically, it first find a tight bounding box that surrounds all joints + in each frame, then we expand the tight box by a given padding ratio. For + example, if 'padding == 0.25', then the expanded box has unchanged center, + and 1.25x width and height. + + Required keys in results are "img_shape", "keypoint", add or modified keys + are "img_shape", "keypoint", "crop_quadruple". + + Args: + padding (float): The padding size. Default: 0.25. + threshold (int): The threshold for the tight bounding box. If the width + or height of the tight bounding box is smaller than the threshold, + we do not perform the compact operation. Default: 10. + hw_ratio (float | tuple[float] | None): The hw_ratio of the expanded + box. Float indicates the specific ratio and tuple indicates a + ratio range. If set as None, it means there is no requirement on + hw_ratio. Default: None. + allow_imgpad (bool): Whether to allow expanding the box outside the + image to meet the hw_ratio requirement. Default: True. + + Returns: + type: Description of returned object. + """ + + def __init__(self, + padding=0.25, + threshold=10, + hw_ratio=None, + allow_imgpad=True): + + self.padding = padding + self.threshold = threshold + if hw_ratio is not None: + hw_ratio = _pair(hw_ratio) + + self.hw_ratio = hw_ratio + + self.allow_imgpad = allow_imgpad + assert self.padding >= 0 + + def _combine_quadruple(self, a, b): + return (a[0] + a[2] * b[0], a[1] + a[3] * b[1], a[2] * b[2], + a[3] * b[3]) + + def __call__(self, results): + img_shape = results['img_shape'] + h, w = img_shape + kp = results['keypoint'] + + # Make NaN zero + kp[np.isnan(kp)] = 0. + kp_x = kp[..., 0] + kp_y = kp[..., 1] + + min_x = np.min(kp_x[kp_x != 0], initial=np.Inf) + min_y = np.min(kp_y[kp_y != 0], initial=np.Inf) + max_x = np.max(kp_x[kp_x != 0], initial=-np.Inf) + max_y = np.max(kp_y[kp_y != 0], initial=-np.Inf) + + # The compact area is too small + if max_x - min_x < self.threshold or max_y - min_y < self.threshold: + return results + + center = ((max_x + min_x) / 2, (max_y + min_y) / 2) + half_width = (max_x - min_x) / 2 * (1 + self.padding) + half_height = (max_y - min_y) / 2 * (1 + self.padding) + + if self.hw_ratio is not None: + half_height = max(self.hw_ratio[0] * half_width, half_height) + half_width = max(1 / self.hw_ratio[1] * half_height, half_width) + + min_x, max_x = center[0] - half_width, center[0] + half_width + min_y, max_y = center[1] - half_height, center[1] + half_height + + # hot update + if not self.allow_imgpad: + min_x, min_y = int(max(0, min_x)), int(max(0, min_y)) + max_x, max_y = int(min(w, max_x)), int(min(h, max_y)) + else: + min_x, min_y = int(min_x), int(min_y) + max_x, max_y = int(max_x), int(max_y) + + kp_x[kp_x != 0] -= min_x + kp_y[kp_y != 0] -= min_y + + new_shape = (max_y - min_y, max_x - min_x) + results['img_shape'] = new_shape + + # the order is x, y, w, h (in [0, 1]), a tuple + crop_quadruple = results.get('crop_quadruple', (0., 0., 1., 1.)) + new_crop_quadruple = (min_x / w, min_y / h, (max_x - min_x) / w, + (max_y - min_y) / h) + crop_quadruple = self._combine_quadruple(crop_quadruple, + new_crop_quadruple) + results['crop_quadruple'] = crop_quadruple + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(padding={self.padding}, ' + f'threshold={self.threshold}, ' + f'hw_ratio={self.hw_ratio}, ' + f'allow_imgpad={self.allow_imgpad})') + return repr_str + + +class CropBase: + @staticmethod + def _crop_kps(kps, crop_bbox): + return kps - crop_bbox[:2] + + @staticmethod + def _crop_imgs(imgs, crop_bbox): + x1, y1, x2, y2 = crop_bbox + return [img[y1:y2, x1:x2] for img in imgs] + + @staticmethod + def _box_crop(box, crop_bbox): + """Crop the bounding boxes according to the crop_bbox. + + Args: + box (np.ndarray): The bounding boxes. + crop_bbox(np.ndarray): The bbox used to crop the original image. + """ + + x1, y1, x2, y2 = crop_bbox + img_w, img_h = x2 - x1, y2 - y1 + + box_ = box.copy() + box_[..., 0::2] = np.clip(box[..., 0::2] - x1, 0, img_w - 1) + box_[..., 1::2] = np.clip(box[..., 1::2] - y1, 0, img_h - 1) + return box_ + + def _all_box_crop(self, results, crop_bbox): + """Crop the gt_bboxes and proposals in results according to crop_bbox. + + Args: + results (dict): All information about the sample, which contain + 'gt_bboxes' and 'proposals' (optional). + crop_bbox(np.ndarray): The bbox used to crop the original image. + """ + results['gt_bboxes'] = self._box_crop(results['gt_bboxes'], crop_bbox) + if 'proposals' in results and results['proposals'] is not None: + assert results['proposals'].shape[1] == 4 + results['proposals'] = self._box_crop(results['proposals'], + crop_bbox) + return results + + def __call__(self, results): + raise NotImplementedError + + +@PIPELINES.register() +class RandomResizedCrop_V2(CropBase): + """Random crop that specifics the area and height-weight ratio range. + + Required keys in results are "img_shape", "crop_bbox", "imgs" (optional), + "keypoint" (optional), added or modified keys are "imgs", "keypoint", + "crop_bbox" and "lazy"; Required keys in "lazy" are "flip", "crop_bbox", + added or modified key is "crop_bbox". + + Args: + area_range (Tuple[float]): The candidate area scales range of + output cropped images. Default: (0.08, 1.0). + aspect_ratio_range (Tuple[float]): The candidate aspect ratio range of + output cropped images. Default: (3 / 4, 4 / 3). + lazy (bool): Determine whether to apply lazy operation. Default: False. + """ + + def __init__(self, + area_range=(0.08, 1.0), + aspect_ratio_range=(3 / 4, 4 / 3), + lazy=False): + self.area_range = eval(area_range) + self.aspect_ratio_range = aspect_ratio_range + self.lazy = lazy + if not is_tuple_of(self.area_range, float): + raise TypeError(f'Area_range must be a tuple of float, ' + f'but got {type(area_range)}') + if not is_tuple_of(self.aspect_ratio_range, float): + raise TypeError(f'Aspect_ratio_range must be a tuple of float, ' + f'but got {type(aspect_ratio_range)}') + + @staticmethod + def get_crop_bbox(img_shape, + area_range, + aspect_ratio_range, + max_attempts=10): + """Get a crop bbox given the area range and aspect ratio range. + + Args: + img_shape (Tuple[int]): Image shape + area_range (Tuple[float]): The candidate area scales range of + output cropped images. Default: (0.08, 1.0). + aspect_ratio_range (Tuple[float]): The candidate aspect + ratio range of output cropped images. Default: (3 / 4, 4 / 3). + max_attempts (int): The maximum of attempts. Default: 10. + max_attempts (int): Max attempts times to generate random candidate + bounding box. If it doesn't qualified one, the center bounding + box will be used. + Returns: + (list[int]) A random crop bbox within the area range and aspect + ratio range. + """ + assert 0 < area_range[0] <= area_range[1] <= 1 + assert 0 < aspect_ratio_range[0] <= aspect_ratio_range[1] + + img_h, img_w = img_shape + area = img_h * img_w + + min_ar, max_ar = aspect_ratio_range + aspect_ratios = np.exp( + np.random.uniform( + np.log(min_ar), np.log(max_ar), size=max_attempts)) + target_areas = np.random.uniform(*area_range, size=max_attempts) * area + candidate_crop_w = np.round(np.sqrt( + target_areas * aspect_ratios)).astype(np.int32) + candidate_crop_h = np.round(np.sqrt( + target_areas / aspect_ratios)).astype(np.int32) + + for i in range(max_attempts): + crop_w = candidate_crop_w[i] + crop_h = candidate_crop_h[i] + if crop_h <= img_h and crop_w <= img_w: + x_offset = random.randint(0, img_w - crop_w) + y_offset = random.randint(0, img_h - crop_h) + return x_offset, y_offset, x_offset + crop_w, y_offset + crop_h + + # Fallback + crop_size = min(img_h, img_w) + x_offset = (img_w - crop_size) // 2 + y_offset = (img_h - crop_size) // 2 + return x_offset, y_offset, x_offset + crop_size, y_offset + crop_size + + def __call__(self, results): + """Performs the RandomResizeCrop augmentation. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + _init_lazy_if_proper(results, self.lazy) + if 'keypoint' in results: + assert not self.lazy, ('Keypoint Augmentations are not compatible ' + 'with lazy == True') + + img_h, img_w = results['img_shape'] + + left, top, right, bottom = self.get_crop_bbox( + (img_h, img_w), self.area_range, self.aspect_ratio_range) + new_h, new_w = bottom - top, right - left + + if 'crop_quadruple' not in results: + results['crop_quadruple'] = np.array( + [0, 0, 1, 1], # x, y, w, h + dtype=np.float32) + + x_ratio, y_ratio = left / img_w, top / img_h + w_ratio, h_ratio = new_w / img_w, new_h / img_h + + old_crop_quadruple = results['crop_quadruple'] + old_x_ratio, old_y_ratio = old_crop_quadruple[0], old_crop_quadruple[1] + old_w_ratio, old_h_ratio = old_crop_quadruple[2], old_crop_quadruple[3] + new_crop_quadruple = [ + old_x_ratio + x_ratio * old_w_ratio, + old_y_ratio + y_ratio * old_h_ratio, w_ratio * old_w_ratio, + h_ratio * old_h_ratio + ] + results['crop_quadruple'] = np.array( + new_crop_quadruple, dtype=np.float32) + + crop_bbox = np.array([left, top, right, bottom]) + results['crop_bbox'] = crop_bbox + results['img_shape'] = (new_h, new_w) + + if not self.lazy: + if 'keypoint' in results: + results['keypoint'] = self._crop_kps(results['keypoint'], + crop_bbox) + if 'imgs' in results: + results['imgs'] = self._crop_imgs(results['imgs'], crop_bbox) + else: + lazyop = results['lazy'] + if lazyop['flip']: + raise NotImplementedError('Put Flip at last for now') + + # record crop_bbox in lazyop dict to ensure only crop once in Fuse + lazy_left, lazy_top, lazy_right, lazy_bottom = lazyop['crop_bbox'] + left = left * (lazy_right - lazy_left) / img_w + right = right * (lazy_right - lazy_left) / img_w + top = top * (lazy_bottom - lazy_top) / img_h + bottom = bottom * (lazy_bottom - lazy_top) / img_h + lazyop['crop_bbox'] = np.array( + [(lazy_left + left), (lazy_top + top), (lazy_left + right), + (lazy_top + bottom)], + dtype=np.float32) + + if 'gt_bboxes' in results: + assert not self.lazy + results = self._all_box_crop(results, results['crop_bbox']) + + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(' + f'area_range={self.area_range}, ' + f'aspect_ratio_range={self.aspect_ratio_range}, ' + f'lazy={self.lazy})') + return repr_str + + +def is_seq_of(seq, expected_type, seq_type=None): + """Check whether it is a sequence of some type. + + Args: + seq (Sequence): The sequence to be checked. + expected_type (type): Expected type of sequence items. + seq_type (type, optional): Expected sequence type. + + Returns: + bool: Whether the sequence is valid. + """ + if seq_type is None: + exp_seq_type = abc.Sequence + else: + assert isinstance(seq_type, type) + exp_seq_type = seq_type + if not isinstance(seq, exp_seq_type): + return False + for item in seq: + if not isinstance(item, expected_type): + return False + return True + + +def is_tuple_of(seq, expected_type): + """Check whether it is a tuple of some type. + + A partial method of :func:`is_seq_of`. + """ + return is_seq_of(seq, expected_type, seq_type=tuple) + + +@PIPELINES.register() +class CenterCrop_V2(CropBase): + """Crop the center area from images. + + Required keys are "img_shape", "imgs" (optional), "keypoint" (optional), + added or modified keys are "imgs", "keypoint", "crop_bbox", "lazy" and + "img_shape". Required keys in "lazy" is "crop_bbox", added or modified key + is "crop_bbox". + + Args: + crop_size (int | tuple[int]): (w, h) of crop size. + lazy (bool): Determine whether to apply lazy operation. Default: False. + """ + + def __init__(self, crop_size, lazy=False): + self.crop_size = _pair(crop_size) + self.lazy = lazy + if not is_tuple_of(self.crop_size, int): + raise TypeError(f'Crop_size must be int or tuple of int, ' + f'but got {type(crop_size)}') + + def __call__(self, results): + """Performs the CenterCrop augmentation. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + _init_lazy_if_proper(results, self.lazy) + if 'keypoint' in results: + assert not self.lazy, ('Keypoint Augmentations are not compatible ' + 'with lazy == True') + + img_h, img_w = results['img_shape'] + crop_w, crop_h = self.crop_size + + left = (img_w - crop_w) // 2 + top = (img_h - crop_h) // 2 + right = left + crop_w + bottom = top + crop_h + new_h, new_w = bottom - top, right - left + + crop_bbox = np.array([left, top, right, bottom]) + results['crop_bbox'] = crop_bbox + results['img_shape'] = (new_h, new_w) + + if 'crop_quadruple' not in results: + results['crop_quadruple'] = np.array( + [0, 0, 1, 1], # x, y, w, h + dtype=np.float32) + + x_ratio, y_ratio = left / img_w, top / img_h + w_ratio, h_ratio = new_w / img_w, new_h / img_h + + old_crop_quadruple = results['crop_quadruple'] + old_x_ratio, old_y_ratio = old_crop_quadruple[0], old_crop_quadruple[1] + old_w_ratio, old_h_ratio = old_crop_quadruple[2], old_crop_quadruple[3] + new_crop_quadruple = [ + old_x_ratio + x_ratio * old_w_ratio, + old_y_ratio + y_ratio * old_h_ratio, w_ratio * old_w_ratio, + h_ratio * old_h_ratio + ] + results['crop_quadruple'] = np.array( + new_crop_quadruple, dtype=np.float32) + + if not self.lazy: + if 'keypoint' in results: + results['keypoint'] = self._crop_kps(results['keypoint'], + crop_bbox) + if 'imgs' in results: + results['imgs'] = self._crop_imgs(results['imgs'], crop_bbox) + else: + lazyop = results['lazy'] + if lazyop['flip']: + raise NotImplementedError('Put Flip at last for now') + + # record crop_bbox in lazyop dict to ensure only crop once in Fuse + lazy_left, lazy_top, lazy_right, lazy_bottom = lazyop['crop_bbox'] + left = left * (lazy_right - lazy_left) / img_w + right = right * (lazy_right - lazy_left) / img_w + top = top * (lazy_bottom - lazy_top) / img_h + bottom = bottom * (lazy_bottom - lazy_top) / img_h + lazyop['crop_bbox'] = np.array( + [(lazy_left + left), (lazy_top + top), (lazy_left + right), + (lazy_top + bottom)], + dtype=np.float32) + + if 'gt_bboxes' in results: + assert not self.lazy + results = self._all_box_crop(results, results['crop_bbox']) + + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(crop_size={self.crop_size}, ' + f'lazy={self.lazy})') + return repr_str + + +@PIPELINES.register() +class Flip_V2: + """Flip the input images with a probability. + + Reverse the order of elements in the given imgs with a specific direction. + The shape of the imgs is preserved, but the elements are reordered. + + Required keys are "img_shape", "modality", "imgs" (optional), "keypoint" + (optional), added or modified keys are "imgs", "keypoint", "lazy" and + "flip_direction". Required keys in "lazy" is None, added or modified key + are "flip" and "flip_direction". The Flip augmentation should be placed + after any cropping / reshaping augmentations, to make sure crop_quadruple + is calculated properly. + + Args: + flip_ratio (float): Probability of implementing flip. Default: 0.5. + direction (str): Flip imgs horizontally or vertically. Options are + "horizontal" | "vertical". Default: "horizontal". + flip_label_map (Dict[int, int] | None): Transform the label of the + flipped image with the specific label. Default: None. + left_kp (list[int]): Indexes of left keypoints, used to flip keypoints. + Default: None. + right_kp (list[ind]): Indexes of right keypoints, used to flip + keypoints. Default: None. + lazy (bool): Determine whether to apply lazy operation. Default: False. + """ + _directions = ['horizontal', 'vertical'] + + def __init__(self, + flip_ratio=0.5, + direction='horizontal', + flip_label_map=None, + left_kp=None, + right_kp=None, + lazy=False): + if direction not in self._directions: + raise ValueError(f'Direction {direction} is not supported. ' + f'Currently support ones are {self._directions}') + self.flip_ratio = flip_ratio + self.direction = direction + self.flip_label_map = flip_label_map + self.left_kp = left_kp + self.right_kp = right_kp + self.lazy = lazy + + def _flip_imgs(self, imgs, modality): + _ = [imflip_(img, self.direction) for img in imgs] + lt = len(imgs) + if modality == 'Flow': + # The 1st frame of each 2 frames is flow-x + for i in range(0, lt, 2): + imgs[i] = iminvert(imgs[i]) + return imgs + + def _flip_kps(self, kps, kpscores, img_width): + kp_x = kps[..., 0] + kp_x[kp_x != 0] = img_width - kp_x[kp_x != 0] + new_order = list(range(kps.shape[2])) + if self.left_kp is not None and self.right_kp is not None: + for left, right in zip(self.left_kp, self.right_kp): + new_order[left] = right + new_order[right] = left + kps = kps[:, :, new_order] + if kpscores is not None: + kpscores = kpscores[:, :, new_order] + return kps, kpscores + + @staticmethod + def _box_flip(box, img_width): + """Flip the bounding boxes given the width of the image. + + Args: + box (np.ndarray): The bounding boxes. + img_width (int): The img width. + """ + box_ = box.copy() + box_[..., 0::4] = img_width - box[..., 2::4] + box_[..., 2::4] = img_width - box[..., 0::4] + return box_ + + def __call__(self, results): + """Performs the Flip augmentation. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + _init_lazy_if_proper(results, self.lazy) + if 'keypoint' in results: + assert not self.lazy, ('Keypoint Augmentations are not compatible ' + 'with lazy == True') + assert self.direction == 'horizontal', ( + 'Only horizontal flips are' + 'supported for human keypoints') + + modality = results['modality'] + if modality == 'Flow': + assert self.direction == 'horizontal' + + flip = np.random.rand() < self.flip_ratio + + results['flip'] = flip + results['flip_direction'] = self.direction + img_width = results['img_shape'][1] + + if self.flip_label_map is not None and flip: + results['label'] = self.flip_label_map.get(results['label'], + results['label']) + + if not self.lazy: + if flip: + if 'imgs' in results: + results['imgs'] = self._flip_imgs(results['imgs'], modality) + if 'keypoint' in results: + kp = results['keypoint'] + kpscore = results.get('keypoint_score', None) + kp, kpscore = self._flip_kps(kp, kpscore, img_width) + results['keypoint'] = kp + if 'keypoint_score' in results: + results['keypoint_score'] = kpscore + else: + lazyop = results['lazy'] + if lazyop['flip']: + raise NotImplementedError('Use one Flip please') + lazyop['flip'] = flip + lazyop['flip_direction'] = self.direction + + if 'gt_bboxes' in results and flip: + assert not self.lazy and self.direction == 'horizontal' + width = results['img_shape'][1] + results['gt_bboxes'] = self._box_flip(results['gt_bboxes'], width) + if 'proposals' in results and results['proposals'] is not None: + assert results['proposals'].shape[1] == 4 + results['proposals'] = self._box_flip(results['proposals'], + width) + + return results + + def __repr__(self): + repr_str = ( + f'{self.__class__.__name__}(' + f'flip_ratio={self.flip_ratio}, direction={self.direction}, ' + f'flip_label_map={self.flip_label_map}, lazy={self.lazy})') + return repr_str + + +@PIPELINES.register() +class FormatShape: + """Format final imgs shape to the given input_format. + + Required keys are "imgs", "num_clips" and "clip_len", added or modified + keys are "imgs" and "input_shape". + + Args: + input_format (str): Define the final imgs format. + collapse (bool): To collpase input_format N... to ... (NCTHW to CTHW, + etc.) if N is 1. Should be set as True when training and testing + detectors. Default: False. + """ + + def __init__(self, input_format, collapse=False): + self.input_format = input_format + self.collapse = collapse + if self.input_format not in ['NCTHW', 'NCHW', 'NCHW_Flow', 'NPTCHW']: + raise ValueError( + f'The input format {self.input_format} is invalid.') + + def __call__(self, results): + """Performs the FormatShape formating. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + if not isinstance(results['imgs'], np.ndarray): + results['imgs'] = np.array(results['imgs']) + imgs = results['imgs'] + # [M x H x W x C] + # M = 1 * N_crops * N_clips * L + if self.collapse: + assert results['num_clips'] == 1 + + if self.input_format == 'NCTHW': + num_clips = results['num_clips'] + clip_len = results['clip_len'] + + imgs = imgs.reshape((-1, num_clips, clip_len) + imgs.shape[1:]) + # N_crops x N_clips x L x H x W x C + imgs = np.transpose(imgs, (0, 1, 5, 2, 3, 4)) + # N_crops x N_clips x C x L x H x W + imgs = imgs.reshape((-1, ) + imgs.shape[2:]) + # M' x C x L x H x W + # M' = N_crops x N_clips + elif self.input_format == 'NCHW': + imgs = np.transpose(imgs, (0, 3, 1, 2)) + # M x C x H x W + elif self.input_format == 'NCHW_Flow': + num_clips = results['num_clips'] + clip_len = results['clip_len'] + imgs = imgs.reshape((-1, num_clips, clip_len) + imgs.shape[1:]) + # N_crops x N_clips x L x H x W x C + imgs = np.transpose(imgs, (0, 1, 2, 5, 3, 4)) + # N_crops x N_clips x L x C x H x W + imgs = imgs.reshape((-1, imgs.shape[2] * imgs.shape[3]) + + imgs.shape[4:]) + # M' x C' x H x W + # M' = N_crops x N_clips + # C' = L x C + elif self.input_format == 'NPTCHW': + num_proposals = results['num_proposals'] + num_clips = results['num_clips'] + clip_len = results['clip_len'] + imgs = imgs.reshape((num_proposals, num_clips * clip_len) + + imgs.shape[1:]) + # P x M x H x W x C + # M = N_clips x L + imgs = np.transpose(imgs, (0, 1, 4, 2, 3)) + # P x M x C x H x W + + if self.collapse: + assert imgs.shape[0] == 1 + imgs = imgs.squeeze(0) + + results['imgs'] = imgs + results['input_shape'] = imgs.shape + return results + + def __repr__(self): + repr_str = self.__class__.__name__ + repr_str += f"(input_format='{self.input_format}')" + return repr_str + + +@PIPELINES.register() +class Collect: + """Collect data from the loader relevant to the specific task. + + This keeps the items in ``keys`` as it is, and collect items in + ``meta_keys`` into a meta item called ``meta_name``.This is usually + the last stage of the data loader pipeline. + For example, when keys='imgs', meta_keys=('filename', 'label', + 'original_shape'), meta_name='img_metas', the results will be a dict with + keys 'imgs' and 'img_metas', where 'img_metas' is a DataContainer of + another dict with keys 'filename', 'label', 'original_shape'. + + Args: + keys (Sequence[str]): Required keys to be collected. + meta_name (str): The name of the key that contains meta infomation. + This key is always populated. Default: "img_metas". + meta_keys (Sequence[str]): Keys that are collected under meta_name. + The contents of the ``meta_name`` dictionary depends on + ``meta_keys``. + By default this includes: + + - "filename": path to the image file + - "label": label of the image file + - "original_shape": original shape of the image as a tuple + (h, w, c) + - "img_shape": shape of the image input to the network as a tuple + (h, w, c). Note that images may be zero padded on the + bottom/right, if the batch tensor is larger than this shape. + - "pad_shape": image shape after padding + - "flip_direction": a str in ("horiziontal", "vertival") to + indicate if the image is fliped horizontally or vertically. + - "img_norm_cfg": a dict of normalization information: + - mean - per channel mean subtraction + - std - per channel std divisor + - to_rgb - bool indicating if bgr was converted to rgb + nested (bool): If set as True, will apply data[x] = [data[x]] to all + items in data. The arg is added for compatibility. Default: False. + """ + + def __init__(self, + keys, + meta_keys=('filename', 'label', 'original_shape', 'img_shape', + 'pad_shape', 'flip_direction', 'img_norm_cfg'), + meta_name='img_metas'): + self.keys = keys + self.meta_keys = meta_keys + self.meta_name = meta_name + + def __call__(self, results): + """Performs the Collect formating. + + Args: + results (dict): The resulting dict to be modified and passed + to the next transform in pipeline. + """ + data = [] + for key in self.keys: + data.append(results[key]) + + if len(self.meta_keys) != 0: + meta = {} + for key in self.meta_keys: + meta[key] = results[key] + data.append(meta) + + return data + + def __repr__(self): + return (f'{self.__class__.__name__}(' + f'keys={self.keys}, meta_keys={self.meta_keys}, ' + f'nested={self.nested})') + + +@PIPELINES.register() +class GeneratePoseTarget: + """Generate pseudo heatmaps based on joint coordinates and confidence. + + Required keys are "keypoint", "img_shape", "keypoint_score" (optional), + added or modified keys are "imgs". + + Args: + sigma (float): The sigma of the generated gaussian map. Default: 0.6. + use_score (bool): Use the confidence score of keypoints as the maximum + of the gaussian maps. Default: True. + with_kp (bool): Generate pseudo heatmaps for keypoints. Default: True. + with_limb (bool): Generate pseudo heatmaps for limbs. At least one of + 'with_kp' and 'with_limb' should be True. Default: False. + skeletons (tuple[tuple]): The definition of human skeletons. + Default: ((0, 1), (0, 2), (1, 3), (2, 4), (0, 5), (5, 7), (7, 9), + (0, 6), (6, 8), (8, 10), (5, 11), (11, 13), (13, 15), + (6, 12), (12, 14), (14, 16), (11, 12)), + which is the definition of COCO-17p skeletons. + double (bool): Output both original heatmaps and flipped heatmaps. + Default: False. + left_kp (tuple[int]): Indexes of left keypoints, which is used when + flipping heatmaps. Default: (1, 3, 5, 7, 9, 11, 13, 15), + which is left keypoints in COCO-17p. + right_kp (tuple[int]): Indexes of right keypoints, which is used when + flipping heatmaps. Default: (2, 4, 6, 8, 10, 12, 14, 16), + which is right keypoints in COCO-17p. + """ + + def __init__(self, + sigma=0.6, + use_score=True, + with_kp=True, + with_limb=False, + skeletons=((0, 1), (0, 2), (1, 3), (2, 4), (0, 5), (5, 7), + (7, 9), (0, 6), (6, 8), (8, 10), (5, 11), (11, 13), + (13, 15), (6, 12), (12, 14), (14, 16), (11, 12)), + double=False, + left_kp=(1, 3, 5, 7, 9, 11, 13, 15), + right_kp=(2, 4, 6, 8, 10, 12, 14, 16)): + + self.sigma = sigma + self.use_score = use_score + self.with_kp = with_kp + self.with_limb = with_limb + self.double = double + + # an auxiliary const + self.eps = 1e-4 + + assert self.with_kp or self.with_limb, ( + 'At least one of "with_limb" ' + 'and "with_kp" should be set as True.') + self.left_kp = left_kp + self.right_kp = right_kp + self.skeletons = skeletons + + def generate_a_heatmap(self, img_h, img_w, centers, sigma, max_values): + """Generate pseudo heatmap for one keypoint in one frame. + + Args: + img_h (int): The height of the heatmap. + img_w (int): The width of the heatmap. + centers (np.ndarray): The coordinates of corresponding keypoints + (of multiple persons). + sigma (float): The sigma of generated gaussian. + max_values (np.ndarray): The max values of each keypoint. + + Returns: + np.ndarray: The generated pseudo heatmap. + """ + + heatmap = np.zeros([img_h, img_w], dtype=np.float32) + + for center, max_value in zip(centers, max_values): + mu_x, mu_y = center[0], center[1] + if max_value < self.eps: + continue + + st_x = max(int(mu_x - 3 * sigma), 0) + ed_x = min(int(mu_x + 3 * sigma) + 1, img_w) + st_y = max(int(mu_y - 3 * sigma), 0) + ed_y = min(int(mu_y + 3 * sigma) + 1, img_h) + x = np.arange(st_x, ed_x, 1, np.float32) + y = np.arange(st_y, ed_y, 1, np.float32) + + # if the keypoint not in the heatmap coordinate system + if not (len(x) and len(y)): + continue + y = y[:, None] + + patch = np.exp(-((x - mu_x)**2 + (y - mu_y)**2) / 2 / sigma**2) + patch = patch * max_value + heatmap[st_y:ed_y, st_x:ed_x] = np.maximum( + heatmap[st_y:ed_y, st_x:ed_x], patch) + + return heatmap + + def generate_a_limb_heatmap(self, img_h, img_w, starts, ends, sigma, + start_values, end_values): + """Generate pseudo heatmap for one limb in one frame. + + Args: + img_h (int): The height of the heatmap. + img_w (int): The width of the heatmap. + starts (np.ndarray): The coordinates of one keypoint in the + corresponding limbs (of multiple persons). + ends (np.ndarray): The coordinates of the other keypoint in the + corresponding limbs (of multiple persons). + sigma (float): The sigma of generated gaussian. + start_values (np.ndarray): The max values of one keypoint in the + corresponding limbs. + end_values (np.ndarray): The max values of the other keypoint in + the corresponding limbs. + + Returns: + np.ndarray: The generated pseudo heatmap. + """ + + heatmap = np.zeros([img_h, img_w], dtype=np.float32) + + for start, end, start_value, end_value in zip(starts, ends, + start_values, end_values): + value_coeff = min(start_value, end_value) + if value_coeff < self.eps: + continue + + min_x, max_x = min(start[0], end[0]), max(start[0], end[0]) + min_y, max_y = min(start[1], end[1]), max(start[1], end[1]) + + min_x = max(int(min_x - 3 * sigma), 0) + max_x = min(int(max_x + 3 * sigma) + 1, img_w) + min_y = max(int(min_y - 3 * sigma), 0) + max_y = min(int(max_y + 3 * sigma) + 1, img_h) + + x = np.arange(min_x, max_x, 1, np.float32) + y = np.arange(min_y, max_y, 1, np.float32) + + if not (len(x) and len(y)): + continue + + y = y[:, None] + x_0 = np.zeros_like(x) + y_0 = np.zeros_like(y) + + # distance to start keypoints + d2_start = ((x - start[0])**2 + (y - start[1])**2) + + # distance to end keypoints + d2_end = ((x - end[0])**2 + (y - end[1])**2) + + # the distance between start and end keypoints. + d2_ab = ((start[0] - end[0])**2 + (start[1] - end[1])**2) + + if d2_ab < 1: + full_map = self.generate_a_heatmap(img_h, img_w, [start], sigma, + [start_value]) + heatmap = np.maximum(heatmap, full_map) + continue + + coeff = (d2_start - d2_end + d2_ab) / 2. / d2_ab + + a_dominate = coeff <= 0 + b_dominate = coeff >= 1 + seg_dominate = 1 - a_dominate - b_dominate + + position = np.stack([x + y_0, y + x_0], axis=-1) + projection = start + np.stack([coeff, coeff], + axis=-1) * (end - start) + d2_line = position - projection + d2_line = d2_line[:, :, 0]**2 + d2_line[:, :, 1]**2 + d2_seg = (a_dominate * d2_start + b_dominate * d2_end + + seg_dominate * d2_line) + + patch = np.exp(-d2_seg / 2. / sigma**2) + patch = patch * value_coeff + + heatmap[min_y:max_y, min_x:max_x] = np.maximum( + heatmap[min_y:max_y, min_x:max_x], patch) + + return heatmap + + def generate_heatmap(self, img_h, img_w, kps, sigma, max_values): + """Generate pseudo heatmap for all keypoints and limbs in one frame (if + needed). + + Args: + img_h (int): The height of the heatmap. + img_w (int): The width of the heatmap. + kps (np.ndarray): The coordinates of keypoints in this frame. + sigma (float): The sigma of generated gaussian. + max_values (np.ndarray): The confidence score of each keypoint. + + Returns: + np.ndarray: The generated pseudo heatmap. + """ + + heatmaps = [] + if self.with_kp: + num_kp = kps.shape[1] + for i in range(num_kp): + heatmap = self.generate_a_heatmap(img_h, img_w, kps[:, i], + sigma, max_values[:, i]) + heatmaps.append(heatmap) + + if self.with_limb: + for limb in self.skeletons: + start_idx, end_idx = limb + starts = kps[:, start_idx] + ends = kps[:, end_idx] + + start_values = max_values[:, start_idx] + end_values = max_values[:, end_idx] + heatmap = self.generate_a_limb_heatmap( + img_h, img_w, starts, ends, sigma, start_values, end_values) + heatmaps.append(heatmap) + + return np.stack(heatmaps, axis=-1) + + def gen_an_aug(self, results): + """Generate pseudo heatmaps for all frames. + + Args: + results (dict): The dictionary that contains all info of a sample. + + Returns: + list[np.ndarray]: The generated pseudo heatmaps. + """ + + all_kps = results['keypoint'] + kp_shape = all_kps.shape + + if 'keypoint_score' in results: + all_kpscores = results['keypoint_score'] + else: + all_kpscores = np.ones(kp_shape[:-1], dtype=np.float32) + + img_h, img_w = results['img_shape'] + num_frame = kp_shape[1] + + imgs = [] + for i in range(num_frame): + sigma = self.sigma + kps = all_kps[:, i] + kpscores = all_kpscores[:, i] + + max_values = np.ones(kpscores.shape, dtype=np.float32) + if self.use_score: + max_values = kpscores + + hmap = self.generate_heatmap(img_h, img_w, kps, sigma, max_values) + imgs.append(hmap) + + return imgs + + def __call__(self, results): + if not self.double: + results['imgs'] = np.stack(self.gen_an_aug(results)) + else: + results_ = cp.deepcopy(results) + flip = Flip_V2( + flip_ratio=1, left_kp=self.left_kp, right_kp=self.right_kp) + results_ = flip(results_) + results['imgs'] = np.concatenate( + [self.gen_an_aug(results), + self.gen_an_aug(results_)]) + results['label'] = np.array([results['label']]) + return results + + def __repr__(self): + repr_str = (f'{self.__class__.__name__}(' + f'sigma={self.sigma}, ' + f'use_score={self.use_score}, ' + f'with_kp={self.with_kp}, ' + f'with_limb={self.with_limb}, ' + f'skeletons={self.skeletons}, ' + f'double={self.double}, ' + f'left_kp={self.left_kp}, ' + f'right_kp={self.right_kp})') + return repr_str diff --git a/Bank_second_part/detect_process/paddlevideo/loader/registry.py b/Bank_second_part/detect_process/paddlevideo/loader/registry.py new file mode 100644 index 0000000..add6631 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/loader/registry.py @@ -0,0 +1,18 @@ +# 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. + +from ..utils import Registry + +PIPELINES = Registry("pipeline") +DATASETS = Registry("datasets") diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/__init__.py b/Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/__init__.py new file mode 100644 index 0000000..eefabbd --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/__init__.py @@ -0,0 +1,3 @@ +from .anet_prop import ANETproposal + +__all__ = ['ANETproposal'] diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c5a7b5f0c99c853272bf54d5fd6455c6d51de525 GIT binary patch literal 239 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/anet_prop.py b/Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/anet_prop.py new file mode 100644 index 0000000..411b164 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ActivityNet/anet_prop.py @@ -0,0 +1,359 @@ +# 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. + +import json +import numpy as np +import pandas as pd +import urllib.request as urllib2 +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +class ANETproposal(object): + """ + This class is used for calculating AR@N and AUC; + Code transfer from ActivityNet Gitub repository](https://github.com/activitynet/ActivityNet.git) + """ + GROUND_TRUTH_FIELDS = ['database', 'taxonomy', 'version'] + PROPOSAL_FIELDS = ['results', 'version', 'external_data'] + API = 'http://ec2-52-25-205-214.us-west-2.compute.amazonaws.com/challenge19/api.py' + + def __init__(self, + ground_truth_filename=None, + proposal_filename=None, + ground_truth_fields=GROUND_TRUTH_FIELDS, + proposal_fields=PROPOSAL_FIELDS, + tiou_thresholds=np.linspace(0.5, 0.95, 10), + max_avg_nr_proposals=None, + subset='validation', + verbose=False, + check_status=True): + if not ground_truth_filename: + raise IOError('Please input a valid ground truth file.') + if not proposal_filename: + raise IOError('Please input a valid proposal file.') + self.subset = subset + self.tiou_thresholds = tiou_thresholds + self.max_avg_nr_proposals = max_avg_nr_proposals + self.verbose = verbose + self.gt_fields = ground_truth_fields + self.pred_fields = proposal_fields + self.recall = None + self.avg_recall = None + self.proposals_per_video = None + self.check_status = check_status + # Retrieve blocked videos from server. + if self.check_status: + self.blocked_videos = self.get_blocked_videos() + else: + self.blocked_videos = list() + # Import ground truth and proposals. + self.ground_truth, self.activity_index = self._import_ground_truth( + ground_truth_filename) + self.proposal = self._import_proposal(proposal_filename) + + if self.verbose: + print('[INIT] Loaded annotations from {} subset.'.format(subset)) + nr_gt = len(self.ground_truth) + print('\tNumber of ground truth instances: {}'.format(nr_gt)) + nr_pred = len(self.proposal) + print('\tNumber of proposals: {}'.format(nr_pred)) + print('\tFixed threshold for tiou score: {}'.format( + self.tiou_thresholds)) + + def _import_ground_truth(self, ground_truth_filename): + """ + Reads ground truth file, checks if it is well formatted, and returns + the ground truth instances and the activity classes. + + Parameters: + ground_truth_filename (str): full path to the ground truth json file. + Returns: + ground_truth (df): Data frame containing the ground truth instances. + activity_index (dict): Dictionary containing class index. + """ + with open(ground_truth_filename, 'r') as fobj: + data = json.load(fobj) + # Checking format + if not all([field in data.keys() for field in self.gt_fields]): + raise IOError('Please input a valid ground truth file.') + + # Read ground truth data. + activity_index, cidx = {}, 0 + video_lst, t_start_lst, t_end_lst, label_lst = [], [], [], [] + for videoid, v in data['database'].items(): + if self.subset != v['subset']: + continue + if videoid in self.blocked_videos: + continue + for ann in v['annotations']: + if ann['label'] not in activity_index: + activity_index[ann['label']] = cidx + cidx += 1 + video_lst.append(videoid) + t_start_lst.append(float(ann['segment'][0])) + t_end_lst.append(float(ann['segment'][1])) + label_lst.append(activity_index[ann['label']]) + + ground_truth = pd.DataFrame({ + 'video-id': video_lst, + 't-start': t_start_lst, + 't-end': t_end_lst, + 'label': label_lst + }) + return ground_truth, activity_index + + def _import_proposal(self, proposal_filename): + """ + Reads proposal file, checks if it is well formatted, and returns + the proposal instances. + + Parameters: + proposal_filename (str): Full path to the proposal json file. + Returns: + proposal (df): Data frame containing the proposal instances. + """ + with open(proposal_filename, 'r') as fobj: + data = json.load(fobj) + # Checking format... + if not all([field in data.keys() for field in self.pred_fields]): + raise IOError('Please input a valid proposal file.') + + # Read predictions. + video_lst, t_start_lst, t_end_lst = [], [], [] + score_lst = [] + for videoid, v in data['results'].items(): + if videoid in self.blocked_videos: + continue + for result in v: + video_lst.append(videoid) + t_start_lst.append(float(result['segment'][0])) + t_end_lst.append(float(result['segment'][1])) + score_lst.append(result['score']) + proposal = pd.DataFrame({ + 'video-id': video_lst, + 't-start': t_start_lst, + 't-end': t_end_lst, + 'score': score_lst + }) + return proposal + + def evaluate(self): + """ + Evaluates a proposal file. To measure the performance of a + method for the proposal task, we computes the area under the + average recall vs average number of proposals per video curve. + """ + recall, avg_recall, proposals_per_video = self.average_recall_vs_avg_nr_proposals( + self.ground_truth, + self.proposal, + max_avg_nr_proposals=self.max_avg_nr_proposals, + tiou_thresholds=self.tiou_thresholds) + + area_under_curve = np.trapz(avg_recall, proposals_per_video) + + if self.verbose: + print('[RESULTS] Performance on ActivityNet proposal task.') + with open("data/bmn/BMN_Test_results/auc_result.txt", + "a") as text_file: + text_file.write( + '\tArea Under the AR vs AN curve: {}% \n'.format( + 100. * float(area_under_curve) / + proposals_per_video[-1])) + print('\tArea Under the AR vs AN curve: {}%'.format( + 100. * float(area_under_curve) / proposals_per_video[-1])) + + self.recall = recall + self.avg_recall = avg_recall + self.proposals_per_video = proposals_per_video + + def average_recall_vs_avg_nr_proposals(self, + ground_truth, + proposals, + max_avg_nr_proposals=None, + tiou_thresholds=np.linspace( + 0.5, 0.95, 10)): + """ + Computes the average recall given an average number of + proposals per video. + + Parameters: + ground_truth(df): Data frame containing the ground truth instances. + Required fields: ['video-id', 't-start', 't-end'] + proposal(df): Data frame containing the proposal instances. + Required fields: ['video-id, 't-start', 't-end', 'score'] + tiou_thresholds(1d-array | optional): array with tiou thresholds. + + Returns: + recall(2d-array): recall[i,j] is recall at ith tiou threshold at the jth + average number of average number of proposals per video. + average_recall(1d-array): recall averaged over a list of tiou threshold. + This is equivalent to recall.mean(axis=0). + proposals_per_video(1d-array): average number of proposals per video. + """ + + # Get list of videos. + video_lst = ground_truth['video-id'].unique() + + if not max_avg_nr_proposals: + max_avg_nr_proposals = float( + proposals.shape[0]) / video_lst.shape[0] + + ratio = max_avg_nr_proposals * float( + video_lst.shape[0]) / proposals.shape[0] + + # Adaptation to query faster + ground_truth_gbvn = ground_truth.groupby('video-id') + proposals_gbvn = proposals.groupby('video-id') + + # For each video, computes tiou scores among the retrieved proposals. + score_lst = [] + total_nr_proposals = 0 + for videoid in video_lst: + # Get ground-truth instances associated to this video. + ground_truth_videoid = ground_truth_gbvn.get_group(videoid) + this_video_ground_truth = ground_truth_videoid.loc[:, [ + 't-start', 't-end' + ]].values + + # Get proposals for this video. + try: + proposals_videoid = proposals_gbvn.get_group(videoid) + except: + n = this_video_ground_truth.shape[0] + score_lst.append(np.zeros((n, 1))) + continue + + this_video_proposals = proposals_videoid.loc[:, + ['t-start', 't-end' + ]].values + + if this_video_proposals.shape[0] == 0: + n = this_video_ground_truth.shape[0] + score_lst.append(np.zeros((n, 1))) + continue + + # Sort proposals by score. + sort_idx = proposals_videoid['score'].argsort()[::-1] + this_video_proposals = this_video_proposals[sort_idx, :] + + if this_video_proposals.ndim != 2: + this_video_proposals = np.expand_dims(this_video_proposals, + axis=0) + if this_video_ground_truth.ndim != 2: + this_video_ground_truth = np.expand_dims( + this_video_ground_truth, axis=0) + + nr_proposals = np.minimum( + int(this_video_proposals.shape[0] * ratio), + this_video_proposals.shape[0]) + total_nr_proposals += nr_proposals + this_video_proposals = this_video_proposals[:nr_proposals, :] + + # Compute tiou scores. + tiou = self.wrapper_segment_iou(this_video_proposals, + this_video_ground_truth) + score_lst.append(tiou) + + # Given that the length of the videos is really varied, we + # compute the number of proposals in terms of a ratio of the total + # proposals retrieved, i.e. average recall at a percentage of proposals + # retrieved per video. + + # Computes average recall. + pcn_lst = np.arange(1, 101) / 100.0 * (max_avg_nr_proposals * float( + video_lst.shape[0]) / total_nr_proposals) + matches = np.empty((video_lst.shape[0], pcn_lst.shape[0])) + positives = np.empty(video_lst.shape[0]) + recall = np.empty((tiou_thresholds.shape[0], pcn_lst.shape[0])) + # Iterates over each tiou threshold. + for ridx, tiou in enumerate(tiou_thresholds): + + # Inspect positives retrieved per video at different + # number of proposals (percentage of the total retrieved). + for i, score in enumerate(score_lst): + # Total positives per video. + positives[i] = score.shape[0] + # Find proposals that satisfies minimum tiou threshold. + true_positives_tiou = score >= tiou + # Get number of proposals as a percentage of total retrieved. + pcn_proposals = np.minimum( + (score.shape[1] * pcn_lst).astype(int), score.shape[1]) + + for j, nr_proposals in enumerate(pcn_proposals): + # Compute the number of matches for each percentage of the proposals + matches[i, j] = np.count_nonzero( + (true_positives_tiou[:, :nr_proposals]).sum(axis=1)) + + # Computes recall given the set of matches per video. + recall[ridx, :] = matches.sum(axis=0) / positives.sum() + + # Recall is averaged. + avg_recall = recall.mean(axis=0) + + # Get the average number of proposals per video. + proposals_per_video = pcn_lst * (float(total_nr_proposals) / + video_lst.shape[0]) + + return recall, avg_recall, proposals_per_video + + def get_blocked_videos(self, api=API): + api_url = '{}?action=get_blocked'.format(api) + req = urllib2.Request(api_url) + response = urllib2.urlopen(req) + return json.loads(response.read()) + + def wrapper_segment_iou(self, target_segments, candidate_segments): + """ + Compute intersection over union btw segments + Parameters: + target_segments(nd-array): 2-dim array in format [m x 2:=[init, end]] + candidate_segments(nd-array): 2-dim array in format [n x 2:=[init, end]] + Returns: + tiou(nd-array): 2-dim array [n x m] with IOU ratio. + Note: It assumes that candidate-segments are more scarce that target-segments + """ + if candidate_segments.ndim != 2 or target_segments.ndim != 2: + raise ValueError('Dimension of arguments is incorrect') + + n, m = candidate_segments.shape[0], target_segments.shape[0] + tiou = np.empty((n, m)) + for i in range(m): + tiou[:, i] = self.segment_iou(target_segments[i, :], + candidate_segments) + + return tiou + + def segment_iou(self, target_segment, candidate_segments): + """ + Compute the temporal intersection over union between a + target segment and all the test segments. + + Parameters: + target_segment(1d-array): Temporal target segment containing [starting, ending] times. + candidate_segments(2d-array): Temporal candidate segments containing N x [starting, ending] times. + + Returns: + tiou(1d-array): Temporal intersection over union score of the N's candidate segments. + """ + tt1 = np.maximum(target_segment[0], candidate_segments[:, 0]) + tt2 = np.minimum(target_segment[1], candidate_segments[:, 1]) + # Intersection including Non-negative overlap score. + segments_intersection = (tt2 - tt1).clip(0) + # Segment union. + segments_union = (candidate_segments[:, 1] - candidate_segments[:, 0]) \ + + (target_segment[1] - target_segment[0]) - segments_intersection + # Compute overlap as the ratio of the intersection + # over union of two segments. + tIoU = segments_intersection.astype(float) / segments_union + return tIoU diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/__init__.py b/Bank_second_part/detect_process/paddlevideo/metrics/__init__.py new file mode 100644 index 0000000..b693b87 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/__init__.py @@ -0,0 +1,36 @@ +# 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. + +from .bmn_metric import BMNMetric +from .build import build_metric +from .center_crop_metric import CenterCropMetric +from .depth_metric import DepthMetric +from .msrvtt_metric import MSRVTTMetric +from .multi_crop_metric import MultiCropMetric +from .registry import METRIC +from .skeleton_metric import SkeletonMetric +from .transnetv2_metric import TransNetV2Metric +from .youtube8m.eval_util import HitOneMetric +from .segmentation_metric import SegmentationMetric +from .ava_metric import AVAMetric +from .vos_metric import VOSMetric +from .center_crop_metric_MRI import CenterCropMetric_MRI +from .yowo_metric import YOWOMetric + +__all__ = [ + 'METRIC', 'build_metric', 'MultiCropMetric', 'BMNMetric', + 'CenterCropMetric', 'SkeletonMetric', 'HitOneMetric', 'TransNetV2Metric', + 'DepthMetric', 'MSRVTTMetric', 'VOSMetric', 'CenterCropMetric_MRI','AVAMetric', + 'SegmentationMetric', 'YOWOMetric' +] diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9629b72607ed5049aa908dd6499745d5f309c3b8 GIT binary patch literal 1025 zcmaJ<&2G~`5VrGg$By&UA4(~3?WICJA%qZZL86BwQWFI+inMa$rC6P{qxB{z&%j%7 z<1Kgu&bh*cSK!3X5?d)q*z%|E8_n$Oe4fC^Rj3+X!J4Q;-S8?lgaeM@HFQN2nugcW6F&HcH?SoF2n=_y zEjrLK+{LcwLC^3e?ucF3HQd8Ju@C!(`*=?rz=7c{ye|&n(C`2sh$A?%ts5(9f41Ra z)EQaF-JiA|IneUyrXYFZB7X(Je==(xgalk7bx-1Fj~gMa+8>t6{XB+RGjc-h-{%^G-E?A z+wwcFp=rSlmth_t55QffSsoyJVDH~i$$euRG*{`zG*2hz)^)~0M8>{Yaz|?ezs~uy z>3NvkviC9a><@i%I-SdO#sr}Hq1kT2tir&D3pHJdUPC$VDeWWHKAo{KbEAb&w? Oo;}v!wLJSjZ|OIOZxlZO literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/ava_metric.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/ava_metric.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..48d88181deee42d33230a48055bd7ad33bc28b13 GIT binary patch literal 2406 zcmZ8jOOG2x5bmD$!}dC16E+WoQ6j(>CxWa%5uj`mgd&j*3Xj8RVKkX;d&kUpobH(= zG2YWg%7F_P?z_kQ4SoUVzH-VRK!O8M)nj|D9cya7u6|5)*H_=TY_|gf*B|yT?6(#n ze_~_(vY~MYZuu)1Mi|XWMD^2%40sy3Sy+)pvCquy!ik*1joiYEyuy!s@LSBzgCdMV zjh(zzw4=5jPxDUHfq8DeQEWsTy5GyY#kuGlCEQ{D5sl9Kgooodz91}M;S0h--aazH zzscy=q~CfCQIXv~RpBGSxZv!5mR5aB1tVU?c{v(!p{%@2nDU_&KS`=|U$u4)xJX9) zA+NZ2O<@ICzaD%R2i%6+gj@a&rXok=n9k|kn7bz?C3AC5Vq1Ywm!x zM+B_HXyr19<;WO9Jb)n{jcvg80y}`61$F_u3+w^*7T5>uFK_@jSl|$FYk}KnU*0i{osPRdKBRVV3iFnpD6){w&RF#$$A;AWxp~yuqEc zmQ`8AX`V>QrE(V>6Aolm7+~v zfnXurgIoRpW=_V)dGmw<-^tiu^b$EXE9=-oR*mf~f;~<9&|=0hRKVC>jvRYep#RXW zeDusI)Bse$+&*$Zm2BXnGkd?Dq7*Et*kiTGCZirt(*0frXSm{~*nn_mm$Iq6-TV1A zaPhF0O=Oi!Qhr17bRbZ1Aaxv>5{OIKa`>}~Pnb@Ea+)`ZE6^jZ>TalkBB=zPqB1dC zsLOpvyoC<0A!x>wg~?ZLSy$7#lFeKb0uk3>Tw|^ydJl{~xekDqb(wn9qFrkJw`I(_ zrzhXUk)p0FFT}`0J-Z74REER^l!nCcU4WCKyM04h*<@I%5W|tE#C*~>b+BRpbHoia z*H#8&Qe7OloPg7J!7DN64h`t+@@ZIS2c~$S%L^x+F84X>ffQ*%$ia#dyZumv5X;)`G3`w)u1Ztcz@tKH66h4^eD^JVaFK_E!H9TMpsmrmU+(8Dk~?lQNVL+iZiIIESCaVDKPW8F0@)IPw)|F zq&hX42!v3=)l(YqB)CuQQjxb*?flNlPI2E U%L6sr(u#(tMLolymVJ@_4-a-*#Q*>R literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/ava_utils.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/ava_utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2d80209b1fdb74b371f3b3a27f9879c905fb585a GIT binary patch literal 10787 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/base.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0e4c617d3f0b9e7282d83a3eccbd0dbd53115429 GIT binary patch literal 1768 zcmb7E&2Jnv6t_LIvy;i@s~-pz1g1iyD^*K@TZF29P(g*7L+NR?($qWlZYG`CS!_>B zSLuc1hWH=aWBwb?zH;iB8;6$n#z}S(!2wHt^Ze|2@Ap2dwY7x6`lIuk>~{(I6A$eb z!r=~VgG3TZ3sTY{rO2~_4Hej{BSS>PJD!W(7T@bBJl}%-CY?{v|)m!QxMvopmdHnExhX1u!2M%{&n;(EE zGNh6KmUYQwa72f}N+>sEM}_+x86lm7vMb}G&M;D4xgwJza!7|U@T;=d@GEi+@NK%} zo-pc>vO3Q+`ko;(<4S69tMuNF=(X$sqPmQDL zG12QF`TMro8Ql}JXXzv_l=1AXuSauTWy+XFI+_b93-vsgsv1Gi!9Oz^gRg`6OBbhL zG`DH`0cbO5DWVbW(S$B8FXJ&deWfuskS}5PluoPhzRIkNw6e9HW$4rC!q{P=?!z{p z1DTRnfhGI&HG>Gz*TEa|hEW2N5Y9}}-?2!TxC;incK$@oOr`lmS0xuk!Kd@uaEMUF z1uvjjxR^cSchp4@7|d)!3v0>X2U zP7z7|MN6rY7okB*g=ihhFY*f9Dz=x-$F)_`B@oWk`|iT5mcm6IV?WfZkSo0f#I3fx z8(umWsubhj6rd*?_+!N4jrYoxgQ_Atf3Odis$9LP^E$fl29bv)Z?rW#vD_3dAG6;m$whJ zuJkeWj$#kBT!_5#n`pV|c*bb>ezDa;?qB>TVEqyNi$K5G7Fkx8b@4yIY7CkFoBXGoUeI)kP$PFG=@4}ruap)3yHg_OMyS@Mo;!Z}>0&8z;33&c3{ zN*h~St)pDI9vd8$ythFN2PBJ0W>7DAC?b(^` zVRa9eJLv(0EM+;ciCkV18xFARmxS*^enB4ckN|#7W$>Z)_T^PMwEz3wVFeq?@!eeX3z`4?&&JxnyN;Y|M&1yh(hR64~~?WnS? zb#!?(I;Ol@oeI;KKD0+p$59p3jiEcLcB-;&4r`-&r;fV9tYKr+>@-y+Y_iI(+G#PH zIggdj0&`gv*F{!ibzGN1XR!RX!WyjkSYgeux~rr2DW=|0+O21pm$Lp$McGz`_3o{^ z@4s^cHTQauhVOBQG3CW{v2rV9q$|!ggjV2>hqF7ce7STtwT~RHc^l|G*BX}e#7+*?@3MAEG82e>^ zVMlT1Kcc6~8agQv0v2J#yg@FB@=%;$~NaSI)|~-1`1oRsWr8QUrjYseg>j0 zDZ%`(Q6c4(oA(%%Ov#m9bw(SfGId$mGG$CMggclc0LeB~D*OqWs6ZrSQ-brC<>u?Fqgi@0&j;93w= zaLPUVE_O3l1~4UplP4N>3Hvk923X%>g|Tynlo`ilrj(h-WL969RdCukoeaCQt1|2u z{}^=#b!$uEALrIyC9~-s_RGzj%-yTz#=a`A*h84Jdq&AkDtC=pHLI~oG1jhjQ@Q`z ztd`eucT4BHc{Q&=1L{TJ;yD07BdbCNA%ua W**e6dF|7`JpI*dVQ+C?nKg4K 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 NXtoY%(`cVo{}W_s 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 pDruUj1#V#`qogoA+p*jA8XhH*3+I$J zO4952UlZX9?~DjfI;R$lmId7*wbD!QO}1-P`v)=$cR4*xv;m~H3$}O3xb`vyb z>(TDxZyxG$5(yE@&8MOK;=$eJ5elUKvAs{==6RETphV5QE3q$Qj`)R0Ttey0U>AC8r zQhSJ)Jr zH!6+%A?W}CkGT3hqaD_<3SUO%9b1%sV>shB8S$wde&rgwJ+;H{Ut@Qsc8Kg6yF0Z* z%-7hxsU22xjlDFr!#c0A<4T=#cgQa&1yXiAknOQt0@)eMKFID^E`#iid-8f$qJ6@w|lL=cHnGxqf9Mh@HYW!WwnIUyy7Ufh30rZwcF3L zB+t?}Ny6Lc%)l*luEr z^XEXk^`NNECe>E2`rC!vPa4Gp= z*zJovM!6D(Px2@(ET;Oa4`9Cf5I|SQH%wE)VGHMidkd!^m6Z#C1t7(u?~w)ORTgVz zv{un}FYm&gau+Aw2GC1$S5Q6A+HtBFj`Mx^=b-SyhO1E?;5k20cz2uBPR67%j_2Z- aWy<@kSkeO|t+~8B;vw-_g?fxztMnfU2Qsw) literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/msrvtt_metric.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/msrvtt_metric.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c1574d9bd6265fbfab2d2c57e21d4cc783bcc441 GIT binary patch literal 2069 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 QH(eHdR`tD2duxULKiIo?2><{9 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/skeleton_metric.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/skeleton_metric.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..10e12cfb0d05fe396cc99a08328137f68e50b4ff GIT binary patch literal 2689 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 HdO!Ogwgirr literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/ucf24_utils.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/ucf24_utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3597d80a417d8a9cba3fc7cd239fd9125314548c GIT binary patch literal 21997 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 OGY#V>3G=(fi~k3@;V-@b literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/vos_metric.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/vos_metric.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..004dc17df1be64cb0013fbde3c5c5fc7c1b75af4 GIT binary patch literal 8918 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 KyBWjeM*cs(k9mmz literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/yowo_metric.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/__pycache__/yowo_metric.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3815b7daae2a80bba03e8a029e599a8e09dbaaf6 GIT binary patch literal 2554 zcmZt|%WfRUv3uS#``}Wh`H&r8oLsUifGarwkY8)^A~j3=KfLVBftHW7t-5AoI$IK_eiUrt0wbjriSud^at!S&=HfRD3D_Qrjpm zcsvr-B$jAr3?>cC<$pJB`sb}ZVFQ{4OSj>IIA#Sh}0Xnq@&{f`w5T-+RsYF08OX6g_mASp(-7-_R?wELT%lZPVUu(OPQ|;!Gfp#P>Mml7vN)wr% zavdF{Dmyf|=z!-0R2&gq1Zx0v8&Vz2P+UAqi?68;lO!urDU;-D^5Z>zbN^0SK20!c zvO(Y5-Jgmo<8TD2`zxux-{hLye^H%ONwXPDUx*ecdIzTL0qAu++I(%RN1a!vZ>*%$ zrAM;MqJax!9VT{+yD;T9P?NRI=nk1Xuv)OXiYQt;3%a0xBv1Z6_mp)8nQ-JlR(Lz) z+?xB!t$k)MtiSwi9zcEo6;A$j9x6}yb;z6@0?^$d%zKM$lLck|2Eci=+TzVbH8J>w{}oh*ZhhQbhoz&bFTvpY`g`(1}$teuzG`RksWdtoa6bm zx?8Vpka@3$yjGEF!Kn^PVu8`n-6ATgdkeZnSc69^cxwf3uizbnuWgZYO3Cr;_!pl- z*LC1qK$Vrj4I=+>0v!B4gL&MA8YD;UO~Ra~miS(E&bq93wq~e3;H<;Ewn45#6i^}~ zPw7vJK|%2(XV0~JP(A1J)H?ZU{ zbd)6UcFqdK+evafON%APPZCyTNn-k-xP^v%06=$^tv2ID0omJS3TqfcH4EFbM0 zz@Hj{ff=^UW0f>#ji=G8mlwD&DpxGM%BbM|=GXrL11?d08!`j)3BSN{>`nSVZ9{%t literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/README.md b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/README.md new file mode 100644 index 0000000..7414d0f --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/README.md @@ -0,0 +1,2 @@ +The code under this folder is from the official [ActivityNet repo](https://github.com/activitynet/ActivityNet). +Some unused codes are removed to minimize the length of codes added. diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__init__.py b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..34f17ef94ddcc614c6543486e61471babf1c710c GIT binary patch literal 174 zcmd1j<>g`kf(xwODIoeWh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o0~{)hfm*F)uql zEi)&z7{W9#iYX|{Pfjf^28+fNB&MX~q?To-q~^!urj`_CCKtyfmL#TjwmL literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/metrics.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/metrics.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..39f6227f76f4c9debb019f08866e0dcebf4a3096 GIT binary patch literal 4487 zcmcgw-EZ8+5$BTkL7nyGSgxfwNQuBrqQ*JNG5Vq!Zd}_bS`=5qE?iWxab0ouPSo+p z%Pvo{4ph-r396zf`q-BiupaZ@>anzH+K*=!Dpt>5M$K&{Fa645$ zPs4yGB9K|we1>J6R_M{s_#uTWcyHs?|3Z^FIm_6Nd+4eQIot8juk<{9A*ZpWu9M8{1A9(-_a%v)O0_cy6h#-Y`A- z(qXEk-Ux05ojB!LkPQ2S{eUaQ_i+q36D<>SRzhad9HM0@1;l(y#zw$an#PhRuNIN1 zph;dH`@-PL}xq+rM6qS&m#@x zOYVm}9?H8)rD`LHIzhHA!2w?jA{``YM&f7;TZTn4a>hQ-#-e04RLPXA(j7N~PZYO1 z2Y;z}sY;OULQ`uVDS|YSx*7a(JJO|EWanK{jr3@NfRszp(_6EKfaT5Mk=2`}0DFF? z6)6{dK_jaW0;p8B6hxYoid!xJ7tKz|8T*FS@)<+yjn>DT=nr)kY{@_)$YU9Zs4o+W z?0{Tk+CN4gSpN%N$uZ@RqaU1j1-VkWJ$=I7$F^}A*|zmV_)@c6gVM+u1;-Add7qRW z$)=)xth%jM>)CTWtMf$zIce;5g_{hDdLm486jhP!4`flHJr!OolcK7(IYt^MZdiDF z*e~iFA(yJGsBvw0yePp(IPBAG)db#Zqo`S16g8{lX3YjeF;Bcww4+2saQ)3C+I)L* z?Cml2MH5&r48MU@+NT)w<^>u%O|FZX(&3Am^|vn_bqUt^_dU7s=*K+iwL4KPwe7Bd z^k|?`Xrs;OqX8Epmb;OV>7#L0f5dlrTaw>%%Kek!=3u{Awh(|#U?r3D+jdEyj-x+9 zv;4+9^VyrO&*oj1xvcVh(es(_R#?NGXAR8xXz90xxp~m36|jW_QIn^NP8~1dh5kDZ zHV0r09kp;ozf8?$&KL!N7s%J1!Ga2q<8tO55iX#wzY8jh1kMgJ^iBOQDv46*<p=fv#iem0w#6@|Zyb?@LkWO^Tzb7N_9qTXfLvEOA~@0k6GaLJ6p z8knK61BaxL_F{h75es7B(7WS2UOXV|o6nuxU4iX#SNNBl73bKc{tf4|zhRba=?nG+ zD9EZ}fqFg26!jI%Tms&KYVpV+q@$MfTyd639!8c3A1iqU__fHt#t}{M>lSh<@5Qxcwlf_3hF9R}c=>u51P^-U6hZMF$(%Qw4|tH^M)Q8Ld(C zr&Fexfa9e6vq>G*LP}6VY@_!}J5EcTV8=96jB$T5^+Ija95r7n>jhxwPO^$Y2t|2j zw0f`f&dEaXM5-_pPvE=|^65IcLv!@**kIp47ZUtT9$JHP*mb=63Yy;|Y97xWAewV# zqKOHIBC^LGI?VaZ6%29Y8r@nZb+5XG+gvYL^d(c@fdDh8meDI_ZggcLpA6K^Z4ys4 zwEMevoYB=uYCi1{h_dF5I7L~mZ#GNT(f7`5i=(VbJ{-pk#j1hIXS5SVX?XR#I!Arl zR^hd7wG=I^YSd7wR_CdiK~q!+kBbWLM+vq3N#Oz8i>fhgaV|`gkY_T%ThuWd^$AM% zwxyD47W}JKMPOpLeVGK-$M{*Ce_?CZE^iUNG0w^>jc^w2EvB26|&{ZEtU{snV@9)6MirlZVY=Z|%3c-R_#|t{Hm0 zCUA3zxm5Z?8HT&p)|&&-IaO*03CD%dmgz{yRQR5)iK9L+z+M`85XM~Vm!@G`C$*z~ zSGS>S+fZ%<*X~&NqlAKBpIl@>J-%94@u$)j+$!UM6>{Ayz;y9()s6+n)-cFL)+$AxTs~f>^I35( z(ch5VKYJ6xI*9yfwO@N#)FuO3CVN+e@~0M;JlvkLSW%0*32vdtRy7e(4N0+z!Z8vi z*|t_IHevWuDct`usoq176doK1JQrVj{Kb3U@(^t7Q=w~Pe_;~)*g+fneu5cI8D((^ z#U~=({m+%>ifYu=T2XJe1x(W}s#tBXZ`3q}s0ngIH6{OK5&s5Cl3^@wQoh&bpBM|i L>wEtC?DhWww6iD; literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/np_box_list.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/np_box_list.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24a08436e18b23f1f0b9d1c8370ade61a1cab3b6 GIT binary patch literal 4861 zcmcgw&u`qu73PrK6}9?lJC3EsX(w$8REe@lT{j0oFk(AR5TMu=u~8I?1Y*P)X(>_U zdWI{nwi^_U+*42OwI~oDed*uQGp{}Q+*>c{_lCO^cjX`Lr4*K&A!pvadGCGSd!uY= zspa7MN8?ZO{cDc%PwLb!51mi&GvCKeIy;VJ(oNWo`?(`M=|6F#f9~#h(tY4;G=}eX z`X{|JelHvRGB!Dn5@C!oT%?j8^wTJhv(&VoLz2^p=w82EbUwk){1!Lm>@ck6N=CA! z_r%%pr7s(JHe^%I;n|ddoX2xcw&Vhyfn1bJc+SgZxq@d)uF5NTF379$8lH>t4d{5i zm>X*+e$N~SZ60MwqO5N1R*U1BsIOH|E2GjJJKzazC_CW$SwEF=dWgn=wq|&0_bjv) zXPf+SS82tSh`Lr(eKd~^uS6p&cc&8-Qemr8L)7{N%2(TWrgX@)SUuREpJ%*;4F6-g|) zj89Z*2$%dI(-#7(xx=@t{F6Sye_u^6(0)!ndk$MU&wbp6{EL@}9jnwO{uwy!R>q6%7mB&c;H~iV^%K7ipvl zH|-U3skAsQS{LRjyhNo%!#c2NNK(0&vs(V_*0}NU?P4X2O=wLTTIq#PX4`NJ->Bq3 zUx9U=IT{S>{QIHW+Px>z)_Ye+F|-GmHH zQa4;{1-*#&Gp4W7d$LD)djqXv9-t}B_c6NvB0W~!;gyNP)z?>ROd0Bl)%#QDoLP;( zH`bU~GR@KtV7M`DwWnm!iWJBX@H1<;9YW4t@HHq!I-n4D#Qy9)qFl$yjnM|+WViiM z!H#FQ)7mEIMA=F2&Nc}o>1)n#bF!a9m4|AOYXP4Vg|@eoEE0*igT`bcEJd-S$)U6I zS7!xm(I8TLxc0I&E-`N9Y^noB;J_p2l-$fZ`X=5ybFHU}hE;J^gZZwYfQ9mRFxGCc z#V#CHeT_VPo?O(XpAE5JqcL*6#mY~aUdow-sc$&ay#d#O?cI@kKrZRxMm zc>gK6;~k7I8Q+E8jS<^+WD~m2iN7P_?jl`T?kclfPesT=lYBK!bi}ilIo$4uNF4l6 z6x|bA0EJ3ZGPGIK^b|7M8HP+{K}x9ms^U(PPM3%X*`TtiFLsrXG<-q6piI$jw`X!i z-c@!>Q*!JI#$-`!(=nxe)CAyF^2^1N|3x~fX4�(MrfOt_HU9(N<=aE(rA)en}C# zXlZttffFbxorpZ@qD|tv$N6E zoW@fy>jk8_uCfP$LN z4bv5&B`r9SO74sOTfh8I)nPm?#>$yw0=kAx+vmd-ULn+C9N6ISRf!#&bm+`CgADy6 zyxYakP-1T_ud+JfSMf822O3$00|gL;!&Ap*RS^CkUFja6w)h%>fZR=e&-T5l@7q2~ z|MB;R?Kej5$Q${i#-R^nHHUxrT;a@_QEb;M>KfU+&MlKe-fd2}CzpA3F#C9xE zm6Syc@SJX_6$k^MCaQUMRuHIRt>7;j_OMqp>|xLL#K88%V8-~x3K_UIH-$h$3>P$4 zS^2lfhBs=stdE|;C}~zXg~}5;ZJjfHbHqM%_O8PjID8}5!a3{Cv5&JB++zF4z{kFR zi#f9KzDx8 zZm-69my!FDtob_Hs|dA*BU{T};?w;sOB4VYWhTq z2z7|GiBh533}FsO^b~XGNKgL@Aqj)mN+@TMEiSTT8DHePGRS_6)@Kh9VU+78$&IjE zu+y2~(NxX<4!<&B76N3mCUd{@-HU*kImC1}mgroOqWB5Jq7{ZGnd~RjUJOIp@A%7H z7|JXPLwz0M%VhgDwK&~=NH+q2r4IcbwMdnkdQ?SgIss_PEYz?En85K_un@c%`1tdJ rYe5iPU0kwbHhlddh7}EqQ5{U?zDQ^hY?pf9p~P%?%U=%MtKNSALC^LN literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/np_box_ops.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/np_box_ops.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7df2341144357dbb2afa71905fafc36591dce74f GIT binary patch literal 2883 zcmds3OK%%D5Zy}go`gQ)1U>j*8%WTLs$jv0w6(6ZyC7G# zWUNkUdnxiCnqzMH7rpkp*Pi?ra%eg;E9>DXX_I3YAZIw7;gU1o3>mGidIo%dy1$8E zR}JGY9L#?f4DLeHcc2qS%MhlpdS=TKws3wnTDEXS0jML2q6E|xW#IuW29BXwph~T2`nI)9>j5^5-FMqPx{kf7acK{VicqPMgELzBfkP$z+w zEC>^+wCvzkZ%4;c-5!L%GTn(_bKV&o-`MMzNG2chF0}j5^j+vubdLFpC9DJM+H7Rw zXmd7p7G~Xi_KE@SDxAK!pYK}JPFZw-$0j%6*|yc8&QFOWnrX7VnJd{zkaU^u@>rfb zx*PS#n|rysM`wQ^lYt87mg4gPSzP5-{n5n$4d>jrcZLX2=!-KOJLH}lRWoyGe+oTB z-OGov*}liapZtTMCw0!=X|!V%b)?oLZO2@Qo;(hOjM{yfsGy_U{FwXlnD+(*qjnhk zu(BV;dMh4f4o37E{6iB`%c=x?2l?}F9hd?%3eyW<6646EPyvRY+HGfSjqR~Bc1aEa z6zB57xHvA2%Zc&3l{(PdY3Z5y%o=;ZJE=vI0!da-0?kcVjzE%n>B^=7niY^)DXa{( zWzt+l&D17IktAyI50f5t~PZJ(kIdl;OXDrru<4 zi8v+bMcg3Z@S~tM-e$kMV88p`xZAyeyQP^*=O#>_IS^Wf-E$LAF${FIm|0<*xjOCz zNmlF!VbCA+vvQ(%sN+aWkbxe`+*7F{4XT(r)%C1E$E;6iqg5FBU|w$(h7$^7KFr5N zX&&@wKG)~Ne2jF1_j*1aK%>1s0^nWYG68CVmd_A^_l5O zAd;@0Wu7X6SF*}f0m|AJAkm*dx9M$~8`g&Dn4VcMoxeBi8DFy1hoG{MO_)j3qIVAl z2^6-}d}58Q1hVRhIkthCK%K-ovQr!L>8VA$19t}SSB=!#G{$ZUnQ;Tlp2KT1eCy=^ zpD)RCD2FQF>*Ylo?+Qfdk|O!;c;BL>-UslLLOa>ayHwg5do$#t!Q>*!H%2&Dcym+b ztvVDas(q>g(riTzV;%}$1btmCsLQB%1t-c=6l5-z&U#K7nM>E*MbOwmH24neG*(g1 zE14zpx@DQxE9(`Y;|2&9(1GcPjcV=Zz|5oL$VzNPMvjQF4e_@r{x*O4ALEZZo-cAs z!oTy{Jx)e9gNRqBrpZZ^*Cp)h3_OKQg9Vxic@TtBu*owafjm?TkAun03@-$-`7*z% zx7c0;j}3a2z^`znFiMyn_48}2Mu5tvb&c)pZ{NgU*JzC@`|O)@QG-PF>i-(ed=bs~ zW*{`50~s-_KEe*KbC6B}tgeC}$Lwnr4#3JEz_i99<*jW1Sk=d9U(AZWFQSg`XD+=w tDM|8l!3sw}Ce=Co)5C=-XX)#HBnCbCE$&m}-kh~kv1FGjrR$Z;{{SunCAt6r literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/object_detection_evaluation.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/object_detection_evaluation.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..40abd9edc765a70bb72193e7d16964a06da8324a GIT binary patch literal 21478 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 KgtE71#{U=4s&mo+ literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/per_image_evaluation.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/per_image_evaluation.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a74a9bb2b2bf770af69feb02a0a7178a2814800e GIT binary patch literal 14716 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 MeZAe@)V3P`1CRaqx&QzG literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/standard_fields.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/__pycache__/standard_fields.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0609b8d5ec92c658ae5d7e706cdaa7ceeac1e0e GIT binary patch literal 4585 zcmb7IOLH7G5FUHi_S&)6@A#2G6kds|j6+eJTojdu!{g$jk{n<#HPMc=yCSnQ8)?Rl zbA=nfgrC7b;KV^!_!XS!mPVQxvnI}@wms8Qw_2_4uUpBMmKFkd{+Rid{k{ZeC(hDSp5`KhS%u<^^fO7a-cLNv3FA5ZfuVzig{MYRaCNvq$T#V@ z$d71FzZ5)S>X4|Mri@CEHVmt&cTOayjLUmt$;UE_xl)p#ps`_E23lh9N8_1-ulw**V<0>Tr@&j&Y$|NA>9EaO;S6hsvuq}uW3yq0 z&4u%<6E3j%@EThP7umINi7kd*wiGV2Zn(mh!&SBtuCdi{ovno%Y(3m$8{u`f8E&!b z;Wpa}ci48g%XY#WY!|$KLoZ+O4n61u!7&|y`_Z@gkQ0IaBRNmO9}1jH;Q2ZOPnuEh zOa>md9>voF`8-3<8a0C9soA5vpboV?8wxn>VOAvIHSW&?7iT=q;80MRQ$k+w^U6Bs zZex};GGYSa0b&Ki3B#tjBzcfBBJxWX9Kmu4ENArjCDD}911Oqu&YUYAqN1bc3a_O1$QkB<%Q*6sdSwaNIrYO-ioDS;}yG z=o?(Hny<1##yk=Xg5A85tbbvZra)gL98c|#csm@+iQ@Sxo|C(0B8Q_w2aiTsO2#xF z?o~?1q zvj#EKoD(m&p{~wb0RmUH!Ppn&=VP>_5;SaL*yJuh7#tA(YMh8z8Jn z-ceC3vokoOAC4Y>`{ePX2hScK?VFsb8;7OKAA!ac3D|6wrcet2gN^Qeat08NK!#uiz>b@3 zs2Xy5DiXl!I8F+aQ=G;_lED%N`f)izpel?r1^GKUG)u5|vutEmo^$-j&P$=bK(?9M zh3`Z`Qp1_`iCNmsuH@@3bUTSgRJ{N-cC5?@H%QFj8x-^~TdBlSd5M;4#v4@m3~Ly0 zhK9?h!SG;N}Y>Pr#I^y4_r-g zoPyA+yDlAV>g#p?T_v#It!s2SU^7(TnmAUamcBW0g4=DwSQpJo->wTeb|Vq=c6~}c zxSMV*LsxH33_`tfF}{xXZt6}HVapIjdLfFSZ7LFcUyP!c1x?D4xhP^;97S>(+FRK| z(nd0aWEROB66iStIgbSI74jOAMI=i|x=5ChtRPuMvW8?G3EV#dxryXDk}V|LNOpky z7RYz;9mzl6@xzmcG<^|aAS(O%$)_i9me}kY?g_>?bSTjHWhWyJon5R>=qZi(DNPEf z=2?2;I$jXK`^3TcTw)iG3#-q7bb|I&`wslB{I4@*G{hj>c>Lu6)xQ1Z02=&7y*csP zLjQyVIsWgZ3h_w+P?@$8>MQhl*!%;2V70YZEWF1Uw3yWS`gFf)=Luo^R;{hS=3P>S zD?8z=EKEAkGcZ-*ZKcVCWdCzrVm~3URsJ?RM54{tNhTyS4xT literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/metrics.py b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/metrics.py new file mode 100644 index 0000000..13eb034 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/metrics.py @@ -0,0 +1,143 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + + +"""Functions for computing metrics like precision, recall, CorLoc and etc.""" + +import numpy as np + + +def compute_precision_recall(scores, labels, num_gt): + """Compute precision and recall. + + Args: + scores: A float numpy array representing detection score + labels: A boolean numpy array representing true/false positive labels + num_gt: Number of ground truth instances + + Raises: + ValueError: if the input is not of the correct format + + Returns: + precision: Fraction of positive instances over detected ones. This + value is None if no ground truth labels are present. + recall: Fraction of detected positive instance over all positive + instances. This value is None if no ground truth labels are + present. + """ + if (not isinstance(labels, np.ndarray) or labels.dtype != np.bool + or len(labels.shape) != 1): + raise ValueError('labels must be single dimension bool numpy array') + + if not isinstance(scores, np.ndarray) or len(scores.shape) != 1: + raise ValueError('scores must be single dimension numpy array') + + if num_gt < np.sum(labels): + raise ValueError( + 'Number of true positives must be smaller than num_gt.') + + if len(scores) != len(labels): + raise ValueError('scores and labels must be of the same size.') + + if num_gt == 0: + return None, None + + sorted_indices = np.argsort(scores) + sorted_indices = sorted_indices[::-1] + labels = labels.astype(int) + true_positive_labels = labels[sorted_indices] + false_positive_labels = 1 - true_positive_labels + cum_true_positives = np.cumsum(true_positive_labels) + cum_false_positives = np.cumsum(false_positive_labels) + precision = cum_true_positives.astype(float) / ( + cum_true_positives + cum_false_positives) + recall = cum_true_positives.astype(float) / num_gt + return precision, recall + + +def compute_average_precision(precision, recall): + """Compute Average Precision according to the definition in VOCdevkit. + + Precision is modified to ensure that it does not decrease as recall + decrease. + + Args: + precision: A float [N, 1] numpy array of precisions + recall: A float [N, 1] numpy array of recalls + + Raises: + ValueError: if the input is not of the correct format + + Returns: + average_precison: The area under the precision recall curve. NaN if + precision and recall are None. + """ + if precision is None: + if recall is not None: + raise ValueError('If precision is None, recall must also be None') + return np.NAN + + if not isinstance(precision, np.ndarray) or not isinstance( + recall, np.ndarray): + raise ValueError('precision and recall must be numpy array') + if precision.dtype != np.float or recall.dtype != np.float: + raise ValueError('input must be float numpy array.') + if len(precision) != len(recall): + raise ValueError('precision and recall must be of the same size.') + if not precision.size: + return 0.0 + if np.amin(precision) < 0 or np.amax(precision) > 1: + raise ValueError('Precision must be in the range of [0, 1].') + if np.amin(recall) < 0 or np.amax(recall) > 1: + raise ValueError('recall must be in the range of [0, 1].') + if not all(recall[i] <= recall[i + 1] for i in range(len(recall) - 1)): + raise ValueError('recall must be a non-decreasing array') + + recall = np.concatenate([[0], recall, [1]]) + precision = np.concatenate([[0], precision, [0]]) + + # Preprocess precision to be a non-decreasing array + for i in range(len(precision) - 2, -1, -1): + precision[i] = np.maximum(precision[i], precision[i + 1]) + + indices = np.where(recall[1:] != recall[:-1])[0] + 1 + average_precision = np.sum( + (recall[indices] - recall[indices - 1]) * precision[indices]) + return average_precision + + +def compute_cor_loc(num_gt_imgs_per_class, + num_images_correctly_detected_per_class): + """Compute CorLoc according to the definition in the following paper. + + https://www.robots.ox.ac.uk/~vgg/rg/papers/deselaers-eccv10.pdf + + Returns nans if there are no ground truth images for a class. + + Args: + num_gt_imgs_per_class: 1D array, representing number of images + containing at least one object instance of a particular class + num_images_correctly_detected_per_class: 1D array, representing number + of images that are correctly detected at least one object instance + of a particular class + + Returns: + corloc_per_class: A float numpy array represents the corloc score of + each class + """ + # Divide by zero expected for classes with no gt examples. + with np.errstate(divide='ignore', invalid='ignore'): + return np.where( + num_gt_imgs_per_class == 0, np.nan, + num_images_correctly_detected_per_class / num_gt_imgs_per_class) diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/np_box_list.py b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/np_box_list.py new file mode 100644 index 0000000..f9b101e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/np_box_list.py @@ -0,0 +1,138 @@ +# Copyright 2017 The TensorFlow 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. +# ============================================================================= +"""Numpy BoxList classes and functions.""" + +import numpy as np + + +class BoxList: + """Box collection. + + BoxList represents a list of bounding boxes as numpy array, where each + bounding box is represented as a row of 4 numbers, + [y_min, x_min, y_max, x_max]. It is assumed that all bounding boxes within + a given list correspond to a single image. + + Optionally, users can add additional related fields (such as + objectness/classification scores). + """ + + def __init__(self, data): + """Constructs box collection. + + Args: + data: a numpy array of shape [N, 4] representing box coordinates + + Raises: + ValueError: if bbox data is not a numpy array + ValueError: if invalid dimensions for bbox data + """ + if not isinstance(data, np.ndarray): + raise ValueError('data must be a numpy array.') + if len(data.shape) != 2 or data.shape[1] != 4: + raise ValueError('Invalid dimensions for box data.') + if data.dtype != np.float32 and data.dtype != np.float64: + raise ValueError( + 'Invalid data type for box data: float is required.') + if not self._is_valid_boxes(data): + raise ValueError('Invalid box data. data must be a numpy array of ' + 'N*[y_min, x_min, y_max, x_max]') + self.data = {'boxes': data} + + def num_boxes(self): + """Return number of boxes held in collections.""" + return self.data['boxes'].shape[0] + + def get_extra_fields(self): + """Return all non-box fields.""" + return [k for k in self.data if k != 'boxes'] + + def has_field(self, field): + return field in self.data + + def add_field(self, field, field_data): + """Add data to a specified field. + + Args: + field: a string parameter used to speficy a related field to be + accessed. + field_data: a numpy array of [N, ...] representing the data + associated with the field. + Raises: + ValueError: if the field is already exist or the dimension of the + field data does not matches the number of boxes. + """ + if self.has_field(field): + raise ValueError('Field ' + field + 'already exists') + if len(field_data.shape) < 1 or field_data.shape[0] != self.num_boxes( + ): + raise ValueError('Invalid dimensions for field data') + self.data[field] = field_data + + def get(self): + """Convenience function for accesssing box coordinates. + + Returns: + a numpy array of shape [N, 4] representing box corners + """ + return self.get_field('boxes') + + def get_field(self, field): + """Accesses data associated with the specified field in the box + collection. + + Args: + field: a string parameter used to speficy a related field to be + accessed. + + Returns: + a numpy 1-d array representing data of an associated field + + Raises: + ValueError: if invalid field + """ + if not self.has_field(field): + raise ValueError(f'field {field} does not exist') + return self.data[field] + + def get_coordinates(self): + """Get corner coordinates of boxes. + + Returns: + a list of 4 1-d numpy arrays [y_min, x_min, y_max, x_max] + """ + box_coordinates = self.get() + y_min = box_coordinates[:, 0] + x_min = box_coordinates[:, 1] + y_max = box_coordinates[:, 2] + x_max = box_coordinates[:, 3] + return [y_min, x_min, y_max, x_max] + + def _is_valid_boxes(self, data): + """Check whether data fullfills the format of N*[ymin, xmin, ymax, + xmin]. + + Args: + data: a numpy array of shape [N, 4] representing box coordinates + + Returns: + a boolean indicating whether all ymax of boxes are equal or greater + than ymin, and all xmax of boxes are equal or greater than xmin. + """ + if len(data): + for v in data: + if v[0] > v[2] or v[1] > v[3]: + return False + return True diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/np_box_ops.py b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/np_box_ops.py new file mode 100644 index 0000000..94e7d30 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/np_box_ops.py @@ -0,0 +1,98 @@ +# Copyright 2017 The TensorFlow 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. +# ============================================================================== +"""Operations for [N, 4] numpy arrays representing bounding boxes. + +Example box operations that are supported: + * Areas: compute bounding box areas + * IOU: pairwise intersection-over-union scores +""" + +import numpy as np + + +def area(boxes): + """Computes area of boxes. + + Args: + boxes: Numpy array with shape [N, 4] holding N boxes + + Returns: + a numpy array with shape [N*1] representing box areas + """ + return (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) + + +def intersection(boxes1, boxes2): + """Compute pairwise intersection areas between boxes. + + Args: + boxes1: a numpy array with shape [N, 4] holding N boxes + boxes2: a numpy array with shape [M, 4] holding M boxes + + Returns: + a numpy array with shape [N*M] representing pairwise intersection area + """ + [y_min1, x_min1, y_max1, x_max1] = np.split(boxes1, 4, axis=1) + [y_min2, x_min2, y_max2, x_max2] = np.split(boxes2, 4, axis=1) + + all_pairs_min_ymax = np.minimum(y_max1, np.transpose(y_max2)) + all_pairs_max_ymin = np.maximum(y_min1, np.transpose(y_min2)) + intersect_heights = np.maximum( + np.zeros(all_pairs_max_ymin.shape), + all_pairs_min_ymax - all_pairs_max_ymin) + all_pairs_min_xmax = np.minimum(x_max1, np.transpose(x_max2)) + all_pairs_max_xmin = np.maximum(x_min1, np.transpose(x_min2)) + intersect_widths = np.maximum( + np.zeros(all_pairs_max_xmin.shape), + all_pairs_min_xmax - all_pairs_max_xmin) + return intersect_heights * intersect_widths + + +def iou(boxes1, boxes2): + """Computes pairwise intersection-over-union between box collections. + + Args: + boxes1: a numpy array with shape [N, 4] holding N boxes. + boxes2: a numpy array with shape [M, 4] holding N boxes. + + Returns: + a numpy array with shape [N, M] representing pairwise iou scores. + """ + intersect = intersection(boxes1, boxes2) + area1 = area(boxes1) + area2 = area(boxes2) + union = ( + np.expand_dims(area1, axis=1) + np.expand_dims(area2, axis=0) - + intersect) + return intersect / union + + +def ioa(boxes1, boxes2): + """Computes pairwise intersection-over-area between box collections. + + Intersection-over-area (ioa) between two boxes box1 and box2 is defined as + their intersection area over box2's area. Note that ioa is not symmetric, + that is, IOA(box1, box2) != IOA(box2, box1). + + Args: + boxes1: a numpy array with shape [N, 4] holding N boxes. + boxes2: a numpy array with shape [M, 4] holding N boxes. + + Returns: + a numpy array with shape [N, M] representing pairwise ioa scores. + """ + intersect = intersection(boxes1, boxes2) + areas = np.expand_dims(area(boxes2), axis=0) + return intersect / areas diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/object_detection_evaluation.py b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/object_detection_evaluation.py new file mode 100644 index 0000000..c9f0054 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/object_detection_evaluation.py @@ -0,0 +1,658 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. +# ============================================================================= +"""object_detection_evaluation module. + +ObjectDetectionEvaluation is a class which manages ground truth information of +a object detection dataset, and computes frequently used detection metrics such +as Precision, Recall, CorLoc of the provided detection results. +It supports the following operations: +1) Add ground truth information of images sequentially. +2) Add detection result of images sequentially. +3) Evaluate detection metrics on already inserted detection results. +4) Write evaluation result into a pickle file for future processing or + visualization. + +Note: This module operates on numpy boxes and box lists. +""" +import collections +import logging +from abc import ABCMeta, abstractmethod + +import numpy as np + +from . import metrics, per_image_evaluation, standard_fields + + +class DetectionEvaluator: + """Interface for object detection evalution classes. + + Example usage of the Evaluator: + ------------------------------ + evaluator = DetectionEvaluator(categories) + + # Detections and groundtruth for image 1. + evaluator.add_single_groundtruth_image_info(...) + evaluator.add_single_detected_image_info(...) + + # Detections and groundtruth for image 2. + evaluator.add_single_groundtruth_image_info(...) + evaluator.add_single_detected_image_info(...) + + metrics_dict = evaluator.evaluate() + """ + + __metaclass__ = ABCMeta + + def __init__(self, categories): + """Constructor. + + Args: + categories: A list of dicts, each of which has the following keys - + 'id': (required) an integer id uniquely identifying this + category. + 'name': (required) string representing category name e.g., + 'cat', 'dog'. + """ + self._categories = categories + + @abstractmethod + def add_single_ground_truth_image_info(self, image_id, groundtruth_dict): + """Adds groundtruth for a single image to be used for evaluation. + + Args: + image_id: A unique string/integer identifier for the image. + groundtruth_dict: A dictionary of groundtruth numpy arrays required + for evaluations. + """ + + @abstractmethod + def add_single_detected_image_info(self, image_id, detections_dict): + """Adds detections for a single image to be used for evaluation. + + Args: + image_id: A unique string/integer identifier for the image. + detections_dict: A dictionary of detection numpy arrays required + for evaluation. + """ + + @abstractmethod + def evaluate(self): + """Evaluates detections and returns a dictionary of metrics.""" + + @abstractmethod + def clear(self): + """Clears the state to prepare for a fresh evaluation.""" + + +class ObjectDetectionEvaluator(DetectionEvaluator): + """A class to evaluate detections.""" + + def __init__( + self, + categories, + matching_iou_threshold=0.5, + evaluate_corlocs=False, + metric_prefix=None, + use_weighted_mean_ap=False, + evaluate_masks=False, + ): + """Constructor. + + Args: + categories: A list of dicts, each of which has the following keys - + 'id': (required) an integer id uniquely identifying this + category. + 'name': (required) string representing category name e.g., + 'cat', 'dog'. + matching_iou_threshold: IOU threshold to use for matching + groundtruth boxes to detection boxes. + evaluate_corlocs: (optional) boolean which determines if corloc + scores are to be returned or not. + metric_prefix: (optional) string prefix for metric name; if None, + no prefix is used. + use_weighted_mean_ap: (optional) boolean which determines if the + mean average precision is computed directly from the scores and + tp_fp_labels of all classes. + evaluate_masks: If False, evaluation will be performed based on + boxes. If True, mask evaluation will be performed instead. + + Raises: + ValueError: If the category ids are not 1-indexed. + """ + super(ObjectDetectionEvaluator, self).__init__(categories) + self._num_classes = max([cat['id'] for cat in categories]) + if min(cat['id'] for cat in categories) < 1: + raise ValueError('Classes should be 1-indexed.') + self._matching_iou_threshold = matching_iou_threshold + self._use_weighted_mean_ap = use_weighted_mean_ap + self._label_id_offset = 1 + self._evaluate_masks = evaluate_masks + self._evaluation = ObjectDetectionEvaluation( + num_groundtruth_classes=self._num_classes, + matching_iou_threshold=self._matching_iou_threshold, + use_weighted_mean_ap=self._use_weighted_mean_ap, + label_id_offset=self._label_id_offset, + ) + self._image_ids = set([]) + self._evaluate_corlocs = evaluate_corlocs + self._metric_prefix = (metric_prefix + '_') if metric_prefix else '' + + def add_single_ground_truth_image_info(self, image_id, groundtruth_dict): + """Adds groundtruth for a single image to be used for evaluation. + + Args: + image_id: A unique string/integer identifier for the image. + groundtruth_dict: A dictionary containing - + standard_fields.InputDataFields.groundtruth_boxes: float32 + numpy array of shape [num_boxes, 4] containing `num_boxes` + groundtruth boxes of the format [ymin, xmin, ymax, xmax] in + absolute image coordinates. + standard_fields.InputDataFields.groundtruth_classes: integer + numpy array of shape [num_boxes] containing 1-indexed + groundtruth classes for the boxes. + standard_fields.InputDataFields.groundtruth_difficult: Optional + length M numpy boolean array denoting whether a ground + truth box is a difficult instance or not. This field is + optional to support the case that no boxes are difficult. + standard_fields.InputDataFields.groundtruth_instance_masks: + Optional numpy array of shape [num_boxes, height, width] + with values in {0, 1}. + + Raises: + ValueError: On adding groundtruth for an image more than once. Will + also raise error if instance masks are not in groundtruth + dictionary. + """ + if image_id in self._image_ids: + raise ValueError( + 'Image with id {} already added.'.format(image_id)) + + groundtruth_classes = ( + groundtruth_dict[ + standard_fields.InputDataFields.groundtruth_classes] - + self._label_id_offset) + # If the key is not present in the groundtruth_dict or the array is + # empty (unless there are no annotations for the groundtruth on this + # image) use values from the dictionary or insert None otherwise. + if (standard_fields.InputDataFields.groundtruth_difficult + in groundtruth_dict.keys()) and (groundtruth_dict[ + standard_fields.InputDataFields.groundtruth_difficult].size + or + not groundtruth_classes.size): + groundtruth_difficult = groundtruth_dict[ + standard_fields.InputDataFields.groundtruth_difficult] + else: + groundtruth_difficult = None + if not len(self._image_ids) % 1000: + logging.warn(('image %s does not have groundtruth difficult ' + 'flag specified'), image_id) + groundtruth_masks = None + if self._evaluate_masks: + if (standard_fields.InputDataFields.groundtruth_instance_masks + not in groundtruth_dict): + raise ValueError( + 'Instance masks not in groundtruth dictionary.') + groundtruth_masks = groundtruth_dict[ + standard_fields.InputDataFields.groundtruth_instance_masks] + self._evaluation.add_single_ground_truth_image_info( + image_key=image_id, + groundtruth_boxes=groundtruth_dict[ + standard_fields.InputDataFields.groundtruth_boxes], + groundtruth_class_labels=groundtruth_classes, + groundtruth_is_difficult_list=groundtruth_difficult, + groundtruth_masks=groundtruth_masks, + ) + self._image_ids.update([image_id]) + + def add_single_detected_image_info(self, image_id, detections_dict): + """Adds detections for a single image to be used for evaluation. + + Args: + image_id: A unique string/integer identifier for the image. + detections_dict: A dictionary containing - + standard_fields.DetectionResultFields.detection_boxes: float32 + numpy array of shape [num_boxes, 4] containing `num_boxes` + detection boxes of the format [ymin, xmin, ymax, xmax] in + absolute image coordinates. + standard_fields.DetectionResultFields.detection_scores: float32 + numpy array of shape [num_boxes] containing detection + scores for the boxes. + standard_fields.DetectionResultFields.detection_classes: + integer numpy array of shape [num_boxes] containing + 1-indexed detection classes for the boxes. + standard_fields.DetectionResultFields.detection_masks: uint8 + numpy array of shape [num_boxes, height, width] containing + `num_boxes` masks of values ranging between 0 and 1. + + Raises: + ValueError: If detection masks are not in detections dictionary. + """ + detection_classes = ( + detections_dict[ + standard_fields.DetectionResultFields.detection_classes] - + self._label_id_offset) + detection_masks = None + if self._evaluate_masks: + if (standard_fields.DetectionResultFields.detection_masks + not in detections_dict): + raise ValueError( + 'Detection masks not in detections dictionary.') + detection_masks = detections_dict[ + standard_fields.DetectionResultFields.detection_masks] + self._evaluation.add_single_detected_image_info( + image_key=image_id, + detected_boxes=detections_dict[ + standard_fields.DetectionResultFields.detection_boxes], + detected_scores=detections_dict[ + standard_fields.DetectionResultFields.detection_scores], + detected_class_labels=detection_classes, + detected_masks=detection_masks, + ) + + def create_category_index(self, categories): + """Creates dictionary of COCO compatible categories keyed by category + id. + + Args: + categories: a list of dicts, each of which has the following keys: + 'id': (required) an integer id uniquely identifying this + category. + 'name': (required) string representing category name + e.g., 'cat', 'dog', 'pizza'. + + Returns: + category_index: a dict containing the same entries as categories, + but keyed by the 'id' field of each category. + """ + category_index = {} + for cat in categories: + category_index[cat['id']] = cat + return category_index + + def evaluate(self): + """Compute evaluation result. + + Returns: + A dictionary of metrics with the following fields - + + 1. summary_metrics: + 'Precision/mAP@IOU': mean average + precision at the specified IOU threshold + + 2. per_category_ap: category specific results with keys of the form + 'PerformanceByCategory/mAP@IOU/category' + """ + ( + per_class_ap, + mean_ap, + _, + _, + per_class_corloc, + mean_corloc, + ) = self._evaluation.evaluate() + + metric = f'mAP@{self._matching_iou_threshold}IOU' + pascal_metrics = {self._metric_prefix + metric: mean_ap} + if self._evaluate_corlocs: + pascal_metrics[self._metric_prefix + + 'Precision/meanCorLoc@{}IOU'.format( + self._matching_iou_threshold)] = mean_corloc + category_index = self.create_category_index(self._categories) + for idx in range(per_class_ap.size): + if idx + self._label_id_offset in category_index: + display_name = ( + self._metric_prefix + + 'PerformanceByCategory/AP@{}IOU/{}'.format( + self._matching_iou_threshold, + category_index[idx + self._label_id_offset]['name'], + )) + pascal_metrics[display_name] = per_class_ap[idx] + + # Optionally add CorLoc metrics.classes + if self._evaluate_corlocs: #False + display_name = ( + self._metric_prefix + + 'PerformanceByCategory/CorLoc@{}IOU/{}'.format( + self._matching_iou_threshold, + category_index[idx + + self._label_id_offset]['name'], + )) + pascal_metrics[display_name] = per_class_corloc[idx] + + return pascal_metrics + + def clear(self): + """Clears the state to prepare for a fresh evaluation.""" + self._evaluation = ObjectDetectionEvaluation( + num_groundtruth_classes=self._num_classes, + matching_iou_threshold=self._matching_iou_threshold, + use_weighted_mean_ap=self._use_weighted_mean_ap, + label_id_offset=self._label_id_offset, + ) + self._image_ids.clear() + + +class PascalDetectionEvaluator(ObjectDetectionEvaluator): + """A class to evaluate detections using PASCAL metrics.""" + + def __init__(self, categories, matching_iou_threshold=0.5): + super(PascalDetectionEvaluator, self).__init__( + categories, + matching_iou_threshold=matching_iou_threshold, + evaluate_corlocs=False, + use_weighted_mean_ap=False, + ) + + +ObjectDetectionEvalMetrics = collections.namedtuple( + 'ObjectDetectionEvalMetrics', + [ + 'average_precisions', + 'mean_ap', + 'precisions', + 'recalls', + 'corlocs', + 'mean_corloc', + ], +) + + +class ObjectDetectionEvaluation: + """Internal implementation of Pascal object detection metrics.""" + + def __init__( + self, + num_groundtruth_classes, + matching_iou_threshold=0.5, + nms_iou_threshold=1.0, + nms_max_output_boxes=10000, + use_weighted_mean_ap=False, + label_id_offset=0, + ): + if num_groundtruth_classes < 1: + raise ValueError( + 'Need at least 1 groundtruth class for evaluation.') + + self.per_image_eval = per_image_evaluation.PerImageEvaluation( + num_groundtruth_classes=num_groundtruth_classes, + matching_iou_threshold=matching_iou_threshold, + ) + self.num_class = num_groundtruth_classes + self.use_weighted_mean_ap = use_weighted_mean_ap + self.label_id_offset = label_id_offset + + self.groundtruth_boxes = {} + self.groundtruth_class_labels = {} + self.groundtruth_masks = {} + self.groundtruth_is_difficult_list = {} + self.groundtruth_is_group_of_list = {} + self.num_gt_instances_per_class = np.zeros(self.num_class, dtype=int) + self.num_gt_imgs_per_class = np.zeros(self.num_class, dtype=int) + + self._initialize_detections() + + def _initialize_detections(self): + self.detection_keys = set() + self.scores_per_class = [[] for _ in range(self.num_class)] + self.tp_fp_labels_per_class = [[] for _ in range(self.num_class)] + self.num_images_correctly_detected_per_class = np.zeros(self.num_class) + self.average_precision_per_class = np.empty( + self.num_class, dtype=float) + self.average_precision_per_class.fill(np.nan) + self.precisions_per_class = [] + self.recalls_per_class = [] + self.corloc_per_class = np.ones(self.num_class, dtype=float) + + def clear_detections(self): + self._initialize_detections() + + def add_single_ground_truth_image_info( + self, + image_key, + groundtruth_boxes, + groundtruth_class_labels, + groundtruth_is_difficult_list=None, + groundtruth_is_group_of_list=None, + groundtruth_masks=None, + ): + """Adds groundtruth for a single image to be used for evaluation. + + Args: + image_key: A unique string/integer identifier for the image. + groundtruth_boxes: float32 numpy array of shape [num_boxes, 4] + containing `num_boxes` groundtruth boxes of the format + [ymin, xmin, ymax, xmax] in absolute image coordinates. + groundtruth_class_labels: integer numpy array of shape [num_boxes] + containing 0-indexed groundtruth classes for the boxes. + groundtruth_is_difficult_list: A length M numpy boolean array + denoting whether a ground truth box is a difficult instance or + not. To support the case that no boxes are difficult, it is by + default set as None. + groundtruth_is_group_of_list: A length M numpy boolean array + denoting whether a ground truth box is a group-of box or not. + To support the case that no boxes are groups-of, it is by + default set as None. + groundtruth_masks: uint8 numpy array of shape + [num_boxes, height, width] containing `num_boxes` groundtruth + masks. The mask values range from 0 to 1. + """ + if image_key in self.groundtruth_boxes: + logging.warn(('image %s has already been added to the ground ' + 'truth database.'), image_key) + return + + self.groundtruth_boxes[image_key] = groundtruth_boxes + self.groundtruth_class_labels[image_key] = groundtruth_class_labels + self.groundtruth_masks[image_key] = groundtruth_masks + if groundtruth_is_difficult_list is None: + num_boxes = groundtruth_boxes.shape[0] + groundtruth_is_difficult_list = np.zeros(num_boxes, dtype=bool) + self.groundtruth_is_difficult_list[ + image_key] = groundtruth_is_difficult_list.astype(dtype=bool) + if groundtruth_is_group_of_list is None: + num_boxes = groundtruth_boxes.shape[0] + groundtruth_is_group_of_list = np.zeros(num_boxes, dtype=bool) + self.groundtruth_is_group_of_list[ + image_key] = groundtruth_is_group_of_list.astype(dtype=bool) + + self._update_ground_truth_statistics( + groundtruth_class_labels, + groundtruth_is_difficult_list.astype(dtype=bool), + groundtruth_is_group_of_list.astype(dtype=bool), + ) + + def add_single_detected_image_info( + self, + image_key, + detected_boxes, + detected_scores, + detected_class_labels, + detected_masks=None, + ): + """Adds detections for a single image to be used for evaluation. + + Args: + image_key: A unique string/integer identifier for the image. + detected_boxes: float32 numpy array of shape [num_boxes, 4] + containing `num_boxes` detection boxes of the format + [ymin, xmin, ymax, xmax] in absolute image coordinates. + detected_scores: float32 numpy array of shape [num_boxes] + containing detection scores for the boxes. + detected_class_labels: integer numpy array of shape [num_boxes] + containing 0-indexed detection classes for the boxes. + detected_masks: np.uint8 numpy array of shape + [num_boxes, height, width] containing `num_boxes` detection + masks with values ranging between 0 and 1. + + Raises: + ValueError: if the number of boxes, scores and class labels differ + in length. + """ + if len(detected_boxes) != len(detected_scores) or len( + detected_boxes) != len(detected_class_labels): + raise ValueError( + 'detected_boxes, detected_scores and ' + 'detected_class_labels should all have same lengths. Got' + '[%d, %d, %d]' % len(detected_boxes), + len(detected_scores), + len(detected_class_labels), + ) + + if image_key in self.detection_keys: + logging.warn(('image %s has already been added to the ground ' + 'truth database.'), image_key) + return + + self.detection_keys.add(image_key) + if image_key in self.groundtruth_boxes: + groundtruth_boxes = self.groundtruth_boxes[image_key] + groundtruth_class_labels = self.groundtruth_class_labels[image_key] + # Masks are popped instead of look up. The reason is that we do not + # want to keep all masks in memory which can cause memory overflow. + groundtruth_masks = self.groundtruth_masks.pop(image_key) + groundtruth_is_difficult_list = self.groundtruth_is_difficult_list[ + image_key] + groundtruth_is_group_of_list = self.groundtruth_is_group_of_list[ + image_key] + else: + groundtruth_boxes = np.empty(shape=[0, 4], dtype=float) + groundtruth_class_labels = np.array([], dtype=int) + if detected_masks is None: + groundtruth_masks = None + else: + groundtruth_masks = np.empty(shape=[0, 1, 1], dtype=float) + groundtruth_is_difficult_list = np.array([], dtype=bool) + groundtruth_is_group_of_list = np.array([], dtype=bool) + ( + scores, + tp_fp_labels, + ) = self.per_image_eval.compute_object_detection_metrics( + detected_boxes=detected_boxes, + detected_scores=detected_scores, + detected_class_labels=detected_class_labels, + groundtruth_boxes=groundtruth_boxes, + groundtruth_class_labels=groundtruth_class_labels, + groundtruth_is_difficult_list=groundtruth_is_difficult_list, + groundtruth_is_group_of_list=groundtruth_is_group_of_list, + detected_masks=detected_masks, + groundtruth_masks=groundtruth_masks, + ) + + for i in range(self.num_class): + if scores[i].shape[0] > 0: + self.scores_per_class[i].append(scores[i]) + self.tp_fp_labels_per_class[i].append(tp_fp_labels[i]) + + def _update_ground_truth_statistics( + self, + groundtruth_class_labels, + groundtruth_is_difficult_list, + groundtruth_is_group_of_list, + ): + """Update grouth truth statitistics. + + 1. Difficult boxes are ignored when counting the number of ground truth + instances as done in Pascal VOC devkit. + 2. Difficult boxes are treated as normal boxes when computing CorLoc + related statitistics. + + Args: + groundtruth_class_labels: An integer numpy array of length M, + representing M class labels of object instances in ground truth + groundtruth_is_difficult_list: A boolean numpy array of length M + denoting whether a ground truth box is a difficult instance or + not + groundtruth_is_group_of_list: A boolean numpy array of length M + denoting whether a ground truth box is a group-of box or not + """ + for class_index in range(self.num_class): + num_gt_instances = np.sum(groundtruth_class_labels[ + ~groundtruth_is_difficult_list + & ~groundtruth_is_group_of_list] == class_index) + self.num_gt_instances_per_class[class_index] += num_gt_instances + if np.any(groundtruth_class_labels == class_index): + self.num_gt_imgs_per_class[class_index] += 1 + + def evaluate(self): + """Compute evaluation result. + + Returns: + A named tuple with the following fields - + average_precision: float numpy array of average precision for + each class. + mean_ap: mean average precision of all classes, float scalar + precisions: List of precisions, each precision is a float numpy + array + recalls: List of recalls, each recall is a float numpy array + corloc: numpy float array + mean_corloc: Mean CorLoc score for each class, float scalar + """ + if (self.num_gt_instances_per_class == 0).any(): + print( + 'The following classes have no ground truth examples: %s', + np.squeeze(np.argwhere(self.num_gt_instances_per_class == 0)) + + self.label_id_offset, "self.detection_keys:",self.detection_keys + ) + + if self.use_weighted_mean_ap: + all_scores = np.array([], dtype=float) + all_tp_fp_labels = np.array([], dtype=bool) + + for class_index in range(self.num_class): + if self.num_gt_instances_per_class[class_index] == 0: + continue + + if not self.scores_per_class[class_index]: + scores = np.array([], dtype=float) + tp_fp_labels = np.array([], dtype=bool) + else: + scores = np.concatenate(self.scores_per_class[class_index]) + tp_fp_labels = np.concatenate( + self.tp_fp_labels_per_class[class_index]) + if self.use_weighted_mean_ap: + all_scores = np.append(all_scores, scores) + all_tp_fp_labels = np.append(all_tp_fp_labels, tp_fp_labels) + precision, recall = metrics.compute_precision_recall( + scores, + tp_fp_labels, + self.num_gt_instances_per_class[class_index], + ) + self.precisions_per_class.append(precision) + self.recalls_per_class.append(recall) + average_precision = metrics.compute_average_precision( + precision, recall) + self.average_precision_per_class[class_index] = average_precision + + self.corloc_per_class = metrics.compute_cor_loc( + self.num_gt_imgs_per_class, + self.num_images_correctly_detected_per_class, + ) + + if self.use_weighted_mean_ap: + num_gt_instances = np.sum(self.num_gt_instances_per_class) + precision, recall = metrics.compute_precision_recall( + all_scores, all_tp_fp_labels, num_gt_instances) + mean_ap = metrics.compute_average_precision(precision, recall) + else: + mean_ap = np.nanmean(self.average_precision_per_class) + mean_corloc = np.nanmean(self.corloc_per_class) + return ObjectDetectionEvalMetrics( + self.average_precision_per_class, + mean_ap, + self.precisions_per_class, + self.recalls_per_class, + self.corloc_per_class, + mean_corloc, + ) diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/per_image_evaluation.py b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/per_image_evaluation.py new file mode 100644 index 0000000..3013ae7 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/per_image_evaluation.py @@ -0,0 +1,452 @@ +# Copyright 2017 The TensorFlow 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. +# ============================================================================= +"""Evaluate Object Detection result on a single image. + +Annotate each detected result as true positives or false positive according to +a predefined IOU ratio. Non Maximum Supression is used by default. Multi class +detection is supported by default. Based on the settings, per image evaluation +is either performed on boxes or on object masks. +""" + +import numpy as np + +from . import np_box_list, np_box_ops + + +class PerImageEvaluation: + """Evaluate detection result of a single image.""" + + def __init__(self, num_groundtruth_classes, matching_iou_threshold=0.5): + """Initialized PerImageEvaluation by evaluation parameters. + + Args: + num_groundtruth_classes: Number of ground truth object classes + matching_iou_threshold: A ratio of area intersection to union, + which is the threshold to consider whether a detection is true + positive or not + """ + self.matching_iou_threshold = matching_iou_threshold + self.num_groundtruth_classes = num_groundtruth_classes + + def compute_object_detection_metrics( + self, + detected_boxes, + detected_scores, + detected_class_labels, + groundtruth_boxes, + groundtruth_class_labels, + groundtruth_is_difficult_list, + groundtruth_is_group_of_list, + detected_masks=None, + groundtruth_masks=None, + ): + """Evaluates detections as being tp, fp or ignored from a single image. + + The evaluation is done in two stages: + 1. All detections are matched to non group-of boxes; true positives + are determined and detections matched to difficult boxes are + ignored. + 2. Detections that are determined as false positives are matched + against group-of boxes and ignored if matched. + + Args: + detected_boxes: A float numpy array of shape [N, 4], representing N + regions of detected object regions. + Each row is of the format [y_min, x_min, y_max, x_max] + detected_scores: A float numpy array of shape [N, 1], representing + the confidence scores of the detected N object instances. + detected_class_labels: A integer numpy array of shape [N, 1], + repreneting the class labels of the detected N object + instances. + groundtruth_boxes: A float numpy array of shape [M, 4], + representing M regions of object instances in ground truth + groundtruth_class_labels: An integer numpy array of shape [M, 1], + representing M class labels of object instances in ground truth + groundtruth_is_difficult_list: A boolean numpy array of length M + denoting whether a ground truth box is a difficult instance or + not + groundtruth_is_group_of_list: A boolean numpy array of length M + denoting whether a ground truth box has group-of tag + detected_masks: (optional) A uint8 numpy array of shape + [N, height, width]. If not None, the metrics will be computed + based on masks. + groundtruth_masks: (optional) A uint8 numpy array of shape + [M, height, width]. + + Returns: + scores: A list of C float numpy arrays. Each numpy array is of + shape [K, 1], representing K scores detected with object class + label c + tp_fp_labels: A list of C boolean numpy arrays. Each numpy array + is of shape [K, 1], representing K True/False positive label of + object instances detected with class label c + """ + ( + detected_boxes, + detected_scores, + detected_class_labels, + detected_masks, + ) = self._remove_invalid_boxes( + detected_boxes, + detected_scores, + detected_class_labels, + detected_masks, + ) + scores, tp_fp_labels = self._compute_tp_fp( + detected_boxes=detected_boxes, + detected_scores=detected_scores, + detected_class_labels=detected_class_labels, + groundtruth_boxes=groundtruth_boxes, + groundtruth_class_labels=groundtruth_class_labels, + groundtruth_is_difficult_list=groundtruth_is_difficult_list, + groundtruth_is_group_of_list=groundtruth_is_group_of_list, + detected_masks=detected_masks, + groundtruth_masks=groundtruth_masks, + ) + + return scores, tp_fp_labels + + def _compute_tp_fp( + self, + detected_boxes, + detected_scores, + detected_class_labels, + groundtruth_boxes, + groundtruth_class_labels, + groundtruth_is_difficult_list, + groundtruth_is_group_of_list, + detected_masks=None, + groundtruth_masks=None, + ): + """Labels true/false positives of detections of an image across all + classes. + + Args: + detected_boxes: A float numpy array of shape [N, 4], representing N + regions of detected object regions. + Each row is of the format [y_min, x_min, y_max, x_max] + detected_scores: A float numpy array of shape [N, 1], representing + the confidence scores of the detected N object instances. + detected_class_labels: A integer numpy array of shape [N, 1], + repreneting the class labels of the detected N object + instances. + groundtruth_boxes: A float numpy array of shape [M, 4], + representing M regions of object instances in ground truth + groundtruth_class_labels: An integer numpy array of shape [M, 1], + representing M class labels of object instances in ground truth + groundtruth_is_difficult_list: A boolean numpy array of length M + denoting whether a ground truth box is a difficult instance or + not + groundtruth_is_group_of_list: A boolean numpy array of length M + denoting whether a ground truth box has group-of tag + detected_masks: (optional) A np.uint8 numpy array of shape + [N, height, width]. If not None, the scores will be computed + based on masks. + groundtruth_masks: (optional) A np.uint8 numpy array of shape + [M, height, width]. + + Returns: + result_scores: A list of float numpy arrays. Each numpy array is of + shape [K, 1], representing K scores detected with object class + label c + result_tp_fp_labels: A list of boolean numpy array. Each numpy + array is of shape [K, 1], representing K True/False positive + label of object instances detected with class label c + + Raises: + ValueError: If detected masks is not None but groundtruth masks are + None, or the other way around. + """ + if detected_masks is not None and groundtruth_masks is None: + raise ValueError( + 'Detected masks is available but groundtruth masks is not.') + if detected_masks is None and groundtruth_masks is not None: + raise ValueError( + 'Groundtruth masks is available but detected masks is not.') + + result_scores = [] + result_tp_fp_labels = [] + for i in range(self.num_groundtruth_classes): + groundtruth_is_difficult_list_at_ith_class = ( + groundtruth_is_difficult_list[groundtruth_class_labels == i]) + groundtruth_is_group_of_list_at_ith_class = ( + groundtruth_is_group_of_list[groundtruth_class_labels == i]) + ( + gt_boxes_at_ith_class, + gt_masks_at_ith_class, + detected_boxes_at_ith_class, + detected_scores_at_ith_class, + detected_masks_at_ith_class, + ) = self._get_ith_class_arrays(detected_boxes, detected_scores, + detected_masks, + detected_class_labels, + groundtruth_boxes, + groundtruth_masks, + groundtruth_class_labels, i) + scores, tp_fp_labels = self._compute_tp_fp_for_single_class( + detected_boxes=detected_boxes_at_ith_class, + detected_scores=detected_scores_at_ith_class, + groundtruth_boxes=gt_boxes_at_ith_class, + groundtruth_is_difficult_list=( + groundtruth_is_difficult_list_at_ith_class), + groundtruth_is_group_of_list=( + groundtruth_is_group_of_list_at_ith_class), + detected_masks=detected_masks_at_ith_class, + groundtruth_masks=gt_masks_at_ith_class, + ) + result_scores.append(scores) + result_tp_fp_labels.append(tp_fp_labels) + return result_scores, result_tp_fp_labels + + def _get_overlaps_and_scores_box_mode( + self, + detected_boxes, + detected_scores, + groundtruth_boxes, + groundtruth_is_group_of_list, + ): + """Computes overlaps and scores between detected and groudntruth boxes. + + Args: + detected_boxes: A numpy array of shape [N, 4] representing detected + box coordinates + detected_scores: A 1-d numpy array of length N representing + classification score + groundtruth_boxes: A numpy array of shape [M, 4] representing + ground truth box coordinates + groundtruth_is_group_of_list: A boolean numpy array of length M + denoting whether a ground truth box has group-of tag. If a + groundtruth box is group-of box, every detection matching this + box is ignored. + + Returns: + iou: A float numpy array of size [num_detected_boxes, + num_gt_boxes]. If gt_non_group_of_boxlist.num_boxes() == 0 it + will be None. + ioa: A float numpy array of size [num_detected_boxes, + num_gt_boxes]. If gt_group_of_boxlist.num_boxes() == 0 it will + be None. + scores: The score of the detected boxlist. + num_boxes: Number of non-maximum suppressed detected boxes. + """ + detected_boxlist = np_box_list.BoxList(detected_boxes) + detected_boxlist.add_field('scores', detected_scores) + gt_non_group_of_boxlist = np_box_list.BoxList( + groundtruth_boxes[~groundtruth_is_group_of_list]) + + iou = np_box_ops.iou(detected_boxlist.get(), + gt_non_group_of_boxlist.get()) + scores = detected_boxlist.get_field('scores') + num_boxes = detected_boxlist.num_boxes() + return iou, None, scores, num_boxes + + def _compute_tp_fp_for_single_class( + self, + detected_boxes, + detected_scores, + groundtruth_boxes, + groundtruth_is_difficult_list, + groundtruth_is_group_of_list, + detected_masks=None, + groundtruth_masks=None, + ): + """Labels boxes detected with the same class from the same image as + tp/fp. + + Args: + detected_boxes: A numpy array of shape [N, 4] representing detected + box coordinates + detected_scores: A 1-d numpy array of length N representing + classification score + groundtruth_boxes: A numpy array of shape [M, 4] representing + groundtruth box coordinates + groundtruth_is_difficult_list: A boolean numpy array of length M + denoting whether a ground truth box is a difficult instance or + not. If a groundtruth box is difficult, every detection + matching this box is ignored. + groundtruth_is_group_of_list: A boolean numpy array of length M + denoting whether a ground truth box has group-of tag. If a + groundtruth box is group-of box, every detection matching this + box is ignored. + detected_masks: (optional) A uint8 numpy array of shape + [N, height, width]. If not None, the scores will be computed + based on masks. + groundtruth_masks: (optional) A uint8 numpy array of shape + [M, height, width]. + + Returns: + Two arrays of the same size, containing all boxes that were + evaluated as being true positives or false positives; if a box + matched to a difficult box or to a group-of box, it is ignored. + + scores: A numpy array representing the detection scores. + tp_fp_labels: a boolean numpy array indicating whether a detection + is a true positive. + """ + if detected_boxes.size == 0: + return np.array([], dtype=float), np.array([], dtype=bool) + + ( + iou, + _, + scores, + num_detected_boxes, + ) = self._get_overlaps_and_scores_box_mode( + detected_boxes=detected_boxes, + detected_scores=detected_scores, + groundtruth_boxes=groundtruth_boxes, + groundtruth_is_group_of_list=groundtruth_is_group_of_list, + ) + + if groundtruth_boxes.size == 0: + return scores, np.zeros(num_detected_boxes, dtype=bool) + + tp_fp_labels = np.zeros(num_detected_boxes, dtype=bool) + is_matched_to_difficult_box = np.zeros(num_detected_boxes, dtype=bool) + is_matched_to_group_of_box = np.zeros(num_detected_boxes, dtype=bool) + + # The evaluation is done in two stages: + # 1. All detections are matched to non group-of boxes; true positives + # are determined and detections matched to difficult boxes are + # ignored. + # 2. Detections that are determined as false positives are matched + # against group-of boxes and ignored if matched. + + # Tp-fp evaluation for non-group of boxes (if any). + if iou.shape[1] > 0: + groundtruth_nongroup_of_is_difficult_list = ( + groundtruth_is_difficult_list[~groundtruth_is_group_of_list]) + max_overlap_gt_ids = np.argmax(iou, axis=1) + is_gt_box_detected = np.zeros(iou.shape[1], dtype=bool) + for i in range(num_detected_boxes): + gt_id = max_overlap_gt_ids[i] + if iou[i, gt_id] >= self.matching_iou_threshold: + if not groundtruth_nongroup_of_is_difficult_list[gt_id]: + if not is_gt_box_detected[gt_id]: + tp_fp_labels[i] = True + is_gt_box_detected[gt_id] = True + else: + is_matched_to_difficult_box[i] = True + + return ( + scores[~is_matched_to_difficult_box & ~is_matched_to_group_of_box], + tp_fp_labels[~is_matched_to_difficult_box + & ~is_matched_to_group_of_box], + ) + + def _get_ith_class_arrays( + self, + detected_boxes, + detected_scores, + detected_masks, + detected_class_labels, + groundtruth_boxes, + groundtruth_masks, + groundtruth_class_labels, + class_index, + ): + """Returns numpy arrays belonging to class with index `class_index`. + + Args: + detected_boxes: A numpy array containing detected boxes. + detected_scores: A numpy array containing detected scores. + detected_masks: A numpy array containing detected masks. + detected_class_labels: A numpy array containing detected class + labels. + groundtruth_boxes: A numpy array containing groundtruth boxes. + groundtruth_masks: A numpy array containing groundtruth masks. + groundtruth_class_labels: A numpy array containing groundtruth + class labels. + class_index: An integer index. + + Returns: + gt_boxes_at_ith_class: A numpy array containing groundtruth boxes + labeled as ith class. + gt_masks_at_ith_class: A numpy array containing groundtruth masks + labeled as ith class. + detected_boxes_at_ith_class: A numpy array containing detected + boxes corresponding to the ith class. + detected_scores_at_ith_class: A numpy array containing detected + scores corresponding to the ith class. + detected_masks_at_ith_class: A numpy array containing detected + masks corresponding to the ith class. + """ + selected_groundtruth = groundtruth_class_labels == class_index + gt_boxes_at_ith_class = groundtruth_boxes[selected_groundtruth] + if groundtruth_masks is not None: + gt_masks_at_ith_class = groundtruth_masks[selected_groundtruth] + else: + gt_masks_at_ith_class = None + selected_detections = detected_class_labels == class_index + detected_boxes_at_ith_class = detected_boxes[selected_detections] + detected_scores_at_ith_class = detected_scores[selected_detections] + if detected_masks is not None: + detected_masks_at_ith_class = detected_masks[selected_detections] + else: + detected_masks_at_ith_class = None + return ( + gt_boxes_at_ith_class, + gt_masks_at_ith_class, + detected_boxes_at_ith_class, + detected_scores_at_ith_class, + detected_masks_at_ith_class, + ) + + def _remove_invalid_boxes( + self, + detected_boxes, + detected_scores, + detected_class_labels, + detected_masks=None, + ): + """Removes entries with invalid boxes. + + A box is invalid if either its xmax is smaller than its xmin, or its + ymax is smaller than its ymin. + + Args: + detected_boxes: A float numpy array of size [num_boxes, 4] + containing box coordinates in [ymin, xmin, ymax, xmax] format. + detected_scores: A float numpy array of size [num_boxes]. + detected_class_labels: A int32 numpy array of size [num_boxes]. + detected_masks: A uint8 numpy array of size + [num_boxes, height, width]. + + Returns: + valid_detected_boxes: A float numpy array of size + [num_valid_boxes, 4] containing box coordinates in + [ymin, xmin, ymax, xmax] format. + valid_detected_scores: A float numpy array of size + [num_valid_boxes]. + valid_detected_class_labels: A int32 numpy array of size + [num_valid_boxes]. + valid_detected_masks: A uint8 numpy array of size + [num_valid_boxes, height, width]. + """ + valid_indices = np.logical_and( + detected_boxes[:, 0] < detected_boxes[:, 2], + detected_boxes[:, 1] < detected_boxes[:, 3], + ) + detected_boxes = detected_boxes[valid_indices] + detected_scores = detected_scores[valid_indices] + detected_class_labels = detected_class_labels[valid_indices] + if detected_masks is not None: + detected_masks = detected_masks[valid_indices] + return [ + detected_boxes, + detected_scores, + detected_class_labels, + detected_masks, + ] diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/standard_fields.py b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/standard_fields.py new file mode 100644 index 0000000..8edf46d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ava_evaluation/standard_fields.py @@ -0,0 +1,115 @@ +# Copyright 2017 The TensorFlow 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. +# ============================================================================= +"""Contains classes specifying naming conventions used for object detection. + +Specifies: + InputDataFields: standard fields used by reader/preprocessor/batcher. + DetectionResultFields: standard fields returned by object detector. +""" + + +class InputDataFields: + """Names for the input tensors. + + Holds the standard data field names to use for identifying input tensors. + This should be used by the decoder to identify keys for the returned + tensor_dict containing input tensors. And it should be used by the model to + identify the tensors it needs. + + Attributes: + image: image. + original_image: image in the original input size. + key: unique key corresponding to image. + source_id: source of the original image. + filename: original filename of the dataset (without common path). + groundtruth_image_classes: image-level class labels. + groundtruth_boxes: coordinates of the ground truth boxes in the image. + groundtruth_classes: box-level class labels. + groundtruth_label_types: box-level label types (e.g. explicit + negative). + groundtruth_is_crowd: [DEPRECATED, use groundtruth_group_of instead] + is the groundtruth a single object or a crowd. + groundtruth_area: area of a groundtruth segment. + groundtruth_difficult: is a `difficult` object + groundtruth_group_of: is a `group_of` objects, e.g. multiple objects of + the same class, forming a connected group, where instances are + heavily occluding each other. + proposal_boxes: coordinates of object proposal boxes. + proposal_objectness: objectness score of each proposal. + groundtruth_instance_masks: ground truth instance masks. + groundtruth_instance_boundaries: ground truth instance boundaries. + groundtruth_instance_classes: instance mask-level class labels. + groundtruth_keypoints: ground truth keypoints. + groundtruth_keypoint_visibilities: ground truth keypoint visibilities. + groundtruth_label_scores: groundtruth label scores. + groundtruth_weights: groundtruth weight factor for bounding boxes. + num_groundtruth_boxes: number of groundtruth boxes. + true_image_shapes: true shapes of images in the resized images, as + resized images can be padded with zeros. + """ + + image = 'image' + original_image = 'original_image' + key = 'key' + source_id = 'source_id' + filename = 'filename' + groundtruth_image_classes = 'groundtruth_image_classes' + groundtruth_boxes = 'groundtruth_boxes' + groundtruth_classes = 'groundtruth_classes' + groundtruth_label_types = 'groundtruth_label_types' + groundtruth_is_crowd = 'groundtruth_is_crowd' + groundtruth_area = 'groundtruth_area' + groundtruth_difficult = 'groundtruth_difficult' + groundtruth_group_of = 'groundtruth_group_of' + proposal_boxes = 'proposal_boxes' + proposal_objectness = 'proposal_objectness' + groundtruth_instance_masks = 'groundtruth_instance_masks' + groundtruth_instance_boundaries = 'groundtruth_instance_boundaries' + groundtruth_instance_classes = 'groundtruth_instance_classes' + groundtruth_keypoints = 'groundtruth_keypoints' + groundtruth_keypoint_visibilities = 'groundtruth_keypoint_visibilities' + groundtruth_label_scores = 'groundtruth_label_scores' + groundtruth_weights = 'groundtruth_weights' + num_groundtruth_boxes = 'num_groundtruth_boxes' + true_image_shape = 'true_image_shape' + + +class DetectionResultFields: + """Naming conventions for storing the output of the detector. + + Attributes: + source_id: source of the original image. + key: unique key corresponding to image. + detection_boxes: coordinates of the detection boxes in the image. + detection_scores: detection scores for the detection boxes in the + image. + detection_classes: detection-level class labels. + detection_masks: contains a segmentation mask for each detection box. + detection_boundaries: contains an object boundary for each detection + box. + detection_keypoints: contains detection keypoints for each detection + box. + num_detections: number of detections in the batch. + """ + + source_id = 'source_id' + key = 'key' + detection_boxes = 'detection_boxes' + detection_scores = 'detection_scores' + detection_classes = 'detection_classes' + detection_masks = 'detection_masks' + detection_boundaries = 'detection_boundaries' + detection_keypoints = 'detection_keypoints' + num_detections = 'num_detections' diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/ava_metric.py new file mode 100644 index 0000000..b17c8c8 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ava_metric.py @@ -0,0 +1,92 @@ +# 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. + +import numpy as np +import paddle +from collections import OrderedDict +from paddlevideo.utils import get_logger, load, log_batch, AverageMeter +from .registry import METRIC +from .base import BaseMetric +import time +from datetime import datetime +from .ava_utils import ava_evaluate_results + +logger = get_logger("paddlevideo") +""" An example for metrics class. + MultiCropMetric for slowfast. +""" + + +@METRIC.register +class AVAMetric(BaseMetric): + def __init__(self, + data_size, + batch_size, + file_path, + exclude_file, + label_file, + custom_classes, + log_interval=1): + """prepare for metrics + """ + super().__init__(data_size, batch_size, log_interval) + + self.file_path = file_path + self.exclude_file = exclude_file + self.label_file = label_file + self.custom_classes = custom_classes + + self.results = [] + + record_list = [ + ("loss", AverageMeter('loss', '7.5f')), + ("recall@thr=0.5", AverageMeter("recall@thr=0.5", '.5f')), + ("prec@thr=0.5", AverageMeter("prec@thr=0.5", '.5f')), + ("recall@top3", AverageMeter("recall@top3", '.5f')), + ("prec@top3", AverageMeter("prec@top3", '.5f')), + ("recall@top5", AverageMeter("recall@top5", '.5f')), + ("prec@top5", AverageMeter("prec@top5", '.5f')), + ("mAP@0.5IOU", AverageMeter("mAP@0.5IOU", '.5f')), + ("batch_time", AverageMeter('batch_cost', '.5f')), + ("reader_time", AverageMeter('reader_cost', '.5f')), + ] + + self.record_list = OrderedDict(record_list) + + self.tic = time.time() + + def update(self, batch_id, data, outputs): + """update metrics during each iter + """ + + self.results.extend(outputs) + self.record_list['batch_time'].update(time.time() - self.tic) + tic = time.time() + ips = "ips: {:.5f} instance/sec.".format( + self.batch_size / self.record_list["batch_time"].val) + log_batch(self.record_list, batch_id, 0, 0, "test", ips) + + def set_dataset_info(self, info, dataset_len): + self.info = info + self.dataset_len = dataset_len + + def accumulate(self): + """accumulate metrics when finished all iters. + """ + test_res = ava_evaluate_results(self.info, self.dataset_len, + self.results, None, self.label_file, + self.file_path, self.exclude_file) + + for name, value in test_res.items(): + self.record_list[name].update(value, self.batch_size) + + return self.record_list diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ava_utils.py b/Bank_second_part/detect_process/paddlevideo/metrics/ava_utils.py new file mode 100644 index 0000000..b127267 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ava_utils.py @@ -0,0 +1,394 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 csv +import heapq +import logging +import time +from collections import defaultdict +from .ava_evaluation import object_detection_evaluation as det_eval +from .ava_evaluation import standard_fields +from .recall import eval_recalls +import shutil +import pickle +import time +import os +import os.path as osp +from paddlevideo.utils import get_logger, get_dist_info +import paddle.distributed as dist +import sys +import numpy as np +from pathlib import Path +from datetime import datetime +import paddle + + +def det2csv(info, dataset_len, results, custom_classes): + csv_results = [] + for idx in range(dataset_len): + video_id = info[idx]['video_id'] + timestamp = info[idx]['timestamp'] + + result = results[idx] + for label, _ in enumerate(result): + for bbox in result[label]: + if type(bbox) == paddle.Tensor: + bbox = bbox.numpy() + + bbox_ = tuple(bbox.tolist()) + if custom_classes is not None: + actual_label = custom_classes[label + 1] + else: + actual_label = label + 1 + csv_results.append(( + video_id, + timestamp, + ) + bbox_[:4] + (actual_label, ) + bbox_[4:]) + return csv_results + + +# results is organized by class +def results2csv(info, dataset_len, results, out_file, custom_classes=None): + if isinstance(results[0], list): + csv_results = det2csv(info, dataset_len, results, custom_classes) + + # save space for float + def tostr(item): + if isinstance(item, float): + return f'{item:.3f}' + return str(item) + + with open(out_file, 'w') as f: + for csv_result in csv_results: + f.write(','.join(map(lambda x: tostr(x), csv_result))) + f.write('\n') + + +def print_time(message, start): + print('==> %g seconds to %s' % (time.time() - start, message)) + + +def make_image_key(video_id, timestamp): + """Returns a unique identifier for a video id & timestamp.""" + return f'{video_id},{int(timestamp):04d}' + + +def read_csv(csv_file, class_whitelist=None, capacity=0): + """Loads boxes and class labels from a CSV file in the AVA format. + + CSV file format described at https://research.google.com/ava/download.html. + + Args: + csv_file: A file object. + class_whitelist: If provided, boxes corresponding to (integer) class + labels not in this set are skipped. + capacity: Maximum number of labeled boxes allowed for each example. + Default is 0 where there is no limit. + + Returns: + boxes: A dictionary mapping each unique image key (string) to a list of + boxes, given as coordinates [y1, x1, y2, x2]. + labels: A dictionary mapping each unique image key (string) to a list + of integer class lables, matching the corresponding box in `boxes`. + scores: A dictionary mapping each unique image key (string) to a list + of score values lables, matching the corresponding label in `labels`. + If scores are not provided in the csv, then they will default to 1.0. + """ + start = time.time() + entries = defaultdict(list) + boxes = defaultdict(list) + labels = defaultdict(list) + scores = defaultdict(list) + reader = csv.reader(csv_file) + for row in reader: + assert len(row) in [7, 8], 'Wrong number of columns: ' + row + image_key = make_image_key(row[0], row[1]) + x1, y1, x2, y2 = [float(n) for n in row[2:6]] + action_id = int(row[6]) + if class_whitelist and action_id not in class_whitelist: + continue + + score = 1.0 + if len(row) == 8: + score = float(row[7]) + if capacity < 1 or len(entries[image_key]) < capacity: + heapq.heappush(entries[image_key], + (score, action_id, y1, x1, y2, x2)) + elif score > entries[image_key][0][0]: + heapq.heapreplace(entries[image_key], + (score, action_id, y1, x1, y2, x2)) + for image_key in entries: + # Evaluation API assumes boxes with descending scores + entry = sorted(entries[image_key], key=lambda tup: -tup[0]) + for item in entry: + score, action_id, y1, x1, y2, x2 = item + boxes[image_key].append([y1, x1, y2, x2]) + labels[image_key].append(action_id) + scores[image_key].append(score) + print_time('read file ' + csv_file.name, start) + return boxes, labels, scores + + +def read_exclusions(exclusions_file): + """Reads a CSV file of excluded timestamps. + + Args: + exclusions_file: A file object containing a csv of video-id,timestamp. + + Returns: + A set of strings containing excluded image keys, e.g. + "aaaaaaaaaaa,0904", + or an empty set if exclusions file is None. + """ + excluded = set() + if exclusions_file: + reader = csv.reader(exclusions_file) + for row in reader: + assert len(row) == 2, 'Expected only 2 columns, got: ' + row + excluded.add(make_image_key(row[0], row[1])) + return excluded + + +def read_labelmap(labelmap_file): + """Reads a labelmap without the dependency on protocol buffers. + + Args: + labelmap_file: A file object containing a label map protocol buffer. + + Returns: + labelmap: The label map in the form used by the + object_detection_evaluation + module - a list of {"id": integer, "name": classname } dicts. + class_ids: A set containing all of the valid class id integers. + """ + labelmap = [] + class_ids = set() + name = '' + class_id = '' + for line in labelmap_file: + if line.startswith(' name:'): + name = line.split('"')[1] + elif line.startswith(' id:') or line.startswith(' label_id:'): + class_id = int(line.strip().split(' ')[-1]) + labelmap.append({'id': class_id, 'name': name}) + class_ids.add(class_id) + return labelmap, class_ids + + +# Seems there is at most 100 detections for each image +def ava_eval(result_file, + result_type, + label_file, + ann_file, + exclude_file, + max_dets=(100, ), + verbose=True, + custom_classes=None): + + assert result_type in ['mAP'] + start = time.time() + categories, class_whitelist = read_labelmap(open(label_file)) + + if custom_classes is not None: + custom_classes = custom_classes[1:] + assert set(custom_classes).issubset(set(class_whitelist)) + class_whitelist = custom_classes + categories = [cat for cat in categories if cat['id'] in custom_classes] + + # loading gt, do not need gt score + gt_boxes, gt_labels, _ = read_csv(open(ann_file), class_whitelist, 0) + if verbose: + print_time('Reading detection results', start) + + if exclude_file is not None: + excluded_keys = read_exclusions(open(exclude_file)) + else: + excluded_keys = list() + + start = time.time() + boxes, labels, scores = read_csv(open(result_file), class_whitelist, 0) + if verbose: + print_time('Reading detection results', start) + + if result_type == 'proposal': + gts = [ + np.array(gt_boxes[image_key], dtype=float) for image_key in gt_boxes + ] + proposals = [] + for image_key in gt_boxes: + if image_key in boxes: + proposals.append( + np.concatenate( + (np.array(boxes[image_key], dtype=float), + np.array(scores[image_key], dtype=float)[:, None]), + axis=1)) + else: + # if no corresponding proposal, add a fake one + proposals.append(np.array([0, 0, 1, 1, 1])) + + # Proposals used here are with scores + recalls = eval_recalls(gts, proposals, np.array(max_dets), + np.arange(0.5, 0.96, 0.05)) + ar = recalls.mean(axis=1) + ret = {} + for i, num in enumerate(max_dets): + print(f'Recall@0.5@{num}\t={recalls[i, 0]:.4f}') + print(f'AR@{num}\t={ar[i]:.4f}') + ret[f'Recall@0.5@{num}'] = recalls[i, 0] + ret[f'AR@{num}'] = ar[i] + return ret + + if result_type == 'mAP': + pascal_evaluator = det_eval.PascalDetectionEvaluator(categories) + + start = time.time() + for image_key in gt_boxes: + if verbose and image_key in excluded_keys: + logging.info( + 'Found excluded timestamp in detections: %s.' + 'It will be ignored.', image_key) + continue + pascal_evaluator.add_single_ground_truth_image_info( + image_key, { + standard_fields.InputDataFields.groundtruth_boxes: + np.array(gt_boxes[image_key], dtype=float), + standard_fields.InputDataFields.groundtruth_classes: + np.array(gt_labels[image_key], dtype=int), + standard_fields.InputDataFields.groundtruth_difficult: + np.zeros(len(gt_boxes[image_key]), dtype=bool) + }) + if verbose: + print_time('Convert groundtruth', start) + + start = time.time() + for image_key in boxes: + if verbose and image_key in excluded_keys: + logging.info( + 'Found excluded timestamp in detections: %s.' + 'It will be ignored.', image_key) + continue + pascal_evaluator.add_single_detected_image_info( + image_key, { + standard_fields.DetectionResultFields.detection_boxes: + np.array(boxes[image_key], dtype=float), + standard_fields.DetectionResultFields.detection_classes: + np.array(labels[image_key], dtype=int), + standard_fields.DetectionResultFields.detection_scores: + np.array(scores[image_key], dtype=float) + }) + if verbose: + print_time('convert detections', start) + + start = time.time() + metrics = pascal_evaluator.evaluate() + if verbose: + print_time('run_evaluator', start) + for display_name in metrics: + print(f'{display_name}=\t{metrics[display_name]}') + ret = { + display_name: metrics[display_name] + for display_name in metrics if 'ByCategory' not in display_name + } + return ret + + +def mkdir_or_exist(dir_name, mode=0o777): + if dir_name == '': + return + dir_name = osp.expanduser(dir_name) + os.makedirs(dir_name, mode=mode, exist_ok=True) + + +def dump_to_fileobj(obj, file, **kwargs): + kwargs.setdefault('protocol', 2) + pickle.dump(obj, file, **kwargs) + + +def dump_to_path(obj, filepath, mode='wb'): + with open(filepath, mode) as f: + dump_to_fileobj(obj, f) + + +def load_from_fileobj(file, **kwargs): + return pickle.load(file, **kwargs) + + +def load_from_path(filepath, mode='rb'): + with open(filepath, mode) as f: + return load_from_fileobj(f) + + +def collect_results_cpu(result_part, size): + """Collect results in cpu mode. + It saves the results on different gpus to 'tmpdir' and collects + them by the rank 0 worker. + """ + tmpdir = osp.join('./', 'collect_results_cpu') + #1. load results of all parts from tmp dir + mkdir_or_exist(tmpdir) + rank, world_size = get_dist_info() + dump_to_path(result_part, osp.join(tmpdir, f'part_{rank}.pkl')) + dist.barrier() + if rank != 0: + return None + #2. collect all parts + while 1: + all_exist = True + for i in range(world_size): + part_file = osp.join(tmpdir, f'part_{i}.pkl') + if not Path(part_file).exists(): + all_exist = False + if all_exist: + break + else: + time.sleep(60) + time.sleep(120) + #3. load results of all parts from tmp dir + part_list = [] + for i in range(world_size): + part_file = osp.join(tmpdir, f'part_{i}.pkl') + part_list.append(load_from_path(part_file)) + #4. sort the results + ordered_results = [] + for res in zip(*part_list): + ordered_results.extend(list(res)) + ordered_results = ordered_results[: + size] #the dataloader may pad some samples + #5. remove results of all parts from tmp dir, avoid dump_file fail to tmp dir when dir not exists. + for i in range(world_size): + part_file = osp.join(tmpdir, f'part_{i}.pkl') + os.remove(part_file) + + return ordered_results + + +def ava_evaluate_results(info, dataset_len, results, custom_classes, label_file, + file_path, exclude_file): + # need to create a temp result file + time_now = datetime.now().strftime('%Y%m%d_%H%M%S') + temp_file = f'AVA_{time_now}_result.csv' + results2csv(info, dataset_len, results, temp_file) + ret = {} + eval_result = ava_eval( + temp_file, + 'mAP', + label_file, + file_path, #ann_file, + exclude_file, + custom_classes=custom_classes) + ret.update(eval_result) + + os.remove(temp_file) + + return ret diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/base.py b/Bank_second_part/detect_process/paddlevideo/metrics/base.py new file mode 100644 index 0000000..9842232 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/base.py @@ -0,0 +1,52 @@ +# 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. + +from abc import abstractmethod + +import paddle +from paddlevideo.utils import get_dist_info + +from .registry import METRIC + + +class BaseMetric(object): + def __init__(self, data_size, batch_size, log_interval=1, **kwargs): + self.data_size = data_size + self.batch_size = batch_size + _, self.world_size = get_dist_info() + self.log_interval = log_interval + + def gather_from_gpu(self, + gather_object: paddle.Tensor, + concat_axis=0) -> paddle.Tensor: + """gather Tensor from all gpus into a list and concatenate them on `concat_axis`. + + Args: + gather_object (paddle.Tensor): gather object Tensor + concat_axis (int, optional): axis for concatenation. Defaults to 0. + + Returns: + paddle.Tensor: gatherd & concatenated Tensor + """ + gather_object_list = [] + paddle.distributed.all_gather(gather_object_list, gather_object.cuda()) + return paddle.concat(gather_object_list, axis=concat_axis) + + @abstractmethod + def update(self): + raise NotImplementedError( + "'update' method must be implemented in subclass") + + @abstractmethod + def accumulate(self): + raise NotImplementedError( + "'accumulate' method must be implemented in subclass") diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/bmn_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/bmn_metric.py new file mode 100644 index 0000000..cc36283 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/bmn_metric.py @@ -0,0 +1,304 @@ +# 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. + +import os +import json +import numpy as np +import pandas as pd +import multiprocessing as mp + +from .registry import METRIC +from .base import BaseMetric +from .ActivityNet import ANETproposal +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +def iou_with_anchors(anchors_min, anchors_max, box_min, box_max): + """Compute jaccard score between a box and the anchors. + """ + len_anchors = anchors_max - anchors_min + int_xmin = np.maximum(anchors_min, box_min) + int_xmax = np.minimum(anchors_max, box_max) + inter_len = np.maximum(int_xmax - int_xmin, 0.) + union_len = len_anchors - inter_len + box_max - box_min + jaccard = np.divide(inter_len, union_len) + return jaccard + + +def boundary_choose(score_list): + """Choose start and end boundary from score. + """ + max_score = max(score_list) + mask_high = (score_list > max_score * 0.5) + score_list = list(score_list) + score_middle = np.array([0.0] + score_list + [0.0]) + score_front = np.array([0.0, 0.0] + score_list) + score_back = np.array(score_list + [0.0, 0.0]) + mask_peak = ((score_middle > score_front) & (score_middle > score_back)) + mask_peak = mask_peak[1:-1] + mask = (mask_high | mask_peak).astype('float32') + return mask + + +def soft_nms(df, alpha, t1, t2): + ''' + df: proposals generated by network; + alpha: alpha value of Gaussian decaying function; + t1, t2: threshold for soft nms. + ''' + df = df.sort_values(by="score", ascending=False) + tstart = list(df.xmin.values[:]) + tend = list(df.xmax.values[:]) + tscore = list(df.score.values[:]) + + rstart = [] + rend = [] + rscore = [] + + while len(tscore) > 1 and len(rscore) < 101: + max_index = tscore.index(max(tscore)) + tmp_iou_list = iou_with_anchors(np.array(tstart), np.array(tend), + tstart[max_index], tend[max_index]) + for idx in range(0, len(tscore)): + if idx != max_index: + tmp_iou = tmp_iou_list[idx] + tmp_width = tend[max_index] - tstart[max_index] + if tmp_iou > t1 + (t2 - t1) * tmp_width: + tscore[idx] = tscore[idx] * np.exp( + -np.square(tmp_iou) / alpha) + + rstart.append(tstart[max_index]) + rend.append(tend[max_index]) + rscore.append(tscore[max_index]) + tstart.pop(max_index) + tend.pop(max_index) + tscore.pop(max_index) + + newDf = pd.DataFrame() + newDf['score'] = rscore + newDf['xmin'] = rstart + newDf['xmax'] = rend + return newDf + + +@METRIC.register +class BMNMetric(BaseMetric): + """ + Metrics for BMN. Two Stages in this metric: + (1) Get test results using trained model, results will be saved in BMNMetric.result_path; + (2) Calculate metrics using results file from stage (1). + """ + + def __init__(self, + data_size, + batch_size, + tscale, + dscale, + file_path, + ground_truth_filename, + subset, + output_path, + result_path, + get_metrics=True, + log_interval=1): + """ + Init for BMN metrics. + Params: + get_metrics: whether to calculate AR@N and AUC metrics or not, default True. + """ + super().__init__(data_size, batch_size, log_interval) + assert self.batch_size == 1, " Now we just support batch_size==1 test" + assert self.world_size == 1, " Now we just support single-card test" + + self.tscale = tscale + self.dscale = dscale + self.file_path = file_path + self.ground_truth_filename = ground_truth_filename + self.subset = subset + self.output_path = output_path + self.result_path = result_path + self.get_metrics = get_metrics + + if not os.path.isdir(self.output_path): + os.makedirs(self.output_path) + if not os.path.isdir(self.result_path): + os.makedirs(self.result_path) + + self.video_dict, self.video_list = self.get_dataset_dict( + self.file_path, self.subset) + + def get_dataset_dict(self, file_path, subset): + annos = json.load(open(file_path)) + video_dict = {} + for video_name in annos.keys(): + video_subset = annos[video_name]["subset"] + if subset in video_subset: + video_dict[video_name] = annos[video_name] + video_list = list(video_dict.keys()) + video_list.sort() + return video_dict, video_list + + def update(self, batch_id, data, outputs): + """update metrics during each iter + """ + fid = data[4].numpy() + pred_bm, pred_start, pred_end = outputs + pred_bm = pred_bm.numpy() + pred_start = pred_start[0].numpy() + pred_end = pred_end[0].numpy() + + snippet_xmins = [1.0 / self.tscale * i for i in range(self.tscale)] + snippet_xmaxs = [ + 1.0 / self.tscale * i for i in range(1, self.tscale + 1) + ] + cols = ["xmin", "xmax", "score"] + + video_name = self.video_list[fid[0]] + pred_bm = pred_bm[0, 0, :, :] * pred_bm[0, 1, :, :] + start_mask = boundary_choose(pred_start) + start_mask[0] = 1. + end_mask = boundary_choose(pred_end) + end_mask[-1] = 1. + score_vector_list = [] + for idx in range(self.dscale): + for jdx in range(self.tscale): + start_index = jdx + end_index = start_index + idx + if end_index < self.tscale and start_mask[ + start_index] == 1 and end_mask[end_index] == 1: + xmin = snippet_xmins[start_index] + xmax = snippet_xmaxs[end_index] + xmin_score = pred_start[start_index] + xmax_score = pred_end[end_index] + bm_score = pred_bm[idx, jdx] + conf_score = xmin_score * xmax_score * bm_score + score_vector_list.append([xmin, xmax, conf_score]) + + score_vector_list = np.stack(score_vector_list) + video_df = pd.DataFrame(score_vector_list, columns=cols) + video_df.to_csv(os.path.join(self.output_path, "%s.csv" % video_name), + index=False) + + if batch_id % self.log_interval == 0: + logger.info("Processing................ batch {}".format(batch_id)) + + def accumulate(self): + """accumulate metrics when finished all iters. + """ + # check clip index of each video + #Stage1 + self.bmn_post_processing(self.video_dict, self.subset, self.output_path, + self.result_path) + if self.get_metrics: + logger.info("[TEST] calculate metrics...") + #Stage2 + uniform_average_nr_proposals_valid, uniform_average_recall_valid, uniform_recall_valid = self.cal_metrics( + self.ground_truth_filename, + os.path.join(self.result_path, "bmn_results_validation.json"), + max_avg_nr_proposals=100, + tiou_thresholds=np.linspace(0.5, 0.95, 10), + subset='validation') + logger.info("AR@1; AR@5; AR@10; AR@100") + logger.info("%.02f %.02f %.02f %.02f" % + (100 * np.mean(uniform_recall_valid[:, 0]), + 100 * np.mean(uniform_recall_valid[:, 4]), + 100 * np.mean(uniform_recall_valid[:, 9]), + 100 * np.mean(uniform_recall_valid[:, -1]))) + + def bmn_post_processing(self, video_dict, subset, output_path, result_path): + video_list = list(video_dict.keys()) + global result_dict + result_dict = mp.Manager().dict() + pp_num = 12 + + num_videos = len(video_list) + num_videos_per_thread = int(num_videos / pp_num) + processes = [] + for tid in range(pp_num - 1): + tmp_video_list = video_list[tid * num_videos_per_thread:(tid + 1) * + num_videos_per_thread] + p = mp.Process(target=self.video_process, + args=(tmp_video_list, video_dict, output_path, + result_dict)) + p.start() + processes.append(p) + tmp_video_list = video_list[(pp_num - 1) * num_videos_per_thread:] + p = mp.Process(target=self.video_process, + args=(tmp_video_list, video_dict, output_path, + result_dict)) + p.start() + processes.append(p) + for p in processes: + p.join() + + result_dict = dict(result_dict) + output_dict = { + "version": "VERSION 1.3", + "results": result_dict, + "external_data": {} + } + outfile = open( + os.path.join(result_path, "bmn_results_%s.json" % subset), "w") + + # json.dump(output_dict, outfile) + # in case of file name in chinese + json.dump(output_dict, outfile, ensure_ascii=False) + outfile.close() + + def video_process(self, + video_list, + video_dict, + output_path, + result_dict, + snms_alpha=0.4, + snms_t1=0.55, + snms_t2=0.9): + + for video_name in video_list: + logger.info("Processing video........" + video_name) + df = pd.read_csv(os.path.join(output_path, video_name + ".csv")) + if len(df) > 1: + df = soft_nms(df, snms_alpha, snms_t1, snms_t2) + + video_duration = video_dict[video_name]["duration_second"] + proposal_list = [] + for idx in range(min(100, len(df))): + tmp_prop={"score":df.score.values[idx], \ + "segment":[max(0,df.xmin.values[idx])*video_duration, \ + min(1,df.xmax.values[idx])*video_duration]} + proposal_list.append(tmp_prop) + + video_name = video_name[2:] if video_name[:2] == 'v_' else video_name + result_dict[video_name] = proposal_list + + def cal_metrics(self, + ground_truth_filename, + proposal_filename, + max_avg_nr_proposals=100, + tiou_thresholds=np.linspace(0.5, 0.95, 10), + subset='validation'): + + anet_proposal = ANETproposal(ground_truth_filename, + proposal_filename, + tiou_thresholds=tiou_thresholds, + max_avg_nr_proposals=max_avg_nr_proposals, + subset=subset, + verbose=True, + check_status=False) + anet_proposal.evaluate() + recall = anet_proposal.recall + average_recall = anet_proposal.avg_recall + average_nr_proposals = anet_proposal.proposals_per_video + + return (average_nr_proposals, average_recall, recall) diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/build.py b/Bank_second_part/detect_process/paddlevideo/metrics/build.py new file mode 100644 index 0000000..82e4b50 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/build.py @@ -0,0 +1,20 @@ +# 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. + +from .registry import METRIC +from ..utils import build + + +def build_metric(cfg): + return build(cfg, METRIC) diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/center_crop_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/center_crop_metric.py new file mode 100644 index 0000000..0ca6112 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/center_crop_metric.py @@ -0,0 +1,79 @@ +# 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. + +from typing import List + +import paddle +from paddlevideo.utils import get_logger + +from .base import BaseMetric +from .registry import METRIC + +logger = get_logger("paddlevideo") + + +@METRIC.register +class CenterCropMetric(BaseMetric): + def __init__(self, data_size, batch_size, log_interval=1, **kwargs): + """prepare for metrics + """ + super().__init__(data_size, batch_size, log_interval, **kwargs) + self.rest_data_size = data_size # Number of samples remaining to be tested + self.all_outputs = [] + self.all_labels = [] + self.topk = kwargs.get("topk", [1, 5]) + + def update(self, batch_id: int, data: List, outputs: paddle.Tensor) -> None: + """update metrics during each iter + + Args: + batch_id (int): iter id of current batch. + data (List): list of batched data, such as [inputs, labels] + outputs (paddle.Tensor): batched outputs from model + """ + labels = data[1] + if self.world_size > 1: + labels_gathered = self.gather_from_gpu(labels, concat_axis=0) + outpus_gathered = self.gather_from_gpu(outputs, concat_axis=0) + else: + labels_gathered = labels + outpus_gathered = outputs + + # Avoid resampling effects when testing with multiple cards + labels_gathered = labels_gathered[0:min(len(labels_gathered), self. + rest_data_size)] + outpus_gathered = outpus_gathered[0:min(len(outpus_gathered), self. + rest_data_size)] + self.all_labels.append(labels_gathered) + self.all_outputs.append(outpus_gathered) + self.rest_data_size -= outpus_gathered.shape[0] + + # preds ensemble + if batch_id % self.log_interval == 0: + logger.info("[TEST] Processing batch {}/{} ...".format( + batch_id, + self.data_size // (self.batch_size * self.world_size))) + + def accumulate(self): + """accumulate, compute, and show metrics when finished all iters. + """ + self.all_outputs = paddle.concat(self.all_outputs, axis=0) + self.all_labels = paddle.concat(self.all_labels, axis=0) + + result_str = [] + for _k in self.topk: + topk_val = paddle.metric.accuracy(input=self.all_outputs, + label=self.all_labels, + k=_k).item() + result_str.append(f"avg_acc{_k}={topk_val}") + result_str = ", ".join(result_str) + logger.info(f"[TEST] finished, {result_str}") diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/center_crop_metric_MRI.py b/Bank_second_part/detect_process/paddlevideo/metrics/center_crop_metric_MRI.py new file mode 100644 index 0000000..b6d231a --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/center_crop_metric_MRI.py @@ -0,0 +1,61 @@ +# 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. + +import numpy as np +import paddle + +from .registry import METRIC +from .base import BaseMetric +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +@METRIC.register +class CenterCropMetric_MRI(BaseMetric): + def __init__(self, data_size, batch_size, log_interval=1, if_slowfast=0): + """prepare for metrics + """ + super().__init__(data_size, batch_size, log_interval) + self.top1 = [] + self.if_slowfast = if_slowfast + + def update(self, batch_id, data, outputs): + """update metrics during each iter + """ + labels = data[1] + + if self.if_slowfast: + labels = data[2] + + top1 = paddle.metric.accuracy(input=outputs, label=labels, k=1) + #top5 = paddle.metric.accuracy(input=outputs, label=labels, k=5) + #NOTE(shipping): deal with multi cards validate + if self.world_size > 1: + top1 = paddle.distributed.all_reduce( + top1, op=paddle.distributed.ReduceOp.SUM) / self.world_size + # top5 = paddle.distributed.all_reduce( + # top5, op=paddle.distributed.ReduceOp.SUM) / self.world_size + + self.top1.append(top1.numpy()) + #self.top5.append(top5.numpy()) + # preds ensemble + if batch_id % self.log_interval == 0: + logger.info("[TEST] Processing batch {}/{} ...".format( + batch_id, + self.data_size // (self.batch_size * self.world_size))) + + def accumulate(self): + """accumulate metrics when finished all iters. + """ + logger.info('[TEST] finished, avg_acc1= {}'.format( + np.mean(np.array(self.top1)))) diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/depth_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/depth_metric.py new file mode 100644 index 0000000..c160e16 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/depth_metric.py @@ -0,0 +1,77 @@ +import numpy as np +import paddle +from paddlevideo.utils import get_logger + +from .base import BaseMetric +from .registry import METRIC + +logger = get_logger("paddlevideo") + + +@METRIC.register +class DepthMetric(BaseMetric): + def __init__(self, data_size, batch_size, log_interval=1): + """prepare for metrics + """ + super().__init__(data_size, batch_size, log_interval) + self.abs_rel = [] + self.sq_rel = [] + self.rmse = [] + self.rmse_log = [] + self.a1 = [] + self.a2 = [] + self.a3 = [] + + def update(self, batch_id, data, outputs): + """update metrics during each iter + """ + abs_rel, sq_rel, rmse, rmse_log, a1, a2, a3 = outputs['abs_rel'], outputs['sq_rel'], outputs['rmse'], \ + outputs['rmse_log'], outputs['a1'], outputs['a2'],outputs['a3'] + # preds ensemble + if self.world_size > 1: + abs_rel = paddle.distributed.all_reduce( + outputs['abs_rel'], + op=paddle.distributed.ReduceOp.SUM) / self.world_size + sq_rel = paddle.distributed.all_reduce( + outputs['sq_rel'], + op=paddle.distributed.ReduceOp.SUM) / self.world_size + rmse = paddle.distributed.all_reduce( + outputs['rmse'], + op=paddle.distributed.ReduceOp.SUM) / self.world_size + rmse_log = paddle.distributed.all_reduce( + outputs['rmse_log'], + op=paddle.distributed.ReduceOp.SUM) / self.world_size + a1 = paddle.distributed.all_reduce( + outputs['a1'], + op=paddle.distributed.ReduceOp.SUM) / self.world_size + a2 = paddle.distributed.all_reduce( + outputs['a2'], + op=paddle.distributed.ReduceOp.SUM) / self.world_size + a3 = paddle.distributed.all_reduce( + outputs['a3'], + op=paddle.distributed.ReduceOp.SUM) / self.world_size + + self.abs_rel.append(abs_rel) + self.sq_rel.append(sq_rel) + self.rmse.append(rmse) + self.rmse_log.append(rmse_log) + self.a1.append(a1) + self.a2.append(a2) + self.a3.append(a3) + if batch_id % self.log_interval == 0: + logger.info("[TEST] Processing batch {}/{} ...".format( + batch_id, + self.data_size // (self.batch_size * self.world_size))) + + def accumulate(self): + """accumulate metrics when finished all iters. + """ + logger.info( + '[TEST] finished, abs_rel= {}, sq_rel= {} , rmse= {}, rmse_log= {},' + 'a1= {}, a2= {}, a3= {}'.format(np.mean(np.array(self.abs_rel)), + np.mean(np.array(self.sq_rel)), + np.mean(np.array(self.rmse)), + np.mean(np.array(self.rmse_log)), + np.mean(np.array(self.a1)), + np.mean(np.array(self.a2)), + np.mean(np.array(self.a3)))) diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/msrvtt_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/msrvtt_metric.py new file mode 100644 index 0000000..99e7334 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/msrvtt_metric.py @@ -0,0 +1,62 @@ +# Copyright (c) 2021 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. + +import numpy as np +import paddle +import paddle.nn.functional as F + +from .registry import METRIC +from .base import BaseMetric +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +@METRIC.register +class MSRVTTMetric(BaseMetric): + def __init__(self, data_size, batch_size, log_interval=1): + """prepare for metrics + """ + super().__init__(data_size, batch_size, log_interval) + self.score_matrix = np.zeros((data_size, data_size)) + self.target_matrix = np.zeros((data_size, data_size)) + self.rank_matrix = np.ones((data_size)) * data_size + + def update(self, batch_id, data, outputs): + """update metrics during each iter + """ + target = data[-1] + cm_logit = outputs[-1] + + self.score_matrix[batch_id, :] = F.softmax( + cm_logit, axis=1)[:, 0].reshape([-1]).numpy() + self.target_matrix[batch_id, :] = target.reshape([-1]).numpy() + + rank = np.where((np.argsort(-self.score_matrix[batch_id]) == np.where( + self.target_matrix[batch_id] == 1)[0][0]) == 1)[0][0] + self.rank_matrix[batch_id] = rank + + rank_matrix_tmp = self.rank_matrix[:batch_id + 1] + r1 = 100.0 * np.sum(rank_matrix_tmp < 1) / len(rank_matrix_tmp) + r5 = 100.0 * np.sum(rank_matrix_tmp < 5) / len(rank_matrix_tmp) + r10 = 100.0 * np.sum(rank_matrix_tmp < 10) / len(rank_matrix_tmp) + + medr = np.floor(np.median(rank_matrix_tmp) + 1) + meanr = np.mean(rank_matrix_tmp) + 1 + logger.info( + "[{}] Final r1:{:.3f}, r5:{:.3f}, r10:{:.3f}, mder:{:.3f}, meanr:{:.3f}" + .format(batch_id, r1, r5, r10, medr, meanr)) + + def accumulate(self): + """accumulate metrics when finished all iters. + """ + logger.info("Eval Finished!") diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/multi_crop_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/multi_crop_metric.py new file mode 100644 index 0000000..5f20ced --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/multi_crop_metric.py @@ -0,0 +1,108 @@ +# 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. + +import numpy as np +import paddle +from paddle.hapi.model import _all_gather + +from paddlevideo.utils import get_logger +from .registry import METRIC +from .base import BaseMetric + +logger = get_logger("paddlevideo") +""" An example for metrics class. + MultiCropMetric for slowfast. +""" + + +@METRIC.register +class MultiCropMetric(BaseMetric): + def __init__(self, + data_size, + batch_size, + num_ensemble_views, + num_spatial_crops, + num_classes, + log_interval=1): + """prepare for metrics + """ + super().__init__(data_size, batch_size, log_interval) + self.num_ensemble_views = num_ensemble_views + self.num_spatial_crops = num_spatial_crops + self.num_classes = num_classes + + self.num_clips = self.num_ensemble_views * self.num_spatial_crops + num_videos = self.data_size // self.num_clips + self.video_preds = np.zeros((num_videos, self.num_classes)) + self.video_labels = np.zeros((num_videos, 1), dtype="int64") + self.clip_count = {} + + def update(self, batch_id, data, outputs): + """update metrics during each iter + """ + labels = data[2] + clip_ids = data[3] + + # gather mulit card, results of following process in each card is the same. + if self.world_size > 1: + outputs = _all_gather(outputs, self.world_size) + labels = _all_gather(labels.cuda(), self.world_size) + clip_ids = _all_gather(clip_ids.cuda(), self.world_size) + + # to numpy + preds = outputs.numpy() + labels = labels.numpy().astype("int64") + clip_ids = clip_ids.numpy() + + # preds ensemble + for ind in range(preds.shape[0]): + vid_id = int(clip_ids[ind]) // self.num_clips + ts_idx = int(clip_ids[ind]) % self.num_clips + if vid_id not in self.clip_count: + self.clip_count[vid_id] = [] + if ts_idx in self.clip_count[vid_id]: + logger.info( + "[TEST] Passed!! read video {} clip index {} / {} repeatedly." + .format(vid_id, ts_idx, clip_ids[ind])) + else: + self.clip_count[vid_id].append(ts_idx) + self.video_preds[vid_id] += preds[ind] # ensemble method: sum + if self.video_labels[vid_id].sum() > 0: + assert self.video_labels[vid_id] == labels[ind] + self.video_labels[vid_id] = labels[ind] + if batch_id % self.log_interval == 0: + logger.info("[TEST] Processing batch {}/{} ...".format( + batch_id, + self.data_size // (self.batch_size * self.world_size))) + + def accumulate(self): + """accumulate metrics when finished all iters. + """ + # check clip index of each video + for key in self.clip_count.keys(): + if len(self.clip_count[key]) != self.num_clips or sum( + self.clip_count[key]) != self.num_clips * (self.num_clips - + 1) / 2: + logger.info( + "[TEST] Count Error!! video [{}] clip count [{}] not match number clips {}" + .format(key, self.clip_count[key], self.num_clips)) + + video_preds = paddle.to_tensor(self.video_preds) + video_labels = paddle.to_tensor(self.video_labels) + acc_top1 = paddle.metric.accuracy(input=video_preds, + label=video_labels, + k=1) + acc_top5 = paddle.metric.accuracy(input=video_preds, + label=video_labels, + k=5) + logger.info('[TEST] finished, avg_acc1= {}, avg_acc5= {} '.format( + acc_top1.numpy(), acc_top5.numpy())) diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/recall.py b/Bank_second_part/detect_process/paddlevideo/metrics/recall.py new file mode 100644 index 0000000..3612e22 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/recall.py @@ -0,0 +1,84 @@ +import numpy as np +import paddle + +def _recalls(all_ious, proposal_nums, thrs): + + img_num = all_ious.shape[0] + total_gt_num = sum([ious.shape[0] for ious in all_ious]) + + ious_ = np.zeros((proposal_nums.size, total_gt_num), dtype=np.float32) + for k, proposal_num in enumerate(proposal_nums): + tmp_ious = np.zeros(0) + for i in range(img_num): + ious = all_ious[i][:, :proposal_num].copy() + gt_ious = np.zeros(ious.shape[0]) + if ious.size == 0: + tmp_ious = np.hstack((tmp_ious, gt_ious)) + continue + for j in range(ious.shape[0]): + gt_max_overlaps = ious.argmax(axis=1) + max_ious = ious[np.arange(0, ious.shape[0]), gt_max_overlaps] + gt_idx = max_ious.argmax() + gt_ious[j] = max_ious[gt_idx] + box_idx = gt_max_overlaps[gt_idx] + ious[gt_idx, :] = -1 + ious[:, box_idx] = -1 + tmp_ious = np.hstack((tmp_ious, gt_ious)) + ious_[k, :] = tmp_ious + + ious_ = np.fliplr(np.sort(ious_, axis=1)) + recalls = np.zeros((proposal_nums.size, thrs.size)) + for i, thr in enumerate(thrs): + recalls[:, i] = (ious_ >= thr).sum(axis=1) / float(total_gt_num) + + return recalls + + +def set_recall_param(proposal_nums, iou_thrs): + if isinstance(proposal_nums, list): + proposal_nums_ = np.array(proposal_nums) + elif isinstance(proposal_nums, int): + proposal_nums_ = np.array([proposal_nums]) + else: + proposal_nums_ = proposal_nums + + if iou_thrs is None: + _iou_thrs = np.array([0.5]) + elif isinstance(iou_thrs, list): + _iou_thrs = np.array(iou_thrs) + elif isinstance(iou_thrs, float): + _iou_thrs = np.array([iou_thrs]) + else: + _iou_thrs = iou_thrs + + return proposal_nums_, _iou_thrs + + +def eval_recalls(gts, proposals, proposal_nums=None, iou_thrs=None): + """Calculate recalls. """ + img_num = len(gts) + assert img_num == len(proposals) + + proposal_nums, iou_thrs = set_recall_param(proposal_nums, iou_thrs) + + all_ious = [] + for i in range(img_num): + if proposals[i].ndim == 2 and proposals[i].shape[1] == 5: + scores = proposals[i][:, 4] + sort_idx = np.argsort(scores)[::-1] + img_proposal = proposals[i][sort_idx, :] + else: + img_proposal = proposals[i] + + prop_num = min(img_proposal.shape[0], proposal_nums[-1]) + if gts[i] is None or gts[i].shape[0] == 0: + ious = np.zeros((0, img_proposal.shape[0]), dtype=np.float32) + else: + ious = bbox_overlaps( + torch.tensor(gts[i]), + torch.tensor(img_proposal[:prop_num, :4])) + ious = ious.data.numpy() + all_ious.append(ious) + all_ious = np.array(all_ious) + recalls = _recalls(all_ious, proposal_nums, iou_thrs) + return recalls diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/registry.py b/Bank_second_part/detect_process/paddlevideo/metrics/registry.py new file mode 100644 index 0000000..2214440 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/registry.py @@ -0,0 +1,17 @@ +# 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. + +from ..utils import Registry + +METRIC = Registry('metric') diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/segmentation_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/segmentation_metric.py new file mode 100644 index 0000000..3719450 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/segmentation_metric.py @@ -0,0 +1,389 @@ +# Copyright (c) 2021 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. + +import numpy as np +import argparse +import pandas as pd + +from .registry import METRIC +from .base import BaseMetric +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +def get_labels_scores_start_end_time(input_np, + frame_wise_labels, + actions_dict, + bg_class=["background", "None"]): + labels = [] + starts = [] + ends = [] + scores = [] + + boundary_score_ptr = 0 + + last_label = frame_wise_labels[0] + if frame_wise_labels[0] not in bg_class: + labels.append(frame_wise_labels[0]) + starts.append(0) + for i in range(len(frame_wise_labels)): + if frame_wise_labels[i] != last_label: + if frame_wise_labels[i] not in bg_class: + labels.append(frame_wise_labels[i]) + starts.append(i) + if last_label not in bg_class: + ends.append(i) + score = np.mean( + input_np[actions_dict[labels[boundary_score_ptr]], \ + starts[boundary_score_ptr]:(ends[boundary_score_ptr] + 1)] + ) + scores.append(score) + boundary_score_ptr = boundary_score_ptr + 1 + last_label = frame_wise_labels[i] + if last_label not in bg_class: + ends.append(i + 1) + score = np.mean( + input_np[actions_dict[labels[boundary_score_ptr]], \ + starts[boundary_score_ptr]:(ends[boundary_score_ptr] + 1)] + ) + scores.append(score) + boundary_score_ptr = boundary_score_ptr + 1 + + return labels, starts, ends, scores + + +def get_labels_start_end_time(frame_wise_labels, + bg_class=["background", "None"]): + labels = [] + starts = [] + ends = [] + last_label = frame_wise_labels[0] + if frame_wise_labels[0] not in bg_class: + labels.append(frame_wise_labels[0]) + starts.append(0) + for i in range(len(frame_wise_labels)): + if frame_wise_labels[i] != last_label: + if frame_wise_labels[i] not in bg_class: + labels.append(frame_wise_labels[i]) + starts.append(i) + if last_label not in bg_class: + ends.append(i) + last_label = frame_wise_labels[i] + if last_label not in bg_class: + ends.append(i + 1) + return labels, starts, ends + + +def levenstein(p, y, norm=False): + m_row = len(p) + n_col = len(y) + D = np.zeros([m_row + 1, n_col + 1], np.float) + for i in range(m_row + 1): + D[i, 0] = i + for i in range(n_col + 1): + D[0, i] = i + + for j in range(1, n_col + 1): + for i in range(1, m_row + 1): + if y[j - 1] == p[i - 1]: + D[i, j] = D[i - 1, j - 1] + else: + D[i, j] = min(D[i - 1, j] + 1, D[i, j - 1] + 1, + D[i - 1, j - 1] + 1) + + if norm: + score = (1 - D[-1, -1] / max(m_row, n_col)) * 100 + else: + score = D[-1, -1] + + return score + + +def edit_score(recognized, + ground_truth, + norm=True, + bg_class=["background", "None"]): + P, _, _ = get_labels_start_end_time(recognized, bg_class) + Y, _, _ = get_labels_start_end_time(ground_truth, bg_class) + return levenstein(P, Y, norm) + + +def f_score(recognized, ground_truth, overlap, bg_class=["background", "None"]): + p_label, p_start, p_end = get_labels_start_end_time(recognized, bg_class) + y_label, y_start, y_end = get_labels_start_end_time(ground_truth, bg_class) + + tp = 0 + fp = 0 + + hits = np.zeros(len(y_label)) + + for j in range(len(p_label)): + intersection = np.minimum(p_end[j], y_end) - np.maximum( + p_start[j], y_start) + union = np.maximum(p_end[j], y_end) - np.minimum(p_start[j], y_start) + IoU = (1.0 * intersection / union) * ( + [p_label[j] == y_label[x] for x in range(len(y_label))]) + # Get the best scoring segment + idx = np.array(IoU).argmax() + + if IoU[idx] >= overlap and not hits[idx]: + tp += 1 + hits[idx] = 1 + else: + fp += 1 + fn = len(y_label) - sum(hits) + return float(tp), float(fp), float(fn) + + +def boundary_AR(pred_boundary, gt_boundary, overlap_list, max_proposal): + + p_label, p_start, p_end, p_scores = pred_boundary + y_label, y_start, y_end, _ = gt_boundary + + # sort proposal + pred_dict = { + "label": p_label, + "start": p_start, + "end": p_end, + "scores": p_scores + } + pdf = pd.DataFrame(pred_dict) + pdf = pdf.sort_values(by="scores", ascending=False) + p_label = list(pdf["label"]) + p_start = list(pdf["start"]) + p_end = list(pdf["end"]) + p_scores = list(pdf["scores"]) + + # refine AN + if len(p_label) < max_proposal and len(p_label) > 0: + p_label = p_label + [p_label[-1]] * (max_proposal - len(p_label)) + p_start = p_start + [p_start[-1]] * (max_proposal - len(p_start)) + p_start = p_start + p_start[len(p_start) - + (max_proposal - len(p_start)):] + p_end = p_end + [p_end[-1]] * (max_proposal - len(p_end)) + p_scores = p_scores + [p_scores[-1]] * (max_proposal - len(p_scores)) + elif len(p_label) > max_proposal: + p_label[max_proposal:] = [] + p_start[max_proposal:] = [] + p_end[max_proposal:] = [] + p_scores[max_proposal:] = [] + + t_AR = np.zeros(len(overlap_list)) + + for i in range(len(overlap_list)): + overlap = overlap_list[i] + + tp = 0 + fp = 0 + hits = np.zeros(len(y_label)) + + for j in range(len(p_label)): + intersection = np.minimum(p_end[j], y_end) - np.maximum( + p_start[j], y_start) + union = np.maximum(p_end[j], y_end) - np.minimum( + p_start[j], y_start) + IoU = (1.0 * intersection / union) + # Get the best scoring segment + idx = np.array(IoU).argmax() + + if IoU[idx] >= overlap and not hits[idx]: + tp += 1 + hits[idx] = 1 + else: + fp += 1 + fn = len(y_label) - sum(hits) + + recall = float(tp) / (float(tp) + float(fn)) + t_AR[i] = recall + + AR = np.mean(t_AR) + return AR + + +@METRIC.register +class SegmentationMetric(BaseMetric): + """ + Test for Video Segmentation based model. + """ + + def __init__(self, + data_size, + batch_size, + overlap, + actions_map_file_path, + log_interval=1, + tolerance=5, + boundary_threshold=0.7, + max_proposal=100): + """prepare for metrics + """ + super().__init__(data_size, batch_size, log_interval) + # actions dict generate + file_ptr = open(actions_map_file_path, 'r') + actions = file_ptr.read().split('\n')[:-1] + file_ptr.close() + self.actions_dict = dict() + for a in actions: + self.actions_dict[a.split()[1]] = int(a.split()[0]) + + # cls score + self.overlap = overlap + self.overlap_len = len(overlap) + + self.cls_tp = np.zeros(self.overlap_len) + self.cls_fp = np.zeros(self.overlap_len) + self.cls_fn = np.zeros(self.overlap_len) + self.total_correct = 0 + self.total_edit = 0 + self.total_frame = 0 + self.total_video = 0 + + # boundary score + self.max_proposal = max_proposal + self.AR_at_AN = [[] for _ in range(max_proposal)] + + def update(self, batch_id, data, outputs): + """update metrics during each iter + """ + groundTruth = data[1] + + predicted = outputs['predict'] + output_np = outputs['output_np'] + + outputs_np = predicted.numpy() + outputs_arr = output_np.numpy()[0, :] + gt_np = groundTruth.numpy()[0, :] + + recognition = [] + for i in range(outputs_np.shape[0]): + recognition = np.concatenate((recognition, [ + list(self.actions_dict.keys())[list( + self.actions_dict.values()).index(outputs_np[i])] + ])) + recog_content = list(recognition) + + gt_content = [] + for i in range(gt_np.shape[0]): + gt_content = np.concatenate((gt_content, [ + list(self.actions_dict.keys())[list( + self.actions_dict.values()).index(gt_np[i])] + ])) + gt_content = list(gt_content) + + pred_boundary = get_labels_scores_start_end_time( + outputs_arr, recog_content, self.actions_dict) + gt_boundary = get_labels_scores_start_end_time( + np.ones(outputs_arr.shape), gt_content, self.actions_dict) + + # cls score + correct = 0 + total = 0 + edit = 0 + + for i in range(len(gt_content)): + total += 1 + #accumulate + self.total_frame += 1 + + if gt_content[i] == recog_content[i]: + correct += 1 + #accumulate + self.total_correct += 1 + + edit_num = edit_score(recog_content, gt_content) + edit += edit_num + self.total_edit += edit_num + + for s in range(self.overlap_len): + tp1, fp1, fn1 = f_score(recog_content, gt_content, self.overlap[s]) + + # accumulate + self.cls_tp[s] += tp1 + self.cls_fp[s] += fp1 + self.cls_fn[s] += fn1 + + # accumulate + self.total_video += 1 + + # proposal score + for AN in range(self.max_proposal): + AR = boundary_AR(pred_boundary, + gt_boundary, + self.overlap, + max_proposal=(AN + 1)) + self.AR_at_AN[AN].append(AR) + + def accumulate(self): + """accumulate metrics when finished all iters. + """ + # cls metric + Acc = 100 * float(self.total_correct) / self.total_frame + Edit = (1.0 * self.total_edit) / self.total_video + Fscore = dict() + for s in range(self.overlap_len): + precision = self.cls_tp[s] / float(self.cls_tp[s] + self.cls_fp[s]) + recall = self.cls_tp[s] / float(self.cls_tp[s] + self.cls_fn[s]) + + f1 = 2.0 * (precision * recall) / (precision + recall) + + f1 = np.nan_to_num(f1) * 100 + Fscore[self.overlap[s]] = f1 + + # proposal metric + proposal_AUC = np.array(self.AR_at_AN) * 100 + AUC = np.mean(proposal_AUC) + AR_at_AN1 = np.mean(proposal_AUC[0, :]) + AR_at_AN5 = np.mean(proposal_AUC[4, :]) + AR_at_AN15 = np.mean(proposal_AUC[14, :]) + + # log metric + log_mertic_info = "dataset model performence: " + # preds ensemble + log_mertic_info += "Acc: {:.4f}, ".format(Acc) + log_mertic_info += 'Edit: {:.4f}, '.format(Edit) + for s in range(len(self.overlap)): + log_mertic_info += 'F1@{:0.2f}: {:.4f}, '.format( + self.overlap[s], Fscore[self.overlap[s]]) + + # boundary metric + log_mertic_info += "Auc: {:.4f}, ".format(AUC) + log_mertic_info += "AR@AN1: {:.4f}, ".format(AR_at_AN1) + log_mertic_info += "AR@AN5: {:.4f}, ".format(AR_at_AN5) + log_mertic_info += "AR@AN15: {:.4f}, ".format(AR_at_AN15) + logger.info(log_mertic_info) + + # log metric + metric_dict = dict() + metric_dict['Acc'] = Acc + metric_dict['Edit'] = Edit + for s in range(len(self.overlap)): + metric_dict['F1@{:0.2f}'.format( + self.overlap[s])] = Fscore[self.overlap[s]] + metric_dict['Auc'] = AUC + metric_dict['AR@AN1'] = AR_at_AN1 + metric_dict['AR@AN5'] = AR_at_AN5 + metric_dict['AR@AN15'] = AR_at_AN15 + + # clear for next epoch + # cls + self.cls_tp = np.zeros(self.overlap_len) + self.cls_fp = np.zeros(self.overlap_len) + self.cls_fn = np.zeros(self.overlap_len) + self.total_correct = 0 + self.total_edit = 0 + self.total_frame = 0 + self.total_video = 0 + # proposal + self.AR_at_AN = [[] for _ in range(self.max_proposal)] + + return metric_dict diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/skeleton_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/skeleton_metric.py new file mode 100644 index 0000000..7978478 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/skeleton_metric.py @@ -0,0 +1,96 @@ +# Copyright (c) 2021 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. + +import numpy as np +import paddle +import csv +import paddle.nn.functional as F + +from .registry import METRIC +from .base import BaseMetric +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +@METRIC.register +class SkeletonMetric(BaseMetric): + """ + Test for Skeleton based model. + note: only support batch size = 1, single card test. + + Args: + out_file: str, file to save test results. + """ + + def __init__(self, + data_size, + batch_size, + out_file='submission.csv', + log_interval=1, + top_k=5): + """prepare for metrics + """ + super().__init__(data_size, batch_size, log_interval) + self.top1 = [] + self.top5 = [] + self.values = [] + self.out_file = out_file + self.k = top_k + + def update(self, batch_id, data, outputs): + """update metrics during each iter + """ + if data[0].shape[0] != outputs.shape[0]: + num_segs = data[0].shape[1] + batch_size = outputs.shape[0] + outputs = outputs.reshape( + [batch_size // num_segs, num_segs, outputs.shape[-1]]) + outputs = outputs.mean(axis=1) + if len(data) == 2: # data with label + labels = data[1] + top1 = paddle.metric.accuracy(input=outputs, label=labels, k=1) + top5 = paddle.metric.accuracy(input=outputs, label=labels, k=self.k) + if self.world_size > 1: + top1 = paddle.distributed.all_reduce( + top1, op=paddle.distributed.ReduceOp.SUM) / self.world_size + top5 = paddle.distributed.all_reduce( + top5, op=paddle.distributed.ReduceOp.SUM) / self.world_size + self.top1.append(top1.numpy()) + self.top5.append(top5.numpy()) + else: # data without label, only support batch_size=1. Used for fsd-10. + prob = F.softmax(outputs) + clas = paddle.argmax(prob, axis=1).numpy()[0] + self.values.append((batch_id, clas)) + + # preds ensemble + if batch_id % self.log_interval == 0: + logger.info("[TEST] Processing batch {}/{} ...".format( + batch_id, + self.data_size // (self.batch_size * self.world_size))) + + def accumulate(self): + """accumulate metrics when finished all iters. + """ + if self.top1: # data with label + logger.info('[TEST] finished, avg_acc1= {}, avg_acc5= {}'.format( + np.mean(np.array(self.top1)), np.mean(np.array(self.top5)))) + else: + headers = ['sample_index', 'predict_category'] + with open( + self.out_file, + 'w', + ) as fp: + writer = csv.writer(fp) + writer.writerow(headers) + writer.writerows(self.values) + logger.info("Results saved in {} !".format(self.out_file)) diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/transnetv2_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/transnetv2_metric.py new file mode 100644 index 0000000..3370881 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/transnetv2_metric.py @@ -0,0 +1,174 @@ +# 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. + +import numpy as np + +from .registry import METRIC +from .base import BaseMetric +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +def predictions_to_scenes(predictions): + scenes = [] + t, t_prev, start = -1, 0, 0 + for i, t in enumerate(predictions): + if t_prev == 1 and t == 0: + start = i + if t_prev == 0 and t == 1 and i != 0: + scenes.append([start, i]) + t_prev = t + if t == 0: + scenes.append([start, i]) + + # just fix if all predictions are 1 + if len(scenes) == 0: + return np.array([[0, len(predictions) - 1]], dtype=np.int32) + + return np.array(scenes, dtype=np.int32) + + +def evaluate_scenes(gt_scenes, pred_scenes, n_frames_miss_tolerance=2): + """ + Adapted from: https://github.com/gyglim/shot-detection-evaluation + The original based on: http://imagelab.ing.unimore.it/imagelab/researchActivity.asp?idActivity=19 + + n_frames_miss_tolerance: + Number of frames it is possible to miss ground truth by, and still being counted as a correct detection. + + Examples of computation with different tolerance margin: + n_frames_miss_tolerance = 0 + pred_scenes: [[0, 5], [6, 9]] -> pred_trans: [[5.5, 5.5]] + gt_scenes: [[0, 5], [6, 9]] -> gt_trans: [[5.5, 5.5]] -> HIT + gt_scenes: [[0, 4], [5, 9]] -> gt_trans: [[4.5, 4.5]] -> MISS + n_frames_miss_tolerance = 1 + pred_scenes: [[0, 5], [6, 9]] -> pred_trans: [[5.0, 6.0]] + gt_scenes: [[0, 5], [6, 9]] -> gt_trans: [[5.0, 6.0]] -> HIT + gt_scenes: [[0, 4], [5, 9]] -> gt_trans: [[4.0, 5.0]] -> HIT + gt_scenes: [[0, 3], [4, 9]] -> gt_trans: [[3.0, 4.0]] -> MISS + n_frames_miss_tolerance = 2 + pred_scenes: [[0, 5], [6, 9]] -> pred_trans: [[4.5, 6.5]] + gt_scenes: [[0, 5], [6, 9]] -> gt_trans: [[4.5, 6.5]] -> HIT + gt_scenes: [[0, 4], [5, 9]] -> gt_trans: [[3.5, 5.5]] -> HIT + gt_scenes: [[0, 3], [4, 9]] -> gt_trans: [[2.5, 4.5]] -> HIT + gt_scenes: [[0, 2], [3, 9]] -> gt_trans: [[1.5, 3.5]] -> MISS + + Users should be careful about adopting these functions in any commercial matters. + """ + + shift = n_frames_miss_tolerance / 2 + gt_scenes = gt_scenes.astype(np.float32) + np.array([[-0.5 + shift, 0.5 - shift]]) + pred_scenes = pred_scenes.astype(np.float32) + np.array([[-0.5 + shift, 0.5 - shift]]) + + gt_trans = np.stack([gt_scenes[:-1, 1], gt_scenes[1:, 0]], 1) + pred_trans = np.stack([pred_scenes[:-1, 1], pred_scenes[1:, 0]], 1) + + i, j = 0, 0 + tp, fp, fn = 0, 0, 0 + + while i < len(gt_trans) or j < len(pred_trans): + if j == len(pred_trans) or pred_trans[j, 0] > gt_trans[i, 1]: + fn += 1 + i += 1 + elif i == len(gt_trans) or pred_trans[j, 1] < gt_trans[i, 0]: + fp += 1 + j += 1 + else: + i += 1 + j += 1 + tp += 1 + + if tp + fp != 0: + p = tp / (tp + fp) + else: + p = 0 + + if tp + fn != 0: + r = tp / (tp + fn) + else: + r = 0 + + if p + r != 0: + f1 = (p * r * 2) / (p + r) + else: + f1 = 0 + + assert tp + fn == len(gt_trans) + assert tp + fp == len(pred_trans) + + return p, r, f1, (tp, fp, fn) + + +def create_scene_based_summaries(one_hot_pred, one_hot_gt): + thresholds = np.array([ + 0.02, 0.06, 0.1, 0.15, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 + ]) + precision, recall, f1, tp, fp, fn = np.zeros_like(thresholds), np.zeros_like(thresholds),\ + np.zeros_like(thresholds), np.zeros_like(thresholds),\ + np.zeros_like(thresholds), np.zeros_like(thresholds) + + gt_scenes = predictions_to_scenes(one_hot_gt) + for i in range(len(thresholds)): + pred_scenes = predictions_to_scenes( + (one_hot_pred > thresholds[i]).astype(np.uint8) + ) + precision[i], recall[i], f1[i], (tp[i], fp[i], fn[i]) = evaluate_scenes(gt_scenes, pred_scenes) + + best_idx = np.argmax(f1) + + return f1[best_idx] + + +@METRIC.register +class TransNetV2Metric(BaseMetric): + def __init__(self, data_size, batch_size, log_interval=1): + """prepare for metrics + """ + super().__init__(data_size, batch_size, log_interval) + self.predictions = [] + self.total_stats = {"tp": 0, "fp": 0, "fn": 0} + + def update(self, batch_id, data, one_hot): + """update metrics during each iter + """ + if isinstance(one_hot, tuple): + one_hot = one_hot[0] + one_hot = paddle.nn.functional.sigmoid(one_hot)[0] + self.predictions.append(one_hot.numpy()[25:75]) + gt_scenes = data[1] + is_new_file = data[2] + if is_new_file: + self.compute(gt_scenes) + # preds ensemble + if batch_id % self.log_interval == 0: + logger.info("[TEST] Processing batch {}/{} ...".format( + batch_id, + self.data_size // (self.batch_size * self.world_size))) + + def compute(self, gt_scenes): + predictions = np.concatenate(self.predictions, 0)[:len(frames)] + _, _, _, (tp, fp, fn), fp_mistakes, fn_mistakes = evaluate_scenes( + gt_scenes, predictions_to_scenes((predictions >= args.thr).astype(np.uint8))) + + self.total_stats["tp"] += tp + self.total_stats["fp"] += fp + self.total_stats["fn"] += fn + + def accumulate(self): + """accumulate metrics when finished all iters. + """ + p = self.total_stats["tp"] / (self.total_stats["tp"] + self.total_stats["fp"]) + r = self.total_stats["tp"] / (self.total_stats["tp"] + self.total_stats["fn"]) + f1 = (p * r * 2) / (p + r) + logger.info('[TEST] finished, Precision= {:5.2f}, Recall= {:5.2f} , F1 Score= {:5.2f} '.format( + p * 100, r * 100, f1 * 100)) \ No newline at end of file diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/ucf24_utils.py b/Bank_second_part/detect_process/paddlevideo/metrics/ucf24_utils.py new file mode 100644 index 0000000..6552645 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/ucf24_utils.py @@ -0,0 +1,783 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. +# +# Forked from: https://github.com/rafaelpadilla/Object-Detection-Metrics +# Developed by: Rafael Padilla (rafael.padilla@smt.ufrj.br) + +import glob +import os +import shutil +import sys +from collections import Counter +import numpy as np +from enum import Enum +import cv2 + + +class MethodAveragePrecision(Enum): + """ + Class representing if the coordinates are relative to the + image size or are absolute values. + + Developed by: Rafael Padilla + Last modification: Apr 28 2018 + """ + EveryPointInterpolation = 1 + ElevenPointInterpolation = 2 + + +class CoordinatesType(Enum): + """ + Class representing if the coordinates are relative to the + image size or are absolute values. + + Developed by: Rafael Padilla + Last modification: Apr 28 2018 + """ + Relative = 1 + Absolute = 2 + + +class BBType(Enum): + """ + Class representing if the bounding box is groundtruth or not. + + Developed by: Rafael Padilla + Last modification: May 24 2018 + """ + GroundTruth = 1 + Detected = 2 + + +class BBFormat(Enum): + """ + Class representing the format of a bounding box. + It can be (X,Y,width,height) => XYWH + or (X1,Y1,X2,Y2) => XYX2Y2 + Developed by: Rafael Padilla + Last modification: May 24 2018 + """ + XYWH = 1 + XYX2Y2 = 2 + + +def convertToRelativeValues(size, box): + dw = 1. / (size[0]) + dh = 1. / (size[1]) + cx = (box[1] + box[0]) / 2.0 + cy = (box[3] + box[2]) / 2.0 + w = box[1] - box[0] + h = box[3] - box[2] + x = cx * dw + y = cy * dh + w = w * dw + h = h * dh + return x, y, w, h + + +def convertToAbsoluteValues(size, box): + xIn = round(((2 * float(box[0]) - float(box[2])) * size[0] / 2)) + yIn = round(((2 * float(box[1]) - float(box[3])) * size[1] / 2)) + xEnd = xIn + round(float(box[2]) * size[0]) + yEnd = yIn + round(float(box[3]) * size[1]) + if xIn < 0: + xIn = 0 + if yIn < 0: + yIn = 0 + if xEnd >= size[0]: + xEnd = size[0] - 1 + if yEnd >= size[1]: + yEnd = size[1] - 1 + return xIn, yIn, xEnd, yEnd + + +def add_bb_into_image(image, bb, color=(255, 0, 0), thickness=2, label=None): + r = int(color[0]) + g = int(color[1]) + b = int(color[2]) + + font = cv2.FONT_HERSHEY_SIMPLEX + fontScale = 0.5 + fontThickness = 1 + + x1, y1, x2, y2 = bb.getAbsoluteBoundingBox(BBFormat.XYX2Y2) + x1 = int(x1) + y1 = int(y1) + x2 = int(x2) + y2 = int(y2) + cv2.rectangle(image, (x1, y1), (x2, y2), (b, g, r), thickness) + # Add label + if label is not None: + # Get size of the text box + (tw, th) = cv2.getTextSize(label, font, fontScale, fontThickness)[0] + # Top-left coord of the textbox + (xin_bb, yin_bb) = (x1 + thickness, y1 - th + int(12.5 * fontScale)) + # Checking position of the text top-left (outside or inside the bb) + if yin_bb - th <= 0: # if outside the image + yin_bb = y1 + th # put it inside the bb + r_Xin = x1 - int(thickness / 2) + r_Yin = y1 - th - int(thickness / 2) + # Draw filled rectangle to put the text in it + cv2.rectangle(image, (r_Xin, r_Yin - thickness), + (r_Xin + tw + thickness * 3, r_Yin + th + int(12.5 * fontScale)), (b, g, r), + -1) + cv2.putText(image, label, (xin_bb, yin_bb), font, fontScale, (0, 0, 0), fontThickness, + cv2.LINE_AA) + return image + + +class BoundingBox: + def __init__(self, + imageName, + classId, + x, + y, + w, + h, + typeCoordinates=None, + imgSize=None, + bbType=None, + classConfidence=None, + format=None): + """Constructor. + Args: + imageName: String representing the image name. + classId: String value representing class id. + x: Float value representing the X upper-left coordinate of the bounding box. + y: Float value representing the Y upper-left coordinate of the bounding box. + w: Float value representing the width bounding box. + h: Float value representing the height bounding box. + typeCoordinates: (optional) Enum (Relative or Absolute) represents if the bounding box + coordinates (x,y,w,h) are absolute or relative to size of the image. Default:'Absolute'. + imgSize: (optional) 2D vector (width, height)=>(int, int) represents the size of the + image of the bounding box. If typeCoordinates is 'Relative', imgSize is required. + bbType: (optional) Enum (Groundtruth or Detection) identifies if the bounding box + represents a ground truth or a detection. If it is a detection, the classConfidence has + to be informed. + classConfidence: (optional) Float value representing the confidence of the detected + class. If detectionType is Detection, classConfidence needs to be informed. + format: (optional) Enum (BBFormat.XYWH or BBFormat.XYX2Y2) indicating the format of the + coordinates of the bounding boxes. BBFormat.XYWH: + BBFormat.XYX2Y2: . + """ + self._imageName = imageName + self._typeCoordinates = typeCoordinates + if typeCoordinates == CoordinatesType.Relative and imgSize is None: + raise IOError( + 'Parameter \'imgSize\' is required. It is necessary to inform the image size.') + if bbType == BBType.Detected and classConfidence is None: + raise IOError( + 'For bbType=\'Detection\', it is necessary to inform the classConfidence value.') + + self._classConfidence = classConfidence + self._bbType = bbType + self._classId = classId + self._format = format + + # If relative coordinates, convert to absolute values + # For relative coords: (x,y,w,h)=(X_center/img_width , Y_center/img_height) + if typeCoordinates == CoordinatesType.Relative: + (self._x, self._y, self._w, self._h) = convertToAbsoluteValues(imgSize, (x, y, w, h)) + self._width_img = imgSize[0] + self._height_img = imgSize[1] + if format == BBFormat.XYWH: + self._x2 = self._w + self._y2 = self._h + self._w = self._x2 - self._x + self._h = self._y2 - self._y + else: + raise IOError( + 'For relative coordinates, the format must be XYWH (x,y,width,height)') + # For absolute coords: (x,y,w,h)=real bb coords + else: + self._x = x + self._y = y + if format == BBFormat.XYWH: + self._w = w + self._h = h + self._x2 = self._x + self._w + self._y2 = self._y + self._h + else: # format == BBFormat.XYX2Y2: . + self._x2 = w + self._y2 = h + self._w = self._x2 - self._x + self._h = self._y2 - self._y + if imgSize is None: + self._width_img = None + self._height_img = None + else: + self._width_img = imgSize[0] + self._height_img = imgSize[1] + + def getAbsoluteBoundingBox(self, format=None): + if format == BBFormat.XYWH: + return self._x, self._y, self._w, self._h + elif format == BBFormat.XYX2Y2: + return self._x, self._y, self._x2, self._y2 + + def getRelativeBoundingBox(self, imgSize=None): + if imgSize is None and self._width_img is None and self._height_img is None: + raise IOError( + 'Parameter \'imgSize\' is required. It is necessary to inform the image size.') + if imgSize is None: + return convertToRelativeValues((imgSize[0], imgSize[1]), + (self._x, self._y, self._w, self._h)) + else: + return convertToRelativeValues((self._width_img, self._height_img), + (self._x, self._y, self._w, self._h)) + + def getImageName(self): + return self._imageName + + def getConfidence(self): + return self._classConfidence + + def getFormat(self): + return self._format + + def getClassId(self): + return self._classId + + def getImageSize(self): + return self._width_img, self._height_img + + def getCoordinatesType(self): + return self._typeCoordinates + + def getBBType(self): + return self._bbType + + @staticmethod + def compare(det1, det2): + det1BB = det1.getAbsoluteBoundingBox(format=BBFormat.XYWH) + det1ImgSize = det1.getImageSize() + det2BB = det2.getAbsoluteBoundingBox(format=BBFormat.XYWH) + det2ImgSize = det2.getImageSize() + + if det1.getClassId() == det2.getClassId() and \ + det1.classConfidence == det2.classConfidenc() and \ + det1BB[0] == det2BB[0] and \ + det1BB[1] == det2BB[1] and \ + det1BB[2] == det2BB[2] and \ + det1BB[3] == det2BB[3] and \ + det1ImgSize[0] == det1ImgSize[0] and \ + det2ImgSize[1] == det2ImgSize[1]: + return True + return False + + @staticmethod + def clone(boundingBox): + absBB = boundingBox.getAbsoluteBoundingBox(format=BBFormat.XYWH) + newBoundingBox = BoundingBox( + boundingBox.getImageName(), + boundingBox.getClassId(), + absBB[0], + absBB[1], + absBB[2], + absBB[3], + typeCoordinates=boundingBox.getCoordinatesType(), + imgSize=boundingBox.getImageSize(), + bbType=boundingBox.getBBType(), + classConfidence=boundingBox.getConfidence(), + format=BBFormat.XYWH) + return newBoundingBox + + +class BoundingBoxes: + def __init__(self): + self._boundingBoxes = [] + + def addBoundingBox(self, bb): + self._boundingBoxes.append(bb) + + def removeBoundingBox(self, _boundingBox): + for d in self._boundingBoxes: + if BoundingBox.compare(d, _boundingBox): + del self._boundingBoxes[d] + return + + def removeAllBoundingBoxes(self): + self._boundingBoxes = [] + + def getBoundingBoxes(self): + return self._boundingBoxes + + def getBoundingBoxByClass(self, classId): + boundingBoxes = [] + for d in self._boundingBoxes: + if d.getClassId() == classId: # get only specified bounding box type + boundingBoxes.append(d) + return boundingBoxes + + def getClasses(self): + classes = [] + for d in self._boundingBoxes: + c = d.getClassId() + if c not in classes: + classes.append(c) + return classes + + def getBoundingBoxesByType(self, bbType): + # get only specified bb type + return [d for d in self._boundingBoxes if d.getBBType() == bbType] + + def getBoundingBoxesByImageName(self, imageName): + # get only specified bb type + return [d for d in self._boundingBoxes if d.getImageName() == imageName] + + def count(self, bbType=None): + if bbType is None: # Return all bounding boxes + return len(self._boundingBoxes) + count = 0 + for d in self._boundingBoxes: + if d.getBBType() == bbType: # get only specified bb type + count += 1 + return count + + def clone(self): + newBoundingBoxes = BoundingBoxes() + for d in self._boundingBoxes: + det = BoundingBox.clone(d) + newBoundingBoxes.addBoundingBox(det) + return newBoundingBoxes + + def drawAllBoundingBoxes(self, image, imageName): + bbxes = self.getBoundingBoxesByImageName(imageName) + for bb in bbxes: + if bb.getBBType() == BBType.GroundTruth: # if ground truth + image = add_bb_into_image(image, bb, color=(0, 255, 0)) # green + else: # if detection + image = add_bb_into_image(image, bb, color=(255, 0, 0)) # red + return image + + +class Evaluator: + def GetPascalVOCMetrics(self, + boundingboxes, + IOUThreshold=0.5, + method=None): + """Get the metrics used by the VOC Pascal 2012 challenge. + Get + Args: + boundingboxes: Object of the class BoundingBoxes representing ground truth and detected + bounding boxes; + IOUThreshold: IOU threshold indicating which detections will be considered TP or FP + (default value = 0.5); + method (default = EveryPointInterpolation): It can be calculated as the implementation + in the official PASCAL VOC toolkit (EveryPointInterpolation), or applying the 11-point + interpolatio as described in the paper "The PASCAL Visual Object Classes(VOC) Challenge" + or EveryPointInterpolation" (ElevenPointInterpolation); + Returns: + A list of dictionaries. Each dictionary contains information and metrics of each class. + The keys of each dictionary are: + dict['class']: class representing the current dictionary; + dict['precision']: array with the precision values; + dict['recall']: array with the recall values; + dict['AP']: average precision; + dict['interpolated precision']: interpolated precision values; + dict['interpolated recall']: interpolated recall values; + dict['total positives']: total number of ground truth positives; + dict['total TP']: total number of True Positive detections; + dict['total FP']: total number of False Negative detections; + """ + ret = [] # list containing metrics (precision, recall, average precision) of each class + # List with all ground truths (Ex: [imageName,class,confidence=1, (bb coordinates XYX2Y2)]) + groundTruths = [] + # List with all detections (Ex: [imageName,class,confidence,(bb coordinates XYX2Y2)]) + detections = [] + # Get all classes + classes = [] + # Loop through all bounding boxes and separate them into GTs and detections + for bb in boundingboxes.getBoundingBoxes(): + # [imageName, class, confidence, (bb coordinates XYX2Y2)] + if bb.getBBType() == BBType.GroundTruth: + groundTruths.append([ + bb.getImageName(), + bb.getClassId(), 1, + bb.getAbsoluteBoundingBox(BBFormat.XYX2Y2) + ]) + else: + detections.append([ + bb.getImageName(), + bb.getClassId(), + bb.getConfidence(), + bb.getAbsoluteBoundingBox(BBFormat.XYX2Y2) + ]) + # get class + if bb.getClassId() not in classes: + classes.append(bb.getClassId()) + classes = sorted(classes) + # Precision x Recall is obtained individually by each class + # Loop through by classes + for c in classes: + # Get only detection of class c + dects = [] + [dects.append(d) for d in detections if d[1] == c] + # Get only ground truths of class c + gts = [] + [gts.append(g) for g in groundTruths if g[1] == c] + npos = len(gts) + # sort detections by decreasing confidence + dects = sorted(dects, key=lambda conf: conf[2], reverse=True) + TP = np.zeros(len(dects)) + FP = np.zeros(len(dects)) + # create dictionary with amount of gts for each image + det = Counter([cc[0] for cc in gts]) + for key, val in det.items(): + det[key] = np.zeros(val) + # Loop through detections + for d in range(len(dects)): + # Find ground truth image + gt = [gt for gt in gts if gt[0] == dects[d][0]] + iouMax = sys.float_info.min + for j in range(len(gt)): + iou = Evaluator.iou(dects[d][3], gt[j][3]) + if iou > iouMax: + iouMax = iou + jmax = j + # Assign detection as true positive/don't care/false positive + if iouMax >= IOUThreshold: + if det[dects[d][0]][jmax] == 0: + TP[d] = 1 # count as true positive + det[dects[d][0]][jmax] = 1 # flag as already 'seen' + else: + FP[d] = 1 # count as false positive + # - A detected "cat" is overlaped with a GT "cat" with IOU >= IOUThreshold. + else: + FP[d] = 1 # count as false positive + # compute precision, recall and average precision + acc_FP = np.cumsum(FP) + acc_TP = np.cumsum(TP) + rec = acc_TP / npos + prec = np.divide(acc_TP, (acc_FP + acc_TP)) + # Depending on the method, call the right implementation + if method == MethodAveragePrecision.EveryPointInterpolation: + [ap, mpre, mrec, ii] = Evaluator.CalculateAveragePrecision(rec, prec) + else: + [ap, mpre, mrec, _] = Evaluator.ElevenPointInterpolatedAP(rec, prec) + # add class result in the dictionary to be returned + r = { + 'class': c, + 'precision': prec, + 'recall': rec, + 'AP': ap, + 'interpolated precision': mpre, + 'interpolated recall': mrec, + 'total positives': npos, + 'total TP': np.sum(TP), + 'total FP': np.sum(FP) + } + ret.append(r) + return ret + + @staticmethod + def CalculateAveragePrecision(rec, prec): + mrec = [0] + [mrec.append(e) for e in rec] + mrec.append(1) + mpre = [0] + [mpre.append(e) for e in prec] + mpre.append(0) + for i in range(len(mpre) - 1, 0, -1): + mpre[i - 1] = max(mpre[i - 1], mpre[i]) + ii = [] + for i in range(len(mrec) - 1): + if mrec[1:][i] != mrec[0:-1][i]: + ii.append(i + 1) + ap = 0 + for i in ii: + ap = ap + np.sum((mrec[i] - mrec[i - 1]) * mpre[i]) + return [ap, mpre[0:len(mpre) - 1], mrec[0:len(mpre) - 1], ii] + + @staticmethod + # 11-point interpolated average precision + def ElevenPointInterpolatedAP(rec, prec): + mrec = [] + [mrec.append(e) for e in rec] + mpre = [] + [mpre.append(e) for e in prec] + recallValues = np.linspace(0, 1, 11) + recallValues = list(recallValues[::-1]) + rhoInterp = [] + recallValid = [] + for r in recallValues: + # Obtain all recall values higher or equal than r + argGreaterRecalls = np.argwhere(mrec[:] >= r) + pmax = 0 + # If there are recalls above r + if argGreaterRecalls.size != 0: + pmax = max(mpre[argGreaterRecalls.min():]) + recallValid.append(r) + rhoInterp.append(pmax) + # By definition AP = sum(max(precision whose recall is above r))/11 + ap = sum(rhoInterp) / 11 + # Generating values for the plot + rvals = [recallValid[0]] + [rvals.append(e) for e in recallValid] + rvals.append(0) + pvals = [0] + [pvals.append(e) for e in rhoInterp] + pvals.append(0) + # rhoInterp = rhoInterp[::-1] + cc = [] + for i in range(len(rvals)): + p = (rvals[i], pvals[i - 1]) + if p not in cc: + cc.append(p) + p = (rvals[i], pvals[i]) + if p not in cc: + cc.append(p) + recallValues = [i[0] for i in cc] + rhoInterp = [i[1] for i in cc] + return [ap, rhoInterp, recallValues, None] + + # For each detections, calculate IOU with reference + @staticmethod + def _getAllIOUs(reference, detections): + ret = [] + bbReference = reference.getAbsoluteBoundingBox(BBFormat.XYX2Y2) + # img = np.zeros((200,200,3), np.uint8) + for d in detections: + bb = d.getAbsoluteBoundingBox(BBFormat.XYX2Y2) + iou = Evaluator.iou(bbReference, bb) + ret.append((iou, reference, d)) # iou, reference, detection + return sorted(ret, key=lambda i: i[0], reverse=True) # sort by iou (from highest to lowest) + + @staticmethod + def iou(boxA, boxB): + # if boxes dont intersect + if Evaluator._boxesIntersect(boxA, boxB) is False: + return 0 + interArea = Evaluator._getIntersectionArea(boxA, boxB) + union = Evaluator._getUnionAreas(boxA, boxB, interArea=interArea) + # intersection over union + iou = interArea / union + assert iou >= 0 + return iou + + @staticmethod + def _boxesIntersect(boxA, boxB): + if boxA[0] > boxB[2]: + return False # boxA is right of boxB + if boxB[0] > boxA[2]: + return False # boxA is left of boxB + if boxA[3] < boxB[1]: + return False # boxA is above boxB + if boxA[1] > boxB[3]: + return False # boxA is below boxB + return True + + @staticmethod + def _getIntersectionArea(boxA, boxB): + xA = max(boxA[0], boxB[0]) + yA = max(boxA[1], boxB[1]) + xB = min(boxA[2], boxB[2]) + yB = min(boxA[3], boxB[3]) + # intersection area + return (xB - xA + 1) * (yB - yA + 1) + + @staticmethod + def _getUnionAreas(boxA, boxB, interArea=None): + area_A = Evaluator._getArea(boxA) + area_B = Evaluator._getArea(boxB) + if interArea is None: + interArea = Evaluator._getIntersectionArea(boxA, boxB) + return float(area_A + area_B - interArea) + + @staticmethod + def _getArea(box): + return (box[2] - box[0] + 1) * (box[3] - box[1] + 1) + + +# Validate formats +def ValidateFormats(argFormat, argName, errors): + if argFormat == 'xywh': + return BBFormat.XYWH + elif argFormat == 'xyrb': + return BBFormat.XYX2Y2 + elif argFormat is None: + return BBFormat.XYWH # default when nothing is passed + else: + errors.append( + 'argument %s: invalid value. It must be either \'xywh\' or \'xyrb\'' % argName) + + +# Validate mandatory args +def ValidateMandatoryArgs(arg, argName, errors): + if arg is None: + errors.append('argument %s: required argument' % argName) + else: + return True + + +def ValidateImageSize(arg, argName, argInformed, errors): + errorMsg = 'argument %s: required argument if %s is relative' % (argName, argInformed) + ret = None + if arg is None: + errors.append(errorMsg) + else: + arg = arg.replace('(', '').replace(')', '') + args = arg.split(',') + if len(args) != 2: + errors.append( + '%s. It must be in the format \'width,height\' (e.g. \'600,400\')' % errorMsg) + else: + if not args[0].isdigit() or not args[1].isdigit(): + errors.append( + '%s. It must be in INdiaTEGER the format \'width,height\' (e.g. \'600,400\')' % + errorMsg) + else: + ret = (int(args[0]), int(args[1])) + return ret + + +# Validate coordinate types +def ValidateCoordinatesTypes(arg, argName, errors): + if arg == 'abs': + return CoordinatesType.Absolute + elif arg == 'rel': + return CoordinatesType.Relative + elif arg is None: + return CoordinatesType.Absolute # default when nothing is passed + errors.append('argument %s: invalid value. It must be either \'rel\' or \'abs\'' % argName) + + +def getBoundingBoxes(directory, + isGT, + bbFormat, + coordType, + allBoundingBoxes=None, + allClasses=None, + imgSize=(0, 0)): + """Read txt files containing bounding boxes (ground truth and detections).""" + print(directory) + if allBoundingBoxes is None: + allBoundingBoxes = BoundingBoxes() + if allClasses is None: + allClasses = [] + # Read ground truths + os.chdir(directory) + files = glob.glob("*.txt") + files.sort() + + for f in files: + nameOfImage = f.replace(".txt", "") + fh1 = open(f, "r") + for line in fh1: + line = line.replace("\n", "") + if line.replace(' ', '') == '': + continue + splitLine = line.split(" ") + if isGT: + idClass = (splitLine[0]) # class + x = float(splitLine[1]) + y = float(splitLine[2]) + w = float(splitLine[3]) + h = float(splitLine[4]) + bb = BoundingBox( + nameOfImage, + idClass, + x, + y, + w, + h, + coordType, + imgSize, + BBType.GroundTruth, + format=bbFormat) + else: + idClass = (splitLine[0]) # class + confidence = float(splitLine[1]) + x = float(splitLine[2]) + y = float(splitLine[3]) + w = float(splitLine[4]) + h = float(splitLine[5]) + bb = BoundingBox( + nameOfImage, + idClass, + x, + y, + w, + h, + coordType, + imgSize, + BBType.Detected, + confidence, + format=bbFormat) + allBoundingBoxes.addBoundingBox(bb) + if idClass not in allClasses: + allClasses.append(idClass) + fh1.close() + return allBoundingBoxes, allClasses + + +def get_mAP(gtFolder, detFolder, threshold=0.5, savePath=None): + gtFormat = 'xyrb' + detFormat = 'xyrb' + gtCoordinates = 'abs' + detCoordinates = 'abs' + gtFolder = os.path.join(os.path.abspath('.'), gtFolder) + detFolder = os.path.join(os.path.abspath('.'), detFolder) + + iouThreshold = threshold + + # Arguments validation + errors = [] + # Validate formats + gtFormat = ValidateFormats(gtFormat, 'gtFormat', errors) + detFormat = ValidateFormats(detFormat, '-detformat', errors) + + # Coordinates types + gtCoordType = ValidateCoordinatesTypes(gtCoordinates, '-gtCoordinates', errors) + detCoordType = ValidateCoordinatesTypes(detCoordinates, '-detCoordinates', errors) + imgSize = (0, 0) + + # Create directory to save results + shutil.rmtree(savePath, ignore_errors=True) # Clear folder + if savePath is not None: + os.makedirs(savePath) + + # Get groundtruth boxes + allBoundingBoxes, allClasses = getBoundingBoxes( + gtFolder, True, gtFormat, gtCoordType, imgSize=imgSize) + # Get detected boxes + allBoundingBoxes, allClasses = getBoundingBoxes( + detFolder, False, detFormat, detCoordType, allBoundingBoxes, allClasses, imgSize=imgSize) + allClasses.sort() + + evaluator = Evaluator() + acc_AP = 0 + validClasses = 0 + + # Plot Precision x Recall curve + detections = evaluator.GetPascalVOCMetrics(allBoundingBoxes, iouThreshold, + method=MethodAveragePrecision.EveryPointInterpolation) + + # each detection is a class and store AP and mAP results in AP_res list + AP_res = [] + for metricsPerClass in detections: + # Get metric values per each class + cl = metricsPerClass['class'] + ap = metricsPerClass['AP'] + totalPositives = metricsPerClass['total positives'] + + if totalPositives > 0: + validClasses = validClasses + 1 + acc_AP = acc_AP + ap + ap_str = "{0:.2f}%".format(ap * 100) + AP_res.append('AP: %s (%s)' % (ap_str, cl)) + mAP = acc_AP / validClasses + mAP_str = "{0:.2f}%".format(mAP * 100) + AP_res.append('mAP: %s' % mAP_str) + return AP_res \ No newline at end of file diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/vos_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/vos_metric.py new file mode 100644 index 0000000..54eadb8 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/vos_metric.py @@ -0,0 +1,276 @@ +# Copyright (c) 2021 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. + +import os +import paddle +import zipfile +import time +from PIL import Image + +from paddle.io import DataLoader + +from .registry import METRIC +from .base import BaseMetric +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +@METRIC.register +class VOSMetric(BaseMetric): + def __init__(self, + data_size, + batch_size, + result_root, + zip_dir, + log_interval=1): + """prepare for metrics + """ + super().__init__(data_size, batch_size, log_interval) + self.video_num = 0 + self.total_time = 0 + self.total_frame = 0 + self.total_sfps = 0 + self.total_video_num = data_size + self.count = 0 + self.result_root = result_root + self.zip_dir = zip_dir + + def update(self, batch_id, data, model): + """update metrics during each iter + """ + self.video_num += 1 + seq_dataset = data + seq_name = seq_dataset.seq_name + + logger.info('Prcessing Seq {} [{}/{}]:'.format(seq_name, self.video_num, + self.total_video_num)) + seq_dataloader = DataLoader(seq_dataset, + return_list=True, + batch_size=1, + shuffle=False, + num_workers=0) + seq_total_time = 0 + seq_total_frame = 0 + ref_embeddings = [] + ref_masks = [] + prev_embedding = [] + prev_mask = [] + with paddle.no_grad(): + for frame_idx, samples in enumerate(seq_dataloader): + time_start = time.time() + all_preds = [] + join_label = None + for aug_idx in range(len(samples)): + if len(ref_embeddings) <= aug_idx: + ref_embeddings.append([]) + ref_masks.append([]) + prev_embedding.append(None) + prev_mask.append(None) + + sample = samples[aug_idx] + ref_emb = ref_embeddings[aug_idx] + ref_m = ref_masks[aug_idx] + prev_emb = prev_embedding[aug_idx] + prev_m = prev_mask[aug_idx] + + current_img = sample['current_img'] + if 'current_label' in sample.keys(): + current_label = sample['current_label'] + current_label = paddle.to_tensor(current_label) + else: + current_label = None + + obj_num = sample['meta']['obj_num'] + imgname = sample['meta']['current_name'] + ori_height = sample['meta']['height'] + ori_width = sample['meta']['width'] + current_img = current_img + obj_num = obj_num + bs, _, h, w = current_img.shape + data_batch = [ + ref_emb, ref_m, prev_emb, prev_m, current_img, + [ori_height, ori_width], obj_num + ] + + all_pred, current_embedding = model(data_batch, mode='test') + + if frame_idx == 0: + if current_label is None: + logger.info( + "No first frame label in Seq {}.".format( + seq_name)) + ref_embeddings[aug_idx].append(current_embedding) + ref_masks[aug_idx].append(current_label) + + prev_embedding[aug_idx] = current_embedding + prev_mask[aug_idx] = current_label + else: + if sample['meta']['flip']: #False + all_pred = self.flip_tensor(all_pred, 3) + # In YouTube-VOS, not all the objects appear in the first frame for the first time. Thus, we + # have to introduce new labels for new objects, if necessary. + if not sample['meta']['flip'] and not ( + current_label is None) and join_label is None: + join_label = paddle.cast(current_label, + dtype='int64') + all_preds.append(all_pred) + if current_label is not None: + ref_embeddings[aug_idx].append(current_embedding) + prev_embedding[aug_idx] = current_embedding + + if frame_idx > 0: + all_preds = paddle.concat(all_preds, axis=0) + all_preds = paddle.mean( + all_preds, axis=0) #average results if augmentation + pred_label = paddle.argmax(all_preds, axis=0) + if join_label is not None: + join_label = paddle.squeeze(paddle.squeeze(join_label, + axis=0), + axis=0) + keep = paddle.cast((join_label == 0), dtype="int64") + pred_label = pred_label * keep + join_label * (1 - keep) + pred_label = pred_label + current_label = paddle.reshape( + pred_label, shape=[1, 1, ori_height, ori_width]) + flip_pred_label = self.flip_tensor(pred_label, 1) + flip_current_label = paddle.reshape( + flip_pred_label, shape=[1, 1, ori_height, ori_width]) + + for aug_idx in range(len(samples)): + if join_label is not None: + if samples[aug_idx]['meta']['flip']: + ref_masks[aug_idx].append(flip_current_label) + else: + ref_masks[aug_idx].append(current_label) + if samples[aug_idx]['meta']['flip']: + prev_mask[aug_idx] = flip_current_label + else: + prev_mask[ + aug_idx] = current_label #update prev_mask + + one_frametime = time.time() - time_start + seq_total_time += one_frametime + seq_total_frame += 1 + obj_num = float(obj_num) + logger.info('Frame: {}, Obj Num: {}, Time: {}'.format( + imgname[0], obj_num, one_frametime)) + self.save_mask( + pred_label, + os.path.join(self.result_root, seq_name, + imgname[0].split('.')[0] + '.png')) + else: + one_frametime = time.time() - time_start + seq_total_time += one_frametime + logger.info('Ref Frame: {}, Time: {}'.format( + imgname[0], one_frametime)) + + del (ref_embeddings) + del (ref_masks) + del (prev_embedding) + del (prev_mask) + del (seq_dataset) + del (seq_dataloader) + + seq_avg_time_per_frame = seq_total_time / seq_total_frame + self.total_time += seq_total_time + self.total_frame += seq_total_frame + total_avg_time_per_frame = self.total_time / self.total_frame + self.total_sfps += seq_avg_time_per_frame + avg_sfps = self.total_sfps / (batch_id + 1) + logger.info("Seq {} FPS: {}, Total FPS: {}, FPS per Seq: {}".format( + seq_name, 1. / seq_avg_time_per_frame, + 1. / total_avg_time_per_frame, 1. / avg_sfps)) + + def flip_tensor(self, tensor, dim=0): + inv_idx = paddle.cast(paddle.arange(tensor.shape[dim] - 1, -1, -1), + dtype="int64") + tensor = paddle.index_select(x=tensor, index=inv_idx, axis=dim) + return tensor + + def save_mask(self, mask_tensor, path): + _palette = [ + 0, 0, 0, 128, 0, 0, 0, 128, 0, 128, 128, 0, 0, 0, 128, 128, 0, 128, + 0, 128, 128, 128, 128, 128, 64, 0, 0, 191, 0, 0, 64, 128, 0, 191, + 128, 0, 64, 0, 128, 191, 0, 128, 64, 128, 128, 191, 128, 128, 0, 64, + 0, 128, 64, 0, 0, 191, 0, 128, 191, 0, 0, 64, 128, 128, 64, 128, 22, + 22, 22, 23, 23, 23, 24, 24, 24, 25, 25, 25, 26, 26, 26, 27, 27, 27, + 28, 28, 28, 29, 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, + 33, 34, 34, 34, 35, 35, 35, 36, 36, 36, 37, 37, 37, 38, 38, 38, 39, + 39, 39, 40, 40, 40, 41, 41, 41, 42, 42, 42, 43, 43, 43, 44, 44, 44, + 45, 45, 45, 46, 46, 46, 47, 47, 47, 48, 48, 48, 49, 49, 49, 50, 50, + 50, 51, 51, 51, 52, 52, 52, 53, 53, 53, 54, 54, 54, 55, 55, 55, 56, + 56, 56, 57, 57, 57, 58, 58, 58, 59, 59, 59, 60, 60, 60, 61, 61, 61, + 62, 62, 62, 63, 63, 63, 64, 64, 64, 65, 65, 65, 66, 66, 66, 67, 67, + 67, 68, 68, 68, 69, 69, 69, 70, 70, 70, 71, 71, 71, 72, 72, 72, 73, + 73, 73, 74, 74, 74, 75, 75, 75, 76, 76, 76, 77, 77, 77, 78, 78, 78, + 79, 79, 79, 80, 80, 80, 81, 81, 81, 82, 82, 82, 83, 83, 83, 84, 84, + 84, 85, 85, 85, 86, 86, 86, 87, 87, 87, 88, 88, 88, 89, 89, 89, 90, + 90, 90, 91, 91, 91, 92, 92, 92, 93, 93, 93, 94, 94, 94, 95, 95, 95, + 96, 96, 96, 97, 97, 97, 98, 98, 98, 99, 99, 99, 100, 100, 100, 101, + 101, 101, 102, 102, 102, 103, 103, 103, 104, 104, 104, 105, 105, + 105, 106, 106, 106, 107, 107, 107, 108, 108, 108, 109, 109, 109, + 110, 110, 110, 111, 111, 111, 112, 112, 112, 113, 113, 113, 114, + 114, 114, 115, 115, 115, 116, 116, 116, 117, 117, 117, 118, 118, + 118, 119, 119, 119, 120, 120, 120, 121, 121, 121, 122, 122, 122, + 123, 123, 123, 124, 124, 124, 125, 125, 125, 126, 126, 126, 127, + 127, 127, 128, 128, 128, 129, 129, 129, 130, 130, 130, 131, 131, + 131, 132, 132, 132, 133, 133, 133, 134, 134, 134, 135, 135, 135, + 136, 136, 136, 137, 137, 137, 138, 138, 138, 139, 139, 139, 140, + 140, 140, 141, 141, 141, 142, 142, 142, 143, 143, 143, 144, 144, + 144, 145, 145, 145, 146, 146, 146, 147, 147, 147, 148, 148, 148, + 149, 149, 149, 150, 150, 150, 151, 151, 151, 152, 152, 152, 153, + 153, 153, 154, 154, 154, 155, 155, 155, 156, 156, 156, 157, 157, + 157, 158, 158, 158, 159, 159, 159, 160, 160, 160, 161, 161, 161, + 162, 162, 162, 163, 163, 163, 164, 164, 164, 165, 165, 165, 166, + 166, 166, 167, 167, 167, 168, 168, 168, 169, 169, 169, 170, 170, + 170, 171, 171, 171, 172, 172, 172, 173, 173, 173, 174, 174, 174, + 175, 175, 175, 176, 176, 176, 177, 177, 177, 178, 178, 178, 179, + 179, 179, 180, 180, 180, 181, 181, 181, 182, 182, 182, 183, 183, + 183, 184, 184, 184, 185, 185, 185, 186, 186, 186, 187, 187, 187, + 188, 188, 188, 189, 189, 189, 190, 190, 190, 191, 191, 191, 192, + 192, 192, 193, 193, 193, 194, 194, 194, 195, 195, 195, 196, 196, + 196, 197, 197, 197, 198, 198, 198, 199, 199, 199, 200, 200, 200, + 201, 201, 201, 202, 202, 202, 203, 203, 203, 204, 204, 204, 205, + 205, 205, 206, 206, 206, 207, 207, 207, 208, 208, 208, 209, 209, + 209, 210, 210, 210, 211, 211, 211, 212, 212, 212, 213, 213, 213, + 214, 214, 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, 218, + 218, 218, 219, 219, 219, 220, 220, 220, 221, 221, 221, 222, 222, + 222, 223, 223, 223, 224, 224, 224, 225, 225, 225, 226, 226, 226, + 227, 227, 227, 228, 228, 228, 229, 229, 229, 230, 230, 230, 231, + 231, 231, 232, 232, 232, 233, 233, 233, 234, 234, 234, 235, 235, + 235, 236, 236, 236, 237, 237, 237, 238, 238, 238, 239, 239, 239, + 240, 240, 240, 241, 241, 241, 242, 242, 242, 243, 243, 243, 244, + 244, 244, 245, 245, 245, 246, 246, 246, 247, 247, 247, 248, 248, + 248, 249, 249, 249, 250, 250, 250, 251, 251, 251, 252, 252, 252, + 253, 253, 253, 254, 254, 254, 255, 255, 255 + ] + mask = mask_tensor.cpu().numpy().astype('uint8') + mask = Image.fromarray(mask).convert('P') + mask.putpalette(_palette) + mask.save(path) + + def zip_folder(self, source_folder, zip_dir): + f = zipfile.ZipFile(zip_dir, 'w', zipfile.ZIP_DEFLATED) + pre_len = len(os.path.dirname(source_folder)) + for dirpath, dirnames, filenames in os.walk(source_folder): + for filename in filenames: + pathfile = os.path.join(dirpath, filename) + arcname = pathfile[pre_len:].strip(os.path.sep) + f.write(pathfile, arcname) + f.close() + + def accumulate(self): + """accumulate metrics when finished all iters. + """ + self.zip_folder(self.result_root, self.zip_dir) + logger.info('Save result to {}.'.format(self.zip_dir)) diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__init__.py b/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..81d734c3d2ad19229a40b54c23839076f0637276 GIT binary patch literal 169 zcmd1j<>g`kf(xwODIoeWh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o6u!)hfm*F)uql zEi)&z7{W9#iYX|{Pfjf^28+fNB&MX~q?To-q~^!urj`_CCKtz4=9iX~CZ$^B#>B^G e=4F<|$LkeT-r}&y%}*)KNwovnQp^M-SQr3jgerpo literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__pycache__/average_precision_calculator.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__pycache__/average_precision_calculator.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a1817ccc0bfadb8e03401657d1aa49a82d29d59f GIT binary patch literal 9058 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__pycache__/eval_util.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/__pycache__/eval_util.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c6404cfa0691e96fd06ffe8c28cf3593d149750a GIT binary patch literal 7500 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/average_precision_calculator.py b/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/average_precision_calculator.py new file mode 100644 index 0000000..bdbd6e0 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/average_precision_calculator.py @@ -0,0 +1,274 @@ +# Copyright 2020 Google Inc. 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. +"""Calculate or keep track of the interpolated average precision. + +It provides an interface for calculating interpolated average precision for an +entire list or the top-n ranked items. For the definition of the +(non-)interpolated average precision: +http://trec.nist.gov/pubs/trec15/appendices/CE.MEASURES06.pdf + +Example usages: +1) Use it as a static function call to directly calculate average precision for +a short ranked list in the memory. + +``` +import random + +p = np.array([random.random() for _ in xrange(10)]) +a = np.array([random.choice([0, 1]) for _ in xrange(10)]) + +ap = average_precision_calculator.AveragePrecisionCalculator.ap(p, a) +``` + +2) Use it as an object for long ranked list that cannot be stored in memory or +the case where partial predictions can be observed at a time (Tensorflow +predictions). In this case, we first call the function accumulate many times +to process parts of the ranked list. After processing all the parts, we call +peek_interpolated_ap_at_n. +``` +p1 = np.array([random.random() for _ in xrange(5)]) +a1 = np.array([random.choice([0, 1]) for _ in xrange(5)]) +p2 = np.array([random.random() for _ in xrange(5)]) +a2 = np.array([random.choice([0, 1]) for _ in xrange(5)]) + +# interpolated average precision at 10 using 1000 break points +calculator = average_precision_calculator.AveragePrecisionCalculator(10) +calculator.accumulate(p1, a1) +calculator.accumulate(p2, a2) +ap3 = calculator.peek_ap_at_n() +``` +""" + +import heapq +import random +import numbers + +import numpy + + +class AveragePrecisionCalculator(object): + """Calculate the average precision and average precision at n.""" + def __init__(self, top_n=None): + """Construct an AveragePrecisionCalculator to calculate average precision. + + This class is used to calculate the average precision for a single label. + + Args: + top_n: A positive Integer specifying the average precision at n, or + None to use all provided data points. + + Raises: + ValueError: An error occurred when the top_n is not a positive integer. + """ + if not ((isinstance(top_n, int) and top_n >= 0) or top_n is None): + raise ValueError("top_n must be a positive integer or None.") + + self._top_n = top_n # average precision at n + self._total_positives = 0 # total number of positives have seen + self._heap = [] # max heap of (prediction, actual) + + @property + def heap_size(self): + """Gets the heap size maintained in the class.""" + return len(self._heap) + + @property + def num_accumulated_positives(self): + """Gets the number of positive samples that have been accumulated.""" + return self._total_positives + + def accumulate(self, predictions, actuals, num_positives=None): + """Accumulate the predictions and their ground truth labels. + + After the function call, we may call peek_ap_at_n to actually calculate + the average precision. + Note predictions and actuals must have the same shape. + + Args: + predictions: a list storing the prediction scores. + actuals: a list storing the ground truth labels. Any value + larger than 0 will be treated as positives, otherwise as negatives. + num_positives = If the 'predictions' and 'actuals' inputs aren't complete, + then it's possible some true positives were missed in them. In that case, + you can provide 'num_positives' in order to accurately track recall. + + Raises: + ValueError: An error occurred when the format of the input is not the + numpy 1-D array or the shape of predictions and actuals does not match. + """ + if len(predictions) != len(actuals): + raise ValueError( + "the shape of predictions and actuals does not match.") + + if not num_positives is None: + if not isinstance(num_positives, + numbers.Number) or num_positives < 0: + raise ValueError( + "'num_positives' was provided but it wan't a nonzero number." + ) + + if not num_positives is None: + self._total_positives += num_positives + else: + self._total_positives += numpy.size(numpy.where(actuals > 0)) + topk = self._top_n + heap = self._heap + + for i in range(numpy.size(predictions)): + if topk is None or len(heap) < topk: + heapq.heappush(heap, (predictions[i], actuals[i])) + else: + if predictions[i] > heap[0][0]: # heap[0] is the smallest + heapq.heappop(heap) + heapq.heappush(heap, (predictions[i], actuals[i])) + + def clear(self): + """Clear the accumulated predictions.""" + self._heap = [] + self._total_positives = 0 + + def peek_ap_at_n(self): + """Peek the non-interpolated average precision at n. + + Returns: + The non-interpolated average precision at n (default 0). + If n is larger than the length of the ranked list, + the average precision will be returned. + """ + if self.heap_size <= 0: + return 0 + predlists = numpy.array(list(zip(*self._heap))) + + ap = self.ap_at_n(predlists[0], + predlists[1], + n=self._top_n, + total_num_positives=self._total_positives) + return ap + + @staticmethod + def ap(predictions, actuals): + """Calculate the non-interpolated average precision. + + Args: + predictions: a numpy 1-D array storing the sparse prediction scores. + actuals: a numpy 1-D array storing the ground truth labels. Any value + larger than 0 will be treated as positives, otherwise as negatives. + + Returns: + The non-interpolated average precision at n. + If n is larger than the length of the ranked list, + the average precision will be returned. + + Raises: + ValueError: An error occurred when the format of the input is not the + numpy 1-D array or the shape of predictions and actuals does not match. + """ + return AveragePrecisionCalculator.ap_at_n(predictions, actuals, n=None) + + @staticmethod + def ap_at_n(predictions, actuals, n=20, total_num_positives=None): + """Calculate the non-interpolated average precision. + + Args: + predictions: a numpy 1-D array storing the sparse prediction scores. + actuals: a numpy 1-D array storing the ground truth labels. Any value + larger than 0 will be treated as positives, otherwise as negatives. + n: the top n items to be considered in ap@n. + total_num_positives : (optionally) you can specify the number of total + positive + in the list. If specified, it will be used in calculation. + + Returns: + The non-interpolated average precision at n. + If n is larger than the length of the ranked list, + the average precision will be returned. + + Raises: + ValueError: An error occurred when + 1) the format of the input is not the numpy 1-D array; + 2) the shape of predictions and actuals does not match; + 3) the input n is not a positive integer. + """ + if len(predictions) != len(actuals): + raise ValueError( + "the shape of predictions and actuals does not match.") + + if n is not None: + if not isinstance(n, int) or n <= 0: + raise ValueError("n must be 'None' or a positive integer." + " It was '%s'." % n) + + ap = 0.0 + + predictions = numpy.array(predictions) + actuals = numpy.array(actuals) + + # add a shuffler to avoid overestimating the ap + predictions, actuals = AveragePrecisionCalculator._shuffle( + predictions, actuals) + sortidx = sorted(range(len(predictions)), + key=lambda k: predictions[k], + reverse=True) + + if total_num_positives is None: + numpos = numpy.size(numpy.where(actuals > 0)) + else: + numpos = total_num_positives + + if numpos == 0: + return 0 + + if n is not None: + numpos = min(numpos, n) + delta_recall = 1.0 / numpos + poscount = 0.0 + + # calculate the ap + r = len(sortidx) + if n is not None: + r = min(r, n) + for i in range(r): + if actuals[sortidx[i]] > 0: + poscount += 1 + ap += poscount / (i + 1) * delta_recall + return ap + + @staticmethod + def _shuffle(predictions, actuals): + random.seed(0) + suffidx = random.sample(range(len(predictions)), len(predictions)) + predictions = predictions[suffidx] + actuals = actuals[suffidx] + return predictions, actuals + + @staticmethod + def _zero_one_normalize(predictions, epsilon=1e-7): + """Normalize the predictions to the range between 0.0 and 1.0. + + For some predictions like SVM predictions, we need to normalize them before + calculate the interpolated average precision. The normalization will not + change the rank in the original list and thus won't change the average + precision. + + Args: + predictions: a numpy 1-D array storing the sparse prediction scores. + epsilon: a small constant to avoid denominator being zero. + + Returns: + The normalized prediction. + """ + denominator = numpy.max(predictions) - numpy.min(predictions) + ret = (predictions - numpy.min(predictions)) / numpy.max( + denominator, epsilon) + return ret diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/eval_util.py b/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/eval_util.py new file mode 100644 index 0000000..724c72f --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/eval_util.py @@ -0,0 +1,205 @@ +# Copyright 2016 Google Inc. 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. +"""Provides functions to help with evaluating models.""" +import numpy as np +import paddle +from paddlevideo.utils import get_logger + +from ..base import BaseMetric +from ..registry import METRIC +from . import average_precision_calculator as ap_calculator +from . import mean_average_precision_calculator as map_calculator + +logger = get_logger("paddlevideo") + + +def flatten(l): + """ Merges a list of lists into a single list. """ + return [item for sublist in l for item in sublist] + + +def calculate_hit_at_one(predictions, actuals): + """ + Hit@k: indicates the fraction of test samples that contain at least + one of the ground truth labels in the top k predictions, + i.e topk. + + Args: + predictions: Matrix containing the outputs of the model. + Dimensions are 'batch' x 'num_classes'. + actuals: Matrix containing the ground truth labels. + Dimensions are 'batch' x 'num_classes'. + + Returns: + float: The average hit at one across the entire batch. + """ + top_prediction = np.argmax(predictions, 1) + hits = actuals[np.arange(actuals.shape[0]), top_prediction] + return np.mean(hits) + + +def calculate_precision_at_equal_recall_rate(predictions, actuals): + """ + PERR: measures the video-level annotation precision when we retrieve the same number + of entities per video as there are in the ground-truth. + More details please refer to: https://arxiv.org/abs/1609.08675 + + Args: + predictions: Matrix containing the outputs of the model. + Dimensions are 'batch' x 'num_classes'. + actuals: Matrix containing the ground truth labels. + Dimensions are 'batch' x 'num_classes'. + + Returns: + float: The average precision at equal recall rate across the entire batch. + """ + aggregated_precision = 0.0 + num_videos = actuals.shape[0] + for row in np.arange(num_videos): + num_labels = int(np.sum(actuals[row])) + top_indices = np.argpartition(predictions[row], + -num_labels)[-num_labels:] + item_precision = 0.0 + for label_index in top_indices: + if predictions[row][label_index] > 0: + item_precision += actuals[row][label_index] + item_precision /= top_indices.size + aggregated_precision += item_precision + aggregated_precision /= num_videos + return aggregated_precision + + +def calculate_gap(predictions, actuals, top_k=20): + """ + GAP: the global average precision. + + Only the top_k predictions are taken for each of the videos. + + Args: + predictions: Matrix containing the outputs of the model. + Dimensions are 'batch' x 'num_classes'. + actuals: Matrix containing the ground truth labels. + Dimensions are 'batch' x 'num_classes'. + top_k: How many predictions to use per video. + + Returns: + float: The global average precision. + """ + gap_calculator = ap_calculator.AveragePrecisionCalculator() + sparse_predictions, sparse_labels, num_positives = top_k_by_class( + predictions, actuals, top_k) + gap_calculator.accumulate(flatten(sparse_predictions), + flatten(sparse_labels), sum(num_positives)) + return gap_calculator.peek_ap_at_n() + + +def top_k_by_class(predictions, labels, k=20): + """Extracts the top k predictions for each video, sorted by class. + + Args: + predictions: A numpy matrix containing the outputs of the model. + Dimensions are 'batch' x 'num_classes'. + k: the top k non-zero entries to preserve in each prediction. + + Returns: + A tuple (predictions,labels, true_positives). 'predictions' and 'labels' + are lists of lists of floats. 'true_positives' is a list of scalars. The + length of the lists are equal to the number of classes. The entries in the + predictions variable are probability predictions, and + the corresponding entries in the labels variable are the ground truth for + those predictions. The entries in 'true_positives' are the number of true + positives for each class in the ground truth. + + Raises: + ValueError: An error occurred when the k is not a positive integer. + """ + if k <= 0: + raise ValueError("k must be a positive integer.") + k = min(k, predictions.shape[1]) + num_classes = predictions.shape[1] + prediction_triplets = [] + for video_index in range(predictions.shape[0]): + prediction_triplets.extend( + top_k_triplets(predictions[video_index], labels[video_index], k)) + out_predictions = [[] for v in range(num_classes)] + out_labels = [[] for v in range(num_classes)] + for triplet in prediction_triplets: + out_predictions[triplet[0]].append(triplet[1]) + out_labels[triplet[0]].append(triplet[2]) + out_true_positives = [np.sum(labels[:, i]) for i in range(num_classes)] + + return out_predictions, out_labels, out_true_positives + + +def top_k_triplets(predictions, labels, k=20): + """Get the top_k for a 1-d numpy array. Returns a sparse list of tuples in + (prediction, class) format""" + m = len(predictions) + k = min(k, m) + indices = np.argpartition(predictions, -k)[-k:] + return [(index, predictions[index], labels[index]) for index in indices] + + +@METRIC.register +class HitOneMetric(BaseMetric): + """A class to store the evaluation metrics.""" + def __init__(self, + num_class, + top_k, + data_size, + batch_size, + log_interval=20): + """Construct an HitOneMetric object to store the evaluation metrics.""" + self.hit_at_one = [] + self.perr = [] + self.gap = [] + super().__init__(data_size, batch_size, log_interval) + + def accumulate(self): + logger.info( + '[TEST] finished, hit_at_one = {:.5f}, perr = {:.5f}, gap = {:.5f}'. + format(np.mean(np.array(self.hit_at_one)), + np.mean(np.array(self.perr)), np.mean(np.array(self.gap)))) + + def clear(self): + """Clear the evaluation metrics and reset the HitOneMetric object.""" + self.hit_at_one = [] + self.perr = [] + self.gap = [] + + def update(self, batch_id, data, outputs): + """update metrics during each iter + """ + hit_at_one = paddle.to_tensor(outputs['hit_at_one']) + perr = paddle.to_tensor(outputs['perr']) + gap = paddle.to_tensor(outputs['gap']) + # NOTE(shipping): deal with multi cards validate + if self.world_size > 1: + hit_at_one = paddle.distributed.all_reduce( + hit_at_one, + op=paddle.distributed.ReduceOp.SUM) / self.world_size + perr = paddle.distributed.all_reduce( + perr, op=paddle.distributed.ReduceOp.SUM) / self.world_size + gap = paddle.distributed.all_reduce( + gap, op=paddle.distributed.ReduceOp.SUM) / self.world_size + + self.hit_at_one.append(hit_at_one.numpy()) + self.perr.append(perr.numpy()) + self.gap.append(gap.numpy()) + # preds ensemble + if batch_id % self.log_interval == 0: + logger.info("[TEST] Processing batch {}/{}...".format( + batch_id, + self.data_size // (self.batch_size * self.world_size), + )) diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/mean_average_precision_calculator.py b/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/mean_average_precision_calculator.py new file mode 100644 index 0000000..0ae8b0e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/youtube8m/mean_average_precision_calculator.py @@ -0,0 +1,114 @@ +# Copyright 2016 Google Inc. 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. +"""Calculate the mean average precision. + +It provides an interface for calculating mean average precision +for an entire list or the top-n ranked items. + +Example usages: +We first call the function accumulate many times to process parts of the ranked +list. After processing all the parts, we call peek_map_at_n +to calculate the mean average precision. + +``` +import random + +p = np.array([[random.random() for _ in xrange(50)] for _ in xrange(1000)]) +a = np.array([[random.choice([0, 1]) for _ in xrange(50)] + for _ in xrange(1000)]) + +# mean average precision for 50 classes. +calculator = mean_average_precision_calculator.MeanAveragePrecisionCalculator( + num_class=50) +calculator.accumulate(p, a) +aps = calculator.peek_map_at_n() +``` +""" + +import numpy +from . import average_precision_calculator + + +class MeanAveragePrecisionCalculator(object): + """This class is to calculate mean average precision. + """ + + def __init__(self, num_class): + """Construct a calculator to calculate the (macro) average precision. + + Args: + num_class: A positive Integer specifying the number of classes. + top_n_array: A list of positive integers specifying the top n for each + class. The top n in each class will be used to calculate its average + precision at n. + The size of the array must be num_class. + + Raises: + ValueError: An error occurred when num_class is not a positive integer; + or the top_n_array is not a list of positive integers. + """ + if not isinstance(num_class, int) or num_class <= 1: + raise ValueError("num_class must be a positive integer.") + + self._ap_calculators = [] # member of AveragePrecisionCalculator + self._num_class = num_class # total number of classes + for i in range(num_class): + self._ap_calculators.append( + average_precision_calculator.AveragePrecisionCalculator()) + + def accumulate(self, predictions, actuals, num_positives=None): + """Accumulate the predictions and their ground truth labels. + + Args: + predictions: A list of lists storing the prediction scores. The outer + dimension corresponds to classes. + actuals: A list of lists storing the ground truth labels. The dimensions + should correspond to the predictions input. Any value + larger than 0 will be treated as positives, otherwise as negatives. + num_positives: If provided, it is a list of numbers representing the + number of true positives for each class. If not provided, the number of + true positives will be inferred from the 'actuals' array. + + Raises: + ValueError: An error occurred when the shape of predictions and actuals + does not match. + """ + if not num_positives: + num_positives = [None for i in predictions.shape[1]] + + calculators = self._ap_calculators + for i in range(len(predictions)): + calculators[i].accumulate(predictions[i], actuals[i], + num_positives[i]) + + def clear(self): + for calculator in self._ap_calculators: + calculator.clear() + + def is_empty(self): + return ([calculator.heap_size for calculator in self._ap_calculators] == + [0 for _ in range(self._num_class)]) + + def peek_map_at_n(self): + """Peek the non-interpolated mean average precision at n. + + Returns: + An array of non-interpolated average precision at n (default 0) for each + class. + """ + aps = [ + self._ap_calculators[i].peek_ap_at_n() + for i in range(self._num_class) + ] + return aps diff --git a/Bank_second_part/detect_process/paddlevideo/metrics/yowo_metric.py b/Bank_second_part/detect_process/paddlevideo/metrics/yowo_metric.py new file mode 100644 index 0000000..032df0c --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/metrics/yowo_metric.py @@ -0,0 +1,82 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import os +from paddlevideo.utils import get_logger +from .registry import METRIC +from .base import BaseMetric +from .ucf24_utils import get_mAP + +logger = get_logger("paddlevideo") + + +@METRIC.register +class YOWOMetric(BaseMetric): + """ + Metrics for YOWO. Two Stages in this metric: + (1) Get test results using trained model, results will be saved in YOWOMetric.result_path; + (2) Calculate metrics using results file from stage (1). + """ + + def __init__(self, + data_size, + batch_size, + gt_folder, + result_path, + threshold=0.5, + save_path=None, + log_interval=1): + """ + Init for BMN metrics. + Params: + gtfolder:groundtruth folder path for ucf24 + """ + super().__init__(data_size, batch_size, log_interval) + self.result_path = result_path + self.gt_folder = gt_folder + self.threshold = threshold + self.save_path = save_path + + if not osp.isdir(self.result_path): + os.makedirs(self.result_path) + + def update(self, batch_id, data, outputs): + frame_idx = outputs['frame_idx'] + boxes = outputs["boxes"] + for j in range(len(frame_idx)): + detection_path = osp.join(self.result_path, frame_idx[j]) + with open(detection_path, 'w+') as f_detect: + for box in boxes[j]: + x1 = round(float(box[0] - box[2] / 2.0) * 320.0) + y1 = round(float(box[1] - box[3] / 2.0) * 240.0) + x2 = round(float(box[0] + box[2] / 2.0) * 320.0) + y2 = round(float(box[1] + box[3] / 2.0) * 240.0) + + det_conf = float(box[4]) + for j in range((len(box) - 5) // 2): + cls_conf = float(box[5 + 2 * j].item()) + prob = det_conf * cls_conf + f_detect.write( + str(int(box[6]) + 1) + ' ' + str(prob) + ' ' + str(x1) + ' ' + str(y1) + ' ' + str( + x2) + ' ' + str(y2) + '\n') + if batch_id % self.log_interval == 0: + logger.info("[TEST] Processing batch {}/{} ...".format( + batch_id, + self.data_size // (self.batch_size * self.world_size))) + + def accumulate(self): + metric_list = get_mAP(self.gt_folder, self.result_path, self.threshold, self.save_path) + for info in metric_list: + logger.info(info) diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/__init__.py new file mode 100644 index 0000000..639bd34 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/__init__.py @@ -0,0 +1,37 @@ +# 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. + +from .assigners import MaxIoUAssignerAVA +from .backbones import ResNet +from .builder import (build_backbone, build_head, build_localizer, build_loss, + build_recognizer) +from .framework.detectors import BaseDetector, FastRCNN, TwoStageDetector +from .framework.recognizers import BaseRecognizer, Recognizer2D +from .heads import (AVARoIHead, BaseHead, BBoxHeadAVA, SingleRoIExtractor3D, + TSNHead) +from .losses import CrossEntropyLoss +from .registry import (BACKBONES, DETECTORS, HEADS, LOCALIZERS, LOSSES, + PARTITIONERS, RECOGNIZERS, ROI_EXTRACTORS) +from .samplers import RandomSampler +from .weight_init import kaiming_normal_, trunc_normal_, weight_init_ + +__all__ = [ + 'BACKBONES', 'HEADS', 'RECOGNIZERS', 'LOCALIZERS', 'PARTITIONERS', 'LOSSES', + 'build_recognizer', 'build_localizer', 'build_head', 'build_backbone', + 'build_loss', 'ResNet', 'TSNHead', 'BaseHead', 'BaseRecognizer', + 'Recognizer2d', 'CrossEntropyLoss', 'ROI_EXTRACTORS', + 'SingleRoIExtractor3D', 'AVARoIHead', 'BBoxHeadAVA', 'MaxIoUAssignerAVA', + 'RandomSampler', 'DETECTORS', 'kaiming_normal_', 'trunc_normal_', + 'weight_init_' +] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..172853e7c7da357a4c635ce1c82ceac6942ba601 GIT binary patch literal 1249 zcmZ9L&2HO95XVW$k|>G#uq``|Ka(bL!b=dOx1uPjuQozmDInFN7ziL}aU&DnA%$JK zw)+Zwi{AP+J@mBKp85(s6x~@SwowB7VRmN7{m<-d)@n5@{rpk+HU771S%1;u;ZxF! zuk|bc)QGLv<`&vu+hmt`3CmD6cA0Nr1u9sDD%PNe4mencx`}P@1~#FIF1Xl&mhn}1 z8#~a!E_BVh$~SQfws0G^u?IcefgRk1T@$PEN4N)j#&-B)+=qQUfCD^)Lp*{bJceUD zffIZJPw*)`HFia0EU)#qtxNN4wfTK? zGs%AFOPQ=vCi*}2wX^CoIc2$5QSI}qgva4|w7fjeQl=Wk`hrEV>J&E5mJv^WVd7Je zXHu$e5fp5htx}45W#tYc$wn+^%RCdx`6iONKb%fgcYd7(d9=EVc_r1RT>tKC<=)$G zM_O1zEA_LoJJ`e-~K59c#KP?dM%{wPq5v)QnJHi5BrRnKNYptIcfeSbcg zPxL3++w{l7*|*aorR~oq;rOSy-#35JJGT5NjWY})TyxWs&SjLKmKmm*z=(&cm5Zx% zdAD@0S+csw!z4}e&^r)4eQIKtuuphIcud$MI0QY=mZ%Um2sJ{Putn$)Tn%{G(O7Jg z|A4SbXcM{wx(nivutPW^91~77rk)4&=;Q22lMD4v!y?VLs%9pEi9(JMW+WP6q!_k8 zhzQwrCN5vcAE!f#I_*K%R5U4P=RW6trlhGvv~+^1TX}(QE!T&!c~>Vl1Wpj zas*o?G8eZ+LrrC-tEQo*m!_+x$1FsK;Y=3ho41R#$d*h><6W$yIOgolqt`|$PpRykj4_Z4Sf Y(dCsS*loM^q1`KWHQmxH{r2?xA2`uVx&QzG literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/bbox_utils.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/bbox_utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a6a2b901eb148fbb9e2ca79ca6e1b1b2529f728 GIT binary patch literal 14172 zcmbtbYm8gjUH5(Z`Z0;y^ne!u^@ zzP2ZmEzoi9dHm1go^$U1{XglIO8E@_zT*9?`nUIIGXKiT?4N_mb9e@eRwkn|%Iail zCbw#q)a`x8&RCg!x8_;%J^Wf$*~)o6Qwx-MiOCK-Z2zzfZjt&~^3w>LTVkt*Yutg{S1 z`8o9t^%U~+%6d6defl2H>PnNRH2GUW!Nc=GJcAG8)FPfr=99LvcI-3Ln$6nj%-BiW zow;^5X?N3h8KJz$S;?$t#$F1So`Aao_alCn>H8+N$@{WtyLsQFee%8_ZJ)d^EA!@3 z_~d_Q9kme?xMaJm4=xkE6TF4YPo@K*01#r!$B=KYz<8@&K`vA*6wgn z^Vob~vR%`;In?#TX>nBZI1YW7p%1g9&!jkt?Sn%+%n$JF#&UNzgf*;Zli>V6O7+uhdHYuHNt z#<1NPZ1zWSp4DxcdJWSKE+DB`73(y972D)Rd(m37mhoG&T}!W{%N+7@Jt^}3F%Fj> zM_G3*py>or1TE5EX{ zBpv?BDC;LNq{%~_{AE$#Sqks>zbo%o;N)X_ijH&qKOr3HGnEl1$dL7n^qI;DLx2;h zBl9GEyvUBM_wbz{XXFletrdaaB6oz(f-EEZG!Pu5K^X#Ke^r{LJQ4>mNYl+~*|?q}=gmPytV~Akr-bQEuB~dq$YchdP476ghWoaL38#5bh~( z8}O+R7oL{(_tXCJG1LCpp#|aS;_&?_+j5~^d3S6auzy8lq9JJ^bD?k{V@IFIQiXsG zi3Yj?KpeF9>*kcL-PnR;I^2rw5uU?sIym>-q79peq*qwFJm|Q zJxItR2Ya!*7lsdDTM3hf`~Bfa@NEaZ2jprM$Yih*{J=yk{Q^Kusxgy4meXT<4wW}Q zwzSnq#R;AX-ca#+Iiop=e9o#RyL#Z$@~hSxI&AdOb3pug&e9)3Hi!O{10(_AZhwQq z5KFsljln%43%N72j%+;SR@Pnc4rP;rNa`@%aSXA{KtMPo4~*h-(nwek$3_~6840bI z`X;~lb&poY9ZSl-B0sanAef_UlvOTphGi$RxwgmwpUR%joXY?fMA^I6U1uCb0eMve z)=VZ}!QTfPo#qYTLs;qE40Wf`A5^Y|!-FvFR)iOARe(FDxSf{~@7JxtWhrrd(&^$y z!tS7_tCtO+a?l>`R)q2@ue`WXdHU7)0o#=~8*oJi$cUE&A*ZiP7daiDf*!i=qmePaTXec)W~vT7b>iZy@TCQhjCsQd%e@% z3#&PBb29U-B;SrbV&9g@wqyTr1Ufr3dAl1IMQf-Vogwzx-C?NXV6wU6=v)$Xp0p0J zlELFhf9&GOs2kl@DDnncV`DHxAM#7H zyA6~eV{Ss$+IoAaXHLyhN zD7OMOHZI9H|4qlG>ymLW-^Cg#z_KYtWx-0n@o^la3Y#!7E2CbgN0#*v)>gULY2&+I zuDo)%Q5kJi4mK*guWnQtola%9aWkw8cf$#nyS7p3Hqb1cwx;~9(QWSbbUIN|75+Fg znnSmzgH-RJJ810pJ7HZnhV5SEBKQH8F@;wIzEM%(PUA*rSh=*Fa#&FwD;Gtr#2Beg zJ8o^7y&mVRID~YO=5U1VZ~Q;EZqzjDo}!=_-K`qvcMw86*Fqp!4RV4OY=|p2?A4)| zK#=HVmEz1G&jT#*5Q4FlVD*Vb`lnrYeiwZNxqatPWR%ZnOtmE#;Y3=;Fek=f;};(-}Yw56nM1 z1Gos31DZ-6Xw@hWZsem3MS;o#Y<(9Br>8)5;~cr8wz zMlLFzgO*m!-ulK=;b`}6RC+t4zEsJ0n2NDAuP+#ZK0`jx7+%~uu4WulGEN+{{cu%- z%bRK$tj#DG(-ogME!Og4Le54%CyP()7omx>s8@YaCmxm+i zHvABMxbOOhTca&z+oSE8*D|#hYq84;QkJucYM@`@lrJNRy&K(juX`NZ%h(u{|NVBS zq1(gJm(WuXKA+E9AHa_i)>w;+R$%D^v^ObRCx352A=Tu+F_BQdkw%dPX$9XF9jBDR zz?D33%eX_cQ32%zk;g$)M0rulxu}Hl5}c!D;1y&C`2A9}Fe$^GungRU!xdNs3`HG| zQ_~M6IAhULiVD&~uanFGPtmDp1vt5kRu4G28ZAewkPT~*J^0DU#pCGzk~PX&WF@j% zXg=!#mvsqTRu1^-$kv~V)}zyqHJtNIv=*I-R`G^2=b$mYoQc+zeJT^3W{P*S&sm&7 zfHGHEJPkg8_H2{`1S^h820~W`)^-kS`fbd4E;^gcH?wcf1|D#J{K)K{6X=EUqgbgM zosS-&%UQ}7qDNWAx+}^Vde?ov8^%EfvbX|%WaA_siyl)jHn5sCtmd(GO3%mPc7MDc zOx6)S7ClbyrR;AFH0?KRSW~bv6FY)r`F|tr?^(uzNdHyVj`7ZjV@6mUS>8vgxs%u%LKwqFSD!OM_vr52d)F+98ykw`dyb`Ze}(`2k{=M+r?Esn!HLV1_lP4}ORe7-SzT z(E&?DLKwIrOWRYCKVxIu;N&TD)Hh{5&Tlv2CTc=!Xo|N0WpGx#+uPP14%uf%`vC5v zU08JDUyZGsFzPz}-Ntd|8i-z^YGEGSUw(jV}A})JYc+~rp|JzW{{krXu$KS;ExbRBT=gp|EsBqI|a*9>%LnZ%5(QSjhBp9~Rqwh2JC` zKrg1=S-IGS22ibBJcNx86<^Xr*ySuY4y$IMaf?CyesJtNIhI~}3@{mO1egfjRwp#W zHHEzvn!pEw8bBH`5eqn>rfyl?o^sOKHCZ4i&@nOU6OK zm(Xt+fxzG>f7d8c3sEj9uMFMmP~vfti|Dl)t+KAN=fDS8T9cG@C=;vlO;&LtC?V2v zDhbVsJiO7&MfE$v=uh6)OXsp*fIhQ2% zDEojO7epw->v1P-3+r^ z2==!S>~BF@F0@JG;& zy=RRBjCW2zdwHR~CBOs7*`@0_RRk^CQg_liN)jifDY6tT$yw&{UX($zrCZIDoMv!` z_j?1V##5htYd9?%GOTPJzEenw5d@(_fe6U>r7&D-ReMv!C36SgmpO@TbE<6;M6ttM z1dT{qk-5YMp~7kbf^WbOtQK)cgtI3}POa)=jguvh(kkJ&W@CzfZ zP@w7u@nGNaKrk5)Q;}+*a$1Zs7a_2Gcnd5m^BU}OieM6@i4fnqow#+Wr&V@zZy)|q zUPBUGIu^J>mpZRfK!Ch*W#fg7k8Zqk>VP%QMmD|hWZEz*42ZcCZE$|L{zaS!qL6g$ z-=kh*P?fj{|0mB)iyWYG7keg#a73sGhDTW<23AWZ%5T;fXOk7ppj|+nuf5+I#MTS3 z_0ia>*9vAyh(Ha7v5&So0u?y|WtwD0Ig=9^wv311pl|%Ah&+@@`2x5u5TOXW#P#Bi|87nD}v;QacH)sepKQ4n7sKNC~&I1@7o(T1y z$?WiofvtS0gFm9qkPNsYQXmcL2t}#9)C*GgfhG=+hI7C+;hn?z8Z;S)bE6fhw9eGX zpMic^nMKA!_cOE1)i8^UN2{4-u9nOa0EvN=w`~MtV6R9CVHAW@P~LO(UA%?s%_ein zx@Zw4Fz!KiLKqOf&^=FkX3x`qkdE|aFY_aP+5Ox|oNrLbD98?$TK0~ma0m5u3q(|m z3W#Qt^l(p6M#_$P4q^?`UB?!llI%8ZG0r;#Q{aAso43Wl(gIxCxd@lOK$I>35x7>7OSse41jsBx=BY`0g8#bpexgN@w{VU}jVm3u;BqI*#+7?~h$2?`Knhy5l> z_ehcV=%b&z0l=Q@NS~>oKUfv)48a=F8X#e%zK$*o5l&yixMkIb=%DSVe+#t-c(W*G z(*7lq7hiVXx>eyp)Diq3>)w2((}Oo{@a*QabG0CHOMjkoQXE0^drc3Gu1T#E{6RP2 zQ-M!H;yy;O2{R#|sV>DH-!Z6_=1vmfYe3;S8E!Fwzob9B#N_FkN5c`GW@eaGWE*ZG ziCnAYxlkk6^zU&^KhNaTNNRj&oU>FZzn?E4KT5baa+&?(RPU3?zgwjyR5k`>;- zuQ@~36#vyzab7gOb{FjKB*!JL6I{Zz0z8LLBYzt49{8+cm!2z@aiav~2JUk=d;8a9 z8vI9t0d8VEsY>jHO81j)X?V%y(YaoleQ0=0iSfGV+K>A%L{IjkmK zq$)FKS!256LibFfP$H0k@A&zGyNI_$Ip7^N);wGB z$i+J3jD%VRxRWO3NgHsH{R>e6CLhfp2vKOBCYnktwAOiV2LC}|ya3Tx#D4>swgI=$ zwlrQIpBk@-5(Mmp2nDvmA+i{)wCFtYR2IrmaR~hu!Wr}9f?sg!CyW53OAfM9e2gaw zzC==zpMDpadPP(InZP8zULq3(XDK#;sWg&|u=xy2w2fj%^@hf;!4Fnlh3?8VOx9Bmqdao`|=Wyn*E zGca&k-cS;ZD@7$>94sE(>IYYw!75zv16Bdsh*{)fGi|Q40o%r_<2Av!1k-?bjD4=n zU|bm(R|dwFp~hu-pMOq`gM`5SO5TNp`Emkc=)XnN6frcFj_NvG%lym({fBJ*Dw9-4 zIEEME?_$_cBS*ME^6Zv~JCVx=q~E z={7pJ;oXh%Gj;3v*n_3kADP1=+R3eYxqB^FisgQ+xo`L}w(>%oxg*2-B@%O&$d7p1 z^$}sT$;I{({YDf6;iH1)vV|Fv5#kXQBX|b?vF1i6e3rYDfK*V%jd1z}tiTCYgG#WR r&jtCw4bBI-z{{V@uLqa?Gd_*JZ>??no4%F*c5p6ud*BCWi>vO>RZ6Jts&1o1S^?DaRtWo;ov2F^Gv0(b;Z2&8Ue?TdIWyJqM2FgM#z=6FPHt|L= zXV@gmLOaWHOow)ktI#g7YwS9-SJ(}96WTJn&`~P4--C~oiV@~& z)%ufKyVdA~na7RlYA2jnZ+AMt<~JMl_FAiHHa0tY&Uz2=iSX}z1xPl z+-jrSkX@rzYd`N*JDuiQ3%3=C?^HLQt|OZ#w%%Svrtq}7*==^4fDN3!@oc@@+-R>> z*Tcz9V{N0+>V|sMfd%h1)K?8N+xw2oDn*Vw&mqYp!O-AYAfevqfS@X>#xW%L1d=oo zh#G|#kYtcd0_me4MnCN1mO6YNP@+(d6rsM>z+>v+R1Kla+g5*f+aKC16^)l*4QX<$ zhN=F};8@}3Vd%e_{qt7M8t(RX9M=wH_s+eoJ?{7IAfVB$J&Q5de&I0N-|~EByUuX1 zMb_DTW$z#~sNWmGq1+E>w65_5Xg;erpM}|D^>9wA%YCP8zZBf+3!kqXM>?bFd=3f9 zm1G`z;jBc3UA=hMMO?Co>=M`Lz72ZLv81@%$5GNtb@a#rH=D{5teLQTPimt{((33}tYFSHlPf7e9<) z@YGJhVAj{+`(OZ(xy@9j{h5ONP92t{ZQSnrgQ0T>krL*1xaHZu`Fs}>eAhl0EJkKW)s@-8rb=}h8moIH zCCf$*3Ys(QLCH0QU8}d9xG4-W!L-=)suxF2FT3$vwy<&Dj zYJjCItLkd@jDK3=KfzKkwN+UTv)mpyf#3)7affFl-)&TF$zFQ5kd^fGqbr==f0T(7 zm1G;58fNx|;|B7PM*hHe6J5e|fAVX{;(f$#AR(`kd&sNgM)E4TkvxblBaKgZfF2L@ fcFH~g5A3`4L%h-g6!*v|s1MX^Ci$<&oy~YP{+l?_UjWJS6Dv_2Oz~pAqq?s~fC3o6sW~jNkbz|br zxA1LT&(@W%;K~nr7j7KF`JL|!=kUSEAn+`#pM!7gd*8Btwc_8^gLsWwe??#xvxT*{ ziEUflX1y;q>46vE1=t7s-~b$eLvRR=z!B(x4(Ng|=z$(M2FIWe`d|PC-~^n2m*6FM z1zxf1!kRw%-TIo^#>x4v){XjPoGq>Hw(`JD{{yFtc#2nYcc?#eMZALV_WaOrrHLzK zMMYaS<0Dl~-PCAOrZ1${Bv7*6@cTy5s*#Ggj5oZ^u(RFD`wi8)-r;fLcT&^+QM51U zR3#Y(xm-8(o}$Tk`;$N}85L%v&mLCOYcn`Cwa}{l2IJ1c=_%~r*CS`&~>p?yBn}WlZpoHRE!P-@!$F*sayW(LFul^j@NT68x2o Rx%vr$KXH1F{lCk%{{l#x$hrUk literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/weight_init.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/__pycache__/weight_init.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8b4c7aa4299227c48cb896fb3a81afa8cea1249d GIT binary patch literal 3982 zcmZ`+TW{RP6`mo7T<+>(#a`Qrogggg)Y?|w_|^t>d~4DqD4Oa;O^V7&H`ESyMT<+a z!&y0!DWHh_R0z!}AaCxANLq#{NZ(qmPTmeUvgoC7I+YTdCiCh1<3>avjFmNUV6g?(tU|=yB3u z)LdzD*5vrP@{APHd%{;*(wB`VY-LIYvWfS!Y|9xri=G*IR=y-pLz9t+3eA z>v`6)eKcD#DsrVUmy~IIQk#uO#a0-VVOC5=$Vf-w9jLl_7MBYTZY+j3KVA%_-YVid zmj`Jc=^NKCcMj)DlPr!DM%3TvW?A?art_YTvoco;^udW)p^{85 z)RT4}#mR78PdaP$f}N@}S#oXGqm$|#3|$N_FXd_!rI#TM`n^Y24}>)mN-ghP?OwgM z7>?p7gLrN7jc;6l@$2s_8L^f`sY0A(7(SX0XgT8a@_G>R2L&jjz} zS*fE;cYNce(N+u_x>GZCuy!&vO`5l7#g-K}qjVe_f8$Z4hNU9l+Um>q;#;e4N7+Vi zkfd>0i&w9&7Ao(@Wofmm^>u6}GR{{=fC$cRxO(KIy2X~6KGN=;!}MhvReSyd4|w3T zojJUxo!~3ss59s|=0;5@0+e@9%KxI0aGfV?$E$edO1E;_Y@TgkMzlrUKF>CUn%7JU zath7&oPGBBGF-}oWAJ&n)2{^4E71(&;;l1@kzsP4?>GqOc-s2Yca<5bEV?G?mnfH!A3-x zY{v?LgLPgqp7k{2*FZImgT)&sD~zwAOy(og7-z`<+b|-N8qrUa!ZgcR_i9gS90`5F(d8Z-Ix^vudEa?#pb4;t%2zB)Hp-sO@1Z)OQfipr^9uVh({= zCEDbgfIHsgVEzE{r{gWDi}=>|(t8AjEX1jY1Bf}Ox{r63Yr4sPJ_32i=*v}DA6xh+ z(d*$LeiTDfV@D<9|kv==pPusXvAGfT;yiD_4pq9KZm4DreWR(6EWmPNQmA^74tcz?Tj|>GL*t z+aWgI^Q8y21PE<{^CG_d{@3`jvD7DwKY!?`s93)IF@%cOn5P8}9UvUXw#ii+*mw7A zYv1|+ax;8()!8B3lYclWtlVW*31C_*+2c@mFyZ$1eumH&KHjlNF2@CBL$O>83!GIM zhhr3^ImBI$cRB*GIR~KC4=@yPBL39&(hqJ5T!HD#6xbw@J(A1Gw@zN!xg&5pAVR|0 z7<1b&YcWMQ!_Rppo=t-SxILFet_JTfFxue@~d>=6e_JIfaU|7E*mo>Y0Vusds*WSG;-bYx|IZ^H?8C$ z|Gial*fg{+TYHTPVU*aao)H1tl~ZTfc}5X%nZafnHjv4tGqZ$L%CD0<`HtgIusY|=I@_1O5r)U-wj8hSV{$P0Vc=D- zL7_ra2#v#d1RtI{u|SP6 zC8b8#+Ei=4#b>d_HoWW7|I{Z?BimY1^zXDI?8~yax(7v_j<~g!c+_H{bE@7B?Zlj& z{Ixl<74?9OSE(X~wGpk@Qs1(2*-s!7+1bq5(tRC1EMI>@9g{6tsZQ)}gH^_9e3yb} b9gb!Lej2wm%^i=zQtPYW_2ApB)3f6L1vvEc literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/assigners/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/assigners/__init__.py new file mode 100644 index 0000000..a4570db --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/assigners/__init__.py @@ -0,0 +1,17 @@ +# Copyright (c) 2021 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. + +from .max_iou_assigner_ava import MaxIoUAssignerAVA + +__all__ = ['MaxIoUAssignerAVA'] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/assigners/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/assigners/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7eb211567e8dd6301fb819451dc9ad15a04cb948 GIT binary patch literal 254 zcmd1j<>g`kf(xwODchMC7#@Q-$N(tD-~hzMVn8B=A%!uAA(t_Vk&z*VDV;HjDTO(h zL6hYrBT!P4@s^-(VufdZsAF+)W_n&~kz<%+5lFwECUcZXZem4zW`1dWB2+Ryu`CfR zdy73jJ~1aJK7J)b5erZ?nE2(JY8B&@n3o-&mYI`U3}G4=#S|3fC#Mz{gGFNs5>rxg zQp++^QuAYS^HWlDGV{`7VCEOc#K&jmWtPOp>lIYq;;;cKD9uT=1G%&qWDO4=7ZU*e CctlMA literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/assigners/__pycache__/max_iou_assigner_ava.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/assigners/__pycache__/max_iou_assigner_ava.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..485995b118b4e5c7c963b1a742a5ea8ccf55d8a0 GIT binary patch literal 3765 zcmZ`+-EJI774GW4=^4+A$K$axc9KmmVp#@|i2_$kgyN78EfQWfUeKmx)ap!^$78p< zC)GWPZPiFC9Ij9##1q)u1>OL0#S?H{w_N23kPs+*r+V5p3ESg7U3KczsZ;0QS*z7B z@ciBRUHrG}hVc)YTzzaz?%~aU0T3H8ON^lWvcQbZ*h;KJJFuC7v7I=FZs0QGkr6ww z`_hQrQ!}V>`^-BhTrKv1^G?lE7Sv<5Z4Byfz}47#V*(DCYTv*A*_Yww_V%ZbwjMs- z2B!7&X?7H5&$&pVNj@a%tB-}rJ-qn`0Ne;zY(OfPk-`*KBKGt6Dle3`a$-YNH|? zr*W>DhtZ|1%1xrDJjn-+vU8s7iW;~Ik3gLOsr|Jfn)v+d3IAm0ev}@ByW@oC?0p6wiFF;B+nXeZJa;v(OnqsQ4atT18pJldEXD=&m><01@u zI4Gy%T}HnKJ6XA^j*W_LNNT7a7Xwm_R?8nSD2#m;v%-|@6yIxPb?cQiGl7Sa_HEMm zD|2QQ#+d`2ur(a^IeYKWlLwitA;f%u1%SEq*uUc-H_0L_Zw>0oEmf}ENJQy~D=Xots^!n7oS$%QN#zc+bQl%N-km1NrCkTE zSfHco@Ql(6f;#ztc9URn?l0k-RnV%)!Yt)^(7WnJ6_Iw7610eQ4ekK%3)eBpy8wN& z!#ZpgZwJO*W%k>X-v1bQzCn;p;goQUG&TEeDrSV15_#q}= zmo%h9F(6$)M|yy+gl~s6N+zW}Jhd>%avj0No=^)ZA6-rk$7wiURZFlr`A6yAVU#4Q z4L{EW2mNkHn^)%Z7orG<5p)no14|x~Obq*qTFDNauQ*(xde8!NLt#fncNC$qwPFCkm0HYU~HZG^oADDu8sO7od zNH|9Fs>`6(1 z=&RF7cMV`nswcl^;&IW%82UvWGY{ zMTCI(1_4SMVhLbiDs~{Kec2K#fImep_M$v2rjvvVDnOK+QOFMmOm|g->&nUZB4Adr zDA3g!NZ#4xKshh=xZpaqsRn8|GHxdzl| z09~uD1G-xcR^C}g%Yt@Dv2oDQ7Y~oZbW)9vX{@_msstoR(7DQu+G9vH@5I7+E7ZS0 zKpNT<&J`GVy2=roW;F_N?cn_#RqJ%^Jzk}9gARC?=T+)vn~Hs@*b~LRP;6V7n-2qP z^C8BMl_hxbPBs_cgZdxf&5r<9&92$Adsf$KqPeo)Hti>P2j~cI4 z*2cVJnqM`{o_T|HF>hmqUF-h!y znyZcfwCjTC&@Jfr`UGP^MNfHxkH!e3V?mWIXppyt(_)= self.pos_iou_thr, + argmax_overlaps_int32 + 1, match_labels) + assigned_gt_inds = match_labels + if self.match_low_quality: + # Low-quality matching will overwirte the assigned_gt_inds + # assigned in Step 3. Thus, the assigned gt might not be the + # best one for prediction. + # For example, if bbox A has 0.9 and 0.8 iou with GT bbox + # 1 & 2, bbox 1 will be assigned as the best target for bbox A + # in step 3. However, if GT bbox 2's gt_argmax_overlaps = A, + # bbox A's assigned_gt_inds will be overwritten to be bbox B. + # This might be the reason that it is not used in ROI Heads. + for i in range(num_gts): + if gt_max_overlaps.numpy()[i] >= self.min_pos_iou: + if self.gt_max_assign_all: + equal_x_np = overlaps[i, :].numpy() + equal_y_np = gt_max_overlaps[i].numpy() + max_iou_inds = np.equal(equal_x_np, equal_y_np) + max_iou_inds = paddle.to_tensor(max_iou_inds) + max_iou_inds = paddle.reshape( max_iou_inds, [1,max_iou_inds.shape[0]] ) + match_labels_gts = paddle.full(max_iou_inds.shape, i+1, dtype='int32') + match_labels = paddle.where(max_iou_inds, match_labels_gts, match_labels) + assigned_gt_inds = match_labels + else: + assigned_gt_inds[gt_argmax_overlaps[i]] = i + 1 + + if gt_labels is not None: + # consider multi-class case (AVA) + assert len(gt_labels[0]) > 1 + assigned_labels = paddle.full([num_bboxes, len(gt_labels[0])], 0, dtype='float32') + assigned_gt_inds_reshape = assigned_gt_inds.reshape([assigned_gt_inds.shape[1]]) + pos_inds = paddle.nonzero( assigned_gt_inds_reshape , as_tuple=False) + pos_inds_num = float(paddle.numel(pos_inds)) + if pos_inds_num > 0: + pos_inds = paddle.squeeze(pos_inds, axis = 1 ) + assigned_gt_inds_squeeze = paddle.squeeze(assigned_gt_inds, axis=0) + assigned_gt_inds_select = paddle.index_select(assigned_gt_inds_squeeze, pos_inds) - 1 + gt_labels_select = paddle.index_select(gt_labels, assigned_gt_inds_select) + A = assigned_gt_inds_squeeze + X = assigned_gt_inds_squeeze - 1 + Y = paddle.zeros_like(X) + if A.shape[0]==1: + if float(A) > 0: + T=X + else: + T=Y + else: + T = paddle.where(A>0, X, Y) + S = paddle.index_select(gt_labels, T) + AE = paddle.expand(A, [S.shape[1], A.shape[0]]) + AET = paddle.transpose(AE, perm=[1, 0]) + R = paddle.where(AET>0, S, assigned_labels) + assigned_labels = R + else: + assigned_labels = None + ret = AssignResult( + num_gts, + assigned_gt_inds, + max_overlaps, + labels=assigned_labels) + return ret diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__init__.py new file mode 100644 index 0000000..a88cedc --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__init__.py @@ -0,0 +1,60 @@ +# 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. + +from .actbert import BertForMultiModalPreTraining +from .adds import ADDS_DepthNet +from .agcn import AGCN +from .asrf import ASRF +from .bmn import BMN +from .cfbi import CFBI +from .movinet import MoViNet +from .ms_tcn import MSTCN +from .resnet import ResNet +from .resnet_slowfast import ResNetSlowFast +from .resnet_slowfast_MRI import ResNetSlowFast_MRI +from .resnet_tsm import ResNetTSM +from .resnet_tsm_MRI import ResNetTSM_MRI +from .resnet_tsn_MRI import ResNetTSN_MRI +from .resnet_tweaks_tsm import ResNetTweaksTSM +from .resnet_tweaks_tsn import ResNetTweaksTSN +from .stgcn import STGCN +from .swin_transformer import SwinTransformer3D +from .transnetv2 import TransNetV2 +from .vit import VisionTransformer +from .vit_tweaks import VisionTransformer_tweaks +from .ms_tcn import MSTCN +from .asrf import ASRF +from .resnet_tsn_MRI import ResNetTSN_MRI +from .resnet_tsm_MRI import ResNetTSM_MRI +from .resnet_slowfast_MRI import ResNetSlowFast_MRI +from .cfbi import CFBI +from .ctrgcn import CTRGCN +from .agcn2s import AGCN2s +from .movinet import MoViNet +from .resnet3d_slowonly import ResNet3dSlowOnly +from .toshift_vit import TokenShiftVisionTransformer +from .pptsm_mv2 import PPTSM_MobileNetV2 +from .pptsm_mv3 import PPTSM_MobileNetV3 +from .pptsm_v2 import PPTSM_v2 +from .yowo import YOWO + +__all__ = [ + 'ResNet', 'ResNetTSM', 'ResNetTweaksTSM', 'ResNetSlowFast', 'BMN', + 'ResNetTweaksTSN', 'VisionTransformer', 'STGCN', 'AGCN', 'TransNetV2', + 'ADDS_DepthNet', 'VisionTransformer_tweaks', 'BertForMultiModalPreTraining', + 'ResNetTSN_MRI', 'ResNetTSM_MRI', 'ResNetSlowFast_MRI', 'CFBI', 'MSTCN', + 'ASRF', 'MoViNet', 'SwinTransformer3D', 'CTRGCN', + 'TokenShiftVisionTransformer', 'AGCN2s', 'PPTSM_MobileNetV2', + 'PPTSM_MobileNetV3', 'PPTSM_v2', 'ResNet3dSlowOnly', 'YOWO' +] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..754b2219fd0f22a6ca3780f486705df6a035e03b GIT binary patch literal 1769 zcmb_c+iu%N5T&g9U9x<)Whc$8YMPtWG)-C*jcvGS0ojHnIOtRWL5Y+@c$O5nj0}H6 z|DtdGhkit#_1dTYLZ3P_RBYCMjSL^1IkVh7J2RqRE*A{?{FVOA{xxqHe{&H3EKu+R z{p&vyhG83a0u7abM1uJOE~q3Vg(oqk(vTLO!i>s7R(Kk7Di3+#87!zG6oqH8q{>hh zp2Lc&LREMkYpM=);RRe&4QL22;*wg1W#J`UQLC^jyo_sV9oB_ca6@gvrtm6msU|dq z*Kk|yz>e@b-cfhquJA?tOx=Tf!W(#BJ%9(om++x_1doI-gJ+_z<8$=_UI^d7w(3Af_$Gd(UcyV^Tllql z1+RoR@f-CTUMGw*!`}Wq0dMS`p3%DV4|ULJC1zW@P7ogWLH7fOZr8UhJPw?GV7Z>_ zol(C0c7MNT?mLt4{hQ3bS4R)QwiAyS=_F&73$o zk}47Fp?`5;Y2I$}|BBf?;a&2P+V6EKC|?Eh?3Hjh7pn6W7mjtVqla!tY%$&IN7n1T z3)iDNdV1^!$_YCAlr4xrHc#6W)lXgR`te01uH6#NP>!TrX0Lw|?VjNRwKZwA$X3VZ z`yP3CN!n)LKX<&|dv_e(+Ktln<74t~cKxA?&Xt*)Vux1dB5}%YQ@ljpQ@zJDUs3^R+)#OFz))J(mLepa`|U9P4j1l*8?a;g@Pz_nQ2>^GfPh0P`U;MV)I#( zZb4=g2D~3P0y135ww7LeG|;i73O-Gp^aF~auX*ZB-jrJh`N@QAn~IL(242S<=_TZ% zJf*p-kh=6Qd}-?}Ynm3KY5rjZ_bDatZ`XM<*tNWKb4;VFBl^5Om<0aF(OT5OgxZhJ z)U_RdpnTgwddUoi*64ibd-RNH(rYI)&8L&gS?)Vp@By9g`9-CFCMZ=(iBIyk@E>U{ B!Cn9W literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/actbert.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/actbert.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d92dc92227113d36aee409ff540acb6e4720de4 GIT binary patch literal 28508 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/adds.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/adds.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..24f8479b9b30060f84b5a8191ee688f113bdb1fd GIT binary patch literal 26709 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 Ee~gvqEdT%j literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/agcn.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/agcn.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dbf6f27370c0eac60e6e8fb340bf1e35ff58d5ea GIT binary patch literal 3531 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/bmn.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/bmn.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..faa091441ffa72364884146e79f30102204bef15 GIT binary patch literal 6020 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/cfbi.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/cfbi.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..63efba1a9a040e6a6cc70bd726da5695bbf70366 GIT binary patch literal 2532 zcmZuzOK;mo5aur5lq^5$Hc63#k7ZG~v74r8ng*?%ItUu51>zH7U_p^9n>HWHl1gNO zJ|#sCh5H-qWByIgd+kX-p$$@ZW+_=oniclr>~hH6o%!aYiiHJFgZ8KSdrTKJ?Jpd> z-Aow#0KI$)5Nk0>wScHA4XC>6nGqPIxo2hu)rgi^fekY>)>9{Q0~c%~Hd8Na1uddI z&|)jLUudz-jl=eHJy_uGS?3(*o!EtWx0!!Vg2k9T)_iXQYir#J1@wt@w|?CIdFz+% zPmd?0nX&J4K6n)NBJ_K^>C-{E2?kd?hh39Ef2s8e?(c;Y7_q1JLjto|Kd@eEh8Ebc za!cwvzjntiz}lnmn2QMGF>7dB&~cSA2B@@()Y@};M$aJ%wRWc0dTpH3T4RP9(do!k zBQhOXwRQ-8wGpd5oq{j3KQQOS8tlpFPH;hC0Qgk4j=0Eq%F1NSr9BAaILY^YSDNK; zz=gp5Nr$l{Pb$V_i)G;vXDOaVI#n@fEH@1+Wo^hyb5q)7Rut92#?09CO=*-o?MpYw zS)63-=IGMAJ(AvZcH`Da+QqO!msgN4#-cPVOU7Pl|2*V(_O`uzbGT#&{YLO<^;u9FCWz}*5UU;(+$AVy%pxY7>| zpgcV^k;=c(Yg!Dkf=C%xH1H(qK3qR|A4=!Ux_qbIytC5J9JJIG)>Bv5L0`wnkC)f_ zg?JWMC^*#7K?sGkgbvH-U066i9ozK~$jf zDu72l;t`9k5a*&nPxr`mI&NVqrrtiC)6{pcfb%fpP{1BzaExJ!cAK#$!!VuRu^Eet zh%r?cD)V9k_q#AHzlf(P+?_Mz3fvWnCMXg(DzN|@AWEBfi%Xsoj|isTX)}V9H(~m1 zO?9cOyM}AJpr}e;QRQ9GSEcHKsZ`Zcs%mWSY&{&WAg&G4VYxP|ZfOZ#=DgaSfPiWf z4J1Fp-OU=>*iiwMsJ|<@m5$XKlT#(Rm5K5T-HfRcRZ9t|-i0c3E?0E>g7YzFy&RJI z5xiGmv51cmu)2I(U|7UA2&g#%bzd&`c~}hvXM9wNFap9fTC4X5xo;_Ui0{z*E&RTX2>R27q$oYOty1ScKH6^gvq82THolbv@6;8ayjkFURXMH3ALy=C=48 z-5kO96Zl3P3uJL%$MEMR4SNl(O!YTo`q^$Afmw=s^UW&@!zG=&jT+p;?^&r%&~YGU ME6@RT>x--8Kjpwp9RL6T literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/ctrgcn.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/ctrgcn.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..86eb2408bcf2dbe2664eaf6fd2751810d3c30f78 GIT binary patch literal 13695 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 C4_e;< literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/darknet.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/darknet.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ea3eb959b143587f278682e1f24bcec6ac894b15 GIT binary patch literal 4583 zcma)A-E-Sm71!0bWXEwGH)+#uNy`FjKD@Ql?gzs#OWIkOr8T7m7EER|ilrn@Y}s5X z{qQI=4DGNFOox9V+2JMs4bK|hc*-+R^d8IZYjET}|TpP*WAA42`ZSDOT71 zsS;>`{z?h-P}_4}YF!r;BQQZRC8Y$471*HIl2Qi630zQINm&Tk6Qxl)#afh3gJsSm zpZmj~Bnj^ksd&-C>5AV22$e1il&t zjJE#TN)^up%~(+mEy!A_8kmr>0xOpixSivmIx7mGi*f0-iMe*5V14DzWTDx^3Y*Wu z{?2X^!w7oh55rGs>HWy-?fOv^4&tmlI!Mk(rTvhD?8W^_n3-|H`$3plV?PM`(N0#% zm3cl4nK@g1KNjdjYi>oEI|%*#7ak7>2NSay_xwRPv6`dp?Kn&(MspbY(L`@P^?Ae0 z%F)5_{H2=TOEPy%MsYeq%T6$KO6zJ&tQ7;tKhLaib!8qic?48-3 z*N^&%=VfXXWhNa``#x8RWq4$e%-Qgh-fm~ahnePWMGZUC<8ZK@Rr=AmXo^J`W{yzW z?hlfX3)^ryWKO5d$$>I!D_`RYe9iNE13!*E??id?ApGIxh9B*Fm>b49db_7SbDTM90lP3yWZULd;43X2y+6T??++M9KYa8c-0E-_}c&#OIKAk{gr{) z|F#`nP|B>#O#I4kCiQ}!HmAnvkwK;x*^TadxZ^7TsdA*G?3f*@z~HF@Q=cd&tkY2W zG9);OH8g$|kIWQ?i!=6|uMtmxo5ZoUNBo)3gEj`S3E(o9>1?u8T$7aHx4=I!=>X}l zae%Jp!5jwz!polbhXa3*bA%oEx9ANE(%8LlFz~#>`)`2DX%WILXw5MlnXRZ+1jtSEXf#F0 zwRjzr%z5ZPe>55m+V>G7L;txq#vsc@+VZ*H(1lYK7DQI$;yBj`6K6_q_!xIg^a?Xo zxc!;S?6aC`QUIJ)fxBvzmCq(i=f`ug|I_Zs9`{HgZD8jA$lCCKiUh*c8Ky}LMMk(S z7ELbB?-004-~#}}3dIM1m%!Q#hz*eQ-p3tNRi&tqkx?rwwipB35$o;ZTYtE#h!o_+YB+DM(E0h#eyi_SLxbnerzb z(jGkis&a^<0j2>%kp-p$GX!P;GgBi~mr-mn?>l0iIUBz(#_Ayo?x79+T3(=2dsRv8 z)J!crtsV229qBvhM!wA5VqVTf?2(+ET6JYdm$KGdvVx11kY=HG$B>ftoMbMiLuXMI zTH%gxy@t~{B^!#!Jv8s^(n@)5y0HHfbl_%uOGZ5TOKs1XVUi>87_$B=13 ze~5y+>yObF@GwW5g!@rE9>rn9DfqmYz&0{=FJnK;*yox0EY8&3xZuaLVE84J$KM4o zSyhIE3#^KAp|k6tsAp>`!5aeJLc~uNa=(#r(qQ@a|7)a>i$0*&%pyhSMElxEvF_(3 zxbu}bp&g1i`5Qd*qBu!(dXyPc>yBIq` zIarY662|4A5-iGb8G0*0RqDMY^)7%~1)bhy1vN>n%*ifE>f%?{P!+T5Qs-qUcL~%w zwB|aOCABsuyCSJebFxC3Sg@dQDPSga${h;ku+=Nv^&`Ht<%# zeFtmIZG1y=uVH`JLH!11tqGgHBWmBxP96knI5`nBnIYO2{yq_eMycpmkcX?@HbW^7)~Bek7kCXI9<=+@2z> zDbg0v2RTlKXi8n@mudZS)}3i3`HXgUK_%G%Jstp{3qa*BiylA)Zl9^>12{g zYXZL^@Hv6s68IfJX6D~WnTapBo}ch8aefbgIwyLpZxZ2MfUY*;{Y-t{!ri{8(EJrb zqRX3hUH|Kumm-v!#p!|ne@z+1={CJ+R%+hkL~B&|CLa0ssFQE18AW-2T%V1b+XqoE z>5n3Rkhuk%eVQ5gavs0H$L%;X#D5QY^ivlo!b!ZQuu$KF?&IycmSGyZ{zd?f72CbaZgrz-8ZR5M6T9ykv75L%wcGYa9UL$A!SM^u z0ysfj0jE-M8sJpp8aTCrvj|Q-UI1sI;55N$#Eal87Mvw;n(-1iO9iJDn^%l>>jZCN zte;q*Z8NW2IDhe#3twG-=}L$E*@N%SBmFE$BJYiNHu1jxd&ZU-+p+U*WdrXMd+!<> z?t6w~YjSlW_R{F<)m0oboYh;`5|ylG*OJvu_FGM}DC?$K zx09|${a6~Jt*vf9Ssg|y+D)=Vr7}o_zioB*lUQp1{-4)=^zFa>?|*xtW6RTOQo+T= zNnZL-AeoVwW8=1UXdPi?GW*aOo7?7*d0?aL7G-B_?092)$IpVD%3*bEADOXv$2xF@ z?@ahk!T0XN_wO@KFg6Zru{Cy&EYpy(J@zJLXY5bP?l_RLH8#R}Y+zQs^|qC}>9uH> z)vq=#3(x*2t@Z}MfX#z`{l zMVn6#-&PB_!_VMMp8{!^b^IK&VR|1q)@fR|*jhKM=ID`+N%Yg@ymhEa<-sYX++D<( zz6k>N>soP_7jGklr zAPg;qp^$-2((9pN`cRLeRq@G0fX|?iQi=it>*zFF!o5G3 zokiDKFsoSj*%dnu1k?!61T_KW8BnX_)eD0x>m~i9bNz(NEHl2|@lh-fmMP1EI)9A9 zY1G*P>WqP*vCYA4A5%1&n8e4UB1oi-INox;*@4AWH3eqWVcMOo1VJh0qa3S*A|- z3T;mq0Iy- zPhY29)K_@d%EZnn5tfN8%aeT(T~a=0!(V}Jd!{w>3qGj&Ucn1KY&dN9hycse<-fn` zbJi|$_}>N@n^f~dTxn)dGHFnxWKBx;q=aSvSgSkX!7S<49X~eqO!XYb^JQd=HMX7y zgn(0yYhMA1t^*D}kLOTdAo()M^CZ7a@+%~q37N412-M?XmB*8AoGRyww?Tk28N9n^hXU0j3yB3eAOJOz$lv;@*(WzO%KnY-h~ z6~F=>4p%scci^A^KAhMTUMM zWTZyXr-eQZ=|dVwx$Lu8^jSuqn)D$Jq+IrCqR$fUwF21k^wg00 z5=(^Ce0hD4{TeZGH|b|d{E|`wB{-{|W1p$Ae~DFUd|r7i+JAj8=mCTM-DrP^VqOb( zqw7i7i{7T&D3@o8>)GOZ4(3-nz4mgr2Pd;&KL@i-uP@ZTX1k&R*_D?l`lR^+U}LzK zh1zVWH9kjmsFF-YaOY$7RWf|tn&y?#s-*V<>puFXn;@RoFa!AkVDKZvc=i;!gS%C) zYPL+zvIMdT>%m>m`{bH#WzV`dTGXmLfp-y&c?(bXhsrD<|5qr)#(^l$(%ZJgw8|m@k45S( zv4@!N>Xqci9%KzMhKN}1MZ;mzkKtTK{q5wqD(kN{_=gusxU{EaSqzN&Ei~k2cLvAB znp^?0L$ zFO6P|sw|mv7fa-~CQC%F^AjwRKU$evqykmuLU!6q+DBO?sy(d0|JHZ151?#NA?+*K z4BQVVo)i2f&9~G!ak1Sk_(?2nSyv2o9=H6s$3#CtF_2Slk1@yre-ODzb zK({^B4|lt9*h_9EJ?%<0dV^cK9&RCw&Kr|AW-0cGKpYwCyug6qS0eZPqevvdbWNOBi`j((h<;+dR^jD z>mBFrXt@-)8GChXUM}4T8trx1uXzVldz}O&Me&zFRPjFdcS2u6>n=`Nv%s*t#$D@6 z#INcH))V?#eX_Zv*pCV~cTnDW{Ftt6>5hskis0_u0I4=6*^GN6*?d^>^H*Mf{WXcF z=kRVW3jI|KeD5d}&LnKn*cEHUICCx*J@myKwg_f*k>>4oReZ7 z7sbltza)WC#!d zEP}4vbTMwT`*WE4zbDBy;;o z)?LH2b{R6Om(fy$XD6KblRAlj3bCz>+-{Rg3^;iLM7>5rj4%D8Qz-Hbo2c_pS?NZC zeAv`6?lO;iY)Xi?{ii?R@%JybAJFLb4*$-OOubG*LCW1I9S)J*;suEM9>{~0o3o4`~k^#NbZ2- z=4I}qU~g+UKyEdW-4)efiw85=fyJCg^^^hihajb;e4LDjN$4C!ev9!QkF6)P9oHB@RSG;^eOc;D+JJ(Bz3{59NF?V-nLNsGXYKc>FL ze@=~q$fyJ#@1WsvKJNsu&myx=ZU^VwVHdR$u>DI(2dkpyf(zm|XO*4PzXQ21X50Os z!0Z)4VL@W-)xZ&>Jeec3kY=T1c*mq{UUFw5%98e%+6K zjtuDq?kD#;g7+2HAe~~a#aP$Yb5A8HAW}oz@8DHV1k41$)O)CRpW&1X^Vd;@VJBp& zKO>o9*2FEF5io*~I5H9`<`rzgW#X-AoYA{Q>W|oK4P>J=4R6Yn{Jn677@SggOPq0# zyIGOMF>*K}fEsC>yLGorzRz*~tKJ+ni*=oXNV)PDSr&EzBFsl%+K@B>I4}o~tY%Td z1`A8FkpeCj>oj1PnYV+?IyU2At|w3dp}_y(2g3LJ9)?Hga7r=153c$X5$7a;H)+0#60~9_Q&n6tseR*nZT?*#eFtp}tto!2gwQ{sjd^baSN~de+~% zzj{)ZZt!U*>iJl+Arkg6^(;N7bT-71uL!CV=Q~C{F8d^_}P!>JS-JybMko`>UL5$h-5(y_$ zE8;sSius^VQYc*907=R)jmLq1|BZrO>N_^TI7g|GC6|{ z3xrtS*g-}V+gb=;@Pz~|_m(qF)wHcqvrvK6t-XGSTavKJdOrRVcUC_HDUIYd${V#J zKO^(>IJ<}vc2Po36O$M2-%BI^f%DNsC*YOY0Ak@|0ca&sFwjLk55xRl`aXu^R^B$gsZnn$szC0(%9OtrD3KtMC3>%7TD6JbbId%pyZ|9855BB7 j?_a>9>+Qdwfn+V_gWg`tZavoeg7K}^8C=&NeExp`{%f=; literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/movinet.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/movinet.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7a42080a923ca83e17b5c84dadc9cefd034c6bd8 GIT binary patch literal 15202 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/ms_tcn.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/ms_tcn.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..88c6561cbfc8d680e9e9b47fc69cf0364dea6be2 GIT binary patch literal 4723 zcmaJ_TXP&o6`t<7?CfZDu_Rk^9K&L$a+Y8bJKPeCEnBh!*x3Y>7}!#n8cokiBhAiA zJ+ro@T2-Zxt8Ae1K=B8(ZwUSj4?OiN58yYdc%c%o_)gF6>SDvF=1lkL)4koNzw@1L zwMR!i1J9rB--<7$4CAj?Njd=VnUpGVu&*lU!UGH8)u=J6jRVl^)=_B(fyg80sXW%3;o$b zzsDN0f-M=f+2>f9QLiyo{xFb1>sFr2=Nu~1+`hGN@Ae1vJ4>ik9!2r$TJFbbockf8 zUj3(pFZEc!oBakNH@e0;+he<|%LLmn+X-($Zj>Rf)A+J$-E*yXxpp=5S>*KG17 z-B-6+!!}!(yH3~GH+$HE4NJb$H3a(5yKnUjv{_wennttrcQ{tfu1ga$+Ies{NUL#L z4N_5UqS)@_)ezsbomW?)YS?aVcJfG62T!vtt9g`W_&kd9wQ4hZ6hX6wF4w9eZlNh| zr`dDzgCtS2m6=4Tva_{dGg97zAn8PRq-;xN!d}^Frxhi&l5&b+m3K6Xaxf)0R+Z?B zsi|>TLxDN@%~r6PsR>e`xHH_((s zSy6oJ+VZAshf$Vk?ebFV-I5N@orQ}k(NejcWCo7?K59|lR- zNrD_dr6=mcjk<^#y^i0@z69Yhm;OwTq2zi0@|eXcY@*O|c@`!i!DR4I*}hs-*1{E{p;h=i7<}dLs%kjltB|krP*gIK2v8b`HXYn_O}k{?0Lv zQ{6&{&;-Uv%tC|&;=x0dMZ}~XCs3ex+hfao*W9&q#Bn*=HFxclcdcDJXZwi09@}+t ziVH`WpYh#Nw?z7`-D4MwU02({&0QB!RL-q+d*A7nM~rS6F<9!Ea33Oxrqg%V^t_~v z@7LVk~=}h*<f#9Vqa+@-~qw`(F9S&06WS zSE?9Keucy(6518E{3^-~cO?!oAKo}}fxJvc6w$|kRMrek#vh^~BcxWiUP=wc5bud+ zfSiAR4eH2fAbcA9snG;83;x7yn3RN&OsuDdWi)KsX*IC~Hzv_i9;`<16E%e7kij!> z5RI(okQ+Gz0{K4gAr0o{zST9KA((q+*YIuB9sPS;m`~ii)J0}k1YUtQ!*|L08Qj;m zMw-M7thx@s6Iq7ng4{*k$jEuCK>a79yNp5}`Nin6DdQRb_RJpp9p3_p)R+$8nyIX? z4V1YeiZ*p=dNC$C6F-fzSagEqey|-$gfyRfOR@NXDUbNJ=@a)JbG>&xiL;!N#f@c} z2F=GYIG;Xr4tK7ccG{d@BujtpdeTPpXE#t7^hW^LS!Xkn@=Xk)+<`4ZCRNTtJAHU{ zQI$e`DKV7w1n;A>vJpmf$#TAJ?w#xL#U3b=QJE(UZUKO5JyB%9N;9QVf z--3ajO|kIrQ1!bIs-khG%_E_ANtG65dy{shB#J_Rw`83<}A2<$nUrYY2>{` zw%IRk`k>fy85V>|WHh^|iULiq|R^#%U_$ZbgnDQoRHQn8y(h<7e zMs*KwHUR;$Hmw&f;p>nSXp9&tem7l6mIXe|E-BPV)rj3GcLJ1k8*=?-=QF zoSq5yNW|+L^gDwCqCT~BaU`UJAQ5qHuRBD_g>92#GwFzEZs8C~o3}Gl)jwbDqt+W- zlJv!=a1T>f@HozJ;Q2Xbpvs*z+v-HoP9!Oz$d5=_%G%Am6+Bi>arICRI3)~_xlTov zDuFI=)5+um>imj0`!)1BOL_XbG09#dt{*MD)Su={kQ+LQayL1tXTT+w0XuML&ezR7 zF5kp44!9;HuUmU;zeMiqF@`L*4i@b&ZQ;VAOctcYxo2p#Wof+gI<9g_JILR@hCE-+ zIxGEb?ZsJ~0uE^y6~NKl>J%qo7)H7OkS>n;RH~dH%eQfvv{rD~lXSWRWgT3RrY;4N$H^06gwCNI$FZ973;Orij{l4I4<0vtA9pgxnmW0SKojkE1dj}yYN|l ShBNPlJ3d*OoN}gS*?$2ve literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/pptsm_mv2.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/pptsm_mv2.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ed5a0fdcf837fe105a1d2f0343da5974d7f3607f GIT binary patch literal 6496 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/pptsm_mv3.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/pptsm_mv3.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c701ace18954a1a8c6f958b6d04002df9e098423 GIT binary patch literal 9847 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 V6UB+oO*}I3;zTij#GD*g{}+O<6(0Zq literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/pptsm_v2.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/pptsm_v2.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..19c44f44ae334484ba865b1eac950ae3595b9dc9 GIT binary patch literal 9793 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet3d_slowonly.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet3d_slowonly.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fb791abfe780e6ce5fdc4333c08cffd54c463291 GIT binary patch literal 6053 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 BF46!1 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_tsn_MRI.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_tsn_MRI.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4825ba0bb44cc54963e43f918a79df91350d697b GIT binary patch literal 7560 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_tweaks_tsm.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/resnet_tweaks_tsm.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9181cc7ea9b9bc58a2aff0dda2fc1a592a1b3e2b GIT binary patch literal 8256 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�m*s}5GZaZ-<)+VWI5x{sj^J3e&Qa^cJtLA}vQs3YY;{lr z^x?lnE2!9;rzVx6a5*?M`@UI1(nX&Zp)bLz{7;vj7bK0*<`2+|aH`fN*_TSd0TRe>*nNEmnuVY0+h4+c22L}L%VITJRp;L- zPvcUzs;+!z{8c>2-wJ!_GPI|zne>V;QeZ|olL~S*;ef)V-zI<~DKF#A2xK;=X18J#$x~M>?LxN6HpNUrAca(Xp hCEZu*tJkZfo`P=BtxijMXp1cy?&)Q3`GwZC{{Z^`H4Fd% literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/stgcn.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/stgcn.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec6d4cb1ad4de26eb594d18f9feaa8540973da3b GIT binary patch literal 9884 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 XKX3yt@Um0EbRjoao_ofB?Xdkn{ZB^b literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/swin_transformer.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/swin_transformer.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c45b075ab28125fbab9b1a9db29dea3a7fc89b8c GIT binary patch literal 22182 zcmeHvTaX;rd0yY2vGTr~mU`zVn~%jEocw{Qhm`=e@757{<4FG5E{i z;zb-m+cXT%@XVI6V$PW>)|_SX+G^P=&YUB0yOo*CBF%2)=5lh*uN3AAab9tyU>T;d zQkpAEiqjfdsmxUn&v@C^=*rmK7~(lE-`cY>J~uA$LTh4Wa&FQz{EAofO1I6qy@-`1 zHsu}hD&FY3=G?wd8Qz$;=Uv0w;}@2uH|)9nNE!DgkTMac9PlQ+z3&=x47ubPp)vf7%(Ie)Ix4#Ijnyl1ntiPD|AS8FVH!+Tbo za`w!*&zyaI_N9x+9tqWIyHRU*)JnZo`!;XEA96C+>aA6OL0|vL3l|z}u>Z>;LSi_F zBWNM$nVz|91=*ezgn40l2w=JY)P$S#Rpl+sTZ036Q9kZ92G}g1dEQTUm|2XLHyy|q_ZarKK+`|{c zPGhkigw2L~-tUHsRk!OaH>j_4TfTev`l8=<>)mdv>3eRo?XJ`ju%_FYcaW#N?Ki?h%&)s% zbAH}eemivMF`{hVLoYk4A#YoE1HW5W_0Y%7(Z87)eXmDRH(2!>os|{TJobrGC!c-# z$DaMf({8`OMc+ruL1Q%tnw|D(cQFjR!Rh127nXjK(JRbV(prhtno$JTL?&@)A zFgX6yvroy>s1jb$J&c*57*tI)BBvz>#0qe9rJ>9(Rwu!vqpPTOm) zM2@PrJyk)iD1*CnRFw6a*P5PR%|+&osKCdpbyep|ln)h#7h@C^mVI9*sy(bY!Ztc9 z{r0mMmhNhJ*H8zM`<>7Gr{6kTZ!g#8n=L=k(Gw@%LYoag2qg6_-AUfI^VUko^IN#h zTUY9hw>IB!D?HX?14mkQ4;O;y9p7CYlF2NXra@H{`=0oPBS;X0~)I&&Y;28Qj z@l|jH5#N|IJ!8)D%sJc3-6Rp)p7U;D&LO`7zsTG)9Al2enUC@$jL+hZYdfrURf(F&cP%z5ZYItQ~ zt)}+j5?lzI?l)FTL9@A6dn|j7 zmG~M$>CzIqwPbC8!zmYuRa@SM+*KD2La4y{^0;Lvp~!A2Zj+ zl3v7_((K(FpON#pR*QJNZ) z<1rSIq2Lfci6h7($QvLoYs`^>-JPg7bVEdCd6w^h|Jn17kQWFG9u-U4=13riM*Z|j4o%YPEO!Y<<&G&zdbKprE!7PH%*Z_AHny|b1 z9{6+5>Xvb~LTl3oomh9kt!v=O8wSo9NwvU(nVQ8_j+`0sJgG^)wt{*XEz7t?R=XW# zUv0Mix{B=i#*>j$6AyUoCyNybiw)1{HTm>(VMi-l&=MN;5Q9jKs zpskubw)zC`D6c_YNJ5s+^Fhg~irKuG#}wxQ(kNr#cBf4a&pFn78Uch3s1xD`kGW|k zF$lCc4Z{@2`e|l=C>%v%P$wBk7f&(v1cPDv6#{z|=|LGm5pziY9doV3uEqphEvPCh zlMktnGdRlNID*Le)Jv~^KBZQ5j5+CDQW~8>#&bAi=8;A%+cFWFmG6#K6my3rD=C?( zpbUsY1e4TwE3m>VLG3nJjUoxoQlS;abNll(C%4ctF6&qn6?$b306FGc3L zC>M8lfIK*3qOrJ6GRU7tYA}vqtl*dj&1p0H{jxJ|TK6F-UqNyM$Iy@6;4dJ#^_iM5 zF%ZMMc}PskN@EU;4NNS9SDT6QuV9YjrM}akLel>+&enKH7luVx%5H4UZa$52Lj8A5 zEhU8Dhq*zMZBaOkLqzrOx;q)9edNn?99mQG-Q@Ly$o`xkH;GL+J6(;9-fOag?-=@8JaK29N|nJpxrHV^OCRu zm$NpR$uGNyF>^6-U-p{|iy>9*=1P4bEpVw{;8N4mn!e88d2-)irw4h)j&oPNfWaM_ zz~reich!$G#NTVe8E5PSsaMGO8Y0xRHbl&O#;U2xxVCWZgk}hlzJa{+#@o|0 zwR#zn1jA)h9f_~)UgkN}kh(`a6HFf0SH~sAP^Ut>XK!Gl=rclR!<@G;%dJ^$Z8(wB zY6fAHfo8toM|R6^M;T$h)ohf#QR91+afyn-Vsk!}gt^hxz>k@%PN*;;EfAT_EmJTW zUGT%fDjRrq(S)f6tLnPrJtKa;m`Z7K4)29BX0$Bw^XtCCi*3UyKnhYDpcL)VGU{m5fC;%VDPO4vFhyarhs|S)Fezafw&vY>zqEV! z(y`Yro~gQ8PsP*#1uMT*51ZFuJaz(+hVGSSJcYNt>*!8hwd+@a3P^>p<6d3$)jLPsWgme+9y5Rt=IeMhr=@1X zajq`cf<~Qq0u11K==R)MSe-+6dmYnM!8&z4-2!^%>N*%mcDlwPK61o8c4FoeZgU>5 zJxtoimb0TRJ=JV2rZ&X|4J2Z76wkxQ> z^nbMBD0yrg!K)zd0lR|Mfd$C{ixWB`Z3(kyA28PQy-assFYlQXkWn=-oTV&KB8xiW zB=o^)K!~_<`d3KfH8e?`J8AUnc`M8jB|?25O`8P|y695=4gkooxLHCR>c)PePKD$e z?cutZT%$c)mvCLiG14paioMbuYM#8V^va%d$66ohjVz6NmY2J2O3Yzw+E}mjDw|`F zk9o>RUU`5%zXbLup*?SB3^38SAAF`~FhpRW!{wZTa_HZ#<*b2n==ZMW;`?H}c;{pU zcm0F zGHRH3>f1jx`42z!$7{d*0#fZD^r{aIn7=mWxE5!HgqZPj@K`~?VIU)8Rx5|b2rQJs){@JmJ678Men6FKA*Q6b?MiV9_vyV#izSL!#ST%aS> zF|BA{My}Rn>MWPby+-vD&z1vM|~#}<>=^(d=zqe@(=|A2TF zE&6IYL(Q@2#~2Lj`oD&xU=I4VvBairlmY#lZq!IgD?%*@|EYSCV1=_#v>7I9dxDGqFt^r>+{*4Y1%;>bSF z;RvpPntLWpYFiuBm{x)^049h21RV>L7{)Wg0|wRZO$Q9e5{3f>oD2>jCOJarYPN0J z>$&y(dZCv?9RlSrp?i6$m1V6lW4(wRvdWy7>p5Uo63&A$Y+7D^0c9A2Zs*{NtgzH8 zN&SM{wL})VnfH(bc)kdxoP#F$<({>K6`uXZdbwAWzL#O@m)UQ&#Gdyo)N=3yX;l%nlhaY+e4F$99Gje=+3U->`drxkM>IEH>)kKr$P13@1$k;Mh* zLY^!tz^K5Vm@tm4m!B_*(NXYejUStQB}z2cPR})5vo*?u>=D6&GfK5BtZHr9LF2jr8T*4yMNc z^Oi>X6d%IM@OQ8R$lwx*gEF26x8OjquPZ%%P!S(9GE^W=qLV0s-sJYZ&?BAco zq|v)E`z0JCm=F?#c_+cQ$p-+ozW9c=u`V>YbkYA&1uWpeoHYU$l|InO!V)@+DoD^; zR&C!Uus)<=pb?V zOHv-!DF4>>^3V!^Gofd>5KB%h3-d4wEu{c+FmoGvOAS)r%Pu?WS_rAXVYaQXBnwdG zr0z&qAv!e)%xb+7jv`*^l~6x-n@>I_hC^PXPHXM}pIBK9WCi}ju>oF_+5lLG5?D?| zUVxESA%jGL6(In*`7~3XVel*iF78zKq?*6F%v5Pan!AY0sF1LoC`0OcQUrqfB8zh2 zP|#di^VIn#BOADftjNHrqt&gB4k+BiZL3?XpY~T4o21iR(3U<%#gw8W0np$!0%wp8 z?lD(k*W%SS+AKRL)O$>j9Yue!q7`a}Q&>96L!IW~+@FGiyxUdLhN>;1Pz%KTcc$}2 zD9-(~^80Ha+gVEOtV2(uC)8Wc;RyZ^eWRNR^*z!xmNCsG6N^-`Kt+8R=w^mAHV?xT z+9qgj!+y(JFNnSgAe?%lXFA4u2}c&5nO`6bf!5?4=OJavfKgl! zjU2ShbDSr!^|3I!lmnfXdSjsC(cVa}G7rri6mL^Ujr+T2eSCcacx+xT_x6hC1(j7d z;TTgu?IQbCGH}Kn<&4%##=Pz2y#iXA>{;u3+W=YCCp}|*FXqo=udrdQPvMzMy{X<_ zuXx*9-`Cr>32&(dlXGq!dc0`%`@)glKBU;aJ-zYX#71^~68$K1**WRQ?@K=>bw6}3 z5TXxB4=`JMlX#*E+<=_mk9uSAd6Z}MZGZ$ZNYcv?D(Ph<%=KZDc~~*A&OV~&Z#p}p z%FP(#_UGnN-y$0F7QV)mLjQ~Dr4vF)7B$6)zfO$K|7CmFxc@yprS1k_~0lW!7 zHO8#yad)lAnmM7Uf(__(vM5$~ZozN+H@fQi*HQjGBEr_sOc`s>>_V-v+9)fPPtH6C zO{?Ato}Wot8A2RH-?pNxFsMNN1R94&&QGx$#36QlGWAO=LQPY5_m`7cY6bsIq|vxk ze+!XnMIZ#N*%Rv4Y>s?M{S^d}c_FglQ-cNi_B(L#>9kt1!l${@i!AmUg6i~uVqc|8) zK)zRlf03viy!Bk+M&AOPD@&?o>A}`lI5PB3Uci_HRK@8D0Am0wt7w;DFz`PqcKw(& zZe@`x=7W`eKkGOa*q0y!6`M9c+1)tI3Sa{YlKV2~OkLbO9qe3CAjvKBe@;d*y+Xbp)J&qI25 z0ugZ&5w8fkhhS!bpK9I_9au z)TTB1Evs{>F3YL|Gt5xbj|pCVw1j$SmJroxvYpIDf$mf!V5lT(>|7E`&``;KTm2eoo5d|9`z8A4v}7r?H=SNyul_7xbw}8mu^B6d zU})I^C@~L@p$prf#2-C7(`elY-jTKw|0-jD4M7a&<+L>a6(;{G16qhg&f5*h>N|iGf3SHD5C-QLlz6-8Cf?@;CK?pNgSuP$QI!~zd&lEb~TorhGPGi zdBi$m@()K^Kx*KAlS9-O3*fuE`>(0rWT#|09AfMkgH);s#S6stHDr9TPwZrG5nAH|2Qw%yZs?FrkWZMP^K@Xzc-A_c7<+I)rw+YAABZ>(>|3Y75waim z;6OWX!$0CP>p3YYns{7GYvp29qa|HS(vn)o#R`!n$>d(5yQ6(M$F(G$)S3X25BGPi zGZV>&Wg+_WJUlOe`J2zc75?fMuD*Enarj$g;D2GkrYUYZo<`G)o0y)!-gyRMk44K8 zoa{)@r8{6-Kh zuXR6vf65jeZ^x?xHp+a@df&;*ijXxat2}VC`E4}Sz%lfr^ye>l5y7Cu^imub97jBR z;XySId={?bbQhs-FR|P~8Cr^pXX`<;A+oam4I4P^85gc1P+h224B@qcWQlTvA$GAg zxZrO z`rZIWclgPp&m4Uw-j~5UCx}W69DWoaH-+k+O8fQyLER5>JxTTH9{|*amyC9^70&VY z5H9;sFy0i#`Y6C`;>fcNmn9v+wYc5iBGfOilUL9Aw49!GaQ>m|k`G@dnH>H$T$!Fh zGO7B8e}ez2o8T0EcbY+@mvJ7L^+xb>2vX(qR_RuuW`(v#e_G>KNuxtZ1BQw)bE}9j z8|F6iH;tR-P3xw8)47?snZ232nZH@MS-e@AFH=>0Hy;-0`N#TqOw=j%$_UZ=Qc1k~ z&f(g;C7ZCAPBm6k+3f7DpoAy{gK*0MBZXVw07*?#!!2qzyyCxtQwv_P_C(7565VwN zG-X?7xbQZ?ar-QS1!6yst(zg#<6GHVSQ++!$#Hv{8uP3+Mr_Hv<=o2O%H6VV8KHH{ z4k164dkgsCexq&PvTtETJ^Oa~7p<%GV{`^qQ2#P+0Nv^`PFs-PKLd@u%^JVJ+Kw1s zBJrYPGib_wJ&4a)mf#rOEoG# zpfV=8h*OD+bD=QOIV8zNoJt=iKb$zA`azxC$N=s(mH;#ZCWQ|h6yy;ok>=Gepf@Ef z%}8Ih3kTpGW2x+A;P7!BR#D<$A-xv&5&}R}AAj^V(z(PZdq4pY%jj-K8%Sg@+V5Jd z?Gau|Ae^UPD$PsELlfmI+z}l;!;GIt09S-=sL`dJY=>*_8aa|YuE6i8*LDdu#XbYt zQCQasJImPYOPBIN74qcKr;a`~Ktb4WMvvwloQ$>qk8Ckb)Z>AcPNiC-cnF9??>0|m z>`R58u}fz<><#9^v-Ygrsl{iXPMiE8wVXujxErrJ3)M@I#e2GU8Nuw3!A#?sSvC$4 zo~hD7NO#zWH_X6+Om>w(q?)qi3MVpA93F+c7d8Q)MqVoo{TMa@U^{7P*;nu$m)C`L z53C(vH71Y?*5-6rr^yg3f6 z(^$d)aV3y8wyK5}Rv)3e_0tDS(B)bG0iX$-2xiKy@YoiYwD9SE3oO~s8!V+;8EAp4 zow#Gt!t!7XNh`=Fj^8giZ49&kZ@U=&;z=bNE#kO7z(<9m4x#QR zNKrG0j8SO-BnAi3?~e;OHXJKDMe`AIYtv1EvOb-~+!~tUzh-!645DIe_py>L8Hj2yFnG~+n4`bBKjo2UARhRs0&Mr{wrGEyb}w&5N3bib>8rYGEH;TNya_EE zJb2LEZ54X=f_sr3W7r~dNj8`TmtFT*0)@EAXBO(}M)TTCM=c!hdh^FmK6&EQ%#%-@ zICWyD)r^#ni342U{1piSoI=Z}t(!^u|jYgdk0Q^b)$4HT4}ze+U>TX+x@GDlF3Ba^Q}CHsW(K?QyCM zorZTbzfZHp?QTbOC#|oiB3seUnp@uwbJ8~JU>6hwuiGrsnH2QFb*g2m>f{0V3idbR7J+1)WqaLKb z#NZ}^H^j$n;a7i!zdv~4g7!oiM^68@7ZF~Is`w&g?^acjD-ogs%BOtbhltHWwJiLe z;Pc0Q3D~X$-KB6)T$#X@E2CDSSbEn8M>og3Om8II z!}jlBEe76y<6(Jo{0@+w+C(^smayj(rtI_U6XD))3QB3VH!%UD7yZffCd6-xp{%6D zM({Y>gD29&m!Jh^csjk?jWOlb&~wThOfohFfN*e~(47@eN;R z%GVhX5s+0!tY&q)z<;AMJJ#PVA~s1>sma{MUS(ki)xBE1{7M=1u+!0|H<8@dYrq$lGionl*zqGDtYOT)V_>dl;JXQst>#<>pFv3*C4U^Tj4m0%4q^I+ zg|hqBX*K0~n9=YOwd1zzZ7n@@_3;GrcC;Vj8)A3BMvzhcCi)dQWZW@)MP)+qM#4yPpWi|M}p@O&@M&`;^YvRA7$k+H94kE(+Dg0~=m(_{$p77Ceva4NnG$_0QBMji`FkI}yL|hws`$Kp> zEP>f-M#UkCYvoYuSei>$ZnECAT-BacZ{seCw}OfP4aSc%IKiNZAj;|;%aL;h`ze*j z^xtH9Miz^~xj02}-*A%8RL!^lDMyOZh>lnC6)$Ydlk@j?B)GWR5Wzu& zi7*p_tscY(upE{R@Z?w`VBE7-ji5SE z&Qc#|UYPq?vudw>Dp_#=lr=5;cW@QCcE0X7Tm13_q0jj{4si5dHSZxVXzzaSN(yc2$lE6SJN0 z6@Ffi->mb!mz3%#^%+*$^3KXK_HlQ9hwqJswv{Uj_M-P_jbVqDL%VpZ`y6O{u=)^X z+h`_X7-U}Z_VDhAS8LZq#+JwcvS0vU7Em0_t0NGaHmqFpEB&&4phKtYZI&90u-Eo% zbNW&Lf=~Ge2mn8QlX02v-(u_xgWo~`1x=_}K!yLo)Zt+fbobwLG-$wcp7W?^8ph7F z?MyQU35JG%lbgf9Ll{T;y&PgUn9>G$9Eg0lwiu5v|C%;z=7hY+$Q|`7R24i;v2;H3mQ0 zwSC(kPui-QZ$Oo(qS#JfyBhEo;ypEqeuptaF^ad@-Ghido@FOaA_Bm~vi51QwN;E^ z0W214mH(N4DPPGK@{>~|^2B(`5^7&iF2d@es33bv@yUrm@lDA0n4)|KpJS_sm<@bf zZ0cBD>As`>CG$s_K%XnX7c=d)1~n&>>zV!*RZ5pMu83nrd(&c^5%GR^1<(ZdSjCs% z0zEJDdf&HtM-`Y=(i2bkrf^@)Z{I^+yy@gs?w8VAQ3zyd2k=ib_8NoFGkBB1y9~a@ zfUYoFArcKMz9m}WAP*3_ki2Hx&w()T#l7drbOU<2j#VJi@DY|WfU~k$235%BOtWZ@ j?-?)U_m5BH^TmnrvGEn-r^hYl5LV@;$1i1{o;Lq4@u;q} literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/toshift_vit.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/toshift_vit.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fbe323aa3e332b48afb47c23a91a77d3618eb49f GIT binary patch literal 10782 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 AmjD0& literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/transnetv2.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/transnetv2.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eba1461f9994864f88118d320d534a1583fd222e GIT binary patch literal 17837 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 K=j=z0=>H2Uwr@57 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/vit_tweaks.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/vit_tweaks.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2bd75fcc147f3b419dbd14e546f20141c4c5bd87 GIT binary patch literal 12832 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/yowo.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/__pycache__/yowo.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62100266dcdc6e53d3b3a131526515f1dbf969d2 GIT binary patch literal 4390 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 8,36,768 + position_embeddings = self.position_embeddings( + position_ids) #8,36 -> 8,36,768 + token_type_embeddings = self.token_type_embeddings( + token_type_ids) #8,36 -> 8,36,768 + + embeddings = words_embeddings + position_embeddings + token_type_embeddings + embeddings = self.LayerNorm(embeddings) + embeddings = self.dropout(embeddings) + return embeddings + + +class BertImageEmbeddings(nn.Layer): + def __init__(self, v_feature_size, v_hidden_size, v_hidden_dropout_prob): + super(BertImageEmbeddings, self).__init__() + self.image_embeddings = nn.Linear(v_feature_size, v_hidden_size) + self.image_location_embeddings = nn.Linear(5, v_hidden_size) + self.LayerNorm = nn.LayerNorm(v_hidden_size, epsilon=1e-12) + self.dropout = nn.Dropout(v_hidden_dropout_prob) + + def forward(self, input_ids, input_loc): + img_embeddings = self.image_embeddings( + input_ids) #8,37,2048 -> 8,37,1024 + loc_embeddings = self.image_location_embeddings( + input_loc) #8,37,5 -> 8,37,1024 + embeddings = self.LayerNorm(img_embeddings + loc_embeddings) + embeddings = self.dropout(embeddings) + return embeddings # shape: bs*seq_len*hs + + +class BertActionEmbeddings(nn.Layer): + def __init__(self, a_feature_size, a_hidden_size, a_hidden_dropout_prob): + super(BertActionEmbeddings, self).__init__() + self.action_embeddings = nn.Linear(a_feature_size, a_hidden_size) + self.LayerNorm = nn.LayerNorm(a_hidden_size, epsilon=1e-12) + self.dropout = nn.Dropout(a_hidden_dropout_prob) + + def forward(self, input_ids): + action_embeddings = self.action_embeddings( + input_ids) #8,5,2048 -> 8,5,768 + embeddings = self.LayerNorm(action_embeddings) + embeddings = self.dropout(embeddings) + return embeddings + + +class BertSelfAttention(nn.Layer): + def __init__(self, hidden_size, num_attention_heads, + attention_probs_dropout_prob): + super(BertSelfAttention, self).__init__() + if hidden_size % num_attention_heads != 0: + raise ValueError( + "The hidden size (%d) is not a multiple of the number of attention " + "heads (%d)" % (hidden_size, num_attention_heads)) + self.num_attention_heads = num_attention_heads + self.attention_head_size = int(hidden_size / num_attention_heads) + self.all_head_size = self.num_attention_heads * self.attention_head_size + + self.query = nn.Linear(hidden_size, self.all_head_size) + self.key = nn.Linear(hidden_size, self.all_head_size) + self.value = nn.Linear(hidden_size, self.all_head_size) + + self.dropout = nn.Dropout(attention_probs_dropout_prob) + + def transpose_for_scores(self, x): + new_x_shape = x.shape[:-1] + [ + self.num_attention_heads, + self.attention_head_size, + ] + x = x.reshape(new_x_shape) + return x.transpose((0, 2, 1, 3)) + + def forward(self, hidden_states, attention_mask): + mixed_query_layer = self.query(hidden_states) + mixed_key_layer = self.key(hidden_states) + mixed_value_layer = self.value(hidden_states) + + query_layer = self.transpose_for_scores(mixed_query_layer) + key_layer = self.transpose_for_scores(mixed_key_layer) + value_layer = self.transpose_for_scores(mixed_value_layer) + + # Take the dot product between "query" and "key" to get the raw attention scores. + attention_scores = paddle.matmul(query_layer, + key_layer.transpose((0, 1, 3, 2))) + attention_scores = attention_scores / math.sqrt( + self.attention_head_size) + # Apply the attention mask is (precomputed for all layers in BertModel forward() function) + attention_scores = attention_scores + attention_mask + + # Normalize the attention scores to probabilities. + attention_probs = nn.Softmax(axis=-1)(attention_scores) + + # This is actually dropping out entire tokens to attend to, which might + # seem a bit unusual, but is taken from the original Transformer paper. + attention_probs = self.dropout(attention_probs) + + context_layer = paddle.matmul(attention_probs, value_layer) + context_layer = context_layer.transpose((0, 2, 1, 3)) + new_context_layer_shape = context_layer.shape[:-2] + [ + self.all_head_size + ] + context_layer = context_layer.reshape(new_context_layer_shape) + + return context_layer, attention_probs + + +class BertSelfOutput(nn.Layer): + def __init__(self, hidden_size, hidden_dropout_prob): + super(BertSelfOutput, self).__init__() + self.dense = nn.Linear(hidden_size, hidden_size) + self.LayerNorm = nn.LayerNorm(hidden_size, epsilon=1e-12) + self.dropout = nn.Dropout(hidden_dropout_prob) + + def forward(self, hidden_states, input_tensor): + hidden_states = self.dense(hidden_states) + hidden_states = self.dropout(hidden_states) + hidden_states = self.LayerNorm(hidden_states + input_tensor) + return hidden_states + + +class BertAttention(nn.Layer): + def __init__(self, hidden_size, hidden_dropout_prob, num_attention_heads, + attention_probs_dropout_prob): + super(BertAttention, self).__init__() + self.self = BertSelfAttention(hidden_size, num_attention_heads, + attention_probs_dropout_prob) + self.output = BertSelfOutput(hidden_size, hidden_dropout_prob) + + def forward(self, input_tensor, attention_mask): + self_output, attention_probs = self.self(input_tensor, attention_mask) + attention_output = self.output(self_output, input_tensor) + return attention_output, attention_probs + + +class BertIntermediate(nn.Layer): + def __init__(self, hidden_size, intermediate_size, hidden_act): + super(BertIntermediate, self).__init__() + self.dense = nn.Linear(hidden_size, intermediate_size) + if isinstance(hidden_act, str) or (sys.version_info[0] == 2 + and isinstance(hidden_act, str)): + self.intermediate_act_fn = ACT2FN[hidden_act] + else: + self.intermediate_act_fn = hidden_act + + def forward(self, hidden_states): + hidden_states = self.dense(hidden_states) + hidden_states = self.intermediate_act_fn(hidden_states) + return hidden_states + + +class BertOutput(nn.Layer): + def __init__(self, intermediate_size, hidden_size, hidden_dropout_prob): + super(BertOutput, self).__init__() + self.dense = nn.Linear(intermediate_size, hidden_size) + self.LayerNorm = nn.LayerNorm(hidden_size, epsilon=1e-12) + self.dropout = nn.Dropout(hidden_dropout_prob) + + def forward(self, hidden_states, input_tensor): + hidden_states = self.dense(hidden_states) + hidden_states = self.dropout(hidden_states) + hidden_states = self.LayerNorm(hidden_states + input_tensor) + return hidden_states + + +class BertEntAttention(nn.Layer): + """Core mudule of tangled transformer. + """ + def __init__( + self, + hidden_size, + v_hidden_size, + a_hidden_size, + bi_hidden_size, + attention_probs_dropout_prob, + v_attention_probs_dropout_prob, + a_attention_probs_dropout_prob, + av_attention_probs_dropout_prob, + at_attention_probs_dropout_prob, + bi_num_attention_heads, + ): + super(BertEntAttention, self).__init__() + if bi_hidden_size % bi_num_attention_heads != 0: + raise ValueError( + "The hidden size (%d) is not a multiple of the number of attention " + "heads (%d)" % (bi_hidden_size, bi_num_attention_heads)) + + self.num_attention_heads = bi_num_attention_heads + self.attention_head_size = int(bi_hidden_size / bi_num_attention_heads) + self.all_head_size = self.num_attention_heads * self.attention_head_size + + # self attention layers for vision input + self.query1 = nn.Linear(v_hidden_size, self.all_head_size) + self.key1 = nn.Linear(v_hidden_size, self.all_head_size) + self.value1 = nn.Linear(v_hidden_size, self.all_head_size) + self.dropout1 = nn.Dropout(v_attention_probs_dropout_prob) + + # self attention layers for text input + self.query2 = nn.Linear(hidden_size, self.all_head_size) + self.key2 = nn.Linear(hidden_size, self.all_head_size) + self.value2 = nn.Linear(hidden_size, self.all_head_size) + self.dropout2 = nn.Dropout(attention_probs_dropout_prob) + + # self attention layers for action input + self.query3 = nn.Linear(a_hidden_size, self.all_head_size) + self.key3 = nn.Linear(a_hidden_size, self.all_head_size) + self.value3 = nn.Linear(a_hidden_size, self.all_head_size) + self.dropout3 = nn.Dropout(a_attention_probs_dropout_prob) + + # self attention layers for action_text + self.key_at = nn.Linear(bi_hidden_size, self.all_head_size) + self.value_at = nn.Linear(bi_hidden_size, self.all_head_size) + self.dropout_at = nn.Dropout(av_attention_probs_dropout_prob) + + # self attention layers for action_vision + self.key_av = nn.Linear(bi_hidden_size, self.all_head_size) + self.value_av = nn.Linear(bi_hidden_size, self.all_head_size) + self.dropout_av = nn.Dropout(at_attention_probs_dropout_prob) + + def transpose_for_scores(self, x): + new_x_shape = x.shape[:-1] + [ + self.num_attention_heads, + self.attention_head_size, + ] + x = x.reshape(new_x_shape) + return x.transpose((0, 2, 1, 3)) + + def forward( + self, + input_tensor1, + attention_mask1, + input_tensor2, + attention_mask2, + input_tensor3, + attention_mask3, + ): + + # for vision input. + mixed_query_layer1 = self.query1(input_tensor1) + mixed_key_layer1 = self.key1(input_tensor1) + mixed_value_layer1 = self.value1(input_tensor1) + + query_layer1 = self.transpose_for_scores(mixed_query_layer1) + key_layer1 = self.transpose_for_scores(mixed_key_layer1) + value_layer1 = self.transpose_for_scores(mixed_value_layer1) + + # for text input: + mixed_query_layer2 = self.query2(input_tensor2) + mixed_key_layer2 = self.key2(input_tensor2) + mixed_value_layer2 = self.value2(input_tensor2) + + query_layer2 = self.transpose_for_scores(mixed_query_layer2) + key_layer2 = self.transpose_for_scores(mixed_key_layer2) + value_layer2 = self.transpose_for_scores(mixed_value_layer2) + + # for action input: + mixed_query_layer3 = self.query3(input_tensor3) + mixed_key_layer3 = self.key3(input_tensor3) + mixed_value_layer3 = self.value3(input_tensor3) + + query_layer3 = self.transpose_for_scores(mixed_query_layer3) + key_layer3 = self.transpose_for_scores(mixed_key_layer3) + value_layer3 = self.transpose_for_scores(mixed_value_layer3) + + def do_attention(query_layer, key_layer, value_layer, attention_mask, + dropout): + """ compute attention """ + attention_scores = paddle.matmul(query_layer, + key_layer.transpose((0, 1, 3, 2))) + attention_scores = attention_scores / math.sqrt( + self.attention_head_size) + attention_scores = attention_scores + attention_mask + + # Normalize the attention scores to probabilities. + attention_probs = nn.Softmax(axis=-1)(attention_scores) + + # This is actually dropping out entire tokens to attend to, which might + # seem a bit unusual, but is taken from the original Transformer paper. + attention_probs = dropout(attention_probs) + + context_layer = paddle.matmul(attention_probs, value_layer) + context_layer = context_layer.transpose((0, 2, 1, 3)) + new_context_layer_shape = context_layer.shape[:-2] + [ + self.all_head_size + ] + context_layer = context_layer.reshape(new_context_layer_shape) + return context_layer + + context_av = do_attention(query_layer3, key_layer1, value_layer1, + attention_mask1, self.dropout_av) + context_at = do_attention(query_layer3, key_layer2, value_layer2, + attention_mask2, self.dropout_at) + + context_key_av = self.key_av(context_av).transpose((0, 2, 1)) + # interpolate only support 4-D tensor now. + context_key_av = F.interpolate(context_key_av.unsqueeze(-1), + size=(key_layer2.shape[2], + 1)).squeeze(-1) + context_key_av = self.transpose_for_scores( + context_key_av.transpose((0, 2, 1))) + key_layer2 = key_layer2 + context_key_av + + context_key_at = self.key_at(context_at).transpose((0, 2, 1)) + context_key_at = F.interpolate(context_key_at.unsqueeze(-1), + size=(key_layer1.shape[2], + 1)).squeeze(-1) + context_key_at = self.transpose_for_scores( + context_key_at.transpose((0, 2, 1))) + key_layer1 = key_layer1 + context_key_at + + context_val_av = self.value_at(context_av).transpose((0, 2, 1)) + context_val_av = F.interpolate(context_val_av.unsqueeze(-1), + size=(value_layer2.shape[2], + 1)).squeeze(-1) + context_val_av = self.transpose_for_scores( + context_val_av.transpose((0, 2, 1))) + value_layer2 = value_layer2 + context_val_av + + context_val_at = self.value_at(context_at).transpose((0, 2, 1)) + context_val_at = F.interpolate(context_val_at.unsqueeze(-1), + size=(value_layer1.shape[2], + 1)).squeeze(-1) + context_val_at = self.transpose_for_scores( + context_val_at.transpose((0, 2, 1))) + value_layer1 = value_layer1 + context_val_at + + context_layer1 = do_attention(query_layer1, key_layer1, value_layer1, + attention_mask1, self.dropout1) + context_layer2 = do_attention(query_layer2, key_layer2, value_layer2, + attention_mask2, self.dropout2) + context_layer3 = do_attention(query_layer3, key_layer3, value_layer3, + attention_mask3, self.dropout3) + + return context_layer1, context_layer2, context_layer3 # vision, text, action + + +class BertEntOutput(nn.Layer): + def __init__( + self, + bi_hidden_size, + hidden_size, + v_hidden_size, + v_hidden_dropout_prob, + hidden_dropout_prob, + ): + super(BertEntOutput, self).__init__() + + self.dense1 = nn.Linear(bi_hidden_size, v_hidden_size) + self.LayerNorm1 = nn.LayerNorm(v_hidden_size, epsilon=1e-12) + self.dropout1 = nn.Dropout(v_hidden_dropout_prob) + + self.dense2 = nn.Linear(bi_hidden_size, hidden_size) + self.LayerNorm2 = nn.LayerNorm(hidden_size, epsilon=1e-12) + self.dropout2 = nn.Dropout(hidden_dropout_prob) + + self.dense3 = nn.Linear(bi_hidden_size, hidden_size) + self.LayerNorm3 = nn.LayerNorm(hidden_size, epsilon=1e-12) + self.dropout3 = nn.Dropout(hidden_dropout_prob) + + def forward( + self, + hidden_states1, + input_tensor1, + hidden_states2, + input_tensor2, + hidden_states3, + input_tensor3, + ): + context_state1 = self.dense1(hidden_states1) + context_state1 = self.dropout1(context_state1) + + context_state2 = self.dense2(hidden_states2) + context_state2 = self.dropout2(context_state2) + + context_state3 = self.dense3(hidden_states3) + context_state3 = self.dropout3(context_state3) + + hidden_states1 = self.LayerNorm1(context_state1 + input_tensor1) + hidden_states2 = self.LayerNorm2(context_state2 + input_tensor2) + hidden_states3 = self.LayerNorm3(context_state3 + input_tensor3) + + return hidden_states1, hidden_states2, hidden_states3 + + +class BertLayer(nn.Layer): + def __init__(self, hidden_size, intermediate_size, hidden_act, + hidden_dropout_prob, num_attention_heads, + attention_probs_dropout_prob): + super(BertLayer, self).__init__() + self.attention = BertAttention(hidden_size, hidden_dropout_prob, + num_attention_heads, + attention_probs_dropout_prob) + self.intermediate = BertIntermediate(hidden_size, intermediate_size, + hidden_act) + self.output = BertOutput(intermediate_size, hidden_size, + hidden_dropout_prob) + + def forward(self, hidden_states, attention_mask): + attention_output, attention_probs = self.attention( + hidden_states, attention_mask) + intermediate_output = self.intermediate(attention_output) + layer_output = self.output(intermediate_output, attention_output) + return layer_output, attention_probs + + +class BertConnectionLayer(nn.Layer): + def __init__(self, hidden_size, v_hidden_size, a_hidden_size, + bi_hidden_size, bi_num_attention_heads, + attention_probs_dropout_prob, v_attention_probs_dropout_prob, + a_attention_probs_dropout_prob, + av_attention_probs_dropout_prob, + at_attention_probs_dropout_prob, intermediate_size, + v_intermediate_size, a_intermediate_size, hidden_act, + v_hidden_act, a_hidden_act, hidden_dropout_prob, + v_hidden_dropout_prob, a_hidden_dropout_prob): + super(BertConnectionLayer, self).__init__() + self.ent_attention = BertEntAttention( + hidden_size, + v_hidden_size, + a_hidden_size, + bi_hidden_size, + attention_probs_dropout_prob, + v_attention_probs_dropout_prob, + a_attention_probs_dropout_prob, + av_attention_probs_dropout_prob, + at_attention_probs_dropout_prob, + bi_num_attention_heads, + ) + + self.ent_output = BertEntOutput( + bi_hidden_size, + hidden_size, + v_hidden_size, + v_hidden_dropout_prob, + hidden_dropout_prob, + ) + + self.v_intermediate = BertIntermediate(v_hidden_size, + v_intermediate_size, + v_hidden_act) + self.v_output = BertOutput(v_intermediate_size, v_hidden_size, + v_hidden_dropout_prob) + + self.t_intermediate = BertIntermediate(hidden_size, intermediate_size, + hidden_act) + self.t_output = BertOutput(intermediate_size, hidden_size, + hidden_dropout_prob) + + self.a_intermediate = BertIntermediate(a_hidden_size, + a_intermediate_size, + a_hidden_act) + self.a_output = BertOutput(a_intermediate_size, a_hidden_size, + a_hidden_dropout_prob) + + def forward( + self, + input_tensor1, + attention_mask1, + input_tensor2, + attention_mask2, + input_tensor3, + attention_mask3, + ): + + ent_output1, ent_output2, ent_output3 = self.ent_attention( + input_tensor1, attention_mask1, input_tensor2, attention_mask2, + input_tensor3, attention_mask3) + + attention_output1, attention_output2, attention_output3 = self.ent_output( + ent_output1, input_tensor1, ent_output2, input_tensor2, ent_output3, + input_tensor3) + + intermediate_output1 = self.v_intermediate(attention_output1) + layer_output1 = self.v_output(intermediate_output1, attention_output1) + + intermediate_output2 = self.t_intermediate(attention_output2) + layer_output2 = self.t_output(intermediate_output2, attention_output2) + + intermediate_output3 = self.a_intermediate(attention_output3) + layer_output3 = self.a_output(intermediate_output3, attention_output3) + + return layer_output1, layer_output2, layer_output3 + + +class BertEncoder(nn.Layer): + """ + ActBert Encoder, consists 3 pathway of multi-BertLayers and BertConnectionLayer. + """ + def __init__( + self, + v_ent_attention_id, + t_ent_attention_id, + a_ent_attention_id, + fixed_t_layer, + fixed_v_layer, + hidden_size, + v_hidden_size, + a_hidden_size, + bi_hidden_size, + intermediate_size, + v_intermediate_size, + a_intermediate_size, + hidden_act, + v_hidden_act, + a_hidden_act, + hidden_dropout_prob, + v_hidden_dropout_prob, + a_hidden_dropout_prob, + attention_probs_dropout_prob, + v_attention_probs_dropout_prob, + a_attention_probs_dropout_prob, + av_attention_probs_dropout_prob, + at_attention_probs_dropout_prob, + num_attention_heads, + v_num_attention_heads, + a_num_attention_heads, + bi_num_attention_heads, + num_hidden_layers, + v_num_hidden_layers, + a_num_hidden_layers, + ): + super(BertEncoder, self).__init__() + self.v_ent_attention_id = v_ent_attention_id + self.t_ent_attention_id = t_ent_attention_id + self.a_ent_attention_id = a_ent_attention_id + self.fixed_t_layer = fixed_t_layer + self.fixed_v_layer = fixed_v_layer + + layer = BertLayer(hidden_size, intermediate_size, hidden_act, + hidden_dropout_prob, num_attention_heads, + attention_probs_dropout_prob) + v_layer = BertLayer(v_hidden_size, v_intermediate_size, v_hidden_act, + v_hidden_dropout_prob, v_num_attention_heads, + v_attention_probs_dropout_prob) + a_layer = BertLayer(a_hidden_size, a_intermediate_size, a_hidden_act, + a_hidden_dropout_prob, a_num_attention_heads, + a_attention_probs_dropout_prob) + connect_layer = BertConnectionLayer( + hidden_size, v_hidden_size, a_hidden_size, bi_hidden_size, + bi_num_attention_heads, attention_probs_dropout_prob, + v_attention_probs_dropout_prob, a_attention_probs_dropout_prob, + av_attention_probs_dropout_prob, at_attention_probs_dropout_prob, + intermediate_size, v_intermediate_size, a_intermediate_size, + hidden_act, v_hidden_act, a_hidden_act, hidden_dropout_prob, + v_hidden_dropout_prob, a_hidden_dropout_prob) + + self.layer = nn.LayerList( + [copy.deepcopy(layer) for _ in range(num_hidden_layers)]) #12 + self.v_layer = nn.LayerList( + [copy.deepcopy(v_layer) for _ in range(v_num_hidden_layers)]) #2 + self.a_layer = nn.LayerList( + [copy.deepcopy(a_layer) for _ in range(a_num_hidden_layers)]) #3 + self.c_layer = nn.LayerList([ + copy.deepcopy(connect_layer) for _ in range(len(v_ent_attention_id)) + ] #2 [0,1] + ) + + def forward( + self, + txt_embedding, + image_embedding, + action_embedding, + txt_attention_mask, + image_attention_mask, + action_attention_mask, + output_all_encoded_layers=True, + ): + v_start, a_start, t_start = 0, 0, 0 + count = 0 + all_encoder_layers_t = [] + all_encoder_layers_v = [] + all_encoder_layers_a = [] + + for v_layer_id, a_layer_id, t_layer_id in zip(self.v_ent_attention_id, + self.a_ent_attention_id, + self.t_ent_attention_id): + v_end = v_layer_id + a_end = a_layer_id + t_end = t_layer_id + + assert self.fixed_t_layer <= t_end + assert self.fixed_v_layer <= v_end + + ### region embedding + for idx in range(v_start, + self.fixed_v_layer): #两次训练,这个循环都没有进去 #前面的层固定住 + with paddle.no_grad(): + image_embedding, image_attention_probs = self.v_layer[idx]( + image_embedding, image_attention_mask) + v_start = self.fixed_v_layer + for idx in range(v_start, v_end): + image_embedding, image_attention_probs = self.v_layer[idx]( + image_embedding, image_attention_mask) + + ### action embedding + for idx in range(a_start, a_end): + action_embedding, action_attention_probs = self.a_layer[idx]( + action_embedding, action_attention_mask) + + ### text embedding + for idx in range(t_start, self.fixed_t_layer): + with paddle.no_grad(): + txt_embedding, txt_attention_probs = self.layer[idx]( + txt_embedding, txt_attention_mask) + t_start = self.fixed_t_layer + for idx in range(t_start, t_end): + txt_embedding, txt_attention_probs = self.layer[idx]( + txt_embedding, txt_attention_mask) + + image_embedding, txt_embedding, action_embedding = self.c_layer[ + count](image_embedding, image_attention_mask, txt_embedding, + txt_attention_mask, action_embedding, + action_attention_mask) + + v_start = v_end + t_start = t_end + a_start = a_end + count += 1 + + if output_all_encoded_layers: + all_encoder_layers_t.append(txt_embedding) + all_encoder_layers_v.append(image_embedding) + all_encoder_layers_a.append(action_embedding) + + for idx in range(v_start, len(self.v_layer)): # 1 + image_embedding, image_attention_probs = self.v_layer[idx]( + image_embedding, image_attention_mask) + + for idx in range(a_start, len(self.a_layer)): + action_embedding, action_attention_probs = self.a_layer[idx]( + action_embedding, action_attention_mask) + + for idx in range(t_start, len(self.layer)): + txt_embedding, txt_attention_probs = self.layer[idx]( + txt_embedding, txt_attention_mask) + + # add the end part to finish. + if not output_all_encoded_layers: + all_encoder_layers_t.append(txt_embedding) #8, 36, 768 + all_encoder_layers_v.append(image_embedding) #8, 37, 1024 + all_encoder_layers_a.append(action_embedding) #8, 5, 768 + + return all_encoder_layers_t, all_encoder_layers_v, all_encoder_layers_a + + +class BertPooler(nn.Layer): + """ "Pool" the model by simply taking the hidden state corresponding + to the first token. + """ + def __init__(self, hidden_size, bi_hidden_size): + super(BertPooler, self).__init__() + self.dense = nn.Linear(hidden_size, bi_hidden_size) + self.activation = nn.ReLU() + + def forward(self, hidden_states): + first_token_tensor = hidden_states[:, 0] #8, 768 + pooled_output = self.dense(first_token_tensor) + pooled_output = self.activation(pooled_output) + return pooled_output + + +class BertModel(nn.Layer): + def __init__( + self, + vocab_size, + max_position_embeddings, + type_vocab_size, + v_feature_size, + a_feature_size, + num_hidden_layers, + v_num_hidden_layers, + a_num_hidden_layers, + v_ent_attention_id, + t_ent_attention_id, + a_ent_attention_id, + fixed_t_layer, + fixed_v_layer, + hidden_size, + v_hidden_size, + a_hidden_size, + bi_hidden_size, + intermediate_size, + v_intermediate_size, + a_intermediate_size, + hidden_act, + v_hidden_act, + a_hidden_act, + hidden_dropout_prob, + v_hidden_dropout_prob, + a_hidden_dropout_prob, + attention_probs_dropout_prob, + v_attention_probs_dropout_prob, + a_attention_probs_dropout_prob, + av_attention_probs_dropout_prob, + at_attention_probs_dropout_prob, + num_attention_heads, + v_num_attention_heads, + a_num_attention_heads, + bi_num_attention_heads, + ): + super(BertModel, self).__init__() + # initilize word embedding + self.embeddings = BertEmbeddings(vocab_size, max_position_embeddings, + type_vocab_size, hidden_size, + hidden_dropout_prob) + # initlize the region embedding + self.v_embeddings = BertImageEmbeddings(v_feature_size, v_hidden_size, + v_hidden_dropout_prob) + # initlize the action embedding + self.a_embeddings = BertActionEmbeddings(a_feature_size, a_hidden_size, + a_hidden_dropout_prob) + + self.encoder = BertEncoder( + v_ent_attention_id, t_ent_attention_id, a_ent_attention_id, + fixed_t_layer, fixed_v_layer, hidden_size, v_hidden_size, + a_hidden_size, bi_hidden_size, intermediate_size, + v_intermediate_size, a_intermediate_size, hidden_act, v_hidden_act, + a_hidden_act, hidden_dropout_prob, v_hidden_dropout_prob, + a_hidden_dropout_prob, attention_probs_dropout_prob, + v_attention_probs_dropout_prob, a_attention_probs_dropout_prob, + av_attention_probs_dropout_prob, at_attention_probs_dropout_prob, + num_attention_heads, v_num_attention_heads, a_num_attention_heads, + bi_num_attention_heads, num_hidden_layers, v_num_hidden_layers, + a_num_hidden_layers) + + self.t_pooler = BertPooler(hidden_size, bi_hidden_size) + self.v_pooler = BertPooler(v_hidden_size, bi_hidden_size) + self.a_pooler = BertPooler(a_hidden_size, bi_hidden_size) + + def forward( + self, + text_ids, + action_feat, + image_feat, + image_loc, + token_type_ids=None, + text_mask=None, + image_mask=None, + action_mask=None, + output_all_encoded_layers=False, + ): + """ + text_ids: input text ids. Shape: [batch_size, seqence_length] + action_feat: input action feature. Shape: [batch_size, action_length, action_feature_dim] + image_feat: input image feature. Shape: [batch_size, region_length, image_feature_dim]] + image_loc: input region location. Shape: [batch_size, region_length, region_location_dim] + token_type_ids: segment ids of each video clip. Shape: [batch_size, seqence_length] + text_mask: text mask, 1 for real tokens and 0 for padding tokens. Shape: [batch_size, seqence_length] + image_mask: image mask, 1 for real tokens and 0 for padding tokens. Shape: [batch_size, region_length] + action_mask: action mask, 1 for real tokens and 0 for padding tokens. Shape: [batch_size, action_length] + output_all_encoded_layers: is output encoded layers feature or not. Type: Bool. + """ + if text_mask is None: + text_mask = paddle.ones_like(text_ids) + if token_type_ids is None: + token_type_ids = paddle.zeros_like(text_ids) + if image_mask is None: + image_mask = paddle.ones(image_feat.shape[0], + image_feat.shape[1]).astype(text_ids.dtype) + if action_mask is None: + action_mask = paddle.ones(action_feat.shape[0], + action_feat.shape[1]).astype( + text_ids.dtype) + + # We create a 3D attention mask from a 2D tensor mask. + # Sizes are [batch_size, 1, 1, to_seq_length] + # So we can broadcast to [batch_size, num_heads, from_seq_length, to_seq_length]. + extended_text_mask = text_mask.unsqueeze(1).unsqueeze(2) + extended_image_mask = image_mask.unsqueeze(1).unsqueeze(2) + extended_action_mask = action_mask.unsqueeze(1).unsqueeze(2) + + # Since attention_mask is 1.0 for positions we want to attend and 0.0 for + # masked positions, this operation will create a tensor which is 0.0 for + # positions we want to attend and -10000.0 for masked positions. + # Since we are adding it to the raw scores before the softmax, this is + # effectively the same as removing these entirely. + def set_mask(extended_attention_mask): + extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0 + return extended_attention_mask + + extended_text_mask = set_mask(extended_text_mask) + extended_image_mask = set_mask(extended_image_mask) + extended_action_mask = set_mask(extended_action_mask) + + t_embedding_output = self.embeddings(text_ids, token_type_ids) + v_embedding_output = self.v_embeddings(image_feat, image_loc) + a_embedding_output = self.a_embeddings(action_feat) + + # var = [t_embedding_output, v_embedding_output, a_embedding_output] + # import numpy as np + # for i, item in enumerate(var): + # np.save('tmp/' + str(i)+'.npy', item.numpy()) + + encoded_layers_t, encoded_layers_v, encoded_layers_a = self.encoder( + t_embedding_output, + v_embedding_output, + a_embedding_output, + extended_text_mask, + extended_image_mask, + extended_action_mask, + output_all_encoded_layers=output_all_encoded_layers, + ) + + sequence_output_t = encoded_layers_t[-1] #get item from list + sequence_output_v = encoded_layers_v[-1] + sequence_output_a = encoded_layers_a[-1] + + pooled_output_t = self.t_pooler(sequence_output_t) + pooled_output_v = self.v_pooler(sequence_output_v) + pooled_output_a = self.a_pooler(sequence_output_a) + + if not output_all_encoded_layers: + encoded_layers_t = encoded_layers_t[-1] + encoded_layers_v = encoded_layers_v[-1] + encoded_layers_a = encoded_layers_a[-1] + + return encoded_layers_t, encoded_layers_v, encoded_layers_a, \ + pooled_output_t, pooled_output_v, pooled_output_a + + +# For Head +class BertPredictionHeadTransform(nn.Layer): + def __init__(self, hidden_size, hidden_act): + super(BertPredictionHeadTransform, self).__init__() + self.dense = nn.Linear(hidden_size, hidden_size) + if isinstance(hidden_act, str) or (sys.version_info[0] == 2 + and isinstance(hidden_act, str)): + self.transform_act_fn = ACT2FN[hidden_act] + else: + self.transform_act_fn = hidden_act + self.LayerNorm = nn.LayerNorm(hidden_size, epsilon=1e-12) + + def forward(self, hidden_states): + hidden_states = self.dense(hidden_states) + hidden_states = self.transform_act_fn(hidden_states) + hidden_states = self.LayerNorm(hidden_states) + return hidden_states + + +class BertLMPredictionHead(nn.Layer): + def __init__(self, hidden_size, hidden_act, bert_model_embedding_weights): + super(BertLMPredictionHead, self).__init__() + self.transform = BertPredictionHeadTransform(hidden_size, hidden_act) + + # The output weights are the same as the input embeddings, but there is + # an output-only bias for each token. + assert bert_model_embedding_weights.shape[1] == hidden_size + vocab_size = bert_model_embedding_weights.shape[0] + + # another implementation which would create another big params: + # self.decoder = nn.Linear(hidden_size, vocab_size) # NOTE bias default: constant 0.0 + # self.decoder.weight = self.create_parameter(shape=[hidden_size, vocab_size], + # default_initializer=nn.initializer.Assign( + # bert_model_embedding_weights.t())) # transpose + + self.decoder_weight = bert_model_embedding_weights + self.decoder_bias = self.create_parameter( + shape=[vocab_size], + dtype=bert_model_embedding_weights.dtype, + is_bias=True) # NOTE bias default: constant 0.0 + + def forward(self, hidden_states): + hidden_states = self.transform(hidden_states) + hidden_states = paddle.tensor.matmul( + hidden_states, self.decoder_weight, + transpose_y=True) + self.decoder_bias + return hidden_states + + +class BertImageActionPredictionHead(nn.Layer): + def __init__(self, hidden_size, hidden_act, target_size): + super(BertImageActionPredictionHead, self).__init__() + self.transform = BertPredictionHeadTransform(hidden_size, hidden_act) + + self.decoder = nn.Linear(hidden_size, target_size) + + def forward(self, hidden_states): + hidden_states = self.transform(hidden_states) + hidden_states = self.decoder(hidden_states) + return hidden_states + + +class BertPreTrainingHeads(nn.Layer): + def __init__(self, hidden_size, v_hidden_size, a_hidden_size, + bi_hidden_size, hidden_act, v_hidden_act, a_hidden_act, + v_target_size, a_target_size, fusion_method, + bert_model_embedding_weights): + super(BertPreTrainingHeads, self).__init__() + self.predictions = BertLMPredictionHead(hidden_size, hidden_act, + bert_model_embedding_weights) + self.seq_relationship = nn.Linear(bi_hidden_size, 2) + self.imagePredictions = BertImageActionPredictionHead( + v_hidden_size, v_hidden_act, v_target_size) # visual class number + self.actionPredictions = BertImageActionPredictionHead( + a_hidden_size, a_hidden_act, a_target_size) # action class number + self.fusion_method = fusion_method + self.dropout = nn.Dropout(0.1) + + def forward(self, sequence_output_t, sequence_output_v, sequence_output_a, + pooled_output_t, pooled_output_v, pooled_output_a): + + if self.fusion_method == 'sum': + pooled_output = self.dropout(pooled_output_t + pooled_output_v + + pooled_output_a) + elif self.fusion_method == 'mul': + pooled_output = self.dropout(pooled_output_t * pooled_output_v + + pooled_output_a) + else: + assert False + + prediction_scores_t = self.predictions( + sequence_output_t) # 8, 36 ,30522 + seq_relationship_score = self.seq_relationship(pooled_output) # 8, 2 + prediction_scores_v = self.imagePredictions( + sequence_output_v) # 8, 37, 1601 + prediction_scores_a = self.actionPredictions( + sequence_output_a) # 8, 5, 401 + + return prediction_scores_t, prediction_scores_v, prediction_scores_a, seq_relationship_score + + +@BACKBONES.register() +class BertForMultiModalPreTraining(nn.Layer): + """BERT model with multi modal pre-training heads. + """ + def __init__( + self, + vocab_size=30522, + max_position_embeddings=512, + type_vocab_size=2, + v_target_size=1601, + a_target_size=700, + v_feature_size=2048, + a_feature_size=2048, + num_hidden_layers=12, + v_num_hidden_layers=2, + a_num_hidden_layers=3, + t_ent_attention_id=[10, 11], + v_ent_attention_id=[0, 1], + a_ent_attention_id=[0, 1], + fixed_t_layer=0, + fixed_v_layer=0, + hidden_size=768, + v_hidden_size=1024, + a_hidden_size=768, + bi_hidden_size=1024, + intermediate_size=3072, + v_intermediate_size=1024, + a_intermediate_size=3072, + hidden_act="gelu", + v_hidden_act="gelu", + a_hidden_act="gelu", + hidden_dropout_prob=0.1, + v_hidden_dropout_prob=0.1, + a_hidden_dropout_prob=0.1, + attention_probs_dropout_prob=0.1, + v_attention_probs_dropout_prob=0.1, + a_attention_probs_dropout_prob=0.1, + av_attention_probs_dropout_prob=0.1, + at_attention_probs_dropout_prob=0.1, + num_attention_heads=12, + v_num_attention_heads=8, + a_num_attention_heads=12, + bi_num_attention_heads=8, + fusion_method="mul", + pretrained=None, + ): + """ + vocab_size: vocabulary size. Default: 30522. + max_position_embeddings: max position id. Default: 512. + type_vocab_size: max segment id. Default: 2. + v_target_size: class number of visual word. Default: 1601. + a_target_size: class number of action word. Default: 700. + v_feature_size: input visual feature dimension. Default: 2048. + a_feature_size: input action feature dimension. Default: 2048. + num_hidden_layers: number of BertLayer in text transformer. Default: 12. + v_num_hidden_layers: number of BertLayer in visual transformer. Default: 2. + a_num_hidden_layers: number of BertLayer in action transformer. Default:3. + t_ent_attention_id: index id of BertConnectionLayer in text transformer. Default: [10, 11]. + v_ent_attention_id: index id of BertConnectionLayer in visual transformer. Default:[0, 1]. + a_ent_attention_id: index id of BertConnectionLayer in action transformer. Default:[0, 1]. + fixed_t_layer: index id of fixed BertLayer in text transformer. Default: 0. + fixed_v_layer: index id of fixed BertLayer in visual transformer. Default: 0. + hidden_size: hidden size in text BertLayer. Default: 768. + v_hidden_size: hidden size in visual BertLayer. Default: 1024. + a_hidden_size: hidden size in action BertLayer. Default: 768. + bi_hidden_size: hidden size in BertConnectionLayer. Default: 1024, + intermediate_size: intermediate size in text BertLayer. Default: 3072. + v_intermediate_size: intermediate size in visual BertLayer. Default: 1024. + a_intermediate_size: intermediate size in text BertLayer. Default: 3072. + hidden_act: hidden activation function in text BertLayer. Default: "gelu". + v_hidden_act: hidden activation function in visual BertLayer. Default: "gelu". + a_hidden_act: hidden activation function in action BertLayer. Default: "gelu". + hidden_dropout_prob: hidden dropout probability in text Embedding Layer. Default: 0.1 + v_hidden_dropout_prob: hidden dropout probability in visual Embedding Layer. Default: 0.1 + a_hidden_dropout_prob: hidden dropout probability in action Embedding Layer. Default: 0.1 + attention_probs_dropout_prob: attention dropout probability in text BertLayer. Default: 0.1 + v_attention_probs_dropout_prob: attention dropout probability in visual BertLayer. Default: 0.1 + a_attention_probs_dropout_prob: attention dropout probability in action BertLayer. Default: 0.1 + av_attention_probs_dropout_prob: attention dropout probability in action-visual BertConnectionLayer. Default: 0.1 + at_attention_probs_dropout_prob: attention dropout probability in action-text BertConnectionLayer. Default: 0.1 + num_attention_heads: number of heads in text BertLayer. Default: 12. + v_num_attention_heads: number of heads in visual BertLayer. Default: 8. + a_num_attention_heads: number of heads in action BertLayer. Default: 12. + bi_num_attention_heads: number of heads in BertConnectionLayer. Default: 8. + fusion_method: methods of fusing pooled output from 3 transformer. Default: "mul". + """ + super(BertForMultiModalPreTraining, self).__init__() + self.pretrained = pretrained + self.vocab_size = vocab_size + self.a_target_size = a_target_size + + self.bert = BertModel( + vocab_size, + max_position_embeddings, + type_vocab_size, + v_feature_size, + a_feature_size, + num_hidden_layers, + v_num_hidden_layers, + a_num_hidden_layers, + v_ent_attention_id, + t_ent_attention_id, + a_ent_attention_id, + fixed_t_layer, + fixed_v_layer, + hidden_size, + v_hidden_size, + a_hidden_size, + bi_hidden_size, + intermediate_size, + v_intermediate_size, + a_intermediate_size, + hidden_act, + v_hidden_act, + a_hidden_act, + hidden_dropout_prob, + v_hidden_dropout_prob, + a_hidden_dropout_prob, + attention_probs_dropout_prob, + v_attention_probs_dropout_prob, + a_attention_probs_dropout_prob, + av_attention_probs_dropout_prob, + at_attention_probs_dropout_prob, + num_attention_heads, + v_num_attention_heads, + a_num_attention_heads, + bi_num_attention_heads, + ) + self.cls = BertPreTrainingHeads( + hidden_size, v_hidden_size, a_hidden_size, bi_hidden_size, + hidden_act, v_hidden_act, a_hidden_act, v_target_size, + a_target_size, fusion_method, + self.bert.embeddings.word_embeddings.weight) + + def init_weights(self): + """Initiate the parameters. + """ + if isinstance(self.pretrained, str) and self.pretrained.strip() != "": + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + for layer in self.sublayers(): + if isinstance(layer, (nn.Linear, nn.Embedding)): + weight_init_(layer, 'Normal', std=0.02) + elif isinstance(layer, nn.LayerNorm): + weight_init_(layer, 'Constant', value=1) + + def forward( + self, + text_ids, #8,36 + action_feat, #8,5,2048 + image_feat, #8,37,2048 + image_loc, #8,37,5 + token_type_ids=None, #8,36 + text_mask=None, #8,36 + image_mask=None, #8,37 + action_mask=None, #8,5 + ): + """ + text_ids: input text ids. Shape: [batch_size, seqence_length] + action_feat: input action feature. Shape: [batch_size, action_length, action_feature_dim] + image_feat: input image feature. Shape: [batch_size, region_length+1, image_feature_dim]], add 1 for image global feature. + image_loc: input region location. Shape: [batch_size, region_length+1, region_location_dim], add 1 for image global feature location. + token_type_ids: segment ids of each video clip. Shape: [batch_size, seqence_length] + text_mask: text mask, 1 for real tokens and 0 for padding tokens. Shape: [batch_size, seqence_length] + image_mask: image mask, 1 for real tokens and 0 for padding tokens. Shape: [batch_size, region_length] + action_mask: action mask, 1 for real tokens and 0 for padding tokens. Shape: [batch_size, action_length] + """ + sequence_output_t, sequence_output_v, sequence_output_a, \ + pooled_output_t, pooled_output_v, pooled_output_a = self.bert( + text_ids, + action_feat, + image_feat, + image_loc, + token_type_ids, + text_mask, + image_mask, + action_mask, + output_all_encoded_layers=False, + ) + + prediction_scores_t, prediction_scores_v, prediction_scores_a, seq_relationship_score = self.cls( + sequence_output_t, sequence_output_v, sequence_output_a, + pooled_output_t, pooled_output_v, pooled_output_a) + + return prediction_scores_t, prediction_scores_v, prediction_scores_a, seq_relationship_score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/adds.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/adds.py new file mode 100644 index 0000000..21cd212 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/adds.py @@ -0,0 +1,1146 @@ +# Copyright (c) 2021 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 math +from collections import OrderedDict + +import numpy as np +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +from paddle.nn import BatchNorm2D, Conv2D +from paddle.nn.initializer import Constant, Normal +from paddle.vision.models import ResNet + +from ...utils import load_ckpt +from ..registry import BACKBONES +from ..weight_init import kaiming_normal_, _calculate_fan_in_and_fan_out + +zeros_ = Constant(value=0.) +ones_ = Constant(value=1.) +normal_ = Normal(mean=0, std=1e-3) + + +def disp_to_depth(disp, min_depth, max_depth): + """Convert network's sigmoid output into depth prediction + The formula for this conversion is given in the 'additional considerations' + section of the paper. + """ + min_disp = 1 / max_depth + max_disp = 1 / min_depth + scaled_disp = min_disp + (max_disp - min_disp) * disp + depth = 1 / scaled_disp + return scaled_disp, depth + + +def gram_matrix(y): + (b, ch, h, w) = y.shape + features = y.reshape([b, ch, w * h]) + features_t = paddle.transpose(features, [0, 2, 1]) + gram = features.bmm(features_t) / (ch * h * w) + return gram + + +def convt_bn_relu(in_channels, + out_channels, + kernel_size, + stride=1, + padding=0, + output_padding=0, + bn=True, + relu=True): + bias = not bn + layers = [] + layers.append( + nn.Conv2DTranspose(in_channels, + out_channels, + kernel_size, + stride, + padding, + output_padding, + bias_attr=bias)) + if bn: + layers.append(nn.BatchNorm2D(out_channels)) + + if relu: + layers.append(nn.LeakyReLU(0.2)) + layers = nn.Sequential(*layers) + + # initialize the weights + for m in layers.sublayers(include_self=True): + if isinstance(m, nn.Conv2DTranspose): + normal_(m.weight) + if m.bias is not None: + zeros_(m.bias) + elif isinstance(m, nn.BatchNorm2D): + ones_(m.weight) + zeros_(m.bias) + return layers + + +def transformation_from_parameters(axisangle, translation, invert=False): + """Convert the network's (axisangle, translation) output into a 4x4 matrix + """ + R = rot_from_axisangle(axisangle) + t = translation.clone() + + if invert: + R = R.transpose([0, 2, 1]) + t *= -1 + + T = get_translation_matrix(t) + + if invert: + M = paddle.matmul(R, T) + else: + M = paddle.matmul(T, R) + + return M + + +def get_translation_matrix(translation_vector): + """Convert a translation vector into a 4x4 transformation matrix + """ + t = translation_vector.reshape([-1, 3, 1]) + gather_object = paddle.stack([ + paddle.zeros([ + translation_vector.shape[0], + ], paddle.float32), + paddle.ones([ + translation_vector.shape[0], + ], paddle.float32), + paddle.squeeze(t[:, 0], axis=-1), + paddle.squeeze(t[:, 1], axis=-1), + paddle.squeeze(t[:, 2], axis=-1), + ]) + gather_index = paddle.to_tensor([ + [1], + [0], + [0], + [2], + [0], + [1], + [0], + [3], + [0], + [0], + [1], + [4], + [0], + [0], + [0], + [1], + ]) + T = paddle.gather_nd(gather_object, gather_index) + T = T.reshape([4, 4, -1]).transpose((2, 0, 1)) + return T + + +def rot_from_axisangle(vec): + """Convert an axisangle rotation into a 4x4 transformation matrix + (adapted from https://github.com/Wallacoloo/printipi) + Input 'vec' has to be Bx1x3 + """ + angle = paddle.norm(vec, 2, 2, True) + axis = vec / (angle + 1e-7) + + ca = paddle.cos(angle) + sa = paddle.sin(angle) + C = 1 - ca + + x = axis[..., 0].unsqueeze(1) + y = axis[..., 1].unsqueeze(1) + z = axis[..., 2].unsqueeze(1) + + xs = x * sa + ys = y * sa + zs = z * sa + xC = x * C + yC = y * C + zC = z * C + xyC = x * yC + yzC = y * zC + zxC = z * xC + + gather_object = paddle.stack([ + paddle.squeeze(x * xC + ca, axis=(-1, -2)), + paddle.squeeze(xyC - zs, axis=(-1, -2)), + paddle.squeeze(zxC + ys, axis=(-1, -2)), + paddle.squeeze(xyC + zs, axis=(-1, -2)), + paddle.squeeze(y * yC + ca, axis=(-1, -2)), + paddle.squeeze(yzC - xs, axis=(-1, -2)), + paddle.squeeze(zxC - ys, axis=(-1, -2)), + paddle.squeeze(yzC + xs, axis=(-1, -2)), + paddle.squeeze(z * zC + ca, axis=(-1, -2)), + paddle.ones([ + vec.shape[0], + ], dtype=paddle.float32), + paddle.zeros([ + vec.shape[0], + ], dtype=paddle.float32) + ]) + gather_index = paddle.to_tensor([ + [0], + [1], + [2], + [10], + [3], + [4], + [5], + [10], + [6], + [7], + [8], + [10], + [10], + [10], + [10], + [9], + ]) + rot = paddle.gather_nd(gather_object, gather_index) + rot = rot.reshape([4, 4, -1]).transpose((2, 0, 1)) + return rot + + +def upsample(x): + """Upsample input tensor by a factor of 2 + """ + return F.interpolate(x, scale_factor=2, mode="nearest") + + +def get_smooth_loss(disp, img): + """Computes the smoothness loss for a disparity image + The color image is used for edge-aware smoothness + """ + grad_disp_x = paddle.abs(disp[:, :, :, :-1] - disp[:, :, :, 1:]) + grad_disp_y = paddle.abs(disp[:, :, :-1, :] - disp[:, :, 1:, :]) + + grad_img_x = paddle.mean(paddle.abs(img[:, :, :, :-1] - img[:, :, :, 1:]), + 1, + keepdim=True) + grad_img_y = paddle.mean(paddle.abs(img[:, :, :-1, :] - img[:, :, 1:, :]), + 1, + keepdim=True) + + grad_disp_x *= paddle.exp(-grad_img_x) + grad_disp_y *= paddle.exp(-grad_img_y) + + return grad_disp_x.mean() + grad_disp_y.mean() + + +def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1): + """3x3 convolution with padding""" + return nn.Conv2D(in_planes, + out_planes, + kernel_size=3, + stride=stride, + padding=dilation, + groups=groups, + bias_attr=False, + dilation=dilation) + + +def conv1x1(in_planes, out_planes, stride=1): + """1x1 convolution""" + return nn.Conv2D(in_planes, + out_planes, + kernel_size=1, + stride=stride, + bias_attr=False) + + +def resnet_multiimage_input(num_layers, num_input_images=1): + """Constructs a ResNet model. + Args: + num_layers (int): Number of resnet layers. Must be 18 or 50 + pretrained (bool): If True, returns a model pre-trained on ImageNet + num_input_images (int): Number of frames stacked as input + """ + assert num_layers in [18, 50], "Can only run with 18 or 50 layer resnet" + blocks = {18: [2, 2, 2, 2], 50: [3, 4, 6, 3]}[num_layers] + + block_type = {18: BasicBlock, 50: Bottleneck}[num_layers] + + model = ResNetMultiImageInput(block_type, + num_layers, + blocks, + num_input_images=num_input_images) + model.init_weights() + return model + + +class ConvBlock(nn.Layer): + """Layer to perform a convolution followed by ELU + """ + def __init__(self, in_channels, out_channels): + super(ConvBlock, self).__init__() + + self.conv = Conv3x3(in_channels, out_channels) + self.nonlin = nn.ELU() + + def forward(self, x): + out = self.conv(x) + out = self.nonlin(out) + return out + + +class Conv3x3(nn.Layer): + """Layer to pad and convolve input + """ + def __init__(self, in_channels, out_channels, use_refl=True): + super(Conv3x3, self).__init__() + + if use_refl: + self.pad = nn.Pad2D(1, mode='reflect') + else: + self.pad = nn.Pad2D(1) + self.conv = nn.Conv2D(int(in_channels), int(out_channels), 3) + + def forward(self, x): + out = self.pad(x) + out = self.conv(out) + return out + + +class BackprojectDepth(nn.Layer): + """Layer to transform a depth image into a point cloud + """ + def __init__(self, batch_size, height, width): + super(BackprojectDepth, self).__init__() + + self.batch_size = batch_size + self.height = height + self.width = width + + meshgrid = np.meshgrid(range(self.width), + range(self.height), + indexing='xy') + id_coords = np.stack(meshgrid, axis=0).astype(np.float32) + self.id_coords = self.create_parameter(shape=list(id_coords.shape), + dtype=paddle.float32) + self.id_coords.set_value(id_coords) + self.add_parameter("id_coords", self.id_coords) + self.id_coords.stop_gradient = True + + self.ones = self.create_parameter( + shape=[self.batch_size, 1, self.height * self.width], + default_initializer=ones_) + self.add_parameter("ones", self.ones) + self.ones.stop_gradient = True + + pix_coords = paddle.unsqueeze( + paddle.stack([ + self.id_coords[0].reshape([ + -1, + ]), self.id_coords[1].reshape([ + -1, + ]) + ], 0), 0) + pix_coords = pix_coords.tile([batch_size, 1, 1]) + pix_coords = paddle.concat([pix_coords, self.ones], 1) + self.pix_coords = self.create_parameter(shape=list(pix_coords.shape), ) + self.pix_coords.set_value(pix_coords) + self.add_parameter("pix_coords", self.pix_coords) + self.pix_coords.stop_gradient = True + + def forward(self, depth, inv_K): + cam_points = paddle.matmul(inv_K[:, :3, :3], self.pix_coords) + cam_points = depth.reshape([self.batch_size, 1, -1]) * cam_points + cam_points = paddle.concat([cam_points, self.ones], 1) + + return cam_points + + +class Project3D(nn.Layer): + """Layer which projects 3D points into a camera with intrinsics K and at position T + """ + def __init__(self, batch_size, height, width, eps=1e-7): + super(Project3D, self).__init__() + + self.batch_size = batch_size + self.height = height + self.width = width + self.eps = eps + + def forward(self, points, K, T): + P = paddle.matmul(K, T)[:, :3, :] + + cam_points = paddle.matmul(P, points) + + pix_coords = cam_points[:, :2, :] / (cam_points[:, 2, :].unsqueeze(1) + + self.eps) + pix_coords = pix_coords.reshape( + [self.batch_size, 2, self.height, self.width]) + pix_coords = pix_coords.transpose([0, 2, 3, 1]) + pix_coords[..., 0] /= self.width - 1 + pix_coords[..., 1] /= self.height - 1 + pix_coords = (pix_coords - 0.5) * 2 + return pix_coords + + +class SSIM(nn.Layer): + """Layer to compute the SSIM loss between a pair of images + """ + def __init__(self): + super(SSIM, self).__init__() + self.mu_x_pool = nn.AvgPool2D(3, 1, exclusive=False) + self.mu_y_pool = nn.AvgPool2D(3, 1, exclusive=False) + self.sig_x_pool = nn.AvgPool2D(3, 1, exclusive=False) + self.sig_y_pool = nn.AvgPool2D(3, 1, exclusive=False) + self.sig_xy_pool = nn.AvgPool2D(3, 1, exclusive=False) + + self.refl = nn.Pad2D(1, mode='reflect') + + self.C1 = 0.01**2 + self.C2 = 0.03**2 + + def forward(self, x, y): + x = self.refl(x) + y = self.refl(y) + + mu_x = self.mu_x_pool(x) + mu_y = self.mu_y_pool(y) + + sigma_x = self.sig_x_pool(x**2) - mu_x**2 + sigma_y = self.sig_y_pool(y**2) - mu_y**2 + sigma_xy = self.sig_xy_pool(x * y) - mu_x * mu_y + + SSIM_n = (2 * mu_x * mu_y + self.C1) * (2 * sigma_xy + self.C2) + SSIM_d = (mu_x**2 + mu_y**2 + self.C1) * (sigma_x + sigma_y + self.C2) + + return paddle.clip((1 - SSIM_n / SSIM_d) / 2, 0, 1) + + +class ResNetMultiImageInput(ResNet): + """Constructs a resnet model with varying number of input images. + Adapted from https://github.com/pypaddle/vision/blob/master/paddlevision/models/resnet.py + """ + def __init__(self, block, depth, layers, num_input_images=1): + super(ResNetMultiImageInput, self).__init__(block, depth) + self.inplanes = 64 + self.conv1 = nn.Conv2D(num_input_images * 3, + 64, + kernel_size=7, + stride=2, + padding=3, + bias_attr=False) + self.bn1 = nn.BatchNorm2D(64) + self.relu = nn.ReLU() + self.maxpool = nn.MaxPool2D(kernel_size=3, stride=2, padding=1) + self.layer1 = self._make_layer(block, 64, layers[0]) + self.layer2 = self._make_layer(block, 128, layers[1], stride=2) + self.layer3 = self._make_layer(block, 256, layers[2], stride=2) + self.layer4 = self._make_layer(block, 512, layers[3], stride=2) + + def init_weights(self): + for layer in self.sublayers(include_self=True): + if isinstance(layer, nn.Conv2D): + kaiming_normal_(layer.weight, + mode='fan_out', + nonlinearity='relu') + elif isinstance(layer, nn.BatchNorm2D): + ones_(layer.weight) + zeros_(layer.bias) + + +class ConvBNLayer(nn.Layer): + """Conv2D and BatchNorm2D layer. + + Args: + in_channels (int): Number of channels for the input. + out_channels (int): Number of channels for the output. + kernel_size (int): Kernel size. + stride (int): Stride in the Conv2D layer. Default: 1. + groups (int): Groups in the Conv2D, Default: 1. + act (str): Indicate activation after BatchNorm2D layer. + name (str): the name of an instance of ConvBNLayer. + + Note: weight and bias initialization include initialize values + and name the restored parameters, values initialization + are explicit declared in the ```init_weights``` method. + + """ + def __init__(self, + in_channels, + out_channels, + kernel_size, + stride=1, + groups=1, + act=None, + name=None): + super(ConvBNLayer, self).__init__() + self._conv = Conv2D(in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=(kernel_size - 1) // 2, + groups=groups, + bias_attr=False) + + self._act = act + + self._batch_norm = BatchNorm2D(out_channels) + + def forward(self, inputs): + y = self._conv(inputs) + y = self._batch_norm(y) + if self._act: + y = getattr(paddle.nn.functional, self._act)(y) + return y + + +class BasicBlock(nn.Layer): + expansion = 1 + + def __init__(self, + inplanes, + planes, + stride=1, + downsample=None, + groups=1, + base_width=64, + dilation=1, + norm_layer=None): + super(BasicBlock, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2D + if groups != 1 or base_width != 64: + raise ValueError( + 'BasicBlock only supports groups=1 and base_width=64') + if dilation > 1: + raise NotImplementedError( + "Dilation > 1 not supported in BasicBlock") + # Both self.conv1 and self.downsample layers downsample the input when stride != 1 + self.conv1 = conv3x3(inplanes, planes, stride) + self.bn1 = norm_layer(planes) + self.relu = nn.ReLU() + self.conv2 = conv3x3(planes, planes) + self.bn2 = norm_layer(planes) + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class Bottleneck(nn.Layer): + # Bottleneck in torchvision places the stride for downsampling at 3x3 convolution(self.conv2) + # while original implementation places the stride at the first 1x1 convolution(self.conv1) + # according to "Deep residual learning for image recognition"https://arxiv.org/abs/1512.03385. + # This variant is also known as ResNet V1.5 and improves accuracy according to + # https://ngc.nvidia.com/catalog/model-scripts/nvidia:resnet_50_v1_5_for_pytorch. + + expansion = 4 + + def __init__(self, + inplanes, + planes, + stride=1, + downsample=None, + groups=1, + base_width=64, + dilation=1, + norm_layer=None): + super(Bottleneck, self).__init__() + if norm_layer is None: + norm_layer = nn.BatchNorm2D + width = int(planes * (base_width / 64.)) * groups + + self.conv1 = conv1x1(inplanes, width) + self.bn1 = norm_layer(width) + self.conv2 = conv3x3(width, width, stride, groups, dilation) + self.bn2 = norm_layer(width) + self.conv3 = conv1x1(width, planes * self.expansion) + self.bn3 = norm_layer(planes * self.expansion) + self.relu = nn.ReLU() + self.downsample = downsample + self.stride = stride + + def forward(self, x): + identity = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.relu(out) + + out = self.conv3(out) + out = self.bn3(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out += identity + out = self.relu(out) + + return out + + +class DepthDecoder(nn.Layer): + def __init__(self, + num_ch_enc, + scales=range(4), + num_output_channels=1, + use_skips=True): + super(DepthDecoder, self).__init__() + + self.num_output_channels = num_output_channels + self.use_skips = use_skips + self.upsample_mode = 'nearest' + self.scales = scales + + self.num_ch_enc = num_ch_enc + self.num_ch_dec = np.array([16, 32, 64, 128, 256]) + + # decoder + self.convs = OrderedDict() + for i in range(4, -1, -1): + # upconv_0 + num_ch_in = self.num_ch_enc[-1] if i == 4 else self.num_ch_dec[i + + 1] + num_ch_out = self.num_ch_dec[i] + self.convs[("upconv", i, 0)] = ConvBlock(num_ch_in, num_ch_out) + + # upconv_1 + num_ch_in = self.num_ch_dec[i] + if self.use_skips and i > 0: + num_ch_in += self.num_ch_enc[i - 1] + num_ch_out = self.num_ch_dec[i] + self.convs[("upconv", i, 1)] = ConvBlock(num_ch_in, num_ch_out) + + for s in self.scales: + self.convs[("dispconv", s)] = Conv3x3(self.num_ch_dec[s], + self.num_output_channels) + + self.decoder = nn.LayerList(list(self.convs.values())) + self.sigmoid = nn.Sigmoid() + + def forward(self, input_features): + outputs = {} + + # decoder + x = input_features[-1] + for i in range(4, -1, -1): + x = self.convs[("upconv", i, 0)](x) + x = [upsample(x)] + if self.use_skips and i > 0: + x += [input_features[i - 1]] + x = paddle.concat(x, 1) + x = self.convs[("upconv", i, 1)](x) + if i in self.scales: + outputs[("disp", i)] = self.sigmoid(self.convs[("dispconv", + i)](x)) + return outputs + + +class PoseDecoder(nn.Layer): + def __init__(self, + num_ch_enc, + num_input_features, + num_frames_to_predict_for=None, + stride=1): + super(PoseDecoder, self).__init__() + + self.num_ch_enc = num_ch_enc + self.num_input_features = num_input_features + + if num_frames_to_predict_for is None: + num_frames_to_predict_for = num_input_features - 1 + self.num_frames_to_predict_for = num_frames_to_predict_for + + self.convs = OrderedDict() + self.convs[("squeeze")] = nn.Conv2D(self.num_ch_enc[-1], 256, 1) + self.convs[("pose", 0)] = nn.Conv2D(num_input_features * 256, 256, 3, + stride, 1) + self.convs[("pose", 1)] = nn.Conv2D(256, 256, 3, stride, 1) + self.convs[("pose", 2)] = nn.Conv2D(256, 6 * num_frames_to_predict_for, + 1) + + self.relu = nn.ReLU() + + self.net = nn.LayerList(list(self.convs.values())) + + def forward(self, input_features): + last_features = [f[-1] for f in input_features] + + cat_features = [ + self.relu(self.convs["squeeze"](f)) for f in last_features + ] + cat_features = paddle.concat(cat_features, 1) + + out = cat_features + for i in range(3): + out = self.convs[("pose", i)](out) + if i != 2: + out = self.relu(out) + + out = out.mean(3).mean(2) + + out = 0.01 * out.reshape([-1, self.num_frames_to_predict_for, 1, 6]) + + axisangle = out[..., :3] + translation = out[..., 3:] + + return axisangle, translation + + +class ResnetEncoder(nn.Layer): + """Pypaddle module for a resnet encoder + """ + def __init__(self, num_layers, pretrained=False, num_input_images=1): + super(ResnetEncoder, self).__init__() + + self.num_ch_enc = np.array([64, 64, 128, 256, 512]) + + resnets = { + 18: paddle.vision.models.resnet18, + 34: paddle.vision.models.resnet34, + 50: paddle.vision.models.resnet50, + 101: paddle.vision.models.resnet101, + 152: paddle.vision.models.resnet152 + } + + if num_layers not in resnets: + raise ValueError( + "{} is not a valid number of resnet layers".format(num_layers)) + + if num_input_images > 1: + self.encoder = resnet_multiimage_input(num_layers, pretrained, + num_input_images) + else: + self.encoder = resnets[num_layers](pretrained) + + if num_layers > 34: + self.num_ch_enc[1:] *= 4 + + ###################################### + # night public first conv + ###################################### + self.conv1 = nn.Conv2D(3, + 64, + kernel_size=7, + stride=2, + padding=3, + bias_attr=False) + self.bn1 = nn.BatchNorm2D(64) + self.relu = nn.ReLU() # NOTE + + self.conv_shared = nn.Conv2D(512, 64, kernel_size=1) + + ########################################## + # private source encoder, day + ########################################## + self.encoder_day = resnets[num_layers](pretrained) + self.conv_diff_day = nn.Conv2D( + 512, 64, kernel_size=1) # no bn after conv, so bias=true + + ########################################## + # private target encoder, night + ########################################## + self.encoder_night = resnets[num_layers](pretrained) + self.conv_diff_night = nn.Conv2D(512, 64, kernel_size=1) + + ###################################### + # shared decoder (small decoder), use a simple de-conv to upsample the features with no skip connection + ###################################### + self.convt5 = convt_bn_relu(in_channels=512, + out_channels=256, + kernel_size=3, + stride=2, + padding=1, + output_padding=1) + self.convt4 = convt_bn_relu(in_channels=256, + out_channels=128, + kernel_size=3, + stride=2, + padding=1, + output_padding=1) + self.convt3 = convt_bn_relu(in_channels=128, + out_channels=64, + kernel_size=3, + stride=2, + padding=1, + output_padding=1) + self.convt2 = convt_bn_relu(in_channels=64, + out_channels=64, + kernel_size=3, + stride=2, + padding=1, + output_padding=1) + self.convt1 = convt_bn_relu(in_channels=64, + out_channels=64, + kernel_size=3, + stride=2, + padding=1, + output_padding=1) + self.convtf = nn.Conv2D(64, 3, kernel_size=1, stride=1, padding=0) + + def forward(self, input_image, is_night): + if self.training: + result = [] + input_data = (input_image - 0.45) / 0.225 + if is_night == 'day': + # source private encoder, day + private_feature = self.encoder_day.conv1(input_data) + private_feature = self.encoder_day.bn1(private_feature) + private_feature = self.encoder_day.relu(private_feature) + private_feature = self.encoder_day.maxpool(private_feature) + private_feature = self.encoder_day.layer1(private_feature) + private_feature = self.encoder_day.layer2(private_feature) + private_feature = self.encoder_day.layer3(private_feature) + private_feature = self.encoder_day.layer4(private_feature) + private_code = self.conv_diff_day(private_feature) + private_gram = gram_matrix(private_feature) + result.append(private_code) + result.append(private_gram) + + elif is_night == 'night': + # target private encoder, night + private_feature = self.encoder_night.conv1(input_data) + private_feature = self.encoder_night.bn1(private_feature) + private_feature = self.encoder_night.relu(private_feature) + private_feature = self.encoder_night.maxpool(private_feature) + private_feature = self.encoder_night.layer1(private_feature) + private_feature = self.encoder_night.layer2(private_feature) + private_feature = self.encoder_night.layer3(private_feature) + private_feature = self.encoder_night.layer4(private_feature) + private_code = self.conv_diff_night(private_feature) + + private_gram = gram_matrix(private_feature) + result.append(private_code) + result.append(private_gram) + + # shared encoder + self.features = [] + x = (input_image - 0.45) / 0.225 + if is_night == 'day': + x = self.encoder.conv1(x) + x = self.encoder.bn1(x) + self.features.append(self.encoder.relu(x)) + else: + x = self.conv1(x) + x = self.bn1(x) + self.features.append(self.relu(x)) + + self.features.append( + self.encoder.layer1(self.encoder.maxpool(self.features[-1]))) + self.features.append(self.encoder.layer2(self.features[-1])) + self.features.append(self.encoder.layer3(self.features[-1])) + self.features.append(self.encoder.layer4(self.features[-1])) + + if self.training: + shared_code = self.conv_shared(self.features[-1]) + shared_gram = gram_matrix(self.features[-1]) + result.append(shared_code) # use this to calculate loss of diff + result.append(shared_gram) + result.append( + self.features[-1]) # use this to calculate loss of similarity + + union_code = private_feature + self.features[-1] + rec_code = self.convt5(union_code) + rec_code = self.convt4(rec_code) + rec_code = self.convt3(rec_code) + rec_code = self.convt2(rec_code) + rec_code = self.convt1(rec_code) + rec_code = self.convtf(rec_code) + result.append(rec_code) + + return self.features, result + else: + return self.features + + +class ResnetEncoder_pose(nn.Layer): + """Pypaddle module for a resnet encoder + """ + def __init__(self, num_layers, pretrained=False, num_input_images=1): + super(ResnetEncoder_pose, self).__init__() + + self.num_ch_enc = np.array([64, 64, 128, 256, 512]) + resnets = { + 18: paddle.vision.models.resnet18, + 34: paddle.vision.models.resnet34, + 50: paddle.vision.models.resnet50, + 101: paddle.vision.models.resnet101, + 152: paddle.vision.models.resnet152 + } + + if num_layers not in resnets: + raise ValueError( + "{} is not a valid number of resnet layers".format(num_layers)) + + if num_input_images > 1: + self.encoder = resnet_multiimage_input(num_layers, num_input_images) + else: + self.encoder = resnets[num_layers](pretrained) + + if num_layers > 34: + self.num_ch_enc[1:] *= 4 + + def forward(self, input_image): + features = [] + x = (input_image - 0.45) / 0.225 + x = self.encoder.conv1(x) + x = self.encoder.bn1(x) + features.append(self.encoder.relu(x)) + features.append(self.encoder.layer1(self.encoder.maxpool(features[-1]))) + features.append(self.encoder.layer2(features[-1])) + features.append(self.encoder.layer3(features[-1])) + features.append(self.encoder.layer4(features[-1])) + + return features + + +@BACKBONES.register() +class ADDS_DepthNet(nn.Layer): + def __init__(self, + num_layers=18, + frame_ids=[0, -1, 1], + height=256, + width=512, + batch_size=6, + pose_model_input="pairs", + use_stereo=False, + only_depth_encoder=False, + pretrained=None, + scales=[0, 1, 2, 3], + min_depth=0.1, + max_depth=100.0, + pose_model_type='separate_resnet', + v1_multiscale=False, + predictive_mask=False, + disable_automasking=False): + super(ADDS_DepthNet, self).__init__() + self.num_layers = num_layers + self.height = height + self.width = width + self.batch_size = batch_size + self.frame_ids = frame_ids + self.pose_model_input = pose_model_input + self.use_stereo = use_stereo + self.only_depth_encoder = only_depth_encoder + self.pretrained = pretrained + self.scales = scales + self.pose_model_type = pose_model_type + self.predictive_mask = predictive_mask + self.disable_automasking = disable_automasking + self.v1_multiscale = v1_multiscale + self.min_depth = min_depth + self.max_depth = max_depth + + self.num_input_frames = len(self.frame_ids) + self.num_pose_frames = 2 if self.pose_model_input == "pairs" else self.num_input_frames + + assert self.frame_ids[0] == 0, "frame_ids must start with 0" + + self.use_pose_net = not (self.use_stereo and self.frame_ids == [0]) + + self.encoder = ResnetEncoder(self.num_layers) + if not self.only_depth_encoder: + self.depth = DepthDecoder(self.encoder.num_ch_enc, self.scales) + if self.use_pose_net and not self.only_depth_encoder: + if self.pose_model_type == "separate_resnet": + self.pose_encoder = ResnetEncoder_pose( + self.num_layers, num_input_images=self.num_pose_frames) + self.pose = PoseDecoder(self.pose_encoder.num_ch_enc, + num_input_features=1, + num_frames_to_predict_for=2) + + self.backproject_depth = {} + self.project_3d = {} + for scale in self.scales: + h = self.height // (2**scale) + w = self.width // (2**scale) + + self.backproject_depth[scale] = BackprojectDepth( + self.batch_size, h, w) + self.project_3d[scale] = Project3D(batch_size, h, w) + + def init_weights(self): + """First init model's weight""" + for m in self.sublayers(include_self=True): + if isinstance(m, nn.Conv2D): + kaiming_normal_(m.weight, a=math.sqrt(5)) + if m.bias is not None: + fan_in, _ = _calculate_fan_in_and_fan_out(m.weight) + bound = 1 / math.sqrt(fan_in) + uniform_ = paddle.nn.initializer.Uniform(-bound, bound) + uniform_(m.bias) + """Second, if provide pretrained ckpt, load it""" + if self.pretrained: # load pretrained weights + load_ckpt(self, self.pretrained) + + def forward(self, inputs, day_or_night='day'): + if self.training: + features, result = self.encoder(inputs["color_aug", 0, 0], 'day') + features_night, result_night = self.encoder( + inputs[("color_n_aug", 0, 0)], 'night') + + outputs = self.depth(features) + outputs_night = self.depth(features_night) + if self.use_pose_net and not self.only_depth_encoder: + outputs.update(self.predict_poses(inputs, 'day')) + outputs_night.update(self.predict_poses(inputs, 'night')) + + self.generate_images_pred(inputs, outputs, 'day') + self.generate_images_pred(inputs, outputs_night, 'night') + + outputs['frame_ids'] = self.frame_ids + outputs['scales'] = self.scales + outputs['result'] = result + outputs['result_night'] = result_night + outputs_night['frame_ids'] = self.frame_ids + outputs_night['scales'] = self.scales + outputs['outputs_night'] = outputs_night + else: + if isinstance(inputs, dict): + input_color = inputs[("color", 0, 0)] + features = self.encoder(input_color, day_or_night[0]) + outputs = self.depth(features) + + pred_disp, _ = disp_to_depth(outputs[("disp", 0)], + self.min_depth, self.max_depth) + + pred_disp = pred_disp[:, 0].numpy() + + outputs['pred_disp'] = np.squeeze(pred_disp) + + outputs['gt'] = np.squeeze(inputs['depth_gt'].numpy()) + else: + input_color = inputs + features = self.encoder(input_color, day_or_night) + outputs = self.depth(features) + + pred_disp, _ = disp_to_depth(outputs[("disp", 0)], + self.min_depth, self.max_depth) + + pred_disp = pred_disp[:, 0] + outputs = paddle.squeeze(pred_disp) + return outputs + + def predict_poses(self, inputs, is_night): + """Predict poses between input frames for monocular sequences. + """ + outputs = {} + if self.num_pose_frames == 2: + if is_night: + pose_feats = { + f_i: inputs["color_n_aug", f_i, 0] + for f_i in self.frame_ids + } + else: + pose_feats = { + f_i: inputs["color_aug", f_i, 0] + for f_i in self.frame_ids + } + + for f_i in self.frame_ids[1:]: + if f_i != "s": + if f_i < 0: + pose_inputs = [pose_feats[f_i], pose_feats[0]] + else: + pose_inputs = [pose_feats[0], pose_feats[f_i]] + + if self.pose_model_type == "separate_resnet": + pose_inputs = [ + self.pose_encoder(paddle.concat(pose_inputs, + axis=1)) + ] + + axisangle, translation = self.pose(pose_inputs) + outputs[("axisangle", 0, f_i)] = axisangle + outputs[("translation", 0, f_i)] = translation + + # Invert the matrix if the frame id is negative + outputs[("cam_T_cam", 0, + f_i)] = transformation_from_parameters( + axisangle[:, 0], + translation[:, 0], + invert=(f_i < 0)) + return outputs + + def generate_images_pred(self, inputs, outputs, is_night): + """Generate the warped (reprojected) color images for a minibatch. + Generated images are saved into the `outputs` dictionary. + """ + _, _, height, width = inputs['color', 0, 0].shape + for scale in self.scales: + disp = outputs[("disp", scale)] + if self.v1_multiscale: + source_scale = scale + else: + disp = F.interpolate(disp, [height, width], + mode="bilinear", + align_corners=False) + source_scale = 0 + + _, depth = disp_to_depth(disp, self.min_depth, self.max_depth) + + outputs[("depth", 0, scale)] = depth + for i, frame_id in enumerate(self.frame_ids[1:]): + + T = outputs[("cam_T_cam", 0, frame_id)] + + cam_points = self.backproject_depth[source_scale]( + depth, inputs[("inv_K", source_scale)]) + pix_coords = self.project_3d[source_scale]( + cam_points, inputs[("K", source_scale)], T) + + outputs[("sample", frame_id, scale)] = pix_coords + + if is_night: + inputs[("color_n", frame_id, + source_scale)].stop_gradient = False + outputs[("color", frame_id, + scale)] = paddle.nn.functional.grid_sample( + inputs[("color_n", frame_id, source_scale)], + outputs[("sample", frame_id, scale)], + padding_mode="border", + align_corners=False) + + else: + inputs[("color", frame_id, + source_scale)].stop_gradient = False + outputs[("color", frame_id, + scale)] = paddle.nn.functional.grid_sample( + inputs[("color", frame_id, source_scale)], + outputs[("sample", frame_id, scale)], + padding_mode="border", + align_corners=False) + + if not self.disable_automasking: + if is_night: + outputs[("color_identity", frame_id, scale)] = \ + inputs[("color_n", frame_id, source_scale)] + else: + outputs[("color_identity", frame_id, scale)] = \ + inputs[("color", frame_id, source_scale)] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/agcn.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/agcn.py new file mode 100644 index 0000000..9f870c6 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/agcn.py @@ -0,0 +1,128 @@ +# Copyright (c) 2021 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 paddle +import paddle.nn as nn +import paddle.nn.functional as F +from ..registry import BACKBONES + + +class GCN(nn.Layer): + def __init__(self, in_channels, out_channels, vertex_nums=25, stride=1): + super(GCN, self).__init__() + self.conv1 = nn.Conv2D(in_channels=in_channels, + out_channels=3 * out_channels, + kernel_size=1, + stride=1) + self.conv2 = nn.Conv2D(in_channels=vertex_nums * 3, + out_channels=vertex_nums, + kernel_size=1) + + def forward(self, x): + # x --- N,C,T,V + x = self.conv1(x) # N,3C,T,V + N, C, T, V = x.shape + x = paddle.reshape(x, [N, C // 3, 3, T, V]) # N,C,3,T,V + x = paddle.transpose(x, perm=[0, 1, 2, 4, 3]) # N,C,3,V,T + x = paddle.reshape(x, [N, C // 3, 3 * V, T]) # N,C,3V,T + x = paddle.transpose(x, perm=[0, 2, 1, 3]) # N,3V,C,T + x = self.conv2(x) # N,V,C,T + x = paddle.transpose(x, perm=[0, 2, 3, 1]) # N,C,T,V + return x + + +class Block(paddle.nn.Layer): + def __init__(self, + in_channels, + out_channels, + vertex_nums=25, + temporal_size=9, + stride=1, + residual=True): + super(Block, self).__init__() + self.residual = residual + self.out_channels = out_channels + + self.bn_res = nn.BatchNorm2D(out_channels) + self.conv_res = nn.Conv2D(in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + stride=(stride, 1)) + self.gcn = GCN(in_channels=in_channels, + out_channels=out_channels, + vertex_nums=vertex_nums) + self.tcn = nn.Sequential( + nn.BatchNorm2D(out_channels), + nn.ReLU(), + nn.Conv2D(in_channels=out_channels, + out_channels=out_channels, + kernel_size=(temporal_size, 1), + padding=((temporal_size - 1) // 2, 0), + stride=(stride, 1)), + nn.BatchNorm2D(out_channels), + ) + + def forward(self, x): + if self.residual: + y = self.conv_res(x) + y = self.bn_res(y) + x = self.gcn(x) + x = self.tcn(x) + out = x + y if self.residual else x + out = F.relu(out) + return out + + +@BACKBONES.register() +class AGCN(nn.Layer): + """ + AGCN model improves the performance of ST-GCN using + Adaptive Graph Convolutional Networks. + Args: + in_channels: int, channels of vertex coordinate. 2 for (x,y), 3 for (x,y,z). Default 2. + """ + def __init__(self, in_channels=2, **kwargs): + super(AGCN, self).__init__() + + self.data_bn = nn.BatchNorm1D(25 * 2) + self.agcn = nn.Sequential( + Block(in_channels=in_channels, + out_channels=64, + residual=False, + **kwargs), Block(in_channels=64, out_channels=64, **kwargs), + Block(in_channels=64, out_channels=64, **kwargs), + Block(in_channels=64, out_channels=64, **kwargs), + Block(in_channels=64, out_channels=128, stride=2, **kwargs), + Block(in_channels=128, out_channels=128, **kwargs), + Block(in_channels=128, out_channels=128, **kwargs), + Block(in_channels=128, out_channels=256, stride=2, **kwargs), + Block(in_channels=256, out_channels=256, **kwargs), + Block(in_channels=256, out_channels=256, **kwargs)) + + self.pool = nn.AdaptiveAvgPool2D(output_size=(1, 1)) + + def forward(self, x): + # data normalization + N, C, T, V, M = x.shape + + x = x.transpose((0, 4, 1, 2, 3)) # N, M, C, T, V + x = x.reshape((N * M, C, T, V)) + + x = self.agcn(x) + + x = self.pool(x) # NM,C,T,V --> NM,C,1,1 + C = x.shape[1] + x = paddle.reshape(x, (N, M, C, 1, 1)).mean(axis=1) # N,C,1,1 + + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/agcn2s.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/agcn2s.py new file mode 100644 index 0000000..a630c68 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/agcn2s.py @@ -0,0 +1,229 @@ +# Copyright (c) 2021 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 paddle +import paddle.nn as nn +import numpy as np +from ..registry import BACKBONES + + +def import_class(name): + components = name.split('.') + mod = __import__(components[0]) + for comp in components[1:]: + mod = getattr(mod, comp) + return mod + + +class UnitTCN(nn.Layer): + def __init__(self, in_channels, out_channels, kernel_size=9, stride=1): + super(UnitTCN, self).__init__() + pad = int((kernel_size - 1) / 2) + self.conv = nn.Conv2D(in_channels, + out_channels, + kernel_size=(kernel_size, 1), + padding=(pad, 0), + stride=(stride, 1)) + + self.bn = nn.BatchNorm2D(out_channels) + self.relu = nn.ReLU() + + def forward(self, x): + " input size : (N*M, C, T, V)" + x = self.bn(self.conv(x)) + return x + + +class UnitGCN(nn.Layer): + def __init__(self, + in_channels, + out_channels, + A, + coff_embedding=4, + num_subset=3): + super(UnitGCN, self).__init__() + inter_channels = out_channels // coff_embedding + self.inter_c = inter_channels + PA = self.create_parameter(shape=A.shape, dtype='float32') + self.PA = PA + self.A = paddle.to_tensor(A.astype(np.float32)) + self.num_subset = num_subset + + self.conv_a = nn.LayerList() + self.conv_b = nn.LayerList() + self.conv_d = nn.LayerList() + for i in range(self.num_subset): + self.conv_a.append(nn.Conv2D(in_channels, inter_channels, 1)) + self.conv_b.append(nn.Conv2D(in_channels, inter_channels, 1)) + self.conv_d.append(nn.Conv2D(in_channels, out_channels, 1)) + + if in_channels != out_channels: + self.down = nn.Sequential(nn.Conv2D(in_channels, out_channels, 1), + nn.BatchNorm2D(out_channels)) + else: + self.down = lambda x: x + + self.bn = nn.BatchNorm2D(out_channels) + self.soft = nn.Softmax(-2) + self.relu = nn.ReLU() + + def forward(self, x): + N, C, T, V = x.shape + A = self.A + self.PA + + y = None + for i in range(self.num_subset): + A1 = paddle.transpose(self.conv_a[i](x), + perm=[0, 3, 1, + 2]).reshape([N, V, self.inter_c * T]) + A2 = self.conv_b[i](x).reshape([N, self.inter_c * T, V]) + A1 = self.soft(paddle.matmul(A1, A2) / A1.shape[-1]) + A1 = A1 + A[i] + A2 = x.reshape([N, C * T, V]) + z = self.conv_d[i](paddle.matmul(A2, A1).reshape([N, C, T, V])) + y = z + y if y is not None else z + + y = self.bn(y) + y += self.down(x) + return self.relu(y) + + +class Block(nn.Layer): + def __init__(self, in_channels, out_channels, A, stride=1, residual=True): + super(Block, self).__init__() + self.gcn1 = UnitGCN(in_channels, out_channels, A) + self.tcn1 = UnitTCN(out_channels, out_channels, stride=stride) + self.relu = nn.ReLU() + if not residual: + self.residual = lambda x: 0 + + elif (in_channels == out_channels) and (stride == 1): + self.residual = lambda x: x + + else: + self.residual = UnitTCN(in_channels, + out_channels, + kernel_size=1, + stride=stride) + + def forward(self, x): + x = self.tcn1(self.gcn1(x)) + self.residual(x) + return self.relu(x) + + +# This Graph structure is for the NTURGB+D dataset. If you use a custom dataset, modify num_node and the corresponding graph adjacency structure. +class Graph: + def __init__(self, labeling_mode='spatial'): + num_node = 25 + self_link = [(i, i) for i in range(num_node)] + inward_ori_index = [(1, 2), (2, 21), (3, 21), (4, 3), (5, 21), (6, 5), + (7, 6), (8, 7), (9, 21), (10, 9), (11, 10), + (12, 11), (13, 1), (14, 13), (15, 14), (16, 15), + (17, 1), (18, 17), (19, 18), (20, 19), (22, 23), + (23, 8), (24, 25), (25, 12)] + inward = [(i - 1, j - 1) for (i, j) in inward_ori_index] + outward = [(j, i) for (i, j) in inward] + neighbor = inward + outward + + self.num_node = num_node + self.self_link = self_link + self.inward = inward + self.outward = outward + self.neighbor = neighbor + self.A = self.get_adjacency_matrix(labeling_mode) + + def edge2mat(self, link, num_node): + A = np.zeros((num_node, num_node)) + for i, j in link: + A[j, i] = 1 + return A + + def normalize_digraph(self, A): + Dl = np.sum(A, 0) + h, w = A.shape + Dn = np.zeros((w, w)) + for i in range(w): + if Dl[i] > 0: + Dn[i, i] = Dl[i]**(-1) + AD = np.dot(A, Dn) + return AD + + def get_spatial_graph(self, num_node, self_link, inward, outward): + I = self.edge2mat(self_link, num_node) + In = self.normalize_digraph(self.edge2mat(inward, num_node)) + Out = self.normalize_digraph(self.edge2mat(outward, num_node)) + A = np.stack((I, In, Out)) + return A + + def get_adjacency_matrix(self, labeling_mode=None): + if labeling_mode is None: + return self.A + if labeling_mode == 'spatial': + A = self.get_spatial_graph(self.num_node, self.self_link, + self.inward, self.outward) + else: + raise ValueError() + return A + + +@BACKBONES.register() +class AGCN2s(nn.Layer): + def __init__(self, + num_point=25, + num_person=2, + graph='ntu_rgb_d', + graph_args=dict(), + in_channels=3): + super(AGCN2s, self).__init__() + + if graph == 'ntu_rgb_d': + self.graph = Graph(**graph_args) + else: + raise ValueError() + + A = self.graph.A + self.data_bn = nn.BatchNorm1D(num_person * in_channels * num_point) + + self.l1 = Block(in_channels, 64, A, residual=False) + self.l2 = Block(64, 64, A) + self.l3 = Block(64, 64, A) + self.l4 = Block(64, 64, A) + self.l5 = Block(64, 128, A, stride=2) + self.l6 = Block(128, 128, A) + self.l7 = Block(128, 128, A) + self.l8 = Block(128, 256, A, stride=2) + self.l9 = Block(256, 256, A) + self.l10 = Block(256, 256, A) + + def forward(self, x): + N, C, T, V, M = x.shape + + x = x.transpose([0, 4, 3, 1, 2]).reshape_([N, M * V * C, T]) + x = self.data_bn(x) + x = x.reshape_([N, M, V, C, + T]).transpose([0, 1, 3, 4, + 2]).reshape_([N * M, C, T, V]) + + x = self.l1(x) + x = self.l2(x) + x = self.l3(x) + x = self.l4(x) + x = self.l5(x) + x = self.l6(x) + x = self.l7(x) + x = self.l8(x) + x = self.l9(x) + x = self.l10(x) + + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/asrf.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/asrf.py new file mode 100644 index 0000000..37437b3 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/asrf.py @@ -0,0 +1,75 @@ +# Copyright (c) 2021 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. + +# https://github.com/yabufarha/ms-tcn/blob/master/model.py +# https://github.com/yiskw713/asrf/libs/models/tcn.py + +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np +import copy +import random +import math + +from paddle import ParamAttr +from ..registry import BACKBONES +from ..weight_init import weight_init_ +from .ms_tcn import DilatedResidualLayer +from ..framework.segmenters.utils import init_bias, KaimingUniform_like_torch + + +@BACKBONES.register() +class ASRF(nn.Layer): + + def __init__(self, in_channel, num_features, num_classes, num_stages, + num_layers): + super().__init__() + self.in_channel = in_channel + self.num_features = num_features + self.num_classes = num_classes + self.num_stages = num_stages + self.num_layers = num_layers + + # define layers + self.conv_in = nn.Conv1D(self.in_channel, self.num_features, 1) + + shared_layers = [ + DilatedResidualLayer(2**i, self.num_features, self.num_features) + for i in range(self.num_layers) + ] + self.shared_layers = nn.LayerList(shared_layers) + + self.init_weights() + + def init_weights(self): + """ + initialize model layers' weight + """ + # init weight + for layer in self.sublayers(): + if isinstance(layer, nn.Conv1D): + layer.weight.set_value( + KaimingUniform_like_torch(layer.weight).astype('float32')) + if layer.bias is not None: + layer.bias.set_value( + init_bias(layer.weight, layer.bias).astype('float32')) + + def forward(self, x): + """ ASRF forward + """ + out = self.conv_in(x) + for layer in self.shared_layers: + out = layer(out) + return out diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/bmn.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/bmn.py new file mode 100644 index 0000000..200d192 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/bmn.py @@ -0,0 +1,290 @@ +# 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 math +import numpy as np +import paddle +from paddle import ParamAttr +from ..registry import BACKBONES + + +def _get_interp1d_bin_mask(seg_xmin, seg_xmax, tscale, num_sample, + num_sample_perbin): + """ generate sample mask for a boundary-matching pair """ + plen = float(seg_xmax - seg_xmin) + plen_sample = plen / (num_sample * num_sample_perbin - 1.0) + total_samples = [ + seg_xmin + plen_sample * ii + for ii in range(num_sample * num_sample_perbin) + ] + p_mask = [] + for idx in range(num_sample): + bin_samples = total_samples[idx * num_sample_perbin:(idx + 1) * + num_sample_perbin] + bin_vector = np.zeros([tscale]) + for sample in bin_samples: + sample_upper = math.ceil(sample) + sample_decimal, sample_down = math.modf(sample) + if (tscale - 1) >= int(sample_down) >= 0: + bin_vector[int(sample_down)] += 1 - sample_decimal + if (tscale - 1) >= int(sample_upper) >= 0: + bin_vector[int(sample_upper)] += sample_decimal + bin_vector = 1.0 / num_sample_perbin * bin_vector + p_mask.append(bin_vector) + p_mask = np.stack(p_mask, axis=1) + return p_mask + + +def get_interp1d_mask(tscale, dscale, prop_boundary_ratio, num_sample, + num_sample_perbin): + """ generate sample mask for each point in Boundary-Matching Map """ + mask_mat = [] + for start_index in range(tscale): + mask_mat_vector = [] + for duration_index in range(dscale): + if start_index + duration_index < tscale: + p_xmin = start_index + p_xmax = start_index + duration_index + center_len = float(p_xmax - p_xmin) + 1 + sample_xmin = p_xmin - center_len * prop_boundary_ratio + sample_xmax = p_xmax + center_len * prop_boundary_ratio + p_mask = _get_interp1d_bin_mask(sample_xmin, sample_xmax, + tscale, num_sample, + num_sample_perbin) + else: + p_mask = np.zeros([tscale, num_sample]) + mask_mat_vector.append(p_mask) + mask_mat_vector = np.stack(mask_mat_vector, axis=2) + mask_mat.append(mask_mat_vector) + mask_mat = np.stack(mask_mat, axis=3) + mask_mat = mask_mat.astype(np.float32) + + sample_mask = np.reshape(mask_mat, [tscale, -1]) + return sample_mask + + +def init_params(name, in_channels, kernel_size): + fan_in = in_channels * kernel_size * 1 + k = 1. / math.sqrt(fan_in) + param_attr = ParamAttr(name=name, + initializer=paddle.nn.initializer.Uniform(low=-k, + high=k)) + return param_attr + + +@BACKBONES.register() +class BMN(paddle.nn.Layer): + """BMN model from + `"BMN: Boundary-Matching Network for Temporal Action Proposal Generation" `_ + Args: + tscale (int): sequence length, default 100. + dscale (int): max duration length, default 100. + prop_boundary_ratio (float): ratio of expanded temporal region in proposal boundary, default 0.5. + num_sample (int): number of samples betweent starting boundary and ending boundary of each propoasl, default 32. + num_sample_perbin (int): number of selected points in each sample, default 3. + """ + + def __init__( + self, + tscale, + dscale, + prop_boundary_ratio, + num_sample, + num_sample_perbin, + feat_dim=400, + ): + super(BMN, self).__init__() + + #init config + self.feat_dim = feat_dim + self.tscale = tscale + self.dscale = dscale + self.prop_boundary_ratio = prop_boundary_ratio + self.num_sample = num_sample + self.num_sample_perbin = num_sample_perbin + + self.hidden_dim_1d = 256 + self.hidden_dim_2d = 128 + self.hidden_dim_3d = 512 + + # Base Module + self.b_conv1 = paddle.nn.Conv1D( + in_channels=self.feat_dim, + out_channels=self.hidden_dim_1d, + kernel_size=3, + padding=1, + groups=4, + weight_attr=init_params('Base_1_w', self.feat_dim, 3), + bias_attr=init_params('Base_1_b', self.feat_dim, 3)) + self.b_conv1_act = paddle.nn.ReLU() + + self.b_conv2 = paddle.nn.Conv1D( + in_channels=self.hidden_dim_1d, + out_channels=self.hidden_dim_1d, + kernel_size=3, + padding=1, + groups=4, + weight_attr=init_params('Base_2_w', self.hidden_dim_1d, 3), + bias_attr=init_params('Base_2_b', self.hidden_dim_1d, 3)) + self.b_conv2_act = paddle.nn.ReLU() + + # Temporal Evaluation Module + self.ts_conv1 = paddle.nn.Conv1D( + in_channels=self.hidden_dim_1d, + out_channels=self.hidden_dim_1d, + kernel_size=3, + padding=1, + groups=4, + weight_attr=init_params('TEM_s1_w', self.hidden_dim_1d, 3), + bias_attr=init_params('TEM_s1_b', self.hidden_dim_1d, 3)) + self.ts_conv1_act = paddle.nn.ReLU() + + self.ts_conv2 = paddle.nn.Conv1D( + in_channels=self.hidden_dim_1d, + out_channels=1, + kernel_size=1, + padding=0, + groups=1, + weight_attr=init_params('TEM_s2_w', self.hidden_dim_1d, 1), + bias_attr=init_params('TEM_s2_b', self.hidden_dim_1d, 1)) + self.ts_conv2_act = paddle.nn.Sigmoid() + + self.te_conv1 = paddle.nn.Conv1D( + in_channels=self.hidden_dim_1d, + out_channels=self.hidden_dim_1d, + kernel_size=3, + padding=1, + groups=4, + weight_attr=init_params('TEM_e1_w', self.hidden_dim_1d, 3), + bias_attr=init_params('TEM_e1_b', self.hidden_dim_1d, 3)) + self.te_conv1_act = paddle.nn.ReLU() + self.te_conv2 = paddle.nn.Conv1D( + in_channels=self.hidden_dim_1d, + out_channels=1, + kernel_size=1, + padding=0, + groups=1, + weight_attr=init_params('TEM_e2_w', self.hidden_dim_1d, 1), + bias_attr=init_params('TEM_e2_b', self.hidden_dim_1d, 1)) + self.te_conv2_act = paddle.nn.Sigmoid() + + #Proposal Evaluation Module + self.p_conv1 = paddle.nn.Conv1D( + in_channels=self.hidden_dim_1d, + out_channels=self.hidden_dim_2d, + kernel_size=3, + padding=1, + groups=1, + weight_attr=init_params('PEM_1d_w', self.hidden_dim_1d, 3), + bias_attr=init_params('PEM_1d_b', self.hidden_dim_1d, 3)) + self.p_conv1_act = paddle.nn.ReLU() + + # init to speed up + sample_mask = get_interp1d_mask(self.tscale, self.dscale, + self.prop_boundary_ratio, + self.num_sample, self.num_sample_perbin) + self.sample_mask = paddle.to_tensor(sample_mask) + self.sample_mask.stop_gradient = True + + self.p_conv3d1 = paddle.nn.Conv3D( + in_channels=128, + out_channels=self.hidden_dim_3d, + kernel_size=(self.num_sample, 1, 1), + stride=(self.num_sample, 1, 1), + padding=0, + weight_attr=ParamAttr(name="PEM_3d1_w"), + bias_attr=ParamAttr(name="PEM_3d1_b")) + self.p_conv3d1_act = paddle.nn.ReLU() + + self.p_conv2d1 = paddle.nn.Conv2D( + in_channels=512, + out_channels=self.hidden_dim_2d, + kernel_size=1, + stride=1, + padding=0, + weight_attr=ParamAttr(name="PEM_2d1_w"), + bias_attr=ParamAttr(name="PEM_2d1_b")) + self.p_conv2d1_act = paddle.nn.ReLU() + + self.p_conv2d2 = paddle.nn.Conv2D( + in_channels=128, + out_channels=self.hidden_dim_2d, + kernel_size=3, + stride=1, + padding=1, + weight_attr=ParamAttr(name="PEM_2d2_w"), + bias_attr=ParamAttr(name="PEM_2d2_b")) + self.p_conv2d2_act = paddle.nn.ReLU() + + self.p_conv2d3 = paddle.nn.Conv2D( + in_channels=128, + out_channels=self.hidden_dim_2d, + kernel_size=3, + stride=1, + padding=1, + weight_attr=ParamAttr(name="PEM_2d3_w"), + bias_attr=ParamAttr(name="PEM_2d3_b")) + self.p_conv2d3_act = paddle.nn.ReLU() + + self.p_conv2d4 = paddle.nn.Conv2D( + in_channels=128, + out_channels=2, + kernel_size=1, + stride=1, + padding=0, + weight_attr=ParamAttr(name="PEM_2d4_w"), + bias_attr=ParamAttr(name="PEM_2d4_b")) + self.p_conv2d4_act = paddle.nn.Sigmoid() + + def init_weights(self): + pass + + def forward(self, x): + #Base Module + x = self.b_conv1(x) + x = self.b_conv1_act(x) + x = self.b_conv2(x) + x = self.b_conv2_act(x) + + #TEM + xs = self.ts_conv1(x) + xs = self.ts_conv1_act(xs) + xs = self.ts_conv2(xs) + xs = self.ts_conv2_act(xs) + xs = paddle.squeeze(xs, axis=[1]) + xe = self.te_conv1(x) + xe = self.te_conv1_act(xe) + xe = self.te_conv2(xe) + xe = self.te_conv2_act(xe) + xe = paddle.squeeze(xe, axis=[1]) + + #PEM + xp = self.p_conv1(x) + xp = self.p_conv1_act(xp) + #BM layer + xp = paddle.matmul(xp, self.sample_mask) + xp = paddle.reshape(xp, shape=[0, 0, -1, self.dscale, self.tscale]) + + xp = self.p_conv3d1(xp) + xp = self.p_conv3d1_act(xp) + xp = paddle.squeeze(xp, axis=[2]) + xp = self.p_conv2d1(xp) + xp = self.p_conv2d1_act(xp) + xp = self.p_conv2d2(xp) + xp = self.p_conv2d2_act(xp) + xp = self.p_conv2d3(xp) + xp = self.p_conv2d3_act(xp) + xp = self.p_conv2d4(xp) + xp = self.p_conv2d4_act(xp) + return xp, xs, xe diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/cfbi.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/cfbi.py new file mode 100644 index 0000000..5fbf044 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/cfbi.py @@ -0,0 +1,88 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +from ..registry import BACKBONES +from .deeplab import DeepLab + + +class FPN(nn.Layer): + """FPN Layer""" + def __init__(self, in_dim_4x, in_dim_8x, in_dim_16x, out_dim): + super(FPN, self).__init__() + self.toplayer = self._make_layer(in_dim_16x, out_dim) + self.latlayer1 = self._make_layer(in_dim_8x, out_dim) + self.latlayer2 = self._make_layer(in_dim_4x, out_dim) + + self.smooth1 = self._make_layer(out_dim, + out_dim, + kernel_size=3, + padding=1) + self.smooth2 = self._make_layer(out_dim, + out_dim, + kernel_size=3, + padding=1) + + def _make_layer(self, in_dim, out_dim, kernel_size=1, padding=0): + return nn.Sequential( + nn.Conv2D(in_dim, + out_dim, + kernel_size=kernel_size, + stride=1, + padding=padding, + bias_attr=False), + nn.GroupNorm(num_groups=32, num_channels=out_dim)) + + def forward(self, x_4x, x_8x, x_16x): + """ forward function""" + x_16x = self.toplayer(x_16x) + x_8x = self.latlayer1(x_8x) + x_4x = self.latlayer2(x_4x) + + x_8x = x_8x + F.interpolate( + x_16x, size=x_8x.shape[-2:], mode='bilinear', align_corners=True) + x_4x = x_4x + F.interpolate( + x_8x, size=x_4x.shape[-2:], mode='bilinear', align_corners=True) + + x_8x = self.smooth1(x_8x) + x_4x = self.smooth2(x_4x) + + return F.relu(x_4x), F.relu(x_8x), F.relu(x_16x) + + +@BACKBONES.register() +class CFBI(nn.Layer): + """CFBI plus backbone""" + def __init__(self, + backbone='resnet', + freeze_bn=True, + model_aspp_outdim=256, + in_dim_8x=512, + model_semantic_embedding_dim=256): #,epsilon=1e-05): + super(CFBI, self).__init__() + #self.epsilon = epsilon + self.feature_extracter = DeepLab(backbone=backbone, freeze_bn=freeze_bn) + self.fpn = FPN(in_dim_4x=model_aspp_outdim, + in_dim_8x=in_dim_8x, + in_dim_16x=model_aspp_outdim, + out_dim=model_semantic_embedding_dim) + + def forward(self, x): + """forward function""" + x, aspp_x, low_level, mid_level = self.feature_extracter(x, True) + x_4x, x_8x, x_16x = self.fpn(x, mid_level, aspp_x) + return x_4x, x_8x, x_16x, low_level diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/ctrgcn.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/ctrgcn.py new file mode 100644 index 0000000..9d645f4 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/ctrgcn.py @@ -0,0 +1,514 @@ +# Copyright (c) 2021 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 paddle +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np +from ..registry import BACKBONES +from ..weight_init import weight_init_ + + +def conv_init(conv): + if conv.weight is not None: + weight_init_(conv.weight, 'kaiming_normal_', mode='fan_in') + if conv.bias is not None: + nn.initializer.Constant(value=0.0)(conv.bias) + + +def bn_init(bn, scale): + nn.initializer.Constant(value=float(scale))(bn.weight) + nn.initializer.Constant(value=0.0)(bn.bias) + + +def einsum(x1, x3): + """paddle.einsum only support in dynamic graph mode. + x1 : n c u v + x2 : n c t v + """ + n, c, u, v1 = x1.shape + n, c, t, v3 = x3.shape + assert (v1 == v3), "Args of einsum not match!" + x1 = paddle.transpose(x1, perm=[0, 1, 3, 2]) # n c v u + y = paddle.matmul(x3, x1) + # out: n c t u + return y + + +class CTRGC(nn.Layer): + + def __init__(self, + in_channels, + out_channels, + rel_reduction=8, + mid_reduction=1): + super(CTRGC, self).__init__() + self.in_channels = in_channels + self.out_channels = out_channels + if in_channels == 3 or in_channels == 9: + self.rel_channels = 8 + self.mid_channels = 16 + else: + self.rel_channels = in_channels // rel_reduction + self.mid_channels = in_channels // mid_reduction + self.conv1 = nn.Conv2D(self.in_channels, + self.rel_channels, + kernel_size=1) + self.conv2 = nn.Conv2D(self.in_channels, + self.rel_channels, + kernel_size=1) + self.conv3 = nn.Conv2D(self.in_channels, + self.out_channels, + kernel_size=1) + self.conv4 = nn.Conv2D(self.rel_channels, + self.out_channels, + kernel_size=1) + self.tanh = nn.Tanh() + + def init_weights(self): + """Initiate the parameters. + """ + for m in self.sublayers(): + if isinstance(m, nn.Conv2D): + conv_init(m) + elif isinstance(m, nn.BatchNorm2D): + bn_init(m, 1) + + def forward(self, x, A=None, alpha=1): + x1, x2, x3 = self.conv1(x).mean(-2), self.conv2(x).mean(-2), self.conv3( + x) + x1 = self.tanh(x1.unsqueeze(-1) - x2.unsqueeze(-2)) + x1 = self.conv4(x1) * alpha + ( + A.unsqueeze(0).unsqueeze(0) if A is not None else 0) # N,C,V,V + # We only support 'paddle.einsum()' in dynamic graph mode, if use in infer model please implement self. + # x1 = paddle.einsum('ncuv,nctv->nctu', x1, x3) + x1 = einsum(x1, x3) + return x1 + + +class TemporalConv(nn.Layer): + + def __init__(self, + in_channels, + out_channels, + kernel_size, + stride=1, + dilation=1): + super(TemporalConv, self).__init__() + pad = (kernel_size + (kernel_size - 1) * (dilation - 1) - 1) // 2 + self.conv = nn.Conv2D(in_channels, + out_channels, + kernel_size=(kernel_size, 1), + padding=(pad, 0), + stride=(stride, 1), + dilation=(dilation, 1)) + + self.bn = nn.BatchNorm2D(out_channels) + + def forward(self, x): + x = self.conv(x) + x = self.bn(x) + return x + + +class MultiScale_TemporalConv(nn.Layer): + + def __init__(self, + in_channels, + out_channels, + kernel_size=3, + stride=1, + dilations=[1, 2, 3, 4], + residual=True, + residual_kernel_size=1): + + super(MultiScale_TemporalConv, self).__init__() + assert out_channels % ( + len(dilations) + + 2) == 0, '# out channels should be multiples of # branches' + + # Multiple branches of temporal convolution + self.num_branches = len(dilations) + 2 + branch_channels = out_channels // self.num_branches + if type(kernel_size) == list: + assert len(kernel_size) == len(dilations) + else: + kernel_size = [kernel_size] * len(dilations) + # Temporal Convolution branches + self.branches = nn.LayerList([ + nn.Sequential( + nn.Conv2D(in_channels, + branch_channels, + kernel_size=1, + padding=0), + nn.BatchNorm2D(branch_channels), + nn.ReLU(), + TemporalConv(branch_channels, + branch_channels, + kernel_size=ks, + stride=stride, + dilation=dilation), + ) for ks, dilation in zip(kernel_size, dilations) + ]) + + # Additional Max & 1x1 branch + self.branches.append( + nn.Sequential( + nn.Conv2D(in_channels, + branch_channels, + kernel_size=1, + padding=0), nn.BatchNorm2D(branch_channels), + nn.ReLU(), + nn.MaxPool2D(kernel_size=(3, 1), + stride=(stride, 1), + padding=(1, 0)), nn.BatchNorm2D(branch_channels))) + + self.branches.append( + nn.Sequential( + nn.Conv2D(in_channels, + branch_channels, + kernel_size=1, + padding=0, + stride=(stride, 1)), nn.BatchNorm2D(branch_channels))) + + # Residual connection + if not residual: + self.residual = lambda x: 0 + elif (in_channels == out_channels) and (stride == 1): + self.residual = lambda x: x + else: + self.residual = TemporalConv(in_channels, + out_channels, + kernel_size=residual_kernel_size, + stride=stride) + + def init_weights(self): + """Initiate the parameters. + """ + # initialize + for m in self.sublayers(): + if isinstance(m, nn.Conv2D): + conv_init(m) + elif isinstance(m, nn.BatchNorm2D): + weight_init_(m.weight, 'Normal', std=0.02, mean=1.0) + nn.initializer.Constant(value=0.0)(m.bias) + + def forward(self, x): + # Input dim: (N,C,T,V) + res = self.residual(x) + branch_outs = [] + for tempconv in self.branches: + out = tempconv(x) + branch_outs.append(out) + + out = paddle.concat(branch_outs, axis=1) + out += res + return out + + +class unit_tcn(nn.Layer): + + def __init__(self, in_channels, out_channels, kernel_size=9, stride=1): + super(unit_tcn, self).__init__() + pad = int((kernel_size - 1) / 2) + self.conv = nn.Conv2D(in_channels, + out_channels, + kernel_size=(kernel_size, 1), + padding=(pad, 0), + stride=(stride, 1)) + + self.bn = nn.BatchNorm2D(out_channels) + self.relu = nn.ReLU() + conv_init(self.conv) + bn_init(self.bn, 1) + + def forward(self, x): + x = self.bn(self.conv(x)) + return x + + +class unit_gcn(nn.Layer): + + def __init__(self, + in_channels, + out_channels, + A, + coff_embedding=4, + adaptive=True, + residual=True): + super(unit_gcn, self).__init__() + inter_channels = out_channels // coff_embedding + self.inter_c = inter_channels + self.out_c = out_channels + self.in_c = in_channels + self.adaptive = adaptive + self.num_subset = A.shape[0] + self.convs = nn.LayerList() + + for i in range(self.num_subset): + self.convs.append(CTRGC(in_channels, out_channels)) + + if residual: + if in_channels != out_channels: + self.down = nn.Sequential( + nn.Conv2D(in_channels, out_channels, 1), + nn.BatchNorm2D(out_channels)) + else: + self.down = lambda x: x + else: + self.down = lambda x: 0 + if self.adaptive: + pa_param = paddle.ParamAttr( + initializer=paddle.nn.initializer.Assign(A.astype(np.float32))) + self.PA = paddle.create_parameter(shape=A.shape, + dtype='float32', + attr=pa_param) + else: + A_tensor = paddle.to_tensor(A, dtype="float32") + self.A = paddle.create_parameter( + shape=A_tensor.shape, + dtype='float32', + default_initializer=paddle.nn.initializer.Assign(A_tensor)) + self.A.stop_gradient = True + alpha_tensor = paddle.to_tensor(np.zeros(1), dtype="float32") + self.alpha = paddle.create_parameter( + shape=alpha_tensor.shape, + dtype='float32', + default_initializer=paddle.nn.initializer.Assign(alpha_tensor)) + self.bn = nn.BatchNorm2D(out_channels) + self.soft = nn.Softmax(-2) + self.relu = nn.ReLU() + + def init_weights(self): + for m in self.sublayers(): + if isinstance(m, nn.Conv2D): + conv_init(m) + elif isinstance(m, nn.BatchNorm2D): + bn_init(m, 1) + bn_init(self.bn, 1e-6) + + def forward(self, x): + y = None + if self.adaptive: + A = self.PA + else: + A = self.A.cuda(x.get_device()) + for i in range(self.num_subset): + z = self.convs[i](x, A[i], self.alpha) + y = z + y if y is not None else z + y = self.bn(y) + y += self.down(x) + y = self.relu(y) + return y + + +class TCN_GCN_unit(nn.Layer): + + def __init__(self, + in_channels, + out_channels, + A, + stride=1, + residual=True, + adaptive=True, + kernel_size=5, + dilations=[1, 2]): + super(TCN_GCN_unit, self).__init__() + self.gcn1 = unit_gcn(in_channels, out_channels, A, adaptive=adaptive) + self.tcn1 = MultiScale_TemporalConv(out_channels, + out_channels, + kernel_size=kernel_size, + stride=stride, + dilations=dilations, + residual=False) + self.relu = nn.ReLU() + if not residual: + self.residual = lambda x: 0 + + elif (in_channels == out_channels) and (stride == 1): + self.residual = lambda x: x + + else: + self.residual = unit_tcn(in_channels, + out_channels, + kernel_size=1, + stride=stride) + + def forward(self, x): + y = self.relu(self.tcn1(self.gcn1(x)) + self.residual(x)) + return y + + +class NTUDGraph: + + def __init__(self, labeling_mode='spatial'): + num_node = 25 + self_link = [(i, i) for i in range(num_node)] + inward_ori_index = [(1, 2), (2, 21), (3, 21), (4, 3), (5, 21), (6, 5), + (7, 6), (8, 7), (9, 21), (10, 9), (11, 10), + (12, 11), (13, 1), (14, 13), (15, 14), (16, 15), + (17, 1), (18, 17), (19, 18), (20, 19), (22, 23), + (23, 8), (24, 25), (25, 12)] + inward = [(i - 1, j - 1) for (i, j) in inward_ori_index] + outward = [(j, i) for (i, j) in inward] + neighbor = inward + outward + + self.num_node = num_node + self.self_link = self_link + self.inward = inward + self.outward = outward + self.neighbor = neighbor + self.A = self.get_adjacency_matrix(labeling_mode) + + def edge2mat(self, link, num_node): + A = np.zeros((num_node, num_node)) + for i, j in link: + A[j, i] = 1 + return A + + def normalize_digraph(self, A): + Dl = np.sum(A, 0) + h, w = A.shape + Dn = np.zeros((w, w)) + for i in range(w): + if Dl[i] > 0: + Dn[i, i] = Dl[i]**(-1) + AD = np.dot(A, Dn) + return AD + + def get_spatial_graph(self, num_node, self_link, inward, outward): + I = self.edge2mat(self_link, num_node) + In = self.normalize_digraph(self.edge2mat(inward, num_node)) + Out = self.normalize_digraph(self.edge2mat(outward, num_node)) + A = np.stack((I, In, Out)) + return A + + def get_adjacency_matrix(self, labeling_mode=None): + if labeling_mode is None: + return self.A + if labeling_mode == 'spatial': + A = self.get_spatial_graph(self.num_node, self.self_link, + self.inward, self.outward) + else: + raise ValueError() + return A + + +@BACKBONES.register() +class CTRGCN(nn.Layer): + """ + CTR-GCN model from: + `"Channel-wise Topology Refinement Graph Convolution for Skeleton-Based Action Recognition" `_ + Args: + num_point: int, numbers of sketeton point. + num_person: int, numbers of person. + base_channel: int, model's hidden dim. + graph: str, sketeton adjacency matrix name. + graph_args: dict, sketeton adjacency graph class args. + in_channels: int, channels of vertex coordinate. 2 for (x,y), 3 for (x,y,z). Default 3. + adaptive: bool, if adjacency matrix can adaptive. + """ + + def __init__(self, + num_point=25, + num_person=2, + base_channel=64, + graph='ntu_rgb_d', + graph_args=dict(), + in_channels=3, + adaptive=True): + super(CTRGCN, self).__init__() + + if graph == 'ntu_rgb_d': + self.graph = NTUDGraph(**graph_args) + else: + raise ValueError() + + A = self.graph.A # 3,25,25 + + self.num_point = num_point + self.data_bn = nn.BatchNorm1D(num_person * in_channels * num_point) + self.base_channel = base_channel + + self.l1 = TCN_GCN_unit(in_channels, + self.base_channel, + A, + residual=False, + adaptive=adaptive) + self.l2 = TCN_GCN_unit(self.base_channel, + self.base_channel, + A, + adaptive=adaptive) + self.l3 = TCN_GCN_unit(self.base_channel, + self.base_channel, + A, + adaptive=adaptive) + self.l4 = TCN_GCN_unit(self.base_channel, + self.base_channel, + A, + adaptive=adaptive) + self.l5 = TCN_GCN_unit(self.base_channel, + self.base_channel * 2, + A, + stride=2, + adaptive=adaptive) + self.l6 = TCN_GCN_unit(self.base_channel * 2, + self.base_channel * 2, + A, + adaptive=adaptive) + self.l7 = TCN_GCN_unit(self.base_channel * 2, + self.base_channel * 2, + A, + adaptive=adaptive) + self.l8 = TCN_GCN_unit(self.base_channel * 2, + self.base_channel * 4, + A, + stride=2, + adaptive=adaptive) + self.l9 = TCN_GCN_unit(self.base_channel * 4, + self.base_channel * 4, + A, + adaptive=adaptive) + self.l10 = TCN_GCN_unit(self.base_channel * 4, + self.base_channel * 4, + A, + adaptive=adaptive) + + def init_weights(self): + bn_init(self.data_bn, 1) + + def forward(self, x): + N, C, T, V, M = x.shape + x = paddle.transpose(x, perm=[0, 4, 3, 1, 2]) + x = paddle.reshape(x, (N, M * V * C, T)) + + x = self.data_bn(x) + + x = paddle.reshape(x, (N, M, V, C, T)) + x = paddle.transpose(x, perm=(0, 1, 3, 4, 2)) + + x = paddle.reshape(x, (N * M, C, T, V)) + + x = self.l1(x) + x = self.l2(x) + x = self.l3(x) + x = self.l4(x) + x = self.l5(x) + x = self.l6(x) + x = self.l7(x) + x = self.l8(x) + x = self.l9(x) + x = self.l10(x) + + return x, N, M diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/darknet.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/darknet.py new file mode 100644 index 0000000..3f48bf6 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/darknet.py @@ -0,0 +1,165 @@ +# Copyright (c) 2021 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 paddle +from paddle import ParamAttr +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np + + +class ConvBNLayer(nn.Layer): + def __init__(self, + input_channels, + output_channels, + filter_size, + stride, + padding, + name=None): + super(ConvBNLayer, self).__init__() + + self._conv = nn.Conv2D( + in_channels=input_channels, + out_channels=output_channels, + kernel_size=filter_size, + stride=stride, + padding=padding, + weight_attr=ParamAttr(name=name + ".conv.weights"), + bias_attr=False) + + bn_name = name + ".bn" + self._bn = nn.BatchNorm( + num_channels=output_channels, + act="leaky_relu", + param_attr=ParamAttr(name=bn_name + ".scale"), + bias_attr=ParamAttr(name=bn_name + ".offset"), + moving_mean_name=bn_name + ".mean", + moving_variance_name=bn_name + ".var") + + def forward(self, inputs): + x = self._conv(inputs) + x = self._bn(x) + return x + + +class BasicBlock(nn.Layer): + def __init__(self, input_channels, output_channels, name=None): + super(BasicBlock, self).__init__() + + self._conv1 = ConvBNLayer(input_channels=input_channels, output_channels=output_channels, filter_size=[ + 3, 3], stride=1, padding=1, name=name+'.0') + self._max_pool = nn.MaxPool2D(kernel_size=2, stride=2, padding=0) + self._conv2 = ConvBNLayer(input_channels=output_channels, output_channels=output_channels * + 2, filter_size=[3, 3], stride=1, padding=1, name=name+'.1') + self._conv3 = ConvBNLayer(input_channels=output_channels*2, output_channels=output_channels, + filter_size=[1, 1], stride=1, padding=0, name=name+'.2') + + def forward(self, x): + x = self._conv1(x) + x = self._max_pool(x) + x = self._conv2(x) + x = self._conv3(x) + return x + + +class Reorg(nn.Layer): + def __init__(self, stride=2): + super(Reorg, self).__init__() + self.stride = stride + + def forward(self, x): + stride = self.stride + assert (x.dim() == 4) + B = x.shape[0] + C = x.shape[1] + H = x.shape[2] + W = x.shape[3] + assert (H % stride == 0) + assert (W % stride == 0) + ws = stride + hs = stride + x = x.reshape([B, C, H // hs, hs, W // ws, ws] + ).transpose([0, 1, 2, 4, 3, 5]) + x = x.reshape([B, C, H // hs * W // ws, hs * ws] + ).transpose([0, 1, 3, 2]) + x = x.reshape([B, C, hs * ws, H // hs, W // ws] + ).transpose([0, 2, 1, 3, 4]) + x = x.reshape([B, hs * ws * C, H // hs, W // ws]) + return x + + +class Darknet(nn.Layer): + def __init__(self, pretrained=None): + super(Darknet, self).__init__() + self.pretrained = pretrained + self._conv1 = ConvBNLayer( + input_channels=3, output_channels=32, filter_size=3, stride=1, padding=1, name='input') + self._max_pool1 = nn.MaxPool2D(kernel_size=2, stride=2, padding=0) + self._basic_block_11 = BasicBlock( + input_channels=32, output_channels=64, name='1.1') + self._basic_block_12 = BasicBlock( + input_channels=64, output_channels=128, name='1.2') + self._basic_block_13 = BasicBlock( + input_channels=128, output_channels=256, name='1.3') + self._conv2 = ConvBNLayer( + input_channels=256, output_channels=512, filter_size=3, stride=1, padding=1, name='up1') + self._conv3 = ConvBNLayer( + input_channels=512, output_channels=256, filter_size=1, stride=1, padding=0, name='down1') + self._conv4 = ConvBNLayer( + input_channels=256, output_channels=512, filter_size=3, stride=1, padding=1, name='2.1') + self._max_pool2 = nn.MaxPool2D(kernel_size=2, stride=2, padding=0) + self._conv5 = ConvBNLayer( + input_channels=512, output_channels=1024, filter_size=3, stride=1, padding=1, name='2.2') + self._conv6 = ConvBNLayer(input_channels=1024, output_channels=512, + filter_size=1, stride=1, padding=0, name='2.3') # ori + self._conv7 = ConvBNLayer( + input_channels=512, output_channels=1024, filter_size=3, stride=1, padding=1, name='up2') + self._conv8 = ConvBNLayer(input_channels=1024, output_channels=512, + filter_size=1, stride=1, padding=0, name='down2') + self._conv9 = ConvBNLayer( + input_channels=512, output_channels=1024, filter_size=3, stride=1, padding=1, name='3.1') + self._conv10 = ConvBNLayer( + input_channels=1024, output_channels=1024, filter_size=3, stride=1, padding=1, name='3.2') + self._conv11 = ConvBNLayer( + input_channels=1024, output_channels=1024, filter_size=3, stride=1, padding=1, name='3.3') + self._conv12 = ConvBNLayer( + input_channels=512, output_channels=64, filter_size=1, stride=1, padding=0, name='4.1') + self._reorg = Reorg() + self._conv13 = ConvBNLayer( + input_channels=1280, output_channels=1024, filter_size=3, stride=1, padding=1, name='5.1') + self._conv14 = nn.Conv2D(1024, 425, kernel_size=1) + + def forward(self, inputs): + x = self._conv1(inputs) + x = self._max_pool1(x) + x = self._basic_block_11(x) + x = self._basic_block_12(x) + x = self._basic_block_13(x) + x = self._conv2(x) + x = self._conv3(x) + ori = self._conv4(x) + x = self._max_pool2(ori) + x = self._conv5(x) + x = self._conv6(x) + x = self._conv7(x) + x = self._conv8(x) + x = self._conv9(x) + x = self._conv10(x) + x1 = self._conv11(x) + x2 = self._conv12(ori) + x2 = self._reorg(x2) + x = paddle.concat([x2, x1], 1) + x = self._conv13(x) + x = self._conv14(x) + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/deeplab.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/deeplab.py new file mode 100644 index 0000000..c566205 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/deeplab.py @@ -0,0 +1,454 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +import copy + +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +from ..registry import BACKBONES + + +class FrozenBatchNorm2D(nn.Layer): + """ + BatchNorm2D where the batch statistics and the affine parameters + are fixed + """ + def __init__(self, n, epsilon=1e-5): + super(FrozenBatchNorm2D, self).__init__() + x1 = paddle.ones([n]) + x2 = paddle.zeros([n]) + weight = self.create_parameter( + shape=x1.shape, default_initializer=nn.initializer.Assign(x1)) + bias = self.create_parameter( + shape=x2.shape, default_initializer=nn.initializer.Assign(x2)) + running_mean = self.create_parameter( + shape=x2.shape, default_initializer=nn.initializer.Assign(x2)) + running_var = self.create_parameter( + shape=x1.shape, default_initializer=nn.initializer.Assign(x1)) + self.add_parameter('weight', weight) + self.add_parameter('bias', bias) + self.add_parameter('running_mean', running_mean) + self.add_parameter('running_var', running_var) + self.epsilon = epsilon + + def forward(self, x): + scale = self.weight * paddle.rsqrt((self.running_var + self.epsilon)) + bias = self.bias - self.running_mean * scale + scale = paddle.reshape(scale, [1, -1, 1, 1]) + bias = paddle.reshape(bias, [1, -1, 1, 1]) + return x * scale + bias + + +class Bottleneck(nn.Layer): + expansion = 4 + + def __init__(self, + inplanes, + planes, + stride=1, + dilation=1, + downsample=None, + BatchNorm=None): + super(Bottleneck, self).__init__() + self.conv1 = nn.Conv2D(inplanes, planes, kernel_size=1, bias_attr=False) + self.bn1 = BatchNorm(planes) + self.conv2 = nn.Conv2D(planes, + planes, + kernel_size=3, + stride=stride, + dilation=dilation, + padding=dilation, + bias_attr=False) + self.bn2 = BatchNorm(planes) + self.conv3 = nn.Conv2D(planes, + planes * 4, + kernel_size=1, + bias_attr=False) + self.bn3 = BatchNorm(planes * 4) + self.relu = nn.ReLU() + self.downsample = downsample + self.stride = stride + self.dilation = dilation + + def forward(self, x): + residual = x + + out = self.conv1(x) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.relu(out) + + out = self.conv3(out) + out = self.bn3(out) + + if self.downsample is not None: + residual = self.downsample(x) + + out += residual + out = self.relu(out) + + return out + + +class ResNet(nn.Layer): + def __init__(self, + block, + layers, + output_stride, + BatchNorm, + pretrained=False): + self.inplanes = 64 + super(ResNet, self).__init__() + blocks = [1, 2, 4] + if output_stride == 16: + strides = [1, 2, 2, 1] + dilations = [1, 1, 1, 2] + elif output_stride == 8: + strides = [1, 2, 1, 1] + dilations = [1, 1, 2, 4] + else: + raise NotImplementedError + + # Modules + self.conv1 = nn.Conv2D(3, + 64, + kernel_size=7, + stride=2, + padding=3, + bias_attr=False) + self.bn1 = BatchNorm(64) + self.relu = nn.ReLU() + self.maxpool = nn.MaxPool2D(kernel_size=3, stride=2, padding=1) + + self.layer1 = self._make_layer(block, + 64, + layers[0], + stride=strides[0], + dilation=dilations[0], + BatchNorm=BatchNorm) + self.layer2 = self._make_layer(block, + 128, + layers[1], + stride=strides[1], + dilation=dilations[1], + BatchNorm=BatchNorm) + self.layer3 = self._make_layer(block, + 256, + layers[2], + stride=strides[2], + dilation=dilations[2], + BatchNorm=BatchNorm) + self.layer4 = self._make_MG_unit(block, + 512, + blocks=blocks, + stride=strides[3], + dilation=dilations[3], + BatchNorm=BatchNorm) + self._init_weight() + + def _make_layer(self, + block, + planes, + blocks, + stride=1, + dilation=1, + BatchNorm=None): + downsample = None + if stride != 1 or self.inplanes != planes * block.expansion: + downsample = nn.Sequential( + nn.Conv2D(self.inplanes, + planes * block.expansion, + kernel_size=1, + stride=stride, + bias_attr=False), + BatchNorm(planes * block.expansion), + ) + + layers = [] + layers.append( + block(self.inplanes, planes, stride, dilation, downsample, + BatchNorm)) + self.inplanes = planes * block.expansion + for i in range(1, blocks): + layers.append( + block(self.inplanes, + planes, + dilation=dilation, + BatchNorm=BatchNorm)) + + return nn.Sequential(*layers) + + def _make_MG_unit(self, + block, + planes, + blocks, + stride=1, + dilation=1, + BatchNorm=None): + downsample = None + if stride != 1 or self.inplanes != planes * block.expansion: + downsample = nn.Sequential( + nn.Conv2D(self.inplanes, + planes * block.expansion, + kernel_size=1, + stride=stride, + bias_attr=False), + BatchNorm(planes * block.expansion), + ) + + layers = [] + layers.append( + block(self.inplanes, + planes, + stride, + dilation=blocks[0] * dilation, + downsample=downsample, + BatchNorm=BatchNorm)) + self.inplanes = planes * block.expansion + for i in range(1, len(blocks)): + layers.append( + block(self.inplanes, + planes, + stride=1, + dilation=blocks[i] * dilation, + BatchNorm=BatchNorm)) + + return nn.Sequential(*layers) + + def forward(self, input, return_mid_level=False): + x = self.conv1(input) + x = self.bn1(x) + x = self.relu(x) + x = self.maxpool(x) + + x = self.layer1(x) + low_level_feat = x + x = self.layer2(x) + mid_level_feat = x + x = self.layer3(x) + x = self.layer4(x) + if return_mid_level: + return x, low_level_feat, mid_level_feat + else: + return x, low_level_feat + + def _init_weight(self): + for m in self.sublayers(): + if isinstance(m, nn.Conv2D): + nn.initializer.KaimingNormal() + elif isinstance(m, nn.GroupNorm): + m.weight.data = nn.initializer.Constant(1) + m.bias.data = nn.initializer.Constant(0) + + +class _ASPPModule(nn.Layer): + def __init__(self, inplanes, planes, kernel_size, padding, dilation, + BatchNorm): + super(_ASPPModule, self).__init__() + self.atrous_conv = nn.Conv2D(inplanes, + planes, + kernel_size=kernel_size, + stride=1, + padding=padding, + dilation=dilation, + bias_attr=False) + self.bn = BatchNorm(planes) + self.relu = nn.ReLU() + + self._init_weight() + + def forward(self, x): + x = self.atrous_conv(x) + x = self.bn(x) + + return self.relu(x) + + def _init_weight(self): + for m in self.sublayers(): + if isinstance(m, nn.Conv2D): + m.weight_attr = nn.initializer.KaimingNormal() + elif isinstance(m, nn.BatchNorm2D): + m.weight.data.fill_(1) + m.bias.data.zero_() + + +class ASPP(nn.Layer): + def __init__(self, backbone, output_stride, BatchNorm): + super(ASPP, self).__init__() + if backbone == 'drn': + inplanes = 512 + elif backbone == 'mobilenet': + inplanes = 320 + else: + inplanes = 2048 + if output_stride == 16: + dilations = [1, 6, 12, 18] + elif output_stride == 8: + dilations = [1, 12, 24, 36] + else: + raise NotImplementedError + + self.aspp1 = _ASPPModule(inplanes, + 256, + 1, + padding=0, + dilation=dilations[0], + BatchNorm=BatchNorm) + self.aspp2 = _ASPPModule(inplanes, + 256, + 3, + padding=dilations[1], + dilation=dilations[1], + BatchNorm=BatchNorm) + self.aspp3 = _ASPPModule(inplanes, + 256, + 3, + padding=dilations[2], + dilation=dilations[2], + BatchNorm=BatchNorm) + self.aspp4 = _ASPPModule(inplanes, + 256, + 3, + padding=dilations[3], + dilation=dilations[3], + BatchNorm=BatchNorm) + + self.global_avg_pool = nn.Sequential( + nn.AdaptiveAvgPool2D((1, 1)), + nn.Conv2D(inplanes, 256, 1, stride=1, bias_attr=False), + BatchNorm(256), nn.ReLU()) + self.conv1 = nn.Conv2D(1280, 256, 1, bias_attr=False) + self.bn1 = BatchNorm(256) + self.relu = nn.ReLU() + self.dropout = nn.Dropout(0.1) + self._init_weight() + + def forward(self, x): + x1 = self.aspp1(x) + x2 = self.aspp2(x) + x3 = self.aspp3(x) + x4 = self.aspp4(x) + x5 = self.global_avg_pool(x) + x5 = F.interpolate(x5, + size=x4.shape[2:], + mode='bilinear', + align_corners=True) + x = paddle.concat(x=[x1, x2, x3, x4, x5], axis=1) + + x = self.conv1(x) + x = self.bn1(x) + x = self.relu(x) + + return self.dropout(x) + + def _init_weight(self): + for m in self.sublayers(): + if isinstance(m, nn.Conv2D): + nn.initializer.KaimingNormal() + elif isinstance(m, nn.GroupNorm): + m.weight.data = nn.initializer.Constant(1) + m.bias.data = nn.initializer.Constant(0) + + +class Decoder(nn.Layer): + def __init__(self, backbone, BatchNorm): + super(Decoder, self).__init__() + if backbone == 'resnet': + low_level_inplanes = 256 + elif backbone == 'mobilenet': + raise NotImplementedError + else: + raise NotImplementedError + + self.conv1 = nn.Conv2D(low_level_inplanes, 48, 1, bias_attr=False) + self.bn1 = BatchNorm(48) + self.relu = nn.ReLU() + + self.last_conv = nn.Sequential( + nn.Conv2D(304, + 256, + kernel_size=3, + stride=1, + padding=1, + bias_attr=False), BatchNorm(256), nn.ReLU(), + nn.Sequential(), + nn.Conv2D(256, + 256, + kernel_size=3, + stride=1, + padding=1, + bias_attr=False), BatchNorm(256), nn.ReLU(), + nn.Sequential()) + + self._init_weight() + + def forward(self, x, low_level_feat): + low_level_feat = self.conv1(low_level_feat) + low_level_feat = self.bn1(low_level_feat) + low_level_feat = self.relu(low_level_feat) + + x = F.interpolate(x, + size=low_level_feat.shape[2:], + mode='bilinear', + align_corners=True) + x = paddle.concat(x=[x, low_level_feat], axis=1) + x = self.last_conv(x) + + return x + + def _init_weight(self): + for m in self.sublayers(): + if isinstance(m, nn.Conv2D): + nn.initializer.KaimingNormal() + elif isinstance(m, nn.GroupNorm): + m.weight.data = nn.initializer.Constant(1) + m.bias.data = nn.initializer.Constant(0) + + +class DeepLab(nn.Layer): + """DeepLab model for segmentation""" + def __init__(self, backbone='resnet', output_stride=16, freeze_bn=True): + super(DeepLab, self).__init__() + + if freeze_bn == True: + print("Use frozen BN in DeepLab!") + BatchNorm = FrozenBatchNorm2D + else: + BatchNorm = nn.BatchNorm2D + + self.backbone = ResNet(Bottleneck, [3, 4, 23, 3], + output_stride, + BatchNorm, + pretrained=True) + self.aspp = ASPP(backbone, output_stride, BatchNorm) + self.decoder = Decoder(backbone, BatchNorm) + + def forward(self, input, return_aspp=False): + """forward function""" + if return_aspp: + x, low_level_feat, mid_level_feat = self.backbone(input, True) + else: + x, low_level_feat = self.backbone(input) + aspp_x = self.aspp(x) + x = self.decoder(aspp_x, low_level_feat) + + if return_aspp: + return x, aspp_x, low_level_feat, mid_level_feat + else: + return x, low_level_feat diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/movinet.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/movinet.py new file mode 100644 index 0000000..cb6d4fd --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/movinet.py @@ -0,0 +1,574 @@ +import collections.abc +from itertools import repeat +from typing import Any, Callable, Optional, Tuple, Union + +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +from paddle.nn.layer import Identity + +from ..registry import BACKBONES +from collections import OrderedDict + +container_abcs = collections.abc +"""Model Config +""" + +A0 = {'block_num': [0, 1, 3, 3, 4, 4]} +A0['conv1'] = [3, 8, (1, 3, 3), (1, 2, 2), (0, 1, 1)] +A0['b2_l0'] = [8, 8, 24, (1, 5, 5), (1, 2, 2), (0, 2, 2), (0, 1, 1)] +A0['b3_l0'] = [8, 32, 80, (3, 3, 3), (1, 2, 2), (1, 0, 0), (0, 0, 0)] +A0['b3_l1'] = [32, 32, 80, (3, 3, 3), (1, 1, 1), (1, 1, 1), (0, 1, 1)] +A0['b3_l2'] = [32, 32, 80, (3, 3, 3), (1, 1, 1), (1, 1, 1), (0, 1, 1)] +A0['b4_l0'] = [32, 56, 184, (5, 3, 3), (1, 2, 2), (2, 0, 0), (0, 0, 0)] +A0['b4_l1'] = [56, 56, 112, (3, 3, 3), (1, 1, 1), (1, 1, 1), (0, 1, 1)] +A0['b4_l2'] = [56, 56, 184, (3, 3, 3), (1, 1, 1), (1, 1, 1), (0, 1, 1)] +A0['b5_l0'] = [56, 56, 184, (5, 3, 3), (1, 1, 1), (2, 1, 1), (0, 1, 1)] +A0['b5_l1'] = [56, 56, 184, (3, 3, 3), (1, 1, 1), (1, 1, 1), (0, 1, 1)] +A0['b5_l2'] = [56, 56, 184, (3, 3, 3), (1, 1, 1), (1, 1, 1), (0, 1, 1)] +A0['b5_l3'] = [56, 56, 184, (3, 3, 3), (1, 1, 1), (1, 1, 1), (0, 1, 1)] +A0['b6_l0'] = [56, 104, 384, (5, 3, 3), (1, 2, 2), (2, 1, 1), (0, 1, 1)] +A0['b6_l1'] = [104, 104, 280, (1, 5, 5), (1, 1, 1), (0, 2, 2), (0, 1, 1)] +A0['b6_l2'] = [104, 104, 280, (1, 5, 5), (1, 1, 1), (0, 2, 2), (0, 1, 1)] +A0['b6_l3'] = [104, 104, 344, (1, 5, 5), (1, 1, 1), (0, 2, 2), (0, 1, 1)] +A0['conv7'] = [104, 480, (1, 1, 1), (1, 1, 1), (0, 0, 0)] + +MODEL_CONFIG = {'A0': A0} + + +def _ntuple(n): + def parse(x): + if isinstance(x, container_abcs.Iterable): + return x + return tuple(repeat(x, n)) + + return parse + + +def _make_divisible(v: float, + divisor: int, + min_value: Optional[int] = None) -> int: + """ + This function is taken from the original tf repo. + It ensures that all layers have a channel number that is divisible by 8. + It can be seen here: + https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py + """ + if min_value is None: + min_value = divisor + new_v = max(min_value, int(v + divisor / 2) // divisor * divisor) + # Make sure that round down does not go down by more than 10%. + if new_v < 0.9 * v: + new_v += divisor + return new_v + + +_single = _ntuple(1) +_pair = _ntuple(2) +_triple = _ntuple(3) +_quadruple = _ntuple(4) + + +class CausalModule(nn.Layer): + def __init__(self) -> None: + super().__init__() + self.activation = None + + def reset_activation(self) -> None: + self.activation = None + + +class Conv2dBNActivation(nn.Sequential): + def __init__( + self, + in_planes: int, + out_planes: int, + kernel_size: Union[int, Tuple[int, int]], + padding: Union[int, Tuple[int, int]], + stride: Union[int, Tuple[int, int]] = 1, + groups: int = 1, + norm_layer: Optional[Callable[..., nn.Layer]] = None, + activation_layer: Optional[Callable[..., nn.Layer]] = None, + **kwargs: Any, + ) -> None: + kernel_size = _pair(kernel_size) + stride = _pair(stride) + padding = _pair(padding) + if norm_layer is None: + norm_layer = Identity + if activation_layer is None: + activation_layer = Identity + self.kernel_size = kernel_size + self.stride = stride + dict_layers = (nn.Conv2D(in_planes, + out_planes, + kernel_size=kernel_size, + stride=stride, + padding=padding, + groups=groups, + **kwargs), norm_layer(out_planes, + momentum=0.1), + activation_layer()) + + self.out_channels = out_planes + super(Conv2dBNActivation, self).__init__(dict_layers[0], dict_layers[1], + dict_layers[2]) + + +class Conv3DBNActivation(nn.Sequential): + def __init__( + self, + in_planes: int, + out_planes: int, + kernel_size: Union[int, Tuple[int, int, int]], + padding: Union[int, Tuple[int, int, int]], + stride: Union[int, Tuple[int, int, int]] = 1, + groups: int = 1, + norm_layer: Optional[Callable[..., nn.Layer]] = None, + activation_layer: Optional[Callable[..., nn.Layer]] = None, + **kwargs: Any, + ) -> None: + kernel_size = _triple(kernel_size) + stride = _triple(stride) + padding = _triple(padding) + if norm_layer is None: + norm_layer = Identity + if activation_layer is None: + activation_layer = Identity + self.kernel_size = kernel_size + self.stride = stride + + dict_layers = (nn.Conv3D(in_planes, + out_planes, + kernel_size=kernel_size, + stride=stride, + padding=padding, + groups=groups, + **kwargs), norm_layer(out_planes, + momentum=0.1), + activation_layer()) + self.out_channels = out_planes + super(Conv3DBNActivation, self).__init__(dict_layers[0], dict_layers[1], + dict_layers[2]) + + +class ConvBlock3D(CausalModule): + def __init__( + self, + in_planes: int, + out_planes: int, + kernel_size: Union[int, Tuple[int, int, int]], + causal: bool, + conv_type: str, + padding: Union[int, Tuple[int, int, int]] = 0, + stride: Union[int, Tuple[int, int, int]] = 1, + norm_layer: Optional[Callable[..., nn.Layer]] = None, + activation_layer: Optional[Callable[..., nn.Layer]] = None, + bias_attr: bool = False, + **kwargs: Any, + ) -> None: + super().__init__() + kernel_size = _triple(kernel_size) + stride = _triple(stride) + padding = _triple(padding) + self.conv_2 = None + + if causal is True: + padding = (0, padding[1], padding[2]) + if conv_type != "2plus1d" and conv_type != "3d": + raise ValueError("only 2plus2d or 3d are " + + "allowed as 3d convolutions") + + if conv_type == "2plus1d": + self.conv_1 = Conv2dBNActivation(in_planes, + out_planes, + kernel_size=(kernel_size[1], + kernel_size[2]), + padding=(padding[1], padding[2]), + stride=(stride[1], stride[2]), + activation_layer=activation_layer, + norm_layer=norm_layer, + bias_attr=bias_attr, + **kwargs) + if kernel_size[0] > 1: + self.conv_2 = Conv2dBNActivation( + in_planes, + out_planes, + kernel_size=(kernel_size[0], 1), + padding=(padding[0], 0), + stride=(stride[0], 1), + activation_layer=activation_layer, + norm_layer=norm_layer, + bias_attr=bias_attr, + **kwargs) + elif conv_type == "3d": + self.conv_1 = Conv3DBNActivation(in_planes, + out_planes, + kernel_size=kernel_size, + padding=padding, + activation_layer=activation_layer, + norm_layer=norm_layer, + stride=stride, + bias_attr=bias_attr, + **kwargs) + self.padding = padding + self.kernel_size = kernel_size + self.dim_pad = self.kernel_size[0] - 1 + self.stride = stride + self.causal = causal + self.conv_type = conv_type + + def _forward(self, x: paddle.Tensor) -> paddle.Tensor: + if self.dim_pad > 0 and self.conv_2 is None and self.causal is True: + x = self._cat_stream_buffer(x) + b, c, t, h, w = x.shape + if self.conv_type == "2plus1d": + x = paddle.transpose(x, (0, 2, 1, 3, 4)) # bcthw --> btchw + x = paddle.reshape_(x, (-1, c, h, w)) # btchw --> bt,c,h,w + x = self.conv_1(x) + if self.conv_type == "2plus1d": + b, c, h, w = x.shape + x = paddle.reshape_(x, (-1, t, c, h, w)) # bt,c,h,w --> b,t,c,h,w + x = paddle.transpose(x, (0, 2, 1, 3, 4)) # b,t,c,h,w --> b,c,t,h,w + if self.conv_2 is not None: + if self.dim_pad > 0 and self.causal is True: + x = self._cat_stream_buffer(x) + b, c, t, h, w = x.shape + x = paddle.reshape_(x, (b, c, t, h * w)) + x = self.conv_2(x) + b, c, t, _ = x.shape + x = paddle.reshape_(x, (b, c, t, h, w)) + return x + + def forward(self, x: paddle.Tensor) -> paddle.Tensor: + x = self._forward(x) + return x + + def _cat_stream_buffer(self, x: paddle.Tensor) -> paddle.Tensor: + if self.activation is None: + self._setup_activation(x.shape) + x = paddle.concat((self.activation, x), 2) + self._save_in_activation(x) + return x + + def _save_in_activation(self, x: paddle.Tensor) -> None: + assert self.dim_pad > 0 + self.activation = paddle.to_tensor(x.numpy()[:, :, -self.dim_pad:, + ...]).clone().detach() + + def _setup_activation(self, input_shape: Tuple[float, ...]) -> None: + assert self.dim_pad > 0 + self.activation = paddle.zeros(shape=[ + *input_shape[:2], # type: ignore + self.dim_pad, + *input_shape[3:] + ]) + + +class TemporalCGAvgPool3D(CausalModule): + def __init__(self, ) -> None: + super().__init__() + self.n_cumulated_values = 0 + self.register_forward_post_hook(self._detach_activation) + + def forward(self, x: paddle.Tensor) -> paddle.Tensor: + input_shape = x.shape + cumulative_sum = paddle.cumsum(x, axis=2) + if self.activation is None: + self.activation = cumulative_sum[:, :, -1:].clone() + else: + cumulative_sum += self.activation + self.activation = cumulative_sum[:, :, -1:].clone() + + noe = paddle.arange(1, input_shape[2] + 1) + axis = paddle.to_tensor([0, 1, 3, 4]) + noe = paddle.unsqueeze(noe, axis=axis) + divisor = noe.expand(x.shape) + x = cumulative_sum / (self.n_cumulated_values + divisor) + self.n_cumulated_values += input_shape[2] + return x + + @staticmethod + def _detach_activation(module: CausalModule, inputs: paddle.Tensor, + output: paddle.Tensor) -> None: + module.activation.detach() + + def reset_activation(self) -> None: + super().reset_activation() + self.n_cumulated_values = 0 + + +class SqueezeExcitation(nn.Layer): + def __init__(self, + input_channels: int, + activation_2: nn.Layer, + activation_1: nn.Layer, + conv_type: str, + causal: bool, + squeeze_factor: int = 4, + bias_attr: bool = True) -> None: + super().__init__() + self.causal = causal + se_multiplier = 2 if causal else 1 + squeeze_channels = _make_divisible( + input_channels // squeeze_factor * se_multiplier, 8) + self.temporal_cumualtive_GAvg3D = TemporalCGAvgPool3D() + self.fc1 = ConvBlock3D(input_channels * se_multiplier, + squeeze_channels, + kernel_size=(1, 1, 1), + padding=0, + causal=causal, + conv_type=conv_type, + bias_attr=bias_attr) + self.activation_1 = activation_1() + self.activation_2 = activation_2() + self.fc2 = ConvBlock3D(squeeze_channels, + input_channels, + kernel_size=(1, 1, 1), + padding=0, + causal=causal, + conv_type=conv_type, + bias_attr=bias_attr) + + def _scale(self, inputs: paddle.Tensor) -> paddle.Tensor: + if self.causal: + x_space = paddle.mean(inputs, axis=[3, 4], keepdim=True) + scale = self.temporal_cumualtive_GAvg3D(x_space) + scale = paddle.concat((scale, x_space), axis=1) + else: + scale = F.adaptive_avg_pool3d(inputs, 1) + scale = self.fc1(scale) + scale = self.activation_1(scale) + scale = self.fc2(scale) + return self.activation_2(scale) + + def forward(self, inputs: paddle.Tensor) -> paddle.Tensor: + scale = self._scale(inputs) + return scale * inputs + + +class BasicBneck(nn.Layer): + def __init__( + self, + input_channels, + out_channels, + expanded_channels, + kernel_size, + stride, + padding, + padding_avg, + causal: bool, + conv_type: str, + norm_layer: Optional[Callable[..., nn.Layer]] = None, + activation_layer: Optional[Callable[..., nn.Layer]] = None, + ) -> None: + super().__init__() + + assert type(stride) is tuple + + if (not stride[0] == 1 or not (1 <= stride[1] <= 2) + or not (1 <= stride[2] <= 2)): + raise ValueError('illegal stride value') + + self.res = None + + layers = [] + if expanded_channels != out_channels: + # expand + self.expand = ConvBlock3D(in_planes=input_channels, + out_planes=expanded_channels, + kernel_size=(1, 1, 1), + padding=(0, 0, 0), + causal=causal, + conv_type=conv_type, + norm_layer=norm_layer, + activation_layer=activation_layer) + # deepwise + self.deep = ConvBlock3D(in_planes=expanded_channels, + out_planes=expanded_channels, + kernel_size=kernel_size, + padding=padding, + stride=stride, + groups=expanded_channels, + causal=causal, + conv_type=conv_type, + norm_layer=norm_layer, + activation_layer=activation_layer) + + # SE + self.se = SqueezeExcitation( + expanded_channels, + causal=causal, + activation_1=activation_layer, + activation_2=(nn.Sigmoid if conv_type == "3d" else nn.Hardsigmoid), + conv_type=conv_type) + # project + self.project = ConvBlock3D(expanded_channels, + out_channels, + kernel_size=(1, 1, 1), + padding=(0, 0, 0), + causal=causal, + conv_type=conv_type, + norm_layer=norm_layer, + activation_layer=Identity) + + if not (stride == (1, 1, 1) and input_channels == out_channels): + if stride != (1, 1, 1): + layers.append( + nn.AvgPool3D((1, 3, 3), stride=stride, padding=padding_avg)) + layers.append( + ConvBlock3D( + in_planes=input_channels, + out_planes=out_channels, + kernel_size=(1, 1, 1), + padding=(0, 0, 0), + norm_layer=norm_layer, + activation_layer=Identity, + causal=causal, + conv_type=conv_type, + )) + self.res = nn.Sequential(*layers) + self.alpha = self.create_parameter(shape=[1], dtype="float32") + + def forward(self, inputs: paddle.Tensor) -> paddle.Tensor: + if self.res is not None: + residual = self.res(inputs) + else: + residual = inputs + if self.expand is not None: + x = self.expand(inputs) + else: + x = inputs + + x = self.deep(x) + x = self.se(x) + x = self.project(x) + result = residual + self.alpha * x + return result + + +@BACKBONES.register() +class MoViNet(nn.Layer): + def __init__( + self, + model_type: str = 'A0', + hidden_dim: int = 2048, + causal: bool = True, + num_classes: int = 400, + conv_type: str = "3d", + ) -> None: + super().__init__() + """ + causal: causal mode + num_classes: number of classes for classifcation + conv_type: type of convolution either 3d or 2plus1d + """ + blocks_dic = OrderedDict() + cfg = MODEL_CONFIG[model_type] + + norm_layer = nn.BatchNorm3D if conv_type == "3d" else nn.BatchNorm2D + activation_layer = nn.Swish if conv_type == "3d" else nn.Hardswish + + # conv1 + self.conv1 = ConvBlock3D(in_planes=cfg['conv1'][0], + out_planes=cfg['conv1'][1], + kernel_size=cfg['conv1'][2], + stride=cfg['conv1'][3], + padding=cfg['conv1'][4], + causal=causal, + conv_type=conv_type, + norm_layer=norm_layer, + activation_layer=activation_layer) + # blocks + for i in range(2, len(cfg['block_num']) + 1): + for j in range(cfg['block_num'][i - 1]): + blocks_dic[f'b{i}_l{j}'] = BasicBneck( + cfg[f'b{i}_l{j}'][0], + cfg[f'b{i}_l{j}'][1], + cfg[f'b{i}_l{j}'][2], + cfg[f'b{i}_l{j}'][3], + cfg[f'b{i}_l{j}'][4], + cfg[f'b{i}_l{j}'][5], + cfg[f'b{i}_l{j}'][6], + causal=causal, + conv_type=conv_type, + norm_layer=norm_layer, + activation_layer=activation_layer) + self.blocks = nn.Sequential(*(blocks_dic.values())) + + # conv7 + self.conv7 = ConvBlock3D(in_planes=cfg['conv7'][0], + out_planes=cfg['conv7'][1], + kernel_size=cfg['conv7'][2], + stride=cfg['conv7'][3], + padding=cfg['conv7'][4], + causal=causal, + conv_type=conv_type, + norm_layer=norm_layer, + activation_layer=activation_layer) + # pool + self.classifier = nn.Sequential( + # dense9 + ConvBlock3D(in_planes=cfg['conv7'][1], + out_planes=hidden_dim, + kernel_size=(1, 1, 1), + causal=causal, + conv_type=conv_type, + bias_attr=True), + nn.Swish(), + nn.Dropout(p=0.2), + # dense10d + ConvBlock3D(in_planes=hidden_dim, + out_planes=num_classes, + kernel_size=(1, 1, 1), + causal=causal, + conv_type=conv_type, + bias_attr=True), + ) + if causal: + self.cgap = TemporalCGAvgPool3D() + self.apply(self._weight_init) + self.causal = causal + + def avg(self, x: paddle.Tensor) -> paddle.Tensor: + if self.causal: + avg = F.adaptive_avg_pool3d(x, (x.shape[2], 1, 1)) + avg = self.cgap(avg)[:, :, -1:] + else: + avg = F.adaptive_avg_pool3d(x, 1) + return avg + + @staticmethod + def _weight_init(m): + if isinstance(m, nn.Conv3D): + nn.initializer.KaimingNormal(m.weight) + if m.bias is not None: + nn.initializer.Constant(0.0)(m.bias) + elif isinstance(m, (nn.BatchNorm3D, nn.BatchNorm2D, nn.GroupNorm)): + nn.initializer.Constant(1.0)(m.weight) + nn.initializer.Constant(0.0)(m.bias) + elif isinstance(m, nn.Linear): + nn.initializer.Normal(m.weight, 0, 0.01) + nn.initializer.Constant(0.0)(m.bias) + + def forward(self, x: paddle.Tensor) -> paddle.Tensor: + x = self.conv1(x) + x = self.blocks(x) + x = self.conv7(x) + x = self.avg(x) + x = self.classifier(x) + x = x.flatten(1) + return x + + @staticmethod + def _clean_activation_buffers(m): + if issubclass(type(m), CausalModule): + m.reset_activation() + + def clean_activation_buffers(self) -> None: + self.apply(self._clean_activation_buffers) + + +if __name__ == '__main__': + net = MoViNet(causal=False, conv_type='3d') + paddle.summary(net, input_size=(1, 3, 8, 224, 224)) diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/ms_tcn.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/ms_tcn.py new file mode 100644 index 0000000..fb49b9c --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/ms_tcn.py @@ -0,0 +1,154 @@ +# Copyright (c) 2021 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 paddle +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np +import copy +import random +import math + +from paddle import ParamAttr +from ..registry import BACKBONES +from ..weight_init import weight_init_ + + +def _calculate_fan_in_and_fan_out(tensor): + dimensions = len(tensor.shape) + if dimensions < 2: + raise ValueError("Fan in and fan out can not be computed \ + for tensor with fewer than 2 dimensions") + + if dimensions == 2: # Linear + fan_in = tensor.shape[1] + fan_out = tensor.shape[0] + else: + num_input_fmaps = tensor.shape[1] + num_output_fmaps = tensor.shape[0] + receptive_field_size = 1 + if tensor.dim() > 2: + receptive_field_size = tensor[0][0].numel() + fan_in = num_input_fmaps * receptive_field_size + fan_out = num_output_fmaps * receptive_field_size + + return fan_in, fan_out + + +def calculate_gain(nonlinearity=None, a=None): + if nonlinearity == 'tanh': + return 5.0 / 3 + elif nonlinearity == 'relu': + return math.sqrt(2.0) + elif nonlinearity == 'leaky_relu': + if a != None: + return math.sqrt(2.0 / (1 + a**2)) + else: + return math.sqrt(2.0 / (1 + 0.01**2)) + elif nonlinearity == 'selu': + return 3.0 / 4 + else: + return 1 + + +def KaimingUniform_like_torch(weight_npy, + mode='fan_in', + nonlinearity='leaky_relu'): + fan_in, fan_out = _calculate_fan_in_and_fan_out(weight_npy) + if mode == 'fan_in': + fan_mode = fan_in + else: + fan_mode = fan_out + a = math.sqrt(5.0) + gain = calculate_gain(nonlinearity=nonlinearity, a=a) + std = gain / math.sqrt(fan_mode) + bound = math.sqrt(3.0) * std + return np.random.uniform(-bound, bound, weight_npy.shape) + + +def init_bias(weight_npy, bias_npy): + # attention this weight is not bias + fan_in, fan_out = _calculate_fan_in_and_fan_out(weight_npy) + bound = 1.0 / math.sqrt(fan_in) + return np.random.uniform(-bound, bound, bias_npy.shape) + + +class SingleStageModel(nn.Layer): + + def __init__(self, num_layers, num_f_maps, dim, num_classes): + super(SingleStageModel, self).__init__() + self.conv_in = nn.Conv1D(dim, num_f_maps, 1) + self.layers = nn.LayerList([ + copy.deepcopy(DilatedResidualLayer(2**i, num_f_maps, num_f_maps)) + for i in range(num_layers) + ]) + self.conv_out = nn.Conv1D(num_f_maps, num_classes, 1) + + def forward(self, x): + out = self.conv_in(x) + for layer in self.layers: + out = layer(out) + out = self.conv_out(out) + return out + + +class DilatedResidualLayer(nn.Layer): + + def __init__(self, dilation, in_channels, out_channels): + super(DilatedResidualLayer, self).__init__() + self.conv_dilated = nn.Conv1D(in_channels, + out_channels, + 3, + padding=dilation, + dilation=dilation) + self.conv_in = nn.Conv1D(out_channels, out_channels, 1) + self.dropout = nn.Dropout() + + def forward(self, x): + out = F.relu(self.conv_dilated(x)) + out = self.conv_in(out) + out = self.dropout(out) + return (x + out) + + +@BACKBONES.register() +class MSTCN(nn.Layer): + + def __init__(self, num_stages, num_layers, num_f_maps, dim, num_classes): + super().__init__() + self.stage1 = SingleStageModel(num_layers, num_f_maps, dim, num_classes) + self.stages = nn.LayerList([ + copy.deepcopy( + SingleStageModel(num_layers, num_f_maps, num_classes, + num_classes)) for s in range(num_stages - 1) + ]) + + def forward(self, x): + """ MSTCN forward + """ + out = self.stage1(x) + outputs = out.unsqueeze(0) + for s in self.stages: + out = s(F.softmax(out, axis=1)) + outputs = paddle.concat((outputs, out.unsqueeze(0)), axis=0) + return outputs + + def init_weights(self): + for layer in self.sublayers(): + if isinstance(layer, nn.Conv1D): + layer.weight.set_value( + KaimingUniform_like_torch(layer.weight).astype('float32')) + if layer.bias is not None: + layer.bias.set_value( + init_bias(layer.weight, layer.bias).astype('float32')) diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_mv2.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_mv2.py new file mode 100644 index 0000000..28d045d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_mv2.py @@ -0,0 +1,282 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +import paddle +from paddle import ParamAttr +import paddle.nn as nn +import paddle.nn.functional as F +from paddle.nn import Conv2D, BatchNorm, Linear, Dropout +from paddle.nn import AdaptiveAvgPool2D, MaxPool2D, AvgPool2D + +from ..registry import BACKBONES +from ..weight_init import weight_init_ +from ...utils import load_ckpt + +# Download URL of pretrained model +# { +# "MobileNetV2": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_ssld_pretrained.pdparams", + +# "MobileNetV2_x0_25": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_x0_25_pretrained.pdparams", +# "MobileNetV2_x0_5": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_x0_5_pretrained.pdparams", +# "MobileNetV2_x0_75": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_x0_75_pretrained.pdparams", +# "MobileNetV2_x1_5": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_x1_5_pretrained.pdparams", +# "MobileNetV2_x2_0": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/MobileNetV2_x2_0_pretrained.pdparams" +# } + + +class ConvBNLayer(nn.Layer): + def __init__(self, + num_channels, + filter_size, + num_filters, + stride, + padding, + channels=None, + num_groups=1, + name=None, + use_cudnn=True): + super(ConvBNLayer, self).__init__() + + self._conv = Conv2D(in_channels=num_channels, + out_channels=num_filters, + kernel_size=filter_size, + stride=stride, + padding=padding, + groups=num_groups, + weight_attr=ParamAttr(name=name + "_weights"), + bias_attr=False) + + self._batch_norm = BatchNorm( + num_filters, + param_attr=ParamAttr(name=name + "_bn_scale"), + bias_attr=ParamAttr(name=name + "_bn_offset"), + moving_mean_name=name + "_bn_mean", + moving_variance_name=name + "_bn_variance") + + def forward(self, inputs, if_act=True): + y = self._conv(inputs) + y = self._batch_norm(y) + if if_act: + y = F.relu6(y) + return y + + +class InvertedResidualUnit(nn.Layer): + def __init__(self, num_channels, num_in_filter, num_filters, stride, + filter_size, padding, expansion_factor, name, num_seg): + super(InvertedResidualUnit, self).__init__() + self.num_seg = num_seg + num_expfilter = int(round(num_in_filter * expansion_factor)) + self._expand_conv = ConvBNLayer(num_channels=num_channels, + num_filters=num_expfilter, + filter_size=1, + stride=1, + padding=0, + num_groups=1, + name=name + "_expand") + + self._bottleneck_conv = ConvBNLayer(num_channels=num_expfilter, + num_filters=num_expfilter, + filter_size=filter_size, + stride=stride, + padding=padding, + num_groups=num_expfilter, + use_cudnn=False, + name=name + "_dwise") + + self._linear_conv = ConvBNLayer(num_channels=num_expfilter, + num_filters=num_filters, + filter_size=1, + stride=1, + padding=0, + num_groups=1, + name=name + "_linear") + + def forward(self, inputs, ifshortcut): + # add temporal shift module + y = inputs + if ifshortcut: + y = F.temporal_shift(y, self.num_seg, 1.0 / self.num_seg) + + y = self._expand_conv(y, if_act=True) + y = self._bottleneck_conv(y, if_act=True) + y = self._linear_conv(y, if_act=False) + if ifshortcut: + y = paddle.add(inputs, y) + return y + + +class InvresiBlocks(nn.Layer): + def __init__(self, in_c, t, c, n, s, name, num_seg): + super(InvresiBlocks, self).__init__() + + self._first_block = InvertedResidualUnit(num_channels=in_c, + num_in_filter=in_c, + num_filters=c, + stride=s, + filter_size=3, + padding=1, + expansion_factor=t, + name=name + "_1", + num_seg=num_seg) + + self._block_list = [] + for i in range(1, n): + block = self.add_sublayer(name + "_" + str(i + 1), + sublayer=InvertedResidualUnit( + num_channels=c, + num_in_filter=c, + num_filters=c, + stride=1, + filter_size=3, + padding=1, + expansion_factor=t, + name=name + "_" + str(i + 1), + num_seg=num_seg)) + self._block_list.append(block) + + def forward(self, inputs): + y = self._first_block(inputs, ifshortcut=False) + for block in self._block_list: + y = block(y, ifshortcut=True) + return y + + +class MobileNet(nn.Layer): + def __init__(self, + class_num=400, + scale=1.0, + pretrained=None, + prefix_name="", + num_seg=8): + super(MobileNet, self).__init__() + self.scale = scale + self.class_num = class_num + self.pretrained = pretrained + self.num_seg = num_seg + + bottleneck_params_list = [ + (1, 16, 1, 1), + (6, 24, 2, 2), + (6, 32, 3, 2), + (6, 64, 4, 2), + (6, 96, 3, 1), + (6, 160, 3, 2), + (6, 320, 1, 1), + ] + + self.conv1 = ConvBNLayer(num_channels=3, + num_filters=int(32 * scale), + filter_size=3, + stride=2, + padding=1, + name=prefix_name + "conv1_1") + + self.block_list = [] + i = 1 + in_c = int(32 * scale) + for layer_setting in bottleneck_params_list: + t, c, n, s = layer_setting + i += 1 + block = self.add_sublayer(prefix_name + "conv" + str(i), + sublayer=InvresiBlocks(in_c=in_c, + t=t, + c=int(c * scale), + n=n, + s=s, + name=prefix_name + + "conv" + str(i), + num_seg=num_seg)) + self.block_list.append(block) + in_c = int(c * scale) + + self.out_c = int(1280 * scale) if scale > 1.0 else 1280 + self.conv9 = ConvBNLayer(num_channels=in_c, + num_filters=self.out_c, + filter_size=1, + stride=1, + padding=0, + name=prefix_name + "conv9") + + self.pool2d_avg = AdaptiveAvgPool2D(1) + + self.out = Linear(self.out_c, + class_num, + weight_attr=ParamAttr(name=prefix_name + + "fc10_weights"), + bias_attr=ParamAttr(name=prefix_name + "fc10_offset")) + + def init_weights(self): + """Initiate the parameters. + """ + if isinstance(self.pretrained, str) and self.pretrained.strip() != "": + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + weight_init_(layer, 'KaimingNormal') + elif isinstance(layer, nn.BatchNorm2D): + weight_init_(layer, 'Constant', value=1) + + def forward(self, inputs): + y = self.conv1(inputs, if_act=True) + for block in self.block_list: + y = block(y) + y = self.conv9(y, if_act=True) + y = self.pool2d_avg(y) + + y = paddle.reshape(y, [-1, self.num_seg, y.shape[1]]) + y = paddle.mean(y, axis=1) + y = paddle.reshape(y, shape=[-1, self.out_c]) + + y = self.out(y) + return y + + +@BACKBONES.register() +def PPTSM_MobileNetV2(pretrained=None, **kwargs): + model = MobileNet(pretrained=pretrained, scale=1.0, **kwargs) + return model + + +def PPTSM_MobileNetV2_x0_25(pretrained=None, **kwargs): + model = MobileNet(pretrained=pretrained, scale=0.25, **kwargs) + return model + + +def PPTSM_MobileNetV2_x0_5(pretrained=None, **kwargs): + model = MobileNet(pretrained=pretrained, scale=0.5, **kwargs) + return model + + +def PPTSM_MobileNetV2_x0_75(pretrained=None, **kwargs): + model = MobileNet(pretrained=pretrained, scale=0.75, **kwargs) + return model + + +def PPTSM_MobileNetV2_x1_5(pretrained=None, **kwargs): + model = MobileNet(pretrained=pretrained, scale=1.5, **kwargs) + return model + + +def PPTSM_MobileNetV2_x2_0(pretrained=None, **kwargs): + model = MobileNet(pretrained=pretrained, scale=2.0, **kwargs) + return model diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_mv3.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_mv3.py new file mode 100644 index 0000000..cd10bac --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_mv3.py @@ -0,0 +1,408 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + +# reference: https://arxiv.org/abs/1905.02244 + +from __future__ import absolute_import, division, print_function + +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +from paddle import ParamAttr +from paddle.nn import AdaptiveAvgPool2D, BatchNorm, Conv2D, Dropout, Linear +from paddle.regularizer import L2Decay + +from ..registry import BACKBONES +from ..weight_init import weight_init_ +from ...utils import load_ckpt + +# Download URL of pretrained model +# MODEL_URLS = { +# "MobileNetV3_small_x1_0": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/legendary_models/MobileNetV3_small_x1_0_ssld_pretrained.pdparams", +# "MobileNetV3_large_x1_0": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/legendary_models/MobileNetV3_large_x1_0_ssld_pretrained.pdparams", +# } + +MODEL_STAGES_PATTERN = { + "MobileNetV3_small": ["blocks[0]", "blocks[2]", "blocks[7]", "blocks[10]"], + "MobileNetV3_large": + ["blocks[0]", "blocks[2]", "blocks[5]", "blocks[11]", "blocks[14]"] +} + +# "large", "small" is just for MobinetV3_large, MobileNetV3_small respectively. +# The type of "large" or "small" config is a list. Each element(list) represents a depthwise block, which is composed of k, exp, se, act, s. +# k: kernel_size +# exp: middle channel number in depthwise block +# c: output channel number in depthwise block +# se: whether to use SE block +# act: which activation to use +# s: stride in depthwise block +NET_CONFIG = { + "large": [ + # k, exp, c, se, act, s + [3, 16, 16, False, "relu", 1], + [3, 64, 24, False, "relu", 2], + [3, 72, 24, False, "relu", 1], + [5, 72, 40, True, "relu", 2], + [5, 120, 40, True, "relu", 1], + [5, 120, 40, True, "relu", 1], + [3, 240, 80, False, "hardswish", 2], + [3, 200, 80, False, "hardswish", 1], + [3, 184, 80, False, "hardswish", 1], + [3, 184, 80, False, "hardswish", 1], + [3, 480, 112, True, "hardswish", 1], + [3, 672, 112, True, "hardswish", 1], + [5, 672, 160, True, "hardswish", 2], + [5, 960, 160, True, "hardswish", 1], + [5, 960, 160, True, "hardswish", 1], + ], + "small": [ + # k, exp, c, se, act, s + [3, 16, 16, True, "relu", 2], + [3, 72, 24, False, "relu", 2], + [3, 88, 24, False, "relu", 1], + [5, 96, 40, True, "hardswish", 2], + [5, 240, 40, True, "hardswish", 1], + [5, 240, 40, True, "hardswish", 1], + [5, 120, 48, True, "hardswish", 1], + [5, 144, 48, True, "hardswish", 1], + [5, 288, 96, True, "hardswish", 2], + [5, 576, 96, True, "hardswish", 1], + [5, 576, 96, True, "hardswish", 1], + ] +} +# first conv output channel number in MobileNetV3 +STEM_CONV_NUMBER = 16 +# last second conv output channel for "small" +LAST_SECOND_CONV_SMALL = 576 +# last second conv output channel for "large" +LAST_SECOND_CONV_LARGE = 960 +# last conv output channel number for "large" and "small" +LAST_CONV = 1280 + + +def _make_divisible(v, divisor=8, min_value=None): + if min_value is None: + min_value = divisor + new_v = max(min_value, int(v + divisor / 2) // divisor * divisor) + if new_v < 0.9 * v: + new_v += divisor + return new_v + + +def _create_act(act): + if act == "hardswish": + return nn.Hardswish() + elif act == "relu": + return nn.ReLU() + elif act is None: + return None + else: + raise RuntimeError( + "The activation function is not supported: {}".format(act)) + + +class MobileNetV3(nn.Layer): + """ + MobileNetV3 + Args: + config: list. MobileNetV3 depthwise blocks config. + scale: float=1.0. The coefficient that controls the size of network parameters. + class_num: int=1000. The number of classes. + inplanes: int=16. The output channel number of first convolution layer. + class_squeeze: int=960. The output channel number of penultimate convolution layer. + class_expand: int=1280. The output channel number of last convolution layer. + dropout_prob: float=0.2. Probability of setting units to zero. + Returns: + model: nn.Layer. Specific MobileNetV3 model depends on args. + """ + def __init__(self, + config, + stages_pattern, + scale=1.0, + class_num=400, + inplanes=STEM_CONV_NUMBER, + class_squeeze=LAST_SECOND_CONV_LARGE, + class_expand=LAST_CONV, + dropout_prob=0.2, + num_seg=8, + pretrained=None, + return_patterns=None, + return_stages=None): + super().__init__() + + self.cfg = config + self.scale = scale + self.inplanes = inplanes + self.class_squeeze = class_squeeze + self.class_expand = class_expand + self.class_num = class_num + self.num_seg = num_seg + self.pretrained = pretrained + + self.conv = ConvBNLayer(in_c=3, + out_c=_make_divisible(self.inplanes * + self.scale), + filter_size=3, + stride=2, + padding=1, + num_groups=1, + if_act=True, + act="hardswish") + + self.blocks = nn.Sequential(*[ + ResidualUnit(in_c=_make_divisible(self.inplanes * self.scale if i == + 0 else self.cfg[i - 1][2] * + self.scale), + mid_c=_make_divisible(self.scale * exp), + out_c=_make_divisible(self.scale * c), + filter_size=k, + stride=s, + use_se=se, + num_seg=self.num_seg, + act=act) + for i, (k, exp, c, se, act, s) in enumerate(self.cfg) + ]) + + self.last_second_conv = ConvBNLayer( + in_c=_make_divisible(self.cfg[-1][2] * self.scale), + out_c=_make_divisible(self.scale * self.class_squeeze), + filter_size=1, + stride=1, + padding=0, + num_groups=1, + if_act=True, + act="hardswish") + + self.avg_pool = AdaptiveAvgPool2D(1) + + self.last_conv = Conv2D(in_channels=_make_divisible(self.scale * + self.class_squeeze), + out_channels=self.class_expand, + kernel_size=1, + stride=1, + padding=0, + bias_attr=False) + + self.hardswish = nn.Hardswish() + if dropout_prob is not None: + self.dropout = Dropout(p=dropout_prob, mode="downscale_in_infer") + else: + self.dropout = None + + self.fc = Linear(self.class_expand, class_num) + + def init_weights(self): + """Initiate the parameters. + """ + if isinstance(self.pretrained, str) and self.pretrained.strip() != "": + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + #XXX: no bias + weight_init_(layer, 'KaimingNormal') + elif isinstance(layer, nn.BatchNorm2D): + weight_init_(layer, 'Constant', value=1) + + def forward(self, x): + x = self.conv(x) + x = self.blocks(x) + x = self.last_second_conv(x) + x = self.avg_pool(x) + x = self.last_conv(x) + x = self.hardswish(x) + if self.dropout is not None: + x = self.dropout(x) + + # feature aggregation for video + x = paddle.reshape(x, [-1, self.num_seg, x.shape[1]]) + x = paddle.mean(x, axis=1) + x = paddle.reshape(x, shape=[-1, self.class_expand]) + + x = self.fc(x) + + return x + + +class ConvBNLayer(nn.Layer): + def __init__(self, + in_c, + out_c, + filter_size, + stride, + padding, + num_groups=1, + if_act=True, + act=None): + super().__init__() + + self.conv = Conv2D(in_channels=in_c, + out_channels=out_c, + kernel_size=filter_size, + stride=stride, + padding=padding, + groups=num_groups, + bias_attr=False) + self.bn = BatchNorm(num_channels=out_c, + act=None, + param_attr=ParamAttr(regularizer=L2Decay(0.0)), + bias_attr=ParamAttr(regularizer=L2Decay(0.0))) + self.if_act = if_act + self.act = _create_act(act) + + def forward(self, x): + x = self.conv(x) + x = self.bn(x) + if self.if_act: + x = self.act(x) + return x + + +class ResidualUnit(nn.Layer): + def __init__(self, + in_c, + mid_c, + out_c, + filter_size, + stride, + use_se, + num_seg=8, + act=None): + super().__init__() + self.if_shortcut = stride == 1 and in_c == out_c + self.if_se = use_se + self.num_seg = num_seg + + self.expand_conv = ConvBNLayer(in_c=in_c, + out_c=mid_c, + filter_size=1, + stride=1, + padding=0, + if_act=True, + act=act) + self.bottleneck_conv = ConvBNLayer(in_c=mid_c, + out_c=mid_c, + filter_size=filter_size, + stride=stride, + padding=int((filter_size - 1) // 2), + num_groups=mid_c, + if_act=True, + act=act) + if self.if_se: + self.mid_se = SEModule(mid_c) + self.linear_conv = ConvBNLayer(in_c=mid_c, + out_c=out_c, + filter_size=1, + stride=1, + padding=0, + if_act=False, + act=None) + + def forward(self, x): + identity = x + + if self.if_shortcut: + x = F.temporal_shift(x, self.num_seg, 1.0 / self.num_seg) + + x = self.expand_conv(x) + x = self.bottleneck_conv(x) + if self.if_se: + x = self.mid_se(x) + x = self.linear_conv(x) + if self.if_shortcut: + x = paddle.add(identity, x) + return x + + +# nn.Hardsigmoid can't transfer "slope" and "offset" in nn.functional.hardsigmoid +class Hardsigmoid(nn.Layer): + def __init__(self, slope=0.2, offset=0.5): + super().__init__() + self.slope = slope + self.offset = offset + + def forward(self, x): + return nn.functional.hardsigmoid(x, + slope=self.slope, + offset=self.offset) + + +class SEModule(nn.Layer): + def __init__(self, channel, reduction=4): + super().__init__() + self.avg_pool = AdaptiveAvgPool2D(1) + self.conv1 = Conv2D(in_channels=channel, + out_channels=channel // reduction, + kernel_size=1, + stride=1, + padding=0) + self.relu = nn.ReLU() + self.conv2 = Conv2D(in_channels=channel // reduction, + out_channels=channel, + kernel_size=1, + stride=1, + padding=0) + self.hardsigmoid = Hardsigmoid(slope=0.2, offset=0.5) + + def forward(self, x): + identity = x + x = self.avg_pool(x) + x = self.conv1(x) + x = self.relu(x) + x = self.conv2(x) + x = self.hardsigmoid(x) + return paddle.multiply(x=identity, y=x) + + +def PPTSM_MobileNetV3_small_x1_0(pretrained=None, **kwargs): + """ + MobileNetV3_small_x1_0 + Args: + pretrained: bool=False or str. If `True` load pretrained parameters, `False` otherwise. + If str, means the path of the pretrained model. + use_ssld: bool=False. Whether using distillation pretrained model when pretrained=True. + Returns: + model: nn.Layer. Specific `MobileNetV3_small_x1_0` model depends on args. + """ + model = MobileNetV3( + config=NET_CONFIG["small"], + scale=1.0, + stages_pattern=MODEL_STAGES_PATTERN["MobileNetV3_small"], + class_squeeze=LAST_SECOND_CONV_SMALL, + pretrained=pretrained, + **kwargs) + return model + + +@BACKBONES.register() +def PPTSM_MobileNetV3(pretrained=None, **kwargs): + """ + MobileNetV3_large_x1_0 + Args: + pretrained: bool=False or str. If `True` load pretrained parameters, `False` otherwise. + If str, means the path of the pretrained model. + use_ssld: bool=False. Whether using distillation pretrained model when pretrained=True. + Returns: + model: nn.Layer. Specific `MobileNetV3_large_x1_0` model depends on args. + """ + model = MobileNetV3( + config=NET_CONFIG["large"], + scale=1.0, + stages_pattern=MODEL_STAGES_PATTERN["MobileNetV3_large"], + class_squeeze=LAST_SECOND_CONV_LARGE, + pretrained=pretrained, + **kwargs) + return model diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_v2.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_v2.py new file mode 100644 index 0000000..07dc5bf --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/pptsm_v2.py @@ -0,0 +1,405 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + +from __future__ import absolute_import, division, print_function + +import paddle +import paddle.nn as nn +from paddle import ParamAttr +from paddle.nn import AdaptiveAvgPool2D, BatchNorm, Conv2D, Dropout, Linear, BatchNorm2D +from paddle.regularizer import L2Decay +from paddle.nn.initializer import KaimingNormal +import paddle.nn.functional as F + +from ..registry import BACKBONES +from ..weight_init import weight_init_ +from ...utils import load_ckpt + +# MODEL_URLS = { +# "PPLCNetV2": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/legendary_models/PPLCNetV2_base_ssld_pretrained.pdparams", +# } + +MODEL_STAGES_PATTERN = { + "PPLCNet": ["blocks2", "blocks3", "blocks4", "blocks5", "blocks6"] +} + +NET_CONFIG = { + # in_channels, kernel_size, split_pw, use_rep, use_se, use_shortcut + "stage1": [64, 3, False, False, False, False], + "stage2": [128, 3, False, False, False, False], + "stage3": [256, 5, True, True, True, False], + "stage4": [512, 5, False, True, False, True], +} + + +def make_divisible(v, divisor=8, min_value=None): + if min_value is None: + min_value = divisor + new_v = max(min_value, int(v + divisor / 2) // divisor * divisor) + if new_v < 0.9 * v: + new_v += divisor + return new_v + + +class GlobalAttention(nn.Layer): + """ + Lightweight temporal attention module. + """ + + def __init__(self, num_seg=8): + super().__init__() + self.fc = nn.Linear(in_features=num_seg, + out_features=num_seg, + weight_attr=ParamAttr(learning_rate=5.0, + regularizer=L2Decay(1e-4)), + bias_attr=ParamAttr(learning_rate=10.0, + regularizer=L2Decay(0.0))) + self.num_seg = num_seg + + def forward(self, x): + _, C, H, W = x.shape + x0 = x + + x = x.reshape([-1, self.num_seg, C * H * W]) + x = paddle.mean(x, axis=2) # efficient way of avg_pool + x = x.squeeze(axis=-1) + x = self.fc(x) + attention = F.sigmoid(x) + attention = attention.reshape( + (-1, self.num_seg, 1, 1, 1)) #for broadcast + + x0 = x0.reshape([-1, self.num_seg, C, H, W]) + y = paddle.multiply(x0, attention) + y = y.reshape_([-1, C, H, W]) + return y + + +class ConvBNLayer(nn.Layer): + + def __init__(self, + in_channels, + out_channels, + kernel_size, + stride, + groups=1, + use_act=True): + super().__init__() + self.use_act = use_act + self.conv = Conv2D(in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=(kernel_size - 1) // 2, + groups=groups, + weight_attr=ParamAttr(initializer=KaimingNormal()), + bias_attr=False) + + self.bn = BatchNorm2D(out_channels, + weight_attr=ParamAttr(regularizer=L2Decay(0.0)), + bias_attr=ParamAttr(regularizer=L2Decay(0.0))) + if self.use_act: + self.act = nn.ReLU() + + def forward(self, x): + x = self.conv(x) + x = self.bn(x) + if self.use_act: + x = self.act(x) + return x + + +class SEModule(nn.Layer): + + def __init__(self, channel, reduction=4): + super().__init__() + self.avg_pool = AdaptiveAvgPool2D(1) + self.conv1 = Conv2D(in_channels=channel, + out_channels=channel // reduction, + kernel_size=1, + stride=1, + padding=0) + self.relu = nn.ReLU() + self.conv2 = Conv2D(in_channels=channel // reduction, + out_channels=channel, + kernel_size=1, + stride=1, + padding=0) + self.hardsigmoid = nn.Sigmoid() + + def forward(self, x): + identity = x + x = self.avg_pool(x) + x = self.conv1(x) + x = self.relu(x) + x = self.conv2(x) + x = self.hardsigmoid(x) + x = paddle.multiply(x=identity, y=x) + return x + + +class RepDepthwiseSeparable(nn.Layer): + + def __init__(self, + in_channels, + out_channels, + stride, + dw_size=3, + split_pw=False, + use_rep=False, + use_se=False, + use_shortcut=False): + super().__init__() + self.is_repped = False + + self.dw_size = dw_size + self.split_pw = split_pw + self.use_rep = use_rep + self.use_se = use_se + self.use_shortcut = True if use_shortcut and stride == 1 and in_channels == out_channels else False + + if self.use_rep: + self.dw_conv_list = nn.LayerList() + for kernel_size in range(self.dw_size, 0, -2): + if kernel_size == 1 and stride != 1: + continue + dw_conv = ConvBNLayer(in_channels=in_channels, + out_channels=in_channels, + kernel_size=kernel_size, + stride=stride, + groups=in_channels, + use_act=False) + self.dw_conv_list.append(dw_conv) + self.dw_conv = nn.Conv2D(in_channels=in_channels, + out_channels=in_channels, + kernel_size=dw_size, + stride=stride, + padding=(dw_size - 1) // 2, + groups=in_channels) + else: + self.dw_conv = ConvBNLayer(in_channels=in_channels, + out_channels=in_channels, + kernel_size=dw_size, + stride=stride, + groups=in_channels) + + self.act = nn.ReLU() + + if use_se: + self.se = SEModule(in_channels) + + if self.split_pw: + pw_ratio = 0.5 + self.pw_conv_1 = ConvBNLayer(in_channels=in_channels, + kernel_size=1, + out_channels=int(out_channels * + pw_ratio), + stride=1) + self.pw_conv_2 = ConvBNLayer(in_channels=int(out_channels * + pw_ratio), + kernel_size=1, + out_channels=out_channels, + stride=1) + else: + self.pw_conv = ConvBNLayer(in_channels=in_channels, + kernel_size=1, + out_channels=out_channels, + stride=1) + + def forward(self, x): + if self.use_rep: + input_x = x + if self.is_repped: + x = self.act(self.dw_conv(x)) + else: + y = self.dw_conv_list[0](x) + for dw_conv in self.dw_conv_list[1:]: + y += dw_conv(x) + x = self.act(y) + else: + x = self.dw_conv(x) + + if self.use_se: + x = self.se(x) + if self.split_pw: + x = self.pw_conv_1(x) + x = self.pw_conv_2(x) + else: + x = self.pw_conv(x) + if self.use_shortcut: + x = x + input_x + return x + + def rep(self): + if self.use_rep: + self.is_repped = True + kernel, bias = self._get_equivalent_kernel_bias() + self.dw_conv.weight.set_value(kernel) + self.dw_conv.bias.set_value(bias) + + def _get_equivalent_kernel_bias(self): + kernel_sum = 0 + bias_sum = 0 + for dw_conv in self.dw_conv_list: + kernel, bias = self._fuse_bn_tensor(dw_conv) + kernel = self._pad_tensor(kernel, to_size=self.dw_size) + kernel_sum += kernel + bias_sum += bias + return kernel_sum, bias_sum + + def _fuse_bn_tensor(self, branch): + kernel = branch.conv.weight + running_mean = branch.bn._mean + running_var = branch.bn._variance + gamma = branch.bn.weight + beta = branch.bn.bias + eps = branch.bn._epsilon + std = (running_var + eps).sqrt() + t = (gamma / std).reshape((-1, 1, 1, 1)) + return kernel * t, beta - running_mean * gamma / std + + def _pad_tensor(self, tensor, to_size): + from_size = tensor.shape[-1] + if from_size == to_size: + return tensor + pad = (to_size - from_size) // 2 + return F.pad(tensor, [pad, pad, pad, pad]) + + +class PPTSM_v2_LCNet(nn.Layer): + + def __init__(self, + scale, + depths, + class_num=400, + dropout_prob=0, + num_seg=8, + use_temporal_att=False, + pretrained=None, + use_last_conv=True, + class_expand=1280): + super().__init__() + self.scale = scale + self.use_last_conv = use_last_conv + self.class_expand = class_expand + self.num_seg = num_seg + self.use_temporal_att = use_temporal_att + self.pretrained = pretrained + + self.stem = nn.Sequential(*[ + ConvBNLayer(in_channels=3, + kernel_size=3, + out_channels=make_divisible(32 * scale), + stride=2), + RepDepthwiseSeparable(in_channels=make_divisible(32 * scale), + out_channels=make_divisible(64 * scale), + stride=1, + dw_size=3) + ]) + + # stages + self.stages = nn.LayerList() + for depth_idx, k in enumerate(NET_CONFIG): + in_channels, kernel_size, split_pw, use_rep, use_se, use_shortcut = NET_CONFIG[ + k] + self.stages.append( + nn.Sequential(*[ + RepDepthwiseSeparable(in_channels=make_divisible( + (in_channels if i == 0 else in_channels * 2) * scale), + out_channels=make_divisible( + in_channels * 2 * scale), + stride=2 if i == 0 else 1, + dw_size=kernel_size, + split_pw=split_pw, + use_rep=use_rep, + use_se=use_se, + use_shortcut=use_shortcut) + for i in range(depths[depth_idx]) + ])) + + self.avg_pool = AdaptiveAvgPool2D(1) + + if self.use_last_conv: + self.last_conv = Conv2D(in_channels=make_divisible( + NET_CONFIG["stage4"][0] * 2 * scale), + out_channels=self.class_expand, + kernel_size=1, + stride=1, + padding=0, + bias_attr=False) + self.act = nn.ReLU() + self.dropout = Dropout(p=dropout_prob, mode="downscale_in_infer") + + self.flatten = nn.Flatten(start_axis=1, stop_axis=-1) + in_features = self.class_expand if self.use_last_conv else NET_CONFIG[ + "stage4"][0] * 2 * scale + self.fc = Linear(in_features, class_num) + if self.use_temporal_att: + self.global_attention = GlobalAttention(num_seg=self.num_seg) + + def init_weights(self): + """Initiate the parameters. + """ + if isinstance(self.pretrained, str) and self.pretrained.strip() != "": + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + weight_init_(layer, 'KaimingNormal') + elif isinstance(layer, nn.BatchNorm2D): + weight_init_(layer, 'Constant', value=1) + + def forward(self, x): + x = self.stem(x) + count = 0 + for stage in self.stages: + # only add temporal attention and tsm in stage3 for efficiency + if count == 2: + # add temporal attention + if self.use_temporal_att: + x = self.global_attention(x) + x = F.temporal_shift(x, self.num_seg, 1.0 / self.num_seg) + count += 1 + x = stage(x) + + x = self.avg_pool(x) + if self.use_last_conv: + x = self.last_conv(x) + x = self.act(x) + x = self.dropout(x) + + # Feature aggregation + x = paddle.reshape(x, [-1, self.num_seg, x.shape[1]]) + x = paddle.mean(x, axis=1) + x = paddle.reshape(x, shape=[-1, self.class_expand]) + + x = self.fc(x) + return x + + +@BACKBONES.register() +def PPTSM_v2(pretrained=None, use_ssld=False, **kwargs): + """ + PP-TSM_v2 model. + Args: + pretrained: str, means the path of the pretrained model. + Returns: + model: nn.Layer. + """ + model = PPTSM_v2_LCNet(pretrained=pretrained, + scale=1.0, + depths=[2, 2, 6, 2], + dropout_prob=0.2, + **kwargs) + return model diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet.py new file mode 100644 index 0000000..2f07991 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet.py @@ -0,0 +1,283 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +import math + +import paddle +import paddle.nn as nn +from paddle.nn import (Conv2D, BatchNorm2D, Linear, Dropout, MaxPool2D, + AvgPool2D) +from paddle import ParamAttr +import paddle.nn.functional as F + +from ..registry import BACKBONES +from ..weight_init import weight_init_ +from ...utils import load_ckpt + + +class ConvBNLayer(nn.Layer): + """Conv2D and BatchNorm2D layer. + + Args: + in_channels (int): Number of channels for the input. + out_channels (int): Number of channels for the output. + kernel_size (int): Kernel size. + stride (int): Stride in the Conv2D layer. Default: 1. + groups (int): Groups in the Conv2D, Default: 1. + act (str): Indicate activation after BatchNorm2D layer. + name (str): the name of an instance of ConvBNLayer. + + Note: weight and bias initialization include initialize values and name the restored parameters, values initialization are explicit declared in the ```init_weights``` method. + + """ + def __init__(self, + in_channels, + out_channels, + kernel_size, + stride=1, + groups=1, + act=None, + name=None): + super(ConvBNLayer, self).__init__() + self._conv = Conv2D(in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=(kernel_size - 1) // 2, + groups=groups, + weight_attr=ParamAttr(name=name + "_weights"), + bias_attr=False) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + + self._act = act + + self._batch_norm = BatchNorm2D(out_channels, + weight_attr=ParamAttr(name=bn_name + + "_scale"), + bias_attr=ParamAttr(bn_name + "_offset")) + + def forward(self, inputs): + y = self._conv(inputs) + y = self._batch_norm(y) + if self._act: + y = getattr(paddle.nn.functional, self._act)(y) + return y + + +class BottleneckBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + name=None): + super(BottleneckBlock, self).__init__() + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + act="relu", + name=name + "_branch2a") + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + kernel_size=3, + stride=stride, + act="relu", + name=name + "_branch2b") + + self.conv2 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels * 4, + kernel_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels * 4, + kernel_size=1, + stride=stride, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(x=short, y=conv2) + return F.relu(y) + + +class BasicBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + name=None): + super(BasicBlock, self).__init__() + self.stride = stride + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + filter_size=3, + stride=stride, + act="relu", + name=name + "_branch2a") + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + filter_size=3, + act=None, + name=name + "_branch2b") + + if not shortcut: + self.short = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + filter_size=1, + stride=stride, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs): + y = self.conv0(inputs) + conv1 = self.conv1(y) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(short, conv1) + y = F.relu(y) + return y + + +@BACKBONES.register() +class ResNet(nn.Layer): + """ResNet backbone. + + Args: + depth (int): Depth of resnet model. + pretrained (str): pretrained model. Default: None. + """ + def __init__(self, depth, pretrained=None): + super(ResNet, self).__init__() + self.pretrained = pretrained + self.layers = depth + + supported_layers = [18, 34, 50, 101, 152] + assert self.layers in supported_layers, \ + "supported layers are {} but input layer is {}".format( + supported_layers, self.layers) + + if self.layers == 18: + depth = [2, 2, 2, 2] + elif self.layers == 34 or self.layers == 50: + depth = [3, 4, 6, 3] + elif self.layers == 101: + depth = [3, 4, 23, 3] + elif self.layers == 152: + depth = [3, 8, 36, 3] + + in_channels = [64, 256, 512, 1024] + out_channels = [64, 128, 256, 512] + + self.conv = ConvBNLayer(in_channels=3, + out_channels=64, + kernel_size=7, + stride=2, + act="relu", + name="conv1") + self.pool2D_max = MaxPool2D(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + if self.layers >= 50: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if self.layers in [101, 152] and block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + conv_name, + BottleneckBlock( + # NOTE: Be careful! Here is different from TSM model. + in_channels=in_channels[block] + if i == 0 else out_channels[block] * 4, + out_channels=out_channels[block], + stride=2 if i == 0 and block != 0 else 1, + shortcut=shortcut, + name=conv_name)) + + self.block_list.append(bottleneck_block) + shortcut = True + else: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + conv_name = "res" + str(block + 2) + chr(97 + i) + basic_block = self.add_sublayer( + conv_name, + BasicBlock(in_channels=in_channels[block] + if i == 0 else out_channels[block], + out_channels=out_channels[block], + stride=2 if i == 0 and block != 0 else 1, + shortcut=shortcut, + name=conv_name)) + self.block_list.append(basic_block) + shortcut = True + + def init_weights(self): + """Initiate the parameters. + Note: + 1. when indicate pretrained loading path, will load it to initiate backbone. + 2. when not indicating pretrained loading path, will follow specific initialization initiate backbone. Always, Conv2D layer will be initiated by KaimingNormal function, and BatchNorm2d will be initiated by Constant function. + Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/api/paddle/nn/initializer/kaiming/KaimingNormal_en.html + """ + #XXX: check bias!!! check pretrained!!! + + if isinstance(self.pretrained, str) and self.pretrained.strip() != "": + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + #XXX: no bias + weight_init_(layer, 'KaimingNormal') + elif isinstance(layer, nn.BatchNorm2D): + weight_init_(layer, 'Constant', value=1) + + def forward(self, inputs): + """Define how the backbone is going to run. + + """ + #NOTE: Already merge axis 0(batches) and axis 1(channels) before extracting feature phase, + # please refer to paddlevideo/modeling/framework/recognizers/recognizer2d.py#L27 + #y = paddle.reshape( + # inputs, [-1, inputs.shape[2], inputs.shape[3], inputs.shape[4]]) + + y = self.conv(inputs) + y = self.pool2D_max(y) + for block in self.block_list: + y = block(y) + return y diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet3d.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet3d.py new file mode 100644 index 0000000..33edefe --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet3d.py @@ -0,0 +1,641 @@ +# 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 warnings +import collections +from itertools import repeat + +import paddle +from paddle import nn + + +def _ntuple(n): + def parse(x): + if isinstance(x, collections.abc.Iterable): + return tuple(x) + return tuple(repeat(x, n)) + + return parse + + +_triple = _ntuple(3) + + +class ConvBNLayer(nn.Layer): + """A conv block that bundles conv/norm/activation layers. + + This block simplifies the usage of convolution layers, which are commonly + used with a norm layer (e.g., BatchNorm) and activation layer (e.g., ReLU). + It is based upon three build methods: `build_conv_layer()`, + `build_norm_layer()` and `build_activation_layer()`. + + Besides, we add some additional features in this module. + 1. Automatically set `bias` of the conv layer. + 2. Spectral norm is supported. + 3. More padding modes are supported. Before PyTorch 1.5, nn.Conv2d only + supports zero and circular padding, and we add "reflect" padding mode. + + Args: + in_channels (int): Number of channels in the input feature map. + Same as that in ``nn._ConvNd``. + out_channels (int): Number of channels produced by the convolution. + Same as that in ``nn._ConvNd``. + kernel_size (int | tuple[int]): Size of the convolving kernel. + Same as that in ``nn._ConvNd``. + stride (int | tuple[int]): Stride of the convolution. + Same as that in ``nn._ConvNd``. + padding (int | tuple[int]): Zero-padding added to both sides of + the input. Same as that in ``nn._ConvNd``. + dilation (int | tuple[int]): Spacing between kernel elements. + Same as that in ``nn._ConvNd``. + groups (int): Number of blocked connections from input channels to + output channels. Same as that in ``nn._ConvNd``. + """ + + def __init__( + self, + in_channels, + out_channels, + kernel_size, + padding=0, + stride=1, + dilation=1, + groups=1, + act=None, + bias=None, + ): + super(ConvBNLayer, self).__init__() + + self._conv = nn.Conv3D( + in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=padding, + dilation=dilation, + groups=groups, + bias_attr=bias) + + self._batch_norm = nn.BatchNorm3D(out_channels, momentum=0.1) + self.act = act + if act is not None: + self._act_op = nn.ReLU() + + def forward(self, inputs): + y = self._conv(inputs) + y = self._batch_norm(y) + if self.act is not None: + y = self._act_op(y) + + return y + + +class Bottleneck3d(nn.Layer): + """Bottleneck 3d block for ResNet3D. + + Args: + inplanes (int): Number of channels for the input in first conv3d layer. + planes (int): Number of channels produced by some norm/conv3d layers. + spatial_stride (int): Spatial stride in the conv3d layer. Default: 1. + temporal_stride (int): Temporal stride in the conv3d layer. Default: 1. + dilation (int): Spacing between kernel elements. Default: 1. + downsample (nn.Module | None): Downsample layer. Default: None. + inflate (bool): Whether to inflate kernel. Default: True. + inflate_style (str): ``3x1x1`` or ``3x3x3``. which determines the + kernel sizes and padding strides for conv1 and conv2 in each block. + Default: '3x1x1'. + non_local (bool): Determine whether to apply non-local module in this + block. Default: False. + non_local_cfg (dict): Config for non-local module. Default: ``dict()``. + conv_cfg (dict): Config dict for convolution layer. + Default: ``dict(type='Conv3d')``. + norm_cfg (dict): Config for norm layers. required keys are ``type``, + Default: ``dict(type='BN3d')``. + act_cfg (dict): Config dict for activation layer. + Default: ``dict(type='ReLU')``. + with_cp (bool): Use checkpoint or not. Using checkpoint will save some + memory while slowing down the training speed. Default: False. + """ + expansion = 4 + + def __init__(self, + inplanes, + planes, + spatial_stride=1, + temporal_stride=1, + dilation=1, + downsample=None, + inflate=True, + inflate_style='3x1x1', + non_local=False, + non_local_cfg=dict(), + conv_cfg=dict(type='Conv3d'), + norm_cfg=dict(type='BN3d'), + act_cfg=dict(type='ReLU'), + with_cp=False): + super().__init__() + assert inflate_style in ['3x1x1', '3x3x3'] + + self.inplanes = inplanes + self.planes = planes + self.spatial_stride = spatial_stride + self.temporal_stride = temporal_stride + self.dilation = dilation + self.inflate = inflate + self.inflate_style = inflate_style + self.norm_cfg = norm_cfg + self.conv_cfg = conv_cfg + self.act_cfg = act_cfg + self.with_cp = with_cp + self.non_local = non_local + self.non_local_cfg = non_local_cfg + + self.conv1_stride_s = 1 + self.conv2_stride_s = spatial_stride + self.conv1_stride_t = 1 + self.conv2_stride_t = temporal_stride + + if self.inflate: + if inflate_style == '3x1x1': + conv1_kernel_size = (3, 1, 1) + conv1_padding = (1, 0, 0) + conv2_kernel_size = (1, 3, 3) + conv2_padding = (0, dilation, dilation) + else: + conv1_kernel_size = (1, 1, 1) + conv1_padding = (0, 0, 0) + conv2_kernel_size = (3, 3, 3) + conv2_padding = (1, dilation, dilation) + else: + conv1_kernel_size = (1, 1, 1) + conv1_padding = (0, 0, 0) + conv2_kernel_size = (1, 3, 3) + conv2_padding = (0, dilation, dilation) + self.conv1 = ConvBNLayer( + in_channels=inplanes, + out_channels=planes, + kernel_size=conv1_kernel_size, + stride=(self.conv1_stride_t, self.conv1_stride_s, + self.conv1_stride_s), + padding=conv1_padding, + bias=False, + act='relu') + + self.conv2 = ConvBNLayer( + in_channels=planes, + out_channels=planes, + kernel_size=conv2_kernel_size, + stride=(self.conv2_stride_t, self.conv2_stride_s, + self.conv2_stride_s), + padding=conv2_padding, + dilation=(1, dilation, dilation), + bias=False, + act='relu') + + self.conv3 = ConvBNLayer( + in_channels=planes, + out_channels=planes * self.expansion, + kernel_size=1, + bias=False, + act=None, + ) + + self.downsample = downsample + self.relu = nn.ReLU() + + def forward(self, x): + """Defines the computation performed at every call.""" + + def _inner_forward(x): + """Forward wrapper for utilizing checkpoint.""" + identity = x + + out = self.conv1(x) + out = self.conv2(out) + out = self.conv3(out) + + if self.downsample is not None: + identity = self.downsample(x) + + out = out + identity + return out + + out = _inner_forward(x) + out = self.relu(out) + + if self.non_local: + out = self.non_local_block(out) + + return out + + +class ResNet3d(nn.Layer): + """ResNet 3d backbone. + + Args: + depth (int): Depth of resnet, from {18, 34, 50, 101, 152}. + pretrained (str | None): Name of pretrained model. + stage_blocks (tuple | None): Set number of stages for each res layer. + Default: None. + pretrained2d (bool): Whether to load pretrained 2D model. + Default: True. + in_channels (int): Channel num of input features. Default: 3. + base_channels (int): Channel num of stem output features. Default: 64. + out_indices (Sequence[int]): Indices of output feature. Default: (3, ). + num_stages (int): Resnet stages. Default: 4. + spatial_strides (Sequence[int]): + Spatial strides of residual blocks of each stage. + Default: ``(1, 2, 2, 2)``. + temporal_strides (Sequence[int]): + Temporal strides of residual blocks of each stage. + Default: ``(1, 1, 1, 1)``. + dilations (Sequence[int]): Dilation of each stage. + Default: ``(1, 1, 1, 1)``. + conv1_kernel (Sequence[int]): Kernel size of the first conv layer. + Default: ``(3, 7, 7)``. + conv1_stride_s (int): Spatial stride of the first conv layer. + Default: 2. + conv1_stride_t (int): Temporal stride of the first conv layer. + Default: 1. + pool1_stride_s (int): Spatial stride of the first pooling layer. + Default: 2. + pool1_stride_t (int): Temporal stride of the first pooling layer. + Default: 1. + with_pool2 (bool): Whether to use pool2. Default: True. + inflate (Sequence[int]): Inflate Dims of each block. + Default: (1, 1, 1, 1). + inflate_style (str): ``3x1x1`` or ``3x3x3``. which determines the + kernel sizes and padding strides for conv1 and conv2 in each block. + Default: '3x1x1'. + conv_cfg (dict): Config for conv layers. required keys are ``type`` + Default: ``dict(type='Conv3d')``. + norm_cfg (dict): Config for norm layers. required keys are ``type`` and + ``requires_grad``. + Default: ``dict(type='BN3d', requires_grad=True)``. + act_cfg (dict): Config dict for activation layer. + Default: ``dict(type='ReLU', inplace=True)``. + norm_eval (bool): Whether to set BN layers to eval mode, namely, freeze + running stats (mean and var). Default: False. + with_cp (bool): Use checkpoint or not. Using checkpoint will save some + memory while slowing down the training speed. Default: False. + non_local (Sequence[int]): Determine whether to apply non-local module + in the corresponding block of each stages. Default: (0, 0, 0, 0). + non_local_cfg (dict): Config for non-local module. Default: ``dict()``. + zero_init_residual (bool): + Whether to use zero initialization for residual block, + Default: True. + kwargs (dict, optional): Key arguments for "make_res_layer". + """ + + arch_settings = { + 50: (Bottleneck3d, (3, 4, 6, 3)), + 101: (Bottleneck3d, (3, 4, 23, 3)), + 152: (Bottleneck3d, (3, 8, 36, 3)) + } + + def __init__(self, + depth, + stage_blocks=None, + pretrained2d=True, + in_channels=3, + num_stages=4, + base_channels=64, + out_indices=(3, ), + spatial_strides=(1, 2, 2, 2), + temporal_strides=(1, 1, 1, 1), + dilations=(1, 1, 1, 1), + conv1_kernel=(3, 7, 7), + conv1_stride_s=2, + conv1_stride_t=1, + pool1_stride_s=2, + pool1_stride_t=1, + with_pool1=True, + with_pool2=True, + inflate=(1, 1, 1, 1), + inflate_style='3x1x1', + conv_cfg=dict(type='Conv3d'), + norm_cfg=dict(type='BN3d', requires_grad=True), + act_cfg=dict(type='ReLU', inplace=True), + norm_eval=False, + with_cp=False, + non_local=(0, 0, 0, 0), + non_local_cfg=dict(), + zero_init_residual=True, + **kwargs): + super().__init__() + if depth not in self.arch_settings: + raise KeyError(f'invalid depth {depth} for resnet') + self.depth = depth + self.pretrained2d = pretrained2d + self.in_channels = in_channels + self.base_channels = base_channels + self.num_stages = num_stages + assert 1 <= num_stages <= 4 + self.stage_blocks = stage_blocks + self.out_indices = out_indices + assert max(out_indices) < num_stages + self.spatial_strides = spatial_strides + self.temporal_strides = temporal_strides + self.dilations = dilations + assert len(spatial_strides) == len(temporal_strides) == len( + dilations) == num_stages + if self.stage_blocks is not None: + assert len(self.stage_blocks) == num_stages + + self.conv1_kernel = conv1_kernel + self.conv1_stride_s = conv1_stride_s + self.conv1_stride_t = conv1_stride_t + self.pool1_stride_s = pool1_stride_s + self.pool1_stride_t = pool1_stride_t + self.with_pool1 = with_pool1 + self.with_pool2 = with_pool2 + self.stage_inflations = _ntuple(num_stages)(inflate) + self.non_local_stages = _ntuple(num_stages)(non_local) + self.inflate_style = inflate_style + self.conv_cfg = conv_cfg + self.norm_cfg = norm_cfg + self.act_cfg = act_cfg + self.norm_eval = norm_eval + self.with_cp = with_cp + self.zero_init_residual = zero_init_residual + + self.block, stage_blocks = self.arch_settings[depth] + + if self.stage_blocks is None: + self.stage_blocks = stage_blocks[:num_stages] + + self.inplanes = self.base_channels + + self.non_local_cfg = non_local_cfg + + self._make_stem_layer() + + self.res_layers = [] + for i, num_blocks in enumerate(self.stage_blocks): + spatial_stride = spatial_strides[i] + temporal_stride = temporal_strides[i] + dilation = dilations[i] + planes = self.base_channels * 2**i + res_layer = self.make_res_layer( + self.block, + self.inplanes, + planes, + num_blocks, + spatial_stride=spatial_stride, + temporal_stride=temporal_stride, + dilation=dilation, + norm_cfg=self.norm_cfg, + conv_cfg=self.conv_cfg, + act_cfg=self.act_cfg, + non_local=self.non_local_stages[i], + non_local_cfg=self.non_local_cfg, + inflate=self.stage_inflations[i], + inflate_style=self.inflate_style, + with_cp=with_cp, + **kwargs) + self.inplanes = planes * self.block.expansion + layer_name = f'layer{i + 1}' + self.add_sublayer(layer_name, res_layer) + self.res_layers.append(layer_name) + + self.feat_dim = self.block.expansion * self.base_channels * 2**( + len(self.stage_blocks) - 1) + + @staticmethod + def make_res_layer(block, + inplanes, + planes, + blocks, + spatial_stride=1, + temporal_stride=1, + dilation=1, + inflate=1, + inflate_style='3x1x1', + non_local=0, + non_local_cfg=dict(), + norm_cfg=None, + act_cfg=None, + conv_cfg=None, + with_cp=False, + **kwargs): + """Build residual layer for ResNet3D. + + Args: + block (nn.Module): Residual module to be built. + inplanes (int): Number of channels for the input feature + in each block. + planes (int): Number of channels for the output feature + in each block. + blocks (int): Number of residual blocks. + spatial_stride (int | Sequence[int]): Spatial strides in + residual and conv layers. Default: 1. + temporal_stride (int | Sequence[int]): Temporal strides in + residual and conv layers. Default: 1. + dilation (int): Spacing between kernel elements. Default: 1. + inflate (int | Sequence[int]): Determine whether to inflate + for each block. Default: 1. + inflate_style (str): ``3x1x1`` or ``3x3x3``. which determines + the kernel sizes and padding strides for conv1 and conv2 + in each block. Default: '3x1x1'. + non_local (int | Sequence[int]): Determine whether to apply + non-local module in the corresponding block of each stages. + Default: 0. + non_local_cfg (dict): Config for non-local module. + Default: ``dict()``. + conv_cfg (dict | None): Config for norm layers. Default: None. + norm_cfg (dict | None): Config for norm layers. Default: None. + act_cfg (dict | None): Config for activate layers. Default: None. + with_cp (bool | None): Use checkpoint or not. Using checkpoint + will save some memory while slowing down the training speed. + Default: False. + + Returns: + nn.Module: A residual layer for the given config. + """ + inflate = inflate if not isinstance(inflate, + int) else (inflate, ) * blocks + non_local = non_local if not isinstance(non_local, + int) else (non_local, ) * blocks + assert len(inflate) == blocks and len(non_local) == blocks + downsample = None + if spatial_stride != 1 or inplanes != planes * block.expansion: + downsample = ConvBNLayer( + in_channels=inplanes, + out_channels=planes * block.expansion, + kernel_size=1, + stride=(temporal_stride, spatial_stride, spatial_stride), + bias=False, + act=None) + + layers = [] + layers.append( + block( + inplanes, + planes, + spatial_stride=spatial_stride, + temporal_stride=temporal_stride, + dilation=dilation, + downsample=downsample, + inflate=(inflate[0] == 1), + inflate_style=inflate_style, + non_local=(non_local[0] == 1), + non_local_cfg=non_local_cfg, + norm_cfg=norm_cfg, + conv_cfg=conv_cfg, + act_cfg=act_cfg, + with_cp=with_cp, + **kwargs)) + inplanes = planes * block.expansion + for i in range(1, blocks): + layers.append( + block( + inplanes, + planes, + spatial_stride=1, + temporal_stride=1, + dilation=dilation, + inflate=(inflate[i] == 1), + inflate_style=inflate_style, + non_local=(non_local[i] == 1), + non_local_cfg=non_local_cfg, + norm_cfg=norm_cfg, + conv_cfg=conv_cfg, + act_cfg=act_cfg, + with_cp=with_cp, + **kwargs)) + + return nn.Sequential(*layers) + + @staticmethod + def _inflate_conv_params(conv3d, state_dict_2d, module_name_2d, + inflated_param_names): + """Inflate a conv module from 2d to 3d. + + Args: + conv3d (nn.Module): The destination conv3d module. + state_dict_2d (OrderedDict): The state dict of pretrained 2d model. + module_name_2d (str): The name of corresponding conv module in the + 2d model. + inflated_param_names (list[str]): List of parameters that have been + inflated. + """ + weight_2d_name = module_name_2d + '.weight' + + conv2d_weight = state_dict_2d[weight_2d_name] + kernel_t = conv3d.weight.data.shape[2] + + new_weight = conv2d_weight.data.unsqueeze(2).expand_as( + conv3d.weight) / kernel_t + conv3d.weight.data.copy_(new_weight) + inflated_param_names.append(weight_2d_name) + + if getattr(conv3d, 'bias') is not None: + bias_2d_name = module_name_2d + '.bias' + conv3d.bias.data.copy_(state_dict_2d[bias_2d_name]) + inflated_param_names.append(bias_2d_name) + + @staticmethod + def _inflate_bn_params(bn3d, state_dict_2d, module_name_2d, + inflated_param_names): + """Inflate a norm module from 2d to 3d. + + Args: + bn3d (nn.Module): The destination bn3d module. + state_dict_2d (OrderedDict): The state dict of pretrained 2d model. + module_name_2d (str): The name of corresponding bn module in the + 2d model. + inflated_param_names (list[str]): List of parameters that have been + inflated. + """ + for param_name, param in bn3d.named_parameters(): + param_2d_name = f'{module_name_2d}.{param_name}' + param_2d = state_dict_2d[param_2d_name] + if param.data.shape != param_2d.shape: + warnings.warn(f'The parameter of {module_name_2d} is not' + 'loaded due to incompatible shapes. ') + return + + param.data.copy_(param_2d) + inflated_param_names.append(param_2d_name) + + for param_name, param in bn3d.named_buffers(): + param_2d_name = f'{module_name_2d}.{param_name}' + # some buffers like num_batches_tracked may not exist in old + # checkpoints + if param_2d_name in state_dict_2d: + param_2d = state_dict_2d[param_2d_name] + param.data.copy_(param_2d) + inflated_param_names.append(param_2d_name) + + def _make_stem_layer(self): + """Construct the stem layers consists of a conv+norm+act module and a + pooling layer.""" + + self.conv1 = ConvBNLayer( + in_channels=self.in_channels, + out_channels=self.base_channels, + kernel_size=self.conv1_kernel, + stride=(self.conv1_stride_t, self.conv1_stride_s, + self.conv1_stride_s), + padding=tuple([(k - 1) // 2 for k in _triple(self.conv1_kernel)]), + bias=False, + act="relu") + + self.maxpool = nn.MaxPool3D( + kernel_size=(1, 3, 3), + stride=(self.pool1_stride_t, self.pool1_stride_s, + self.pool1_stride_s), + padding=(0, 1, 1)) + + self.pool2 = nn.MaxPool3D(kernel_size=(2, 1, 1), stride=(2, 1, 1)) + + @staticmethod + def _init_weights(self, pretrained=None): + pass + + def init_weights(self, pretrained=None): + self._init_weights(self, pretrained) + + def forward(self, x): + """Defines the computation performed at every call. + + Args: + x (torch.Tensor): The input data. + + Returns: + torch.Tensor: The feature of the input + samples extracted by the backbone. + """ + x = self.conv1(x) + if self.with_pool1: + x = self.maxpool(x) + outs = [] + for i, layer_name in enumerate(self.res_layers): + res_layer = getattr(self, layer_name) + x = res_layer(x) + if i == 0 and self.with_pool2: + x = self.pool2(x) + if i in self.out_indices: + outs.append(x) + if len(outs) == 1: + return outs[0] + + return tuple(outs) + + def train(self, mode=True): + """Set the optimization status when training.""" + super().train() + if mode and self.norm_eval: + for m in self.modules(): + if isinstance(m, paddle.nn._BatchNormBase): + m.eval() diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet3d_slowonly.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet3d_slowonly.py new file mode 100644 index 0000000..eb5b080 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet3d_slowonly.py @@ -0,0 +1,214 @@ +# 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 warnings + +import paddle +import paddle.nn as nn + +from .resnet3d import ResNet3d, ConvBNLayer +from ..registry import BACKBONES + + +@BACKBONES.register() +class ResNet3dSlowOnly(ResNet3d): + """A pathway of Slowfast based on ResNet3d. + + Args: + *args (arguments): Arguments same as :class:``ResNet3d``. + channel_ratio (int): Reduce the channel number of fast pathway + by ``channel_ratio``, corresponding to ``beta`` in the paper. + Default: 8. + **kwargs (keyword arguments): Keywords arguments for ResNet3d. + """ + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.inplanes = self.base_channels + + self.lateral_connections = [] + for i in range(len(self.stage_blocks)): + planes = self.base_channels * 2**i + self.inplanes = planes * self.block.expansion + + def make_res_layer(self, + block, + inplanes, + planes, + blocks, + spatial_stride=1, + temporal_stride=1, + dilation=1, + inflate=1, + inflate_style='3x1x1', + non_local=0, + non_local_cfg=dict(), + conv_cfg=None, + norm_cfg=None, + act_cfg=None, + with_cp=False): + """Build residual layer for Slowfast. + + Args: + block (nn.Module): Residual module to be built. + inplanes (int): Number of channels for the input + feature in each block. + planes (int): Number of channels for the output + feature in each block. + blocks (int): Number of residual blocks. + spatial_stride (int | Sequence[int]): Spatial strides + in residual and conv layers. Default: 1. + temporal_stride (int | Sequence[int]): Temporal strides in + residual and conv layers. Default: 1. + dilation (int): Spacing between kernel elements. Default: 1. + inflate (int | Sequence[int]): Determine whether to inflate + for each block. Default: 1. + inflate_style (str): ``3x1x1`` or ``3x3x3``. which determines + the kernel sizes and padding strides for conv1 and + conv2 in each block. Default: ``3x1x1``. + non_local (int | Sequence[int]): Determine whether to apply + non-local module in the corresponding block of each stages. + Default: 0. + non_local_cfg (dict): Config for non-local module. + Default: ``dict()``. + conv_cfg (dict | None): Config for conv layers. Default: None. + norm_cfg (dict | None): Config for norm layers. Default: None. + act_cfg (dict | None): Config for activate layers. Default: None. + with_cp (bool): Use checkpoint or not. Using checkpoint will save + some memory while slowing down the training speed. + Default: False. + + Returns: + nn.Module: A residual layer for the given config. + """ + inflate = inflate if not isinstance(inflate, + int) else (inflate, ) * blocks + non_local = non_local if not isinstance(non_local, + int) else (non_local, ) * blocks + assert len(inflate) == blocks and len(non_local) == blocks + + lateral_inplanes = 0 + if (spatial_stride != 1 + or (inplanes + lateral_inplanes) != planes * block.expansion): + downsample = ConvBNLayer( + in_channels=inplanes + lateral_inplanes, + out_channels=planes * block.expansion, + kernel_size=1, + stride=(temporal_stride, spatial_stride, spatial_stride), + bias=False, + act=None) + else: + downsample = None + + layers = [] + layers.append( + block( + inplanes + lateral_inplanes, + planes, + spatial_stride, + temporal_stride, + dilation, + downsample, + inflate=(inflate[0] == 1), + inflate_style=inflate_style, + non_local=(non_local[0] == 1), + non_local_cfg=non_local_cfg, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg, + with_cp=with_cp)) + inplanes = planes * block.expansion + + for i in range(1, blocks): + layers.append( + block( + inplanes, + planes, + 1, + 1, + dilation, + inflate=(inflate[i] == 1), + inflate_style=inflate_style, + non_local=(non_local[i] == 1), + non_local_cfg=non_local_cfg, + conv_cfg=conv_cfg, + norm_cfg=norm_cfg, + act_cfg=act_cfg, + with_cp=with_cp)) + + return nn.Sequential(*layers) + + def _inflate_conv_params(self, conv3d, state_dict_2d, module_name_2d, + inflated_param_names): + """Inflate a conv module from 2d to 3d. + + The differences of conv modules betweene 2d and 3d in Pathway + mainly lie in the inplanes due to lateral connections. To fit the + shapes of the lateral connection counterpart, it will expand + parameters by concatting conv2d parameters and extra zero paddings. + + Args: + conv3d (nn.Module): The destination conv3d module. + state_dict_2d (OrderedDict): The state dict of pretrained 2d model. + module_name_2d (str): The name of corresponding conv module in the + 2d model. + inflated_param_names (list[str]): List of parameters that have been + inflated. + """ + weight_2d_name = module_name_2d + '.weight' + conv2d_weight = state_dict_2d[weight_2d_name] + old_shape = conv2d_weight.shape + new_shape = conv3d.weight.data.shape + kernel_t = new_shape[2] + + if new_shape[1] != old_shape[1]: + if new_shape[1] < old_shape[1]: + warnings.warn(f'The parameter of {module_name_2d} is not' + 'loaded due to incompatible shapes. ') + return + # Inplanes may be different due to lateral connections + new_channels = new_shape[1] - old_shape[1] + pad_shape = old_shape + pad_shape = pad_shape[:1] + (new_channels, ) + pad_shape[2:] + # Expand parameters by concat extra channels + conv2d_weight = paddle.concat( + (conv2d_weight, paddle.zeros(pad_shape)), axis=1) + + new_weight = conv2d_weight.data.unsqueeze(2).expand_as( + conv3d.weight) / kernel_t + conv3d.weight.data.copy_(new_weight) + inflated_param_names.append(weight_2d_name) + + if getattr(conv3d, 'bias') is not None: + bias_2d_name = module_name_2d + '.bias' + conv3d.bias.data.copy_(state_dict_2d[bias_2d_name]) + inflated_param_names.append(bias_2d_name) + + +if __name__ == '__main__': + net = ResNet3dSlowOnly( + depth=50, + in_channels=17, + base_channels=32, + conv1_kernel=(1, 7, 7), + num_stages=3, + out_indices=[2], + stage_blocks=[3, 4, 6], + conv1_stride_s=1, + pool1_stride_s=1, + inflate=[0, 1, 1], + with_pool2=False, + spatial_strides=[2, 2, 2], + temporal_strides=[1, 1, 2], + dilations=[1, 1, 1]) + pass diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_slowfast.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_slowfast.py new file mode 100644 index 0000000..a679159 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_slowfast.py @@ -0,0 +1,795 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 paddle +import paddle.nn.functional as F +from paddle.nn.initializer import KaimingNormal +from ..registry import BACKBONES +from paddlevideo.utils.multigrid import get_norm +import sys +import numpy as np +import paddle.distributed as dist + +# seed random seed +paddle.framework.seed(0) + + +# get init parameters for conv layer +def get_conv_init(fan_out): + return KaimingNormal(fan_in=fan_out) + + +def get_bn_param_attr(bn_weight=1.0, coeff=0.0): + param_attr = paddle.ParamAttr( + initializer=paddle.nn.initializer.Constant(bn_weight), + regularizer=paddle.regularizer.L2Decay(coeff)) + return param_attr + + +"""Video models.""" + + +class BottleneckTransform(paddle.nn.Layer): + """ + Bottleneck transformation: Tx1x1, 1x3x3, 1x1x1, where T is the size of + temporal kernel. + """ + def __init__(self, + dim_in, + dim_out, + temp_kernel_size, + stride, + dim_inner, + num_groups, + stride_1x1=False, + inplace_relu=True, + eps=1e-5, + dilation=1, + norm_module=paddle.nn.BatchNorm3D): + """ + Args: + dim_in (int): the channel dimensions of the input. + dim_out (int): the channel dimension of the output. + temp_kernel_size (int): the temporal kernel sizes of the middle + convolution in the bottleneck. + stride (int): the stride of the bottleneck. + dim_inner (int): the inner dimension of the block. + num_groups (int): number of groups for the convolution. num_groups=1 + is for standard ResNet like networks, and num_groups>1 is for + ResNeXt like networks. + stride_1x1 (bool): if True, apply stride to 1x1 conv, otherwise + apply stride to the 3x3 conv. + inplace_relu (bool): if True, calculate the relu on the original + input without allocating new memory. + eps (float): epsilon for batch norm. + dilation (int): size of dilation. + """ + super(BottleneckTransform, self).__init__() + self.temp_kernel_size = temp_kernel_size + self._inplace_relu = inplace_relu + self._eps = eps + self._stride_1x1 = stride_1x1 + self.norm_module = norm_module + self._construct(dim_in, dim_out, stride, dim_inner, num_groups, + dilation) + + def _construct(self, dim_in, dim_out, stride, dim_inner, num_groups, + dilation): + str1x1, str3x3 = (stride, 1) if self._stride_1x1 else (1, stride) + + fan = (dim_inner) * (self.temp_kernel_size * 1 * 1) + initializer_tmp = get_conv_init(fan) + + self.a = paddle.nn.Conv3D( + in_channels=dim_in, + out_channels=dim_inner, + kernel_size=[self.temp_kernel_size, 1, 1], + stride=[1, str1x1, str1x1], + padding=[int(self.temp_kernel_size // 2), 0, 0], + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False) + self.a_bn = self.norm_module(num_features=dim_inner, + epsilon=self._eps, + weight_attr=get_bn_param_attr(), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + # 1x3x3, BN, ReLU. + fan = (dim_inner) * (1 * 3 * 3) + initializer_tmp = get_conv_init(fan) + + self.b = paddle.nn.Conv3D( + in_channels=dim_inner, + out_channels=dim_inner, + kernel_size=[1, 3, 3], + stride=[1, str3x3, str3x3], + padding=[0, dilation, dilation], + groups=num_groups, + dilation=[1, dilation, dilation], + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False) + self.b_bn = self.norm_module(num_features=dim_inner, + epsilon=self._eps, + weight_attr=get_bn_param_attr(), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + # 1x1x1, BN. + fan = (dim_out) * (1 * 1 * 1) + initializer_tmp = get_conv_init(fan) + + self.c = paddle.nn.Conv3D( + in_channels=dim_inner, + out_channels=dim_out, + kernel_size=[1, 1, 1], + stride=[1, 1, 1], + padding=[0, 0, 0], + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False) + self.c_bn = self.norm_module( + num_features=dim_out, + epsilon=self._eps, + weight_attr=get_bn_param_attr(bn_weight=0.0), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + def forward(self, x): + # Branch2a. + x = self.a(x) + x = self.a_bn(x) + x = F.relu(x) + + # Branch2b. + x = self.b(x) + x = self.b_bn(x) + x = F.relu(x) + + # Branch2c + x = self.c(x) + x = self.c_bn(x) + return x + + +class ResBlock(paddle.nn.Layer): + """ + Residual block. + """ + def __init__(self, + dim_in, + dim_out, + temp_kernel_size, + stride, + dim_inner, + num_groups=1, + stride_1x1=False, + inplace_relu=True, + eps=1e-5, + dilation=1, + norm_module=paddle.nn.BatchNorm3D): + """ + ResBlock class constructs redisual blocks. More details can be found in: + Kaiming He, Xiangyu Zhang, Shaoqing Ren, and Jian Sun. + "Deep residual learning for image recognition." + https://arxiv.org/abs/1512.03385 + Args: + dim_in (int): the channel dimensions of the input. + dim_out (int): the channel dimension of the output. + temp_kernel_size (int): the temporal kernel sizes of the middle + convolution in the bottleneck. + stride (int): the stride of the bottleneck. + trans_func (string): transform function to be used to construct the + bottleneck. + dim_inner (int): the inner dimension of the block. + num_groups (int): number of groups for the convolution. num_groups=1 + is for standard ResNet like networks, and num_groups>1 is for + ResNeXt like networks. + stride_1x1 (bool): if True, apply stride to 1x1 conv, otherwise + apply stride to the 3x3 conv. + inplace_relu (bool): calculate the relu on the original input + without allocating new memory. + eps (float): epsilon for batch norm. + dilation (int): size of dilation. + """ + super(ResBlock, self).__init__() + self._inplace_relu = inplace_relu + self._eps = eps + self.norm_module = norm_module + self._construct( + dim_in, + dim_out, + temp_kernel_size, + stride, + dim_inner, + num_groups, + stride_1x1, + inplace_relu, + dilation, + ) + + def _construct( + self, + dim_in, + dim_out, + temp_kernel_size, + stride, + dim_inner, + num_groups, + stride_1x1, + inplace_relu, + dilation, + ): + # Use skip connection with projection if dim or res change. + if (dim_in != dim_out) or (stride != 1): + fan = (dim_out) * (1 * 1 * 1) + initializer_tmp = get_conv_init(fan) + self.branch1 = paddle.nn.Conv3D( + in_channels=dim_in, + out_channels=dim_out, + kernel_size=1, + stride=[1, stride, stride], + padding=0, + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False, + dilation=1) + self.branch1_bn = self.norm_module( + num_features=dim_out, + epsilon=self._eps, + weight_attr=get_bn_param_attr(), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + self.branch2 = BottleneckTransform(dim_in, + dim_out, + temp_kernel_size, + stride, + dim_inner, + num_groups, + stride_1x1=stride_1x1, + inplace_relu=inplace_relu, + dilation=dilation, + norm_module=self.norm_module) + + def forward(self, x): + if hasattr(self, "branch1"): + x1 = self.branch1(x) + x1 = self.branch1_bn(x1) + x2 = self.branch2(x) + x = paddle.add(x=x1, y=x2) + else: + x2 = self.branch2(x) + x = paddle.add(x=x, y=x2) + + x = F.relu(x) + return x + + +class ResStage(paddle.nn.Layer): + """ + Stage of 3D ResNet. It expects to have one or more tensors as input for + multi-pathway (SlowFast) cases. More details can be found here: + + Christoph Feichtenhofer, Haoqi Fan, Jitendra Malik, and Kaiming He. + "Slowfast networks for video recognition." + https://arxiv.org/pdf/1812.03982.pdf + """ + def __init__(self, + dim_in, + dim_out, + stride, + temp_kernel_sizes, + num_blocks, + dim_inner, + num_groups, + num_block_temp_kernel, + dilation, + stride_1x1=False, + inplace_relu=True, + norm_module=paddle.nn.BatchNorm3D): + """ + The `__init__` method of any subclass should also contain these arguments. + ResStage builds p streams, where p can be greater or equal to one. + Args: + dim_in (list): list of p the channel dimensions of the input. + Different channel dimensions control the input dimension of + different pathways. + dim_out (list): list of p the channel dimensions of the output. + Different channel dimensions control the input dimension of + different pathways. + temp_kernel_sizes (list): list of the p temporal kernel sizes of the + convolution in the bottleneck. Different temp_kernel_sizes + control different pathway. + stride (list): list of the p strides of the bottleneck. Different + stride control different pathway. + num_blocks (list): list of p numbers of blocks for each of the + pathway. + dim_inner (list): list of the p inner channel dimensions of the + input. Different channel dimensions control the input dimension + of different pathways. + num_groups (list): list of number of p groups for the convolution. + num_groups=1 is for standard ResNet like networks, and + num_groups>1 is for ResNeXt like networks. + num_block_temp_kernel (list): extent the temp_kernel_sizes to + num_block_temp_kernel blocks, then fill temporal kernel size + of 1 for the rest of the layers. + dilation (list): size of dilation for each pathway. + """ + super(ResStage, self).__init__() + assert all((num_block_temp_kernel[i] <= num_blocks[i] + for i in range(len(temp_kernel_sizes)))) + self.num_blocks = num_blocks + self.temp_kernel_sizes = [ + (temp_kernel_sizes[i] * num_blocks[i])[:num_block_temp_kernel[i]] + + [1] * (num_blocks[i] - num_block_temp_kernel[i]) + for i in range(len(temp_kernel_sizes)) + ] + assert (len({ + len(dim_in), + len(dim_out), + len(temp_kernel_sizes), + len(stride), + len(num_blocks), + len(dim_inner), + len(num_groups), + len(num_block_temp_kernel), + }) == 1) + self.num_pathways = len(self.num_blocks) + self.norm_module = norm_module + self._construct( + dim_in, + dim_out, + stride, + dim_inner, + num_groups, + stride_1x1, + inplace_relu, + dilation, + ) + + def _construct( + self, + dim_in, + dim_out, + stride, + dim_inner, + num_groups, + stride_1x1, + inplace_relu, + dilation, + ): + + for pathway in range(self.num_pathways): + for i in range(self.num_blocks[pathway]): + res_block = ResBlock( + dim_in[pathway] if i == 0 else dim_out[pathway], + dim_out[pathway], + self.temp_kernel_sizes[pathway][i], + stride[pathway] if i == 0 else 1, + dim_inner[pathway], + num_groups[pathway], + stride_1x1=stride_1x1, + inplace_relu=inplace_relu, + dilation=dilation[pathway], + norm_module=self.norm_module) + self.add_sublayer("pathway{}_res{}".format(pathway, i), + res_block) + + def forward(self, inputs): + output = [] + for pathway in range(self.num_pathways): + x = inputs[pathway] + + for i in range(self.num_blocks[pathway]): + m = getattr(self, "pathway{}_res{}".format(pathway, i)) + x = m(x) + output.append(x) + + return output + + +class ResNetBasicStem(paddle.nn.Layer): + """ + ResNe(X)t 3D stem module. + Performs spatiotemporal Convolution, BN, and Relu following by a + spatiotemporal pooling. + """ + def __init__(self, + dim_in, + dim_out, + kernel, + stride, + padding, + eps=1e-5, + norm_module=paddle.nn.BatchNorm3D): + super(ResNetBasicStem, self).__init__() + self.kernel = kernel + self.stride = stride + self.padding = padding + self.eps = eps + self.norm_module = norm_module + self._construct_stem(dim_in, dim_out) + + def _construct_stem(self, dim_in, dim_out): + fan = (dim_out) * (self.kernel[0] * self.kernel[1] * self.kernel[2]) + initializer_tmp = get_conv_init(fan) + + self._conv = paddle.nn.Conv3D( + in_channels=dim_in, + out_channels=dim_out, + kernel_size=self.kernel, + stride=self.stride, + padding=self.padding, + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False) + self._bn = self.norm_module(num_features=dim_out, + epsilon=self.eps, + weight_attr=get_bn_param_attr(), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + def forward(self, x): + x = self._conv(x) + x = self._bn(x) + x = F.relu(x) + + x = F.max_pool3d(x=x, + kernel_size=[1, 3, 3], + stride=[1, 2, 2], + padding=[0, 1, 1], + data_format="NCDHW") + return x + + +class VideoModelStem(paddle.nn.Layer): + """ + Video 3D stem module. Provides stem operations of Conv, BN, ReLU, MaxPool + on input data tensor for slow and fast pathways. + """ + def __init__(self, + dim_in, + dim_out, + kernel, + stride, + padding, + eps=1e-5, + norm_module=paddle.nn.BatchNorm3D): + """ + Args: + dim_in (list): the list of channel dimensions of the inputs. + dim_out (list): the output dimension of the convolution in the stem + layer. + kernel (list): the kernels' size of the convolutions in the stem + layers. Temporal kernel size, height kernel size, width kernel + size in order. + stride (list): the stride sizes of the convolutions in the stem + layer. Temporal kernel stride, height kernel size, width kernel + size in order. + padding (list): the paddings' sizes of the convolutions in the stem + layer. Temporal padding size, height padding size, width padding + size in order. + eps (float): epsilon for batch norm. + """ + super(VideoModelStem, self).__init__() + + assert (len({ + len(dim_in), + len(dim_out), + len(kernel), + len(stride), + len(padding), + }) == 1), "Input pathway dimensions are not consistent." + self.num_pathways = len(dim_in) + self.kernel = kernel + self.stride = stride + self.padding = padding + self.eps = eps + self.norm_module = norm_module + self._construct_stem(dim_in, dim_out) + + def _construct_stem(self, dim_in, dim_out): + for pathway in range(len(dim_in)): + stem = ResNetBasicStem(dim_in[pathway], dim_out[pathway], + self.kernel[pathway], self.stride[pathway], + self.padding[pathway], self.eps, + self.norm_module) + self.add_sublayer("pathway{}_stem".format(pathway), stem) + + def forward(self, x): + assert (len(x) == self.num_pathways + ), "Input tensor does not contain {} pathway".format( + self.num_pathways) + + for pathway in range(len(x)): + m = getattr(self, "pathway{}_stem".format(pathway)) + x[pathway] = m(x[pathway]) + + return x + + +class FuseFastToSlow(paddle.nn.Layer): + """ + Fuses the information from the Fast pathway to the Slow pathway. Given the + tensors from Slow pathway and Fast pathway, fuse information from Fast to + Slow, then return the fused tensors from Slow and Fast pathway in order. + """ + def __init__(self, + dim_in, + fusion_conv_channel_ratio, + fusion_kernel, + alpha, + fuse_bn_relu=1, + eps=1e-5, + norm_module=paddle.nn.BatchNorm3D): + """ + Args: + dim_in (int): the channel dimension of the input. + fusion_conv_channel_ratio (int): channel ratio for the convolution + used to fuse from Fast pathway to Slow pathway. + fusion_kernel (int): kernel size of the convolution used to fuse + from Fast pathway to Slow pathway. + alpha (int): the frame rate ratio between the Fast and Slow pathway. + eps (float): epsilon for batch norm. + """ + super(FuseFastToSlow, self).__init__() + self.fuse_bn_relu = fuse_bn_relu + fan = (dim_in * fusion_conv_channel_ratio) * (fusion_kernel * 1 * 1) + initializer_tmp = get_conv_init(fan) + + self._conv_f2s = paddle.nn.Conv3D( + in_channels=dim_in, + out_channels=dim_in * fusion_conv_channel_ratio, + kernel_size=[fusion_kernel, 1, 1], + stride=[alpha, 1, 1], + padding=[fusion_kernel // 2, 0, 0], + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False) + self._bn = norm_module(num_features=dim_in * fusion_conv_channel_ratio, + epsilon=eps, + weight_attr=get_bn_param_attr(), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + def forward(self, x): + x_s = x[0] + x_f = x[1] + fuse = self._conv_f2s(x_f) + # TODO: For AVA, set fuse_bn_relu=1, check mAP's improve. + if self.fuse_bn_relu: + fuse = self._bn(fuse) + fuse = F.relu(fuse) + x_s_fuse = paddle.concat(x=[x_s, fuse], axis=1, name=None) + + return [x_s_fuse, x_f] + + +@BACKBONES.register() +class ResNetSlowFast(paddle.nn.Layer): + """ + SlowFast model builder for SlowFast network. + + Christoph Feichtenhofer, Haoqi Fan, Jitendra Malik, and Kaiming He. + "Slowfast networks for video recognition." + https://arxiv.org/pdf/1812.03982.pdf + """ + def __init__( + self, + alpha, + beta, + bn_norm_type="batchnorm", + bn_num_splits=1, + num_pathways=2, + depth=50, + num_groups=1, + input_channel_num=[3, 3], + width_per_group=64, + fusion_conv_channel_ratio=2, + fusion_kernel_sz=7, #5? + pool_size_ratio=[[1, 1, 1], [1, 1, 1]], + fuse_bn_relu = 1, + spatial_strides = [[1, 1], [2, 2], [2, 2], [2, 2]], + use_pool_af_s2 = 1, + ): + """ + Args: + cfg (CfgNode): model building configs, details are in the + comments of the config file. + """ + super(ResNetSlowFast, self).__init__() + + self.alpha = alpha #8 + self.beta = beta #8 + self.norm_module = get_norm(bn_norm_type, bn_num_splits) + self.num_pathways = num_pathways + self.depth = depth + self.num_groups = num_groups + self.input_channel_num = input_channel_num + self.width_per_group = width_per_group + self.fusion_conv_channel_ratio = fusion_conv_channel_ratio + self.fusion_kernel_sz = fusion_kernel_sz # NOTE: modify to 7 in 8*8, 5 in old implement + self.pool_size_ratio = pool_size_ratio + self.fuse_bn_relu = fuse_bn_relu + self.spatial_strides = spatial_strides + self.use_pool_af_s2 = use_pool_af_s2 + self._construct_network() + + def _construct_network(self): + """ + Builds a SlowFast model. + The first pathway is the Slow pathway + and the second pathway is the Fast pathway. + + Args: + cfg (CfgNode): model building configs, details are in the + comments of the config file. + """ + temp_kernel = [ + [[1], [5]], # conv1 temporal kernel for slow and fast pathway. + [[1], [3]], # res2 temporal kernel for slow and fast pathway. + [[1], [3]], # res3 temporal kernel for slow and fast pathway. + [[3], [3]], # res4 temporal kernel for slow and fast pathway. + [[3], [3]], + ] # res5 temporal kernel for slow and fast pathway. + + self.s1 = VideoModelStem( + dim_in=self.input_channel_num, + dim_out=[self.width_per_group, self.width_per_group // self.beta], + kernel=[temp_kernel[0][0] + [7, 7], temp_kernel[0][1] + [7, 7]], + stride=[[1, 2, 2]] * 2, + padding=[ + [temp_kernel[0][0][0] // 2, 3, 3], + [temp_kernel[0][1][0] // 2, 3, 3], + ], + norm_module=self.norm_module) + self.s1_fuse = FuseFastToSlow( + dim_in=self.width_per_group // self.beta, + fusion_conv_channel_ratio=self.fusion_conv_channel_ratio, + fusion_kernel=self.fusion_kernel_sz, + alpha=self.alpha, + norm_module=self.norm_module, + fuse_bn_relu=self.fuse_bn_relu) + + # ResNet backbone + MODEL_STAGE_DEPTH = {50: (3, 4, 6, 3)} + (d2, d3, d4, d5) = MODEL_STAGE_DEPTH[self.depth] + + num_block_temp_kernel = [[3, 3], [4, 4], [6, 6], [3, 3]] + spatial_dilations = [[1, 1], [1, 1], [1, 1], [1, 1]] + spatial_strides = self.spatial_strides + #spatial_strides = [[1, 1], [2, 2], [2, 2], [2, 2]] + #spatial_strides = [[1, 1], [2, 2], [2, 2], [1, 1]] #TODO:check which value is FAIR's impliment + + out_dim_ratio = self.beta // self.fusion_conv_channel_ratio #4 + dim_inner = self.width_per_group * self.num_groups #64 + + self.s2 = ResStage(dim_in=[ + self.width_per_group + self.width_per_group // out_dim_ratio, + self.width_per_group // self.beta, + ], + dim_out=[ + self.width_per_group * 4, + self.width_per_group * 4 // self.beta, + ], + dim_inner=[dim_inner, dim_inner // self.beta], + temp_kernel_sizes=temp_kernel[1], + stride=spatial_strides[0], + num_blocks=[d2] * 2, + num_groups=[self.num_groups] * 2, + num_block_temp_kernel=num_block_temp_kernel[0], + dilation=spatial_dilations[0], + norm_module=self.norm_module) + + self.s2_fuse = FuseFastToSlow( + dim_in=self.width_per_group * 4 // self.beta, + fusion_conv_channel_ratio=self.fusion_conv_channel_ratio, + fusion_kernel=self.fusion_kernel_sz, + alpha=self.alpha, + norm_module=self.norm_module, + fuse_bn_relu=self.fuse_bn_relu, + ) + + self.s3 = ResStage( + dim_in=[ + self.width_per_group * 4 + + self.width_per_group * 4 // out_dim_ratio, + self.width_per_group * 4 // self.beta, + ], + dim_out=[ + self.width_per_group * 8, + self.width_per_group * 8 // self.beta, + ], + dim_inner=[dim_inner * 2, dim_inner * 2 // self.beta], + temp_kernel_sizes=temp_kernel[2], + stride=spatial_strides[1], + num_blocks=[d3] * 2, + num_groups=[self.num_groups] * 2, + num_block_temp_kernel=num_block_temp_kernel[1], + dilation=spatial_dilations[1], + norm_module=self.norm_module, + ) + + self.s3_fuse = FuseFastToSlow( + dim_in=self.width_per_group * 8 // self.beta, + fusion_conv_channel_ratio=self.fusion_conv_channel_ratio, + fusion_kernel=self.fusion_kernel_sz, + alpha=self.alpha, + norm_module=self.norm_module, + fuse_bn_relu=self.fuse_bn_relu, + ) + + self.s4 = ResStage( + dim_in=[ + self.width_per_group * 8 + + self.width_per_group * 8 // out_dim_ratio, + self.width_per_group * 8 // self.beta, + ], + dim_out=[ + self.width_per_group * 16, + self.width_per_group * 16 // self.beta, + ], + dim_inner=[dim_inner * 4, dim_inner * 4 // self.beta], + temp_kernel_sizes=temp_kernel[3], + stride=spatial_strides[2], + num_blocks=[d4] * 2, + num_groups=[self.num_groups] * 2, + num_block_temp_kernel=num_block_temp_kernel[2], + dilation=spatial_dilations[2], + norm_module=self.norm_module, + ) + + self.s4_fuse = FuseFastToSlow( + dim_in=self.width_per_group * 16 // self.beta, + fusion_conv_channel_ratio=self.fusion_conv_channel_ratio, + fusion_kernel=self.fusion_kernel_sz, + alpha=self.alpha, + norm_module=self.norm_module, + fuse_bn_relu=self.fuse_bn_relu, + ) + + self.s5 = ResStage( + dim_in=[ + self.width_per_group * 16 + + self.width_per_group * 16 // out_dim_ratio, + self.width_per_group * 16 // self.beta, + ], + dim_out=[ + self.width_per_group * 32, + self.width_per_group * 32 // self.beta, + ], + dim_inner=[dim_inner * 8, dim_inner * 8 // self.beta], + temp_kernel_sizes=temp_kernel[4], + stride=spatial_strides[3], + num_blocks=[d5] * 2, + num_groups=[self.num_groups] * 2, + num_block_temp_kernel=num_block_temp_kernel[3], + dilation=spatial_dilations[3], + norm_module=self.norm_module, + ) + + def init_weights(self): + pass + + def forward(self, x): + x = self.s1(x) #VideoModelStem + x = self.s1_fuse(x) #FuseFastToSlow + x = self.s2(x) #ResStage + x = self.s2_fuse(x) + + # TODO: For AVA, set use_pool_af_s2=1, check mAP's improve. + if self.use_pool_af_s2: + for pathway in range(self.num_pathways): + x[pathway] = F.max_pool3d(x=x[pathway], + kernel_size=self.pool_size_ratio[pathway], + stride=self.pool_size_ratio[pathway], + padding=[0, 0, 0], + data_format="NCDHW") + + x = self.s3(x) + x = self.s3_fuse(x) + x = self.s4(x) + x = self.s4_fuse(x) + x = self.s5(x) + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_slowfast_MRI.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_slowfast_MRI.py new file mode 100644 index 0000000..d348d45 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_slowfast_MRI.py @@ -0,0 +1,796 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 paddle +import paddle.nn.functional as F +from paddle.nn.initializer import KaimingNormal +from ..registry import BACKBONES +from paddlevideo.utils.multigrid import get_norm +import sys +import numpy as np +import paddle.distributed as dist + +# seed random seed +paddle.framework.seed(0) + + +# get init parameters for conv layer +def get_conv_init(fan_out): + return KaimingNormal(fan_in=fan_out) + + +def get_bn_param_attr(bn_weight=1.0, coeff=0.0): + param_attr = paddle.ParamAttr( + initializer=paddle.nn.initializer.Constant(bn_weight), + regularizer=paddle.regularizer.L2Decay(coeff)) + return param_attr + + +"""Video models.""" + + +class BottleneckTransform(paddle.nn.Layer): + """ + Bottleneck transformation: Tx1x1, 1x3x3, 1x1x1, where T is the size of + temporal kernel. + """ + def __init__(self, + dim_in, + dim_out, + temp_kernel_size, + stride, + dim_inner, + num_groups, + stride_1x1=False, + inplace_relu=True, + eps=1e-5, + dilation=1, + norm_module=paddle.nn.BatchNorm3D): + """ + Args: + dim_in (int): the channel dimensions of the input. + dim_out (int): the channel dimension of the output. + temp_kernel_size (int): the temporal kernel sizes of the middle + convolution in the bottleneck. + stride (int): the stride of the bottleneck. + dim_inner (int): the inner dimension of the block. + num_groups (int): number of groups for the convolution. num_groups=1 + is for standard ResNet like networks, and num_groups>1 is for + ResNeXt like networks. + stride_1x1 (bool): if True, apply stride to 1x1 conv, otherwise + apply stride to the 3x3 conv. + inplace_relu (bool): if True, calculate the relu on the original + input without allocating new memory. + eps (float): epsilon for batch norm. + dilation (int): size of dilation. + """ + super(BottleneckTransform, self).__init__() + self.temp_kernel_size = temp_kernel_size + self._inplace_relu = inplace_relu + self._eps = eps + self._stride_1x1 = stride_1x1 + self.norm_module = norm_module + self._construct(dim_in, dim_out, stride, dim_inner, num_groups, + dilation) + + def _construct(self, dim_in, dim_out, stride, dim_inner, num_groups, + dilation): + str1x1, str3x3 = (stride, 1) if self._stride_1x1 else (1, stride) + + fan = (dim_inner) * (self.temp_kernel_size * 1 * 1) + initializer_tmp = get_conv_init(fan) + + self.a = paddle.nn.Conv3D( + in_channels=dim_in, + out_channels=dim_inner, + kernel_size=[self.temp_kernel_size, 1, 1], + stride=[1, str1x1, str1x1], + padding=[int(self.temp_kernel_size // 2), 0, 0], + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False) + self.a_bn = self.norm_module(num_features=dim_inner, + epsilon=self._eps, + weight_attr=get_bn_param_attr(), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + # 1x3x3, BN, ReLU. + fan = (dim_inner) * (1 * 3 * 3) + initializer_tmp = get_conv_init(fan) + + self.b = paddle.nn.Conv3D( + in_channels=dim_inner, + out_channels=dim_inner, + kernel_size=[1, 3, 3], + stride=[1, str3x3, str3x3], + padding=[0, dilation, dilation], + groups=num_groups, + dilation=[1, dilation, dilation], + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False) + self.b_bn = self.norm_module(num_features=dim_inner, + epsilon=self._eps, + weight_attr=get_bn_param_attr(), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + # 1x1x1, BN. + fan = (dim_out) * (1 * 1 * 1) + initializer_tmp = get_conv_init(fan) + + self.c = paddle.nn.Conv3D( + in_channels=dim_inner, + out_channels=dim_out, + kernel_size=[1, 1, 1], + stride=[1, 1, 1], + padding=[0, 0, 0], + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False) + self.c_bn = self.norm_module( + num_features=dim_out, + epsilon=self._eps, + weight_attr=get_bn_param_attr(bn_weight=0.0), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + def forward(self, x): + # Branch2a. + x = self.a(x) + x = self.a_bn(x) + x = F.relu(x) + + # Branch2b. + x = self.b(x) + x = self.b_bn(x) + x = F.relu(x) + + # Branch2c + x = self.c(x) + x = self.c_bn(x) + return x + + +class ResBlock(paddle.nn.Layer): + """ + Residual block. + """ + def __init__(self, + dim_in, + dim_out, + temp_kernel_size, + stride, + dim_inner, + num_groups=1, + stride_1x1=False, + inplace_relu=True, + eps=1e-5, + dilation=1, + norm_module=paddle.nn.BatchNorm3D): + """ + ResBlock class constructs redisual blocks. More details can be found in: + Kaiming He, Xiangyu Zhang, Shaoqing Ren, and Jian Sun. + "Deep residual learning for image recognition." + https://arxiv.org/abs/1512.03385 + Args: + dim_in (int): the channel dimensions of the input. + dim_out (int): the channel dimension of the output. + temp_kernel_size (int): the temporal kernel sizes of the middle + convolution in the bottleneck. + stride (int): the stride of the bottleneck. + trans_func (string): transform function to be used to construct the + bottleneck. + dim_inner (int): the inner dimension of the block. + num_groups (int): number of groups for the convolution. num_groups=1 + is for standard ResNet like networks, and num_groups>1 is for + ResNeXt like networks. + stride_1x1 (bool): if True, apply stride to 1x1 conv, otherwise + apply stride to the 3x3 conv. + inplace_relu (bool): calculate the relu on the original input + without allocating new memory. + eps (float): epsilon for batch norm. + dilation (int): size of dilation. + """ + super(ResBlock, self).__init__() + self._inplace_relu = inplace_relu + self._eps = eps + self.norm_module = norm_module + self._construct( + dim_in, + dim_out, + temp_kernel_size, + stride, + dim_inner, + num_groups, + stride_1x1, + inplace_relu, + dilation, + ) + + def _construct( + self, + dim_in, + dim_out, + temp_kernel_size, + stride, + dim_inner, + num_groups, + stride_1x1, + inplace_relu, + dilation, + ): + # Use skip connection with projection if dim or res change. + if (dim_in != dim_out) or (stride != 1): + fan = (dim_out) * (1 * 1 * 1) + initializer_tmp = get_conv_init(fan) + self.branch1 = paddle.nn.Conv3D( + in_channels=dim_in, + out_channels=dim_out, + kernel_size=1, + stride=[1, stride, stride], + padding=0, + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False, + dilation=1) + self.branch1_bn = self.norm_module( + num_features=dim_out, + epsilon=self._eps, + weight_attr=get_bn_param_attr(), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + self.branch2 = BottleneckTransform(dim_in, + dim_out, + temp_kernel_size, + stride, + dim_inner, + num_groups, + stride_1x1=stride_1x1, + inplace_relu=inplace_relu, + dilation=dilation, + norm_module=self.norm_module) + + def forward(self, x): + if hasattr(self, "branch1"): + x1 = self.branch1(x) + x1 = self.branch1_bn(x1) + x2 = self.branch2(x) + x = paddle.add(x=x1, y=x2) + else: + x2 = self.branch2(x) + x = paddle.add(x=x, y=x2) + + x = F.relu(x) + return x + + +class ResStage(paddle.nn.Layer): + """ + Stage of 3D ResNet. It expects to have one or more tensors as input for + multi-pathway (SlowFast) cases. More details can be found here: + + Christoph Feichtenhofer, Haoqi Fan, Jitendra Malik, and Kaiming He. + "Slowfast networks for video recognition." + https://arxiv.org/pdf/1812.03982.pdf + """ + def __init__(self, + dim_in, + dim_out, + stride, + temp_kernel_sizes, + num_blocks, + dim_inner, + num_groups, + num_block_temp_kernel, + dilation, + stride_1x1=False, + inplace_relu=True, + norm_module=paddle.nn.BatchNorm3D): + """ + The `__init__` method of any subclass should also contain these arguments. + ResStage builds p streams, where p can be greater or equal to one. + Args: + dim_in (list): list of p the channel dimensions of the input. + Different channel dimensions control the input dimension of + different pathways. + dim_out (list): list of p the channel dimensions of the output. + Different channel dimensions control the input dimension of + different pathways. + temp_kernel_sizes (list): list of the p temporal kernel sizes of the + convolution in the bottleneck. Different temp_kernel_sizes + control different pathway. + stride (list): list of the p strides of the bottleneck. Different + stride control different pathway. + num_blocks (list): list of p numbers of blocks for each of the + pathway. + dim_inner (list): list of the p inner channel dimensions of the + input. Different channel dimensions control the input dimension + of different pathways. + num_groups (list): list of number of p groups for the convolution. + num_groups=1 is for standard ResNet like networks, and + num_groups>1 is for ResNeXt like networks. + num_block_temp_kernel (list): extent the temp_kernel_sizes to + num_block_temp_kernel blocks, then fill temporal kernel size + of 1 for the rest of the layers. + dilation (list): size of dilation for each pathway. + """ + super(ResStage, self).__init__() + assert all((num_block_temp_kernel[i] <= num_blocks[i] + for i in range(len(temp_kernel_sizes)))) + self.num_blocks = num_blocks + self.temp_kernel_sizes = [ + (temp_kernel_sizes[i] * num_blocks[i])[:num_block_temp_kernel[i]] + + [1] * (num_blocks[i] - num_block_temp_kernel[i]) + for i in range(len(temp_kernel_sizes)) + ] + assert (len({ + len(dim_in), + len(dim_out), + len(temp_kernel_sizes), + len(stride), + len(num_blocks), + len(dim_inner), + len(num_groups), + len(num_block_temp_kernel), + }) == 1) + self.num_pathways = len(self.num_blocks) + self.norm_module = norm_module + self._construct( + dim_in, + dim_out, + stride, + dim_inner, + num_groups, + stride_1x1, + inplace_relu, + dilation, + ) + + def _construct( + self, + dim_in, + dim_out, + stride, + dim_inner, + num_groups, + stride_1x1, + inplace_relu, + dilation, + ): + + for pathway in range(self.num_pathways): + for i in range(self.num_blocks[pathway]): + res_block = ResBlock( + dim_in[pathway] if i == 0 else dim_out[pathway], + dim_out[pathway], + self.temp_kernel_sizes[pathway][i], + stride[pathway] if i == 0 else 1, + dim_inner[pathway], + num_groups[pathway], + stride_1x1=stride_1x1, + inplace_relu=inplace_relu, + dilation=dilation[pathway], + norm_module=self.norm_module) + self.add_sublayer("pathway{}_res{}".format(pathway, i), + res_block) + + def forward(self, inputs): + output = [] + for pathway in range(self.num_pathways): + x = inputs[pathway] + + for i in range(self.num_blocks[pathway]): + m = getattr(self, "pathway{}_res{}".format(pathway, i)) + x = m(x) + output.append(x) + + return output + + +class ResNetBasicStem(paddle.nn.Layer): + """ + ResNe(X)t 3D stem module. + Performs spatiotemporal Convolution, BN, and Relu following by a + spatiotemporal pooling. + """ + def __init__(self, + dim_in, + dim_out, + kernel, + stride, + padding, + eps=1e-5, + norm_module=paddle.nn.BatchNorm3D): + super(ResNetBasicStem, self).__init__() + self.kernel = kernel + self.stride = stride + self.padding = padding + self.eps = eps + self.norm_module = norm_module + self._construct_stem(dim_in, dim_out) + + def _construct_stem(self, dim_in, dim_out): + fan = (dim_out) * (self.kernel[0] * self.kernel[1] * self.kernel[2]) + initializer_tmp = get_conv_init(fan) + + self._conv = paddle.nn.Conv3D( + in_channels=dim_in, + out_channels=dim_out, + kernel_size=self.kernel, + stride=self.stride, + padding=self.padding, + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False) + self._bn = self.norm_module(num_features=dim_out, + epsilon=self.eps, + weight_attr=get_bn_param_attr(), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + def forward(self, x): + x = self._conv(x) + x = self._bn(x) + x = F.relu(x) + + x = F.max_pool3d(x=x, + kernel_size=[1, 3, 3], + stride=[1, 2, 2], + padding=[0, 1, 1], + data_format="NCDHW") + return x + + +class VideoModelStem(paddle.nn.Layer): + """ + Video 3D stem module. Provides stem operations of Conv, BN, ReLU, MaxPool + on input data tensor for slow and fast pathways. + """ + def __init__(self, + dim_in, + dim_out, + kernel, + stride, + padding, + eps=1e-5, + norm_module=paddle.nn.BatchNorm3D): + """ + Args: + dim_in (list): the list of channel dimensions of the inputs. + dim_out (list): the output dimension of the convolution in the stem + layer. + kernel (list): the kernels' size of the convolutions in the stem + layers. Temporal kernel size, height kernel size, width kernel + size in order. + stride (list): the stride sizes of the convolutions in the stem + layer. Temporal kernel stride, height kernel size, width kernel + size in order. + padding (list): the paddings' sizes of the convolutions in the stem + layer. Temporal padding size, height padding size, width padding + size in order. + eps (float): epsilon for batch norm. + """ + super(VideoModelStem, self).__init__() + + assert (len({ + len(dim_in), + len(dim_out), + len(kernel), + len(stride), + len(padding), + }) == 1), "Input pathway dimensions are not consistent." + self.num_pathways = len(dim_in) + self.kernel = kernel + self.stride = stride + self.padding = padding + self.eps = eps + self.norm_module = norm_module + self._construct_stem(dim_in, dim_out) + + def _construct_stem(self, dim_in, dim_out): + for pathway in range(len(dim_in)): + stem = ResNetBasicStem(dim_in[pathway], dim_out[pathway], + self.kernel[pathway], self.stride[pathway], + self.padding[pathway], self.eps, + self.norm_module) + self.add_sublayer("pathway{}_stem".format(pathway), stem) + + def forward(self, x): + assert (len(x) == self.num_pathways + ), "Input tensor does not contain {} pathway".format( + self.num_pathways) + + for pathway in range(len(x)): + m = getattr(self, "pathway{}_stem".format(pathway)) + x[pathway] = m(x[pathway]) + + return x + + +class FuseFastToSlow(paddle.nn.Layer): + """ + Fuses the information from the Fast pathway to the Slow pathway. Given the + tensors from Slow pathway and Fast pathway, fuse information from Fast to + Slow, then return the fused tensors from Slow and Fast pathway in order. + """ + def __init__(self, + dim_in, + fusion_conv_channel_ratio, + fusion_kernel, + alpha, + fuse_bn_relu=1, + eps=1e-5, + norm_module=paddle.nn.BatchNorm3D): + """ + Args: + dim_in (int): the channel dimension of the input. + fusion_conv_channel_ratio (int): channel ratio for the convolution + used to fuse from Fast pathway to Slow pathway. + fusion_kernel (int): kernel size of the convolution used to fuse + from Fast pathway to Slow pathway. + alpha (int): the frame rate ratio between the Fast and Slow pathway. + eps (float): epsilon for batch norm. + """ + super(FuseFastToSlow, self).__init__() + self.fuse_bn_relu = fuse_bn_relu + fan = (dim_in * fusion_conv_channel_ratio) * (fusion_kernel * 1 * 1) + initializer_tmp = get_conv_init(fan) + + self._conv_f2s = paddle.nn.Conv3D( + in_channels=dim_in, + out_channels=dim_in * fusion_conv_channel_ratio, + kernel_size=[fusion_kernel, 1, 1], + stride=[alpha, 1, 1], + padding=[fusion_kernel // 2, 0, 0], + weight_attr=paddle.ParamAttr(initializer=initializer_tmp), + bias_attr=False) + self._bn = norm_module(num_features=dim_in * fusion_conv_channel_ratio, + epsilon=eps, + weight_attr=get_bn_param_attr(), + bias_attr=get_bn_param_attr(bn_weight=0.0)) + + def forward(self, x): + x_s = x[0] + x_f = x[1] + fuse = self._conv_f2s(x_f) + # TODO: For AVA, set fuse_bn_relu=1, check mAP's improve. + if self.fuse_bn_relu: + fuse = self._bn(fuse) + fuse = F.relu(fuse) + x_s_fuse = paddle.concat(x=[x_s, fuse], axis=1, name=None) + + return [x_s_fuse, x_f] + + +@BACKBONES.register() +class ResNetSlowFast_MRI(paddle.nn.Layer): + """ + SlowFast model builder for SlowFast network. + + Christoph Feichtenhofer, Haoqi Fan, Jitendra Malik, and Kaiming He. + "Slowfast networks for video recognition." + https://arxiv.org/pdf/1812.03982.pdf + """ + def __init__( + self, + alpha, + beta, + bn_norm_type="batchnorm", + bn_num_splits=1, + num_pathways=2, + depth=50, + num_groups=1, + input_channel_num=[1, 1], + width_per_group=64, + fusion_conv_channel_ratio=2, + fusion_kernel_sz=7, #5? + pool_size_ratio=[[1, 1, 1], [1, 1, 1]], + fuse_bn_relu=1, + spatial_strides=[[1, 1], [2, 2], [2, 2], [2, 2]], + use_pool_af_s2=1, + ): + """ + Args: + cfg (CfgNode): model building configs, details are in the + comments of the config file. + """ + super(ResNetSlowFast_MRI, self).__init__() + + self.alpha = alpha #8 + self.beta = beta #8 + self.norm_module = get_norm(bn_norm_type, bn_num_splits) + self.num_pathways = num_pathways + self.depth = depth + self.num_groups = num_groups + self.input_channel_num = input_channel_num + self.width_per_group = width_per_group + self.fusion_conv_channel_ratio = fusion_conv_channel_ratio + self.fusion_kernel_sz = fusion_kernel_sz # NOTE: modify to 7 in 8*8, 5 in old implement + self.pool_size_ratio = pool_size_ratio + self.fuse_bn_relu = fuse_bn_relu + self.spatial_strides = spatial_strides + self.use_pool_af_s2 = use_pool_af_s2 + self._construct_network() + + def _construct_network(self): + """ + Builds a SlowFast model. + The first pathway is the Slow pathway + and the second pathway is the Fast pathway. + + Args: + cfg (CfgNode): model building configs, details are in the + comments of the config file. + """ + temp_kernel = [ + [[1], [5]], # conv1 temporal kernel for slow and fast pathway. + [[1], [3]], # res2 temporal kernel for slow and fast pathway. + [[1], [3]], # res3 temporal kernel for slow and fast pathway. + [[3], [3]], # res4 temporal kernel for slow and fast pathway. + [[3], [3]], + ] # res5 temporal kernel for slow and fast pathway. + + self.s1 = VideoModelStem( + dim_in=self.input_channel_num, + dim_out=[self.width_per_group, self.width_per_group // self.beta], + kernel=[temp_kernel[0][0] + [7, 7], temp_kernel[0][1] + [7, 7]], + stride=[[1, 2, 2]] * 2, + padding=[ + [temp_kernel[0][0][0] // 2, 3, 3], + [temp_kernel[0][1][0] // 2, 3, 3], + ], + norm_module=self.norm_module) + self.s1_fuse = FuseFastToSlow( + dim_in=self.width_per_group // self.beta, + fusion_conv_channel_ratio=self.fusion_conv_channel_ratio, + fusion_kernel=self.fusion_kernel_sz, + alpha=self.alpha, + norm_module=self.norm_module, + fuse_bn_relu=self.fuse_bn_relu) + + # ResNet backbone + MODEL_STAGE_DEPTH = {50: (3, 4, 6, 3)} + (d2, d3, d4, d5) = MODEL_STAGE_DEPTH[self.depth] + + num_block_temp_kernel = [[3, 3], [4, 4], [6, 6], [3, 3]] + spatial_dilations = [[1, 1], [1, 1], [1, 1], [1, 1]] + spatial_strides = self.spatial_strides + #spatial_strides = [[1, 1], [2, 2], [2, 2], [2, 2]] + #spatial_strides = [[1, 1], [2, 2], [2, 2], [1, 1]] #TODO:check which value is FAIR's impliment + + out_dim_ratio = self.beta // self.fusion_conv_channel_ratio #4 + dim_inner = self.width_per_group * self.num_groups #64 + + self.s2 = ResStage(dim_in=[ + self.width_per_group + self.width_per_group // out_dim_ratio, + self.width_per_group // self.beta, + ], + dim_out=[ + self.width_per_group * 4, + self.width_per_group * 4 // self.beta, + ], + dim_inner=[dim_inner, dim_inner // self.beta], + temp_kernel_sizes=temp_kernel[1], + stride=spatial_strides[0], + num_blocks=[d2] * 2, + num_groups=[self.num_groups] * 2, + num_block_temp_kernel=num_block_temp_kernel[0], + dilation=spatial_dilations[0], + norm_module=self.norm_module) + + self.s2_fuse = FuseFastToSlow( + dim_in=self.width_per_group * 4 // self.beta, + fusion_conv_channel_ratio=self.fusion_conv_channel_ratio, + fusion_kernel=self.fusion_kernel_sz, + alpha=self.alpha, + norm_module=self.norm_module, + fuse_bn_relu=self.fuse_bn_relu, + ) + + self.s3 = ResStage( + dim_in=[ + self.width_per_group * 4 + + self.width_per_group * 4 // out_dim_ratio, + self.width_per_group * 4 // self.beta, + ], + dim_out=[ + self.width_per_group * 8, + self.width_per_group * 8 // self.beta, + ], + dim_inner=[dim_inner * 2, dim_inner * 2 // self.beta], + temp_kernel_sizes=temp_kernel[2], + stride=spatial_strides[1], + num_blocks=[d3] * 2, + num_groups=[self.num_groups] * 2, + num_block_temp_kernel=num_block_temp_kernel[1], + dilation=spatial_dilations[1], + norm_module=self.norm_module, + ) + + self.s3_fuse = FuseFastToSlow( + dim_in=self.width_per_group * 8 // self.beta, + fusion_conv_channel_ratio=self.fusion_conv_channel_ratio, + fusion_kernel=self.fusion_kernel_sz, + alpha=self.alpha, + norm_module=self.norm_module, + fuse_bn_relu=self.fuse_bn_relu, + ) + + self.s4 = ResStage( + dim_in=[ + self.width_per_group * 8 + + self.width_per_group * 8 // out_dim_ratio, + self.width_per_group * 8 // self.beta, + ], + dim_out=[ + self.width_per_group * 16, + self.width_per_group * 16 // self.beta, + ], + dim_inner=[dim_inner * 4, dim_inner * 4 // self.beta], + temp_kernel_sizes=temp_kernel[3], + stride=spatial_strides[2], + num_blocks=[d4] * 2, + num_groups=[self.num_groups] * 2, + num_block_temp_kernel=num_block_temp_kernel[2], + dilation=spatial_dilations[2], + norm_module=self.norm_module, + ) + + self.s4_fuse = FuseFastToSlow( + dim_in=self.width_per_group * 16 // self.beta, + fusion_conv_channel_ratio=self.fusion_conv_channel_ratio, + fusion_kernel=self.fusion_kernel_sz, + alpha=self.alpha, + norm_module=self.norm_module, + fuse_bn_relu=self.fuse_bn_relu, + ) + + self.s5 = ResStage( + dim_in=[ + self.width_per_group * 16 + + self.width_per_group * 16 // out_dim_ratio, + self.width_per_group * 16 // self.beta, + ], + dim_out=[ + self.width_per_group * 32, + self.width_per_group * 32 // self.beta, + ], + dim_inner=[dim_inner * 8, dim_inner * 8 // self.beta], + temp_kernel_sizes=temp_kernel[4], + stride=spatial_strides[3], + num_blocks=[d5] * 2, + num_groups=[self.num_groups] * 2, + num_block_temp_kernel=num_block_temp_kernel[3], + dilation=spatial_dilations[3], + norm_module=self.norm_module, + ) + + def init_weights(self): + pass + + def forward(self, x): + x = self.s1(x) #VideoModelStem + x = self.s1_fuse(x) #FuseFastToSlow + x = self.s2(x) #ResStage + x = self.s2_fuse(x) + + # TODO: For AVA, set use_pool_af_s2=1, check mAP's improve. + if self.use_pool_af_s2: + for pathway in range(self.num_pathways): + x[pathway] = F.max_pool3d( + x=x[pathway], + kernel_size=self.pool_size_ratio[pathway], + stride=self.pool_size_ratio[pathway], + padding=[0, 0, 0], + data_format="NCDHW") + + x = self.s3(x) + x = self.s3_fuse(x) + x = self.s4(x) + x = self.s4_fuse(x) + x = self.s5(x) + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsm.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsm.py new file mode 100644 index 0000000..70788ec --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsm.py @@ -0,0 +1,353 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 paddle +import paddle.nn as nn +from paddle.nn import (Conv2D, BatchNorm2D, Linear, Dropout, MaxPool2D, + AvgPool2D) +from paddle import ParamAttr +import paddle.nn.functional as F +from paddle.regularizer import L2Decay +from ..registry import BACKBONES +from ..weight_init import weight_init_ +from ...utils import load_ckpt + + +class ConvBNLayer(nn.Layer): + """Conv2D and BatchNorm2D layer. + + Args: + in_channels (int): Number of channels for the input. + out_channels (int): Number of channels for the output. + kernel_size (int): Kernel size. + stride (int): Stride in the Conv2D layer. Default: 1. + groups (int): Groups in the Conv2D, Default: 1. + act (str): Indicate activation after BatchNorm2D layer. + name (str): the name of an instance of ConvBNLayer. + Note: weight and bias initialization include initialize values and name the restored parameters, values initialization are explicit declared in the ```init_weights``` method. + + """ + def __init__(self, + in_channels, + out_channels, + kernel_size, + stride=1, + groups=1, + act=None, + name=None, + data_format="NCHW"): + super(ConvBNLayer, self).__init__() + self._conv = Conv2D(in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=(kernel_size - 1) // 2, + groups=groups, + weight_attr=ParamAttr(name=name + "_weights"), + bias_attr=False, + data_format=data_format) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + + self._act = act + + self._batch_norm = BatchNorm2D( + out_channels, + weight_attr=ParamAttr(name=bn_name + "_scale", + regularizer=L2Decay(0.0)), + bias_attr=ParamAttr(name=bn_name + "_offset", + regularizer=L2Decay(0.0)), + data_format=data_format) + + def forward(self, inputs): + y = self._conv(inputs) + y = self._batch_norm(y) + if self._act: + y = getattr(paddle.nn.functional, self._act)(y) + return y + + +class BottleneckBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + num_seg=8, + name=None, + data_format="NCHW"): + super(BottleneckBlock, self).__init__() + self.data_format = data_format + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + act="relu", + name=name + "_branch2a", + data_format=data_format) + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + kernel_size=3, + stride=stride, + act="relu", + name=name + "_branch2b", + data_format=data_format) + + self.conv2 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels * 4, + kernel_size=1, + act=None, + name=name + "_branch2c", + data_format=data_format) + + if not shortcut: + self.short = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels * 4, + kernel_size=1, + stride=stride, + name=name + "_branch1", + data_format=data_format) + + self.shortcut = shortcut + self.num_seg = num_seg + + def forward(self, inputs): + if paddle.is_compiled_with_custom_device('npu'): + x = inputs + seg_num = self.num_seg + shift_ratio = 1.0 / self.num_seg + + shape = x.shape #[N*T, C, H, W] + reshape_x = x.reshape( + (-1, seg_num, shape[1], shape[2], shape[3])) #[N, T, C, H, W] + pad_x = F.pad(reshape_x, [ + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + ]) #[N, T+2, C, H, W] + c1 = int(shape[1] * shift_ratio) + c2 = int(shape[1] * 2 * shift_ratio) + slice1 = pad_x[:, :seg_num, :c1, :, :] + slice2 = pad_x[:, 2:seg_num + 2, c1:c2, :, :] + slice3 = pad_x[:, 1:seg_num + 1, c2:, :, :] + concat_x = paddle.concat([slice1, slice2, slice3], + axis=2) #[N, T, C, H, W] + shifts = concat_x.reshape(shape) + else: + shifts = F.temporal_shift(inputs, + self.num_seg, + 1.0 / self.num_seg, + data_format=self.data_format) + + y = self.conv0(shifts) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(x=short, y=conv2) + return F.relu(y) + + +class BasicBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + name=None, + data_format="NCHW"): + super(BasicBlock, self).__init__() + self.stride = stride + self.conv0 = ConvBNLayer( + in_channels=in_channels, + out_channels=out_channels, + filter_size=3, + stride=stride, + act="relu", + name=name + "_branch2a", + data_format=data_format, + ) + self.conv1 = ConvBNLayer( + in_channels=out_channels, + out_channels=out_channels, + filter_size=3, + act=None, + name=name + "_branch2b", + data_format=data_format, + ) + + if not shortcut: + self.short = ConvBNLayer( + in_channels=in_channels, + out_channels=out_channels, + filter_size=1, + stride=stride, + name=name + "_branch1", + data_format=data_format, + ) + + self.shortcut = shortcut + + def forward(self, inputs): + y = self.conv0(inputs) + conv1 = self.conv1(y) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(short, conv1) + y = F.relu(y) + return y + + +@BACKBONES.register() +class ResNetTSM(nn.Layer): + """ResNet TSM backbone. + + Args: + depth (int): Depth of resnet model. + pretrained (str): pretrained model. Default: None. + """ + def __init__(self, depth, num_seg=8, data_format="NCHW", pretrained=None): + super(ResNetTSM, self).__init__() + self.pretrained = pretrained + self.layers = depth + self.num_seg = num_seg + self.data_format = data_format + + supported_layers = [18, 34, 50, 101, 152] + assert self.layers in supported_layers, \ + "supported layers are {} but input layer is {}".format( + supported_layers, self.layers) + + if self.layers == 18: + depth = [2, 2, 2, 2] + elif self.layers == 34 or self.layers == 50: + depth = [3, 4, 6, 3] + elif self.layers == 101: + depth = [3, 4, 23, 3] + elif self.layers == 152: + depth = [3, 8, 36, 3] + + in_channels = 64 + out_channels = [64, 128, 256, 512] + + self.conv = ConvBNLayer(in_channels=3, + out_channels=64, + kernel_size=7, + stride=2, + act="relu", + name="conv1", + data_format=self.data_format) + self.pool2D_max = MaxPool2D( + kernel_size=3, + stride=2, + padding=1, + data_format=self.data_format, + ) + + self.block_list = [] + if self.layers >= 50: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if self.layers in [101, 152] and block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + conv_name, + BottleneckBlock( + in_channels=in_channels + if i == 0 else out_channels[block] * 4, + out_channels=out_channels[block], + stride=2 if i == 0 and block != 0 else 1, + num_seg=self.num_seg, + shortcut=shortcut, + name=conv_name, + data_format=self.data_format)) + in_channels = out_channels[block] * 4 + self.block_list.append(bottleneck_block) + shortcut = True + else: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + conv_name = "res" + str(block + 2) + chr(97 + i) + basic_block = self.add_sublayer( + conv_name, + BasicBlock( + in_channels=in_channels[block] + if i == 0 else out_channels[block], + out_channels=out_channels[block], + stride=2 if i == 0 and block != 0 else 1, + shortcut=shortcut, + name=conv_name, + data_format=self.data_format, + )) + self.block_list.append(basic_block) + shortcut = True + + def init_weights(self): + """Initiate the parameters. + Note: + 1. when indicate pretrained loading path, will load it to initiate backbone. + 2. when not indicating pretrained loading path, will follow specific initialization initiate backbone. Always, Conv2D layer will be initiated by KaimingNormal function, and BatchNorm2d will be initiated by Constant function. + Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/api/paddle/nn/initializer/kaiming/KaimingNormal_en.html + """ + #XXX: check bias!!! check pretrained!!! + + if isinstance(self.pretrained, str) and self.pretrained.strip() != "": + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + #XXX: no bias + weight_init_(layer, 'KaimingNormal') + elif isinstance(layer, nn.BatchNorm2D): + weight_init_(layer, 'Constant', value=1) + + def forward(self, inputs): + """Define how the backbone is going to run. + + """ + #NOTE: (deprecated design) Already merge axis 0(batches) and axis 1(clips) before extracting feature phase, + # please refer to paddlevideo/modeling/framework/recognizers/recognizer2d.py#L27 + #y = paddle.reshape( + # inputs, [-1, inputs.shape[2], inputs.shape[3], inputs.shape[4]]) + + #NOTE: As paddlepaddle to_static method need a "pure" model to trim. It means from + # 1. the phase of generating data[images, label] from dataloader + # to + # 2. last layer of a model, always is FC layer + + y = self.conv(inputs) + y = self.pool2D_max(y) + for block in self.block_list: + y = block(y) + return y diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsm_MRI.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsm_MRI.py new file mode 100644 index 0000000..e814f0f --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsm_MRI.py @@ -0,0 +1,327 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +import math + +import sys +import paddle +import paddle.nn as nn +from paddle.nn import (Conv2D, BatchNorm2D, Linear, Dropout, MaxPool2D, + AvgPool2D) +from paddle import ParamAttr +import paddle.nn.functional as F + +from ..registry import BACKBONES +from ..weight_init import weight_init_ +from ...utils.save_load import load_ckpt +from paddle.regularizer import L2Decay + + +class ConvBNLayer(nn.Layer): + """Conv2D and BatchNorm2D layer. + + Args: + in_channels (int): Number of channels for the input. + out_channels (int): Number of channels for the output. + kernel_size (int): Kernel size. + stride (int): Stride in the Conv2D layer. Default: 1. + groups (int): Groups in the Conv2D, Default: 1. + is_tweaks_mode (bool): switch for tweaks. Default: False. + act (str): Indicate activation after BatchNorm2D layer. + name (str): the name of an instance of ConvBNLayer. + + Note: weight and bias initialization include initialize values and name the restored parameters, values initialization are explicit declared in the ```init_weights``` method. + + """ + def __init__(self, + in_channels, + out_channels, + kernel_size, + stride=1, + groups=1, + is_tweaks_mode=False, + act=None, + name=None): + super(ConvBNLayer, self).__init__() + self.is_tweaks_mode = is_tweaks_mode + #ResNet-D 1/2:add a 2×2 average pooling layer with a stride of 2 before the convolution, + # whose stride is changed to 1, works well in practice. + self._pool2d_avg = AvgPool2D(kernel_size=2, + stride=2, + padding=0, + ceil_mode=True) + + self._conv = Conv2D(in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=(kernel_size - 1) // 2, + groups=groups, + weight_attr=ParamAttr(name=name + "_weights"), + bias_attr=False) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + + self._act = act + + self._batch_norm = BatchNorm2D( + out_channels, + weight_attr=ParamAttr(name=bn_name + "_scale", + regularizer=L2Decay(0.0)), + bias_attr=ParamAttr(bn_name + "_offset", regularizer=L2Decay(0.0))) + + def forward(self, inputs): + if self.is_tweaks_mode: + inputs = self._pool2d_avg(inputs) + y = self._conv(inputs) + y = self._batch_norm(y) + if self._act: + y = getattr(paddle.nn.functional, self._act)(y) + return y + + +class BottleneckBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + if_first=False, + num_seg=8, + name=None): + super(BottleneckBlock, self).__init__() + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + act="leaky_relu", + name=name + "_branch2a") + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + kernel_size=3, + stride=stride, + act="leaky_relu", + name=name + "_branch2b") + + self.conv2 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels * 4, + kernel_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer( + in_channels=in_channels, + out_channels=out_channels * 4, + kernel_size=1, + stride= + 1, #ResNet-D 2/2:add a 2×2 average pooling layer with a stride of 2 before the convolution, + # whose stride is changed to 1, works well in practice. + is_tweaks_mode=False if if_first else True, + name=name + "_branch1") + + self.shortcut = shortcut + self.num_seg = num_seg + + def forward(self, inputs): + shifts = F.temporal_shift(inputs, self.num_seg, 1.0 / self.num_seg) + y = self.conv0(shifts) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(x=short, y=conv2) + return F.leaky_relu(y) + + +class BasicBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + name=None): + super(BasicBlock, self).__init__() + self.stride = stride + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + filter_size=3, + stride=stride, + act="leaky_relu", + name=name + "_branch2a") + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + filter_size=3, + act=None, + name=name + "_branch2b") + + if not shortcut: + self.short = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + filter_size=1, + stride=stride, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs): + y = self.conv0(inputs) + conv1 = self.conv1(y) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(short, conv1) + y = F.leaky_relu(y) + return y + + +@BACKBONES.register() +class ResNetTSM_MRI(nn.Layer): + """ResNet TSM backbone. + + Args: + depth (int): Depth of resnet model. + pretrained (str): pretrained model. Default: None. + """ + def __init__(self, depth, num_seg=8, pretrained=None, in_channels=1): + super(ResNetTSM_MRI, self).__init__() + self.pretrained = pretrained + self.layers = depth + self.num_seg = num_seg + self.in_channels = in_channels + + supported_layers = [18, 34, 50, 101, 152] + assert self.layers in supported_layers, \ + "supported layers are {} but input layer is {}".format( + supported_layers, self.layers) + + if self.layers == 18: + depth = [2, 2, 2, 2] + elif self.layers == 34 or self.layers == 50: + depth = [3, 4, 6, 3] + elif self.layers == 101: + depth = [3, 4, 23, 3] + elif self.layers == 152: + depth = [3, 8, 36, 3] + + in_channels = 64 + out_channels = [64, 128, 256, 512] + + #ResNet-C: use three 3x3 conv, replace, one 7x7 conv + self.conv1_1 = ConvBNLayer(in_channels=self.in_channels, + out_channels=32, + kernel_size=3, + stride=2, + act='leaky_relu', + name="conv1_1") + self.conv1_2 = ConvBNLayer(in_channels=32, + out_channels=32, + kernel_size=3, + stride=1, + act='leaky_relu', + name="conv1_2") + self.conv1_3 = ConvBNLayer(in_channels=32, + out_channels=64, + kernel_size=3, + stride=1, + act='leaky_relu', + name="conv1_3") + self.pool2D_max = MaxPool2D(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + if self.layers >= 50: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if self.layers in [101, 152] and block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % + (block, i), #same with PaddleClas, for loading pretrain + BottleneckBlock( + in_channels=in_channels + if i == 0 else out_channels[block] * 4, + out_channels=out_channels[block], + stride=2 if i == 0 and block != 0 else 1, + num_seg=self.num_seg, + shortcut=shortcut, + if_first=block == i == 0, + name=conv_name)) + in_channels = out_channels[block] * 4 + self.block_list.append(bottleneck_block) + shortcut = True + else: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + conv_name = "res" + str(block + 2) + chr(97 + i) + basic_block = self.add_sublayer( + conv_name, + BasicBlock(in_channels=in_channels[block] + if i == 0 else out_channels[block], + out_channels=out_channels[block], + stride=2 if i == 0 and block != 0 else 1, + shortcut=shortcut, + name=conv_name)) + self.block_list.append(basic_block) + shortcut = True + + def init_weights(self): + """Initiate the parameters. + Note: + 1. when indicate pretrained loading path, will load it to initiate backbone. + 2. when not indicating pretrained loading path, will follow specific initialization initiate backbone. Always, Conv2D layer will be initiated by KaimingNormal function, and BatchNorm2d will be initiated by Constant function. + Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/api/paddle/nn/initializer/kaiming/KaimingNormal_en.html + """ + #XXX: check bias!!! check pretrained!!! + + if isinstance(self.pretrained, str) and self.pretrained.strip() != "": + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + #XXX: no bias + weight_init_(layer, 'KaimingNormal') + elif isinstance(layer, nn.BatchNorm2D): + weight_init_(layer, 'Constant', value=1) + + def forward(self, inputs): + """Define how the backbone is going to run. + + """ + #NOTE: Already merge axis 0(batches) and axis 1(channels) before extracting feature phase, + # please refer to paddlevideo/modeling/framework/recognizers/recognizer2d.py#L27 + #y = paddle.reshape( + # inputs, [-1, inputs.shape[2], inputs.shape[3], inputs.shape[4]]) + + ####ResNet-C: use three 3x3 conv, replace, one 7x7 conv + y = self.conv1_1(inputs) + y = self.conv1_2(y) + y = self.conv1_3(y) + + y = self.pool2D_max(y) + for block in self.block_list: + y = block(y) + return y diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsn_MRI.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsn_MRI.py new file mode 100644 index 0000000..439a0ef --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tsn_MRI.py @@ -0,0 +1,331 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import paddle +from paddle import ParamAttr +import paddle.nn as nn +import paddle.nn.functional as F +from paddle.regularizer import L2Decay +from paddle.nn import Conv2D, BatchNorm +from paddle.nn import MaxPool2D, AvgPool2D + +from ..registry import BACKBONES +from ..weight_init import weight_init_ +from ...utils import load_ckpt + +__all__ = ["ResNetTSN_MRI"] + + +class ConvBNLayer(nn.Layer): + def __init__(self, + in_channels, + out_channels, + kernel_size, + stride=1, + groups=1, + is_tweaks_mode=False, + act=None, + lr_mult=1.0, + name=None): + super(ConvBNLayer, self).__init__() + self.is_tweaks_mode = is_tweaks_mode + self._pool2d_avg = AvgPool2D(kernel_size=2, + stride=2, + padding=0, + ceil_mode=True) + self._conv = Conv2D(in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=(kernel_size - 1) // 2, + groups=groups, + weight_attr=ParamAttr(name=name + "_weights", + learning_rate=lr_mult), + bias_attr=False) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm( + out_channels, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale', + learning_rate=lr_mult, + regularizer=L2Decay(0.0)), + bias_attr=ParamAttr(bn_name + '_offset', + learning_rate=lr_mult, + regularizer=L2Decay(0.0)), + moving_mean_name=bn_name + '_mean', + moving_variance_name=bn_name + '_variance') + + def forward(self, inputs): + if self.is_tweaks_mode: + inputs = self._pool2d_avg(inputs) + y = self._conv(inputs) + y = self._batch_norm(y) + return y + + +class BottleneckBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + if_first=False, + lr_mult=1.0, + name=None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + act='relu', + lr_mult=lr_mult, + name=name + "_branch2a") + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + kernel_size=3, + stride=stride, + act='relu', + lr_mult=lr_mult, + name=name + "_branch2b") + self.conv2 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels * 4, + kernel_size=1, + act=None, + lr_mult=lr_mult, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels * 4, + kernel_size=1, + stride=1, + is_tweaks_mode=False if if_first else True, + lr_mult=lr_mult, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(x=short, y=conv2) + y = F.relu(y) + return y + + +class BasicBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + if_first=False, + lr_mult=1.0, + name=None): + super(BasicBlock, self).__init__() + self.stride = stride + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=3, + stride=stride, + act='relu', + lr_mult=lr_mult, + name=name + "_branch2a") + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + kernel_size=3, + act=None, + lr_mult=lr_mult, + name=name + "_branch2b") + + if not shortcut: + self.short = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + stride=1, + is_tweaks_mode=False if if_first else True, + lr_mult=lr_mult, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs): + y = self.conv0(inputs) + conv1 = self.conv1(y) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(x=short, y=conv1) + y = F.relu(y) + return y + + +@BACKBONES.register() +class ResNetTSN_MRI(nn.Layer): + """ResNetTweaksTSN backbone. + + Args: + depth (int): Depth of resnet model. + pretrained (str): pretrained model. Default: None. + """ + def __init__(self, + layers=50, + pretrained=None, + lr_mult_list=[1.0, 1.0, 1.0, 1.0, 1.0], + in_channels=1): + super(ResNetTSN_MRI, self).__init__() + + self.pretrained = pretrained + self.layers = layers + supported_layers = [18, 34, 50, 101, 152, 200] + assert layers in supported_layers, \ + "supported layers are {} but input layer is {}".format( + supported_layers, layers) + + self.lr_mult_list = lr_mult_list + self.in_channels = in_channels + assert isinstance( + self.lr_mult_list, + (list, tuple + )), "lr_mult_list should be in (list, tuple) but got {}".format( + type(self.lr_mult_list)) + assert len( + self.lr_mult_list + ) == 5, "lr_mult_list length should should be 5 but got {}".format( + len(self.lr_mult_list)) + + if layers == 18: + depth = [2, 2, 2, 2] + elif layers == 34 or layers == 50: + depth = [3, 4, 6, 3] + elif layers == 101: + depth = [3, 4, 23, 3] + elif layers == 152: + depth = [3, 8, 36, 3] + elif layers == 200: + depth = [3, 12, 48, 3] + num_channels = [64, 256, 512, 1024 + ] if layers >= 50 else [64, 64, 128, 256] + num_filters = [64, 128, 256, 512] + + self.conv1_1 = ConvBNLayer(in_channels=self.in_channels, + out_channels=32, + kernel_size=3, + stride=2, + act='relu', + lr_mult=self.lr_mult_list[0], + name="conv1_1") + self.conv1_2 = ConvBNLayer(in_channels=32, + out_channels=32, + kernel_size=3, + stride=1, + act='relu', + lr_mult=self.lr_mult_list[0], + name="conv1_2") + self.conv1_3 = ConvBNLayer(in_channels=32, + out_channels=64, + kernel_size=3, + stride=1, + act='relu', + lr_mult=self.lr_mult_list[0], + name="conv1_3") + self.pool2d_max = MaxPool2D(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + if layers >= 50: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if layers in [101, 152, 200] and block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock( + in_channels=num_channels[block] + if i == 0 else num_filters[block] * 4, + out_channels=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + shortcut=shortcut, + if_first=block == i == 0, + lr_mult=self.lr_mult_list[block + 1], + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + else: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + conv_name = "res" + str(block + 2) + chr(97 + i) + basic_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BasicBlock(in_channels=num_channels[block] + if i == 0 else num_filters[block], + out_channels=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + shortcut=shortcut, + if_first=block == i == 0, + name=conv_name, + lr_mult=self.lr_mult_list[block + 1])) + self.block_list.append(basic_block) + shortcut = True + + def init_weights(self): + """Initiate the parameters. + Note: + 1. when indicate pretrained loading path, will load it to initiate backbone. + 2. when not indicating pretrained loading path, will follow specific initialization initiate backbone. Always, Conv2D layer will be + initiated by KaimingNormal function, and BatchNorm2d will be initiated by Constant function. + Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/api/paddle/nn/initializer/kaiming/KaimingNormal_en.html + """ + # XXX: check bias!!! check pretrained!!! + + if isinstance(self.pretrained, str) and self.pretrained.strip() != "": + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + # XXX: no bias + weight_init_(layer, 'KaimingNormal') + elif isinstance(layer, nn.BatchNorm2D): + weight_init_(layer, 'Constant', value=1) + + def forward(self, inputs): + + y = self.conv1_1(inputs) + y = self.conv1_2(y) + y = self.conv1_3(y) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + return y diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tweaks_tsm.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tweaks_tsm.py new file mode 100644 index 0000000..089da4e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tweaks_tsm.py @@ -0,0 +1,362 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +import math + +import sys +import paddle +import paddle.nn as nn +from paddle.nn import (Conv2D, BatchNorm2D, Linear, Dropout, MaxPool2D, + AvgPool2D) +from paddle import ParamAttr +import paddle.nn.functional as F +from paddle.regularizer import L2Decay + +from ..registry import BACKBONES +from ..weight_init import weight_init_ +from ...utils.save_load import load_ckpt + +# Download URL of pretrained model +# { +# "ResNet50_vd": +# "wget https://videotag.bj.bcebos.com/PaddleVideo/PretrainModel/ResNet50_vd_ssld_v2_pretrained.pdparams", +# "ResNet101_vd": +# "https://videotag.bj.bcebos.com/PaddleVideo-release2.2/ResNet101_vd_ssld_pretrained.pdparams", +# "ResNet18_vd": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/legendary_models/ResNet18_vd_pretrained.pdparams", +# "ResNet34_vd": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/ResNet34_vd_ssld_pretrained.pdparams", +# "ResNet152_vd": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/legendary_models/ResNet152_vd_pretrained.pdparams", +# "ResNet200_vd": +# "https://paddle-imagenet-models-name.bj.bcebos.com/dygraph/legendary_models/ResNet200_vd_pretrained.pdparams", +# } + + +class ConvBNLayer(nn.Layer): + """Conv2D and BatchNorm2D layer. + Args: + in_channels (int): Number of channels for the input. + out_channels (int): Number of channels for the output. + kernel_size (int): Kernel size. + stride (int): Stride in the Conv2D layer. Default: 1. + groups (int): Groups in the Conv2D, Default: 1. + is_tweaks_mode (bool): switch for tweaks. Default: False. + act (str): Indicate activation after BatchNorm2D layer. + name (str): the name of an instance of ConvBNLayer. + """ + def __init__(self, + in_channels, + out_channels, + kernel_size, + stride=1, + groups=1, + is_tweaks_mode=False, + act=None, + name=None): + super(ConvBNLayer, self).__init__() + self.is_tweaks_mode = is_tweaks_mode + #ResNet-D 1/2:add a 2×2 average pooling layer with a stride of 2 before the convolution, + # whose stride is changed to 1, works well in practice. + self._pool2d_avg = AvgPool2D(kernel_size=2, + stride=2, + padding=0, + ceil_mode=True) + + self._conv = Conv2D(in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=(kernel_size - 1) // 2, + groups=groups, + weight_attr=ParamAttr(name=name + "_weights"), + bias_attr=False) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + + self._act = act + + self._batch_norm = BatchNorm2D( + out_channels, + weight_attr=ParamAttr(name=bn_name + "_scale", + regularizer=L2Decay(0.0)), + bias_attr=ParamAttr(bn_name + "_offset", regularizer=L2Decay(0.0))) + + def forward(self, inputs): + if self.is_tweaks_mode: + inputs = self._pool2d_avg(inputs) + y = self._conv(inputs) + y = self._batch_norm(y) + if self._act: + y = getattr(paddle.nn.functional, self._act)(y) + return y + + +class BottleneckBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + if_first=False, + num_seg=8, + name=None): + super(BottleneckBlock, self).__init__() + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + act="leaky_relu", + name=name + "_branch2a") + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + kernel_size=3, + stride=stride, + act="leaky_relu", + name=name + "_branch2b") + + self.conv2 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels * 4, + kernel_size=1, + act=None, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels * 4, + kernel_size=1, + stride=1, + is_tweaks_mode=False if if_first else True, + name=name + "_branch1") + + self.shortcut = shortcut + self.num_seg = num_seg + + def forward(self, inputs): + if paddle.is_compiled_with_custom_device('npu'): + x = inputs + seg_num = self.num_seg + shift_ratio = 1.0 / self.num_seg + + shape = x.shape #[N*T, C, H, W] + reshape_x = x.reshape( + (-1, seg_num, shape[1], shape[2], shape[3])) #[N, T, C, H, W] + pad_x = F.pad(reshape_x, [ + 0, + 0, + 1, + 1, + 0, + 0, + 0, + 0, + 0, + 0, + ]) #[N, T+2, C, H, W] + c1 = int(shape[1] * shift_ratio) + c2 = int(shape[1] * 2 * shift_ratio) + slice1 = pad_x[:, :seg_num, :c1, :, :] + slice2 = pad_x[:, 2:seg_num + 2, c1:c2, :, :] + slice3 = pad_x[:, 1:seg_num + 1, c2:, :, :] + concat_x = paddle.concat([slice1, slice2, slice3], + axis=2) #[N, T, C, H, W] + shifts = concat_x.reshape(shape) + else: + shifts = F.temporal_shift(inputs, self.num_seg, 1.0 / self.num_seg) + + y = self.conv0(shifts) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(x=short, y=conv2) + return F.leaky_relu(y) + + +class BasicBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + num_seg=8, + name=None): + super(BasicBlock, self).__init__() + self.stride = stride + self.num_seg = num_seg + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=3, + stride=stride, + act="leaky_relu", + name=name + "_branch2a") + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + kernel_size=3, + act=None, + name=name + "_branch2b") + + if not shortcut: + self.short = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + stride=stride, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs): + # add temporal shift module + shifts = F.temporal_shift(inputs, self.num_seg, 1.0 / self.num_seg) + y = self.conv0(shifts) + conv1 = self.conv1(y) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(short, conv1) + y = F.leaky_relu(y) + return y + + +@BACKBONES.register() +class ResNetTweaksTSM(nn.Layer): + """ResNet TSM backbone. + + Args: + depth (int): Depth of resnet model. + pretrained (str): pretrained model. Default: None. + """ + def __init__(self, depth, num_seg=8, pretrained=None): + super(ResNetTweaksTSM, self).__init__() + self.pretrained = pretrained + self.layers = depth + self.num_seg = num_seg + + supported_layers = [18, 34, 50, 101, 152] + assert self.layers in supported_layers, \ + "supported layers are {} but input layer is {}".format( + supported_layers, self.layers) + + if self.layers == 18: + depth = [2, 2, 2, 2] + elif self.layers == 34 or self.layers == 50: + depth = [3, 4, 6, 3] + elif self.layers == 101: + depth = [3, 4, 23, 3] + elif self.layers == 152: + depth = [3, 8, 36, 3] + + in_channels = 64 + out_channels = [64, 128, 256, 512] + + #ResNet-C: use three 3x3 conv, replace, one 7x7 conv + self.conv1_1 = ConvBNLayer(in_channels=3, + out_channels=32, + kernel_size=3, + stride=2, + act='leaky_relu', + name="conv1_1") + self.conv1_2 = ConvBNLayer(in_channels=32, + out_channels=32, + kernel_size=3, + stride=1, + act='leaky_relu', + name="conv1_2") + self.conv1_3 = ConvBNLayer(in_channels=32, + out_channels=64, + kernel_size=3, + stride=1, + act='leaky_relu', + name="conv1_3") + self.pool2D_max = MaxPool2D(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + if self.layers >= 50: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if self.layers in [101, 152] and block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % + (block, i), #same with PaddleClas, for loading pretrain + BottleneckBlock( + in_channels=in_channels + if i == 0 else out_channels[block] * 4, + out_channels=out_channels[block], + stride=2 if i == 0 and block != 0 else 1, + num_seg=self.num_seg, + shortcut=shortcut, + if_first=block == i == 0, + name=conv_name)) + in_channels = out_channels[block] * 4 + self.block_list.append(bottleneck_block) + shortcut = True + else: + in_channels = [64, 64, 128, 256] + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + conv_name = "res" + str(block + 2) + chr(97 + i) + basic_block = self.add_sublayer( + conv_name, + BasicBlock(in_channels=in_channels[block] + if i == 0 else out_channels[block], + out_channels=out_channels[block], + stride=2 if i == 0 and block != 0 else 1, + shortcut=shortcut, + num_seg=self.num_seg, + name=conv_name)) + self.block_list.append(basic_block) + shortcut = True + + def init_weights(self): + """Initiate the parameters. + Note: + 1. when indicate pretrained loading path, will load it to initiate backbone. + 2. when not indicating pretrained loading path, will follow specific initialization initiate backbone. Always, Conv2D layer will be initiated by KaimingNormal function, and BatchNorm2d will be initiated by Constant function. + Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/api/paddle/nn/initializer/kaiming/KaimingNormal_en.html + """ + if isinstance(self.pretrained, str) and self.pretrained.strip() != "": + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + # no bias + weight_init_(layer, 'KaimingNormal') + elif isinstance(layer, nn.BatchNorm2D): + weight_init_(layer, 'Constant', value=1) + + def forward(self, inputs): + """Define how the backbone is going to run. + """ + y = self.conv1_1(inputs) + y = self.conv1_2(y) + y = self.conv1_3(y) + + y = self.pool2D_max(y) + for block in self.block_list: + y = block(y) + return y diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tweaks_tsn.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tweaks_tsn.py new file mode 100644 index 0000000..36b3307 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnet_tweaks_tsn.py @@ -0,0 +1,328 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + +from __future__ import absolute_import +from __future__ import division +from __future__ import print_function + +import paddle +from paddle import ParamAttr +import paddle.nn as nn +import paddle.nn.functional as F +from paddle.regularizer import L2Decay +from paddle.nn import Conv2D, BatchNorm +from paddle.nn import MaxPool2D, AvgPool2D + +from ..registry import BACKBONES +from ..weight_init import weight_init_ +from ...utils import load_ckpt + +__all__ = ["ResNetTweaksTSN"] + + +class ConvBNLayer(nn.Layer): + def __init__(self, + in_channels, + out_channels, + kernel_size, + stride=1, + groups=1, + is_tweaks_mode=False, + act=None, + lr_mult=1.0, + name=None): + super(ConvBNLayer, self).__init__() + self.is_tweaks_mode = is_tweaks_mode + self._pool2d_avg = AvgPool2D(kernel_size=2, + stride=2, + padding=0, + ceil_mode=True) + self._conv = Conv2D(in_channels=in_channels, + out_channels=out_channels, + kernel_size=kernel_size, + stride=stride, + padding=(kernel_size - 1) // 2, + groups=groups, + weight_attr=ParamAttr(name=name + "_weights", + learning_rate=lr_mult), + bias_attr=False) + if name == "conv1": + bn_name = "bn_" + name + else: + bn_name = "bn" + name[3:] + self._batch_norm = BatchNorm( + out_channels, + act=act, + param_attr=ParamAttr(name=bn_name + '_scale', + learning_rate=lr_mult, + regularizer=L2Decay(0.0)), + bias_attr=ParamAttr(bn_name + '_offset', + learning_rate=lr_mult, + regularizer=L2Decay(0.0)), + moving_mean_name=bn_name + '_mean', + moving_variance_name=bn_name + '_variance') + + def forward(self, inputs): + if self.is_tweaks_mode: + inputs = self._pool2d_avg(inputs) + y = self._conv(inputs) + y = self._batch_norm(y) + return y + + +class BottleneckBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + if_first=False, + lr_mult=1.0, + name=None): + super(BottleneckBlock, self).__init__() + + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + act='relu', + lr_mult=lr_mult, + name=name + "_branch2a") + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + kernel_size=3, + stride=stride, + act='relu', + lr_mult=lr_mult, + name=name + "_branch2b") + self.conv2 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels * 4, + kernel_size=1, + act=None, + lr_mult=lr_mult, + name=name + "_branch2c") + + if not shortcut: + self.short = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels * 4, + kernel_size=1, + stride=1, + is_tweaks_mode=False if if_first else True, + lr_mult=lr_mult, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs): + y = self.conv0(inputs) + conv1 = self.conv1(y) + conv2 = self.conv2(conv1) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(x=short, y=conv2) + y = F.relu(y) + return y + + +class BasicBlock(nn.Layer): + def __init__(self, + in_channels, + out_channels, + stride, + shortcut=True, + if_first=False, + lr_mult=1.0, + name=None): + super(BasicBlock, self).__init__() + self.stride = stride + self.conv0 = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=3, + stride=stride, + act='relu', + lr_mult=lr_mult, + name=name + "_branch2a") + self.conv1 = ConvBNLayer(in_channels=out_channels, + out_channels=out_channels, + kernel_size=3, + act=None, + lr_mult=lr_mult, + name=name + "_branch2b") + + if not shortcut: + self.short = ConvBNLayer(in_channels=in_channels, + out_channels=out_channels, + kernel_size=1, + stride=1, + is_tweaks_mode=False if if_first else True, + lr_mult=lr_mult, + name=name + "_branch1") + + self.shortcut = shortcut + + def forward(self, inputs): + y = self.conv0(inputs) + conv1 = self.conv1(y) + + if self.shortcut: + short = inputs + else: + short = self.short(inputs) + y = paddle.add(x=short, y=conv1) + y = F.relu(y) + return y + + +@BACKBONES.register() +class ResNetTweaksTSN(nn.Layer): + """ResNetTweaksTSN backbone. + + Args: + depth (int): Depth of resnet model. + pretrained (str): pretrained model. Default: None. + """ + def __init__(self, + layers=50, + pretrained=None, + lr_mult_list=[1.0, 1.0, 1.0, 1.0, 1.0]): + super(ResNetTweaksTSN, self).__init__() + + self.pretrained = pretrained + self.layers = layers + supported_layers = [18, 34, 50, 101, 152, 200] + assert layers in supported_layers, \ + "supported layers are {} but input layer is {}".format( + supported_layers, layers) + + self.lr_mult_list = lr_mult_list + assert isinstance( + self.lr_mult_list, + (list, tuple + )), "lr_mult_list should be in (list, tuple) but got {}".format( + type(self.lr_mult_list)) + assert len( + self.lr_mult_list + ) == 5, "lr_mult_list length should should be 5 but got {}".format( + len(self.lr_mult_list)) + + if layers == 18: + depth = [2, 2, 2, 2] + elif layers == 34 or layers == 50: + depth = [3, 4, 6, 3] + elif layers == 101: + depth = [3, 4, 23, 3] + elif layers == 152: + depth = [3, 8, 36, 3] + elif layers == 200: + depth = [3, 12, 48, 3] + num_channels = [64, 256, 512, 1024 + ] if layers >= 50 else [64, 64, 128, 256] + num_filters = [64, 128, 256, 512] + + self.conv1_1 = ConvBNLayer(in_channels=3, + out_channels=32, + kernel_size=3, + stride=2, + act='relu', + lr_mult=self.lr_mult_list[0], + name="conv1_1") + self.conv1_2 = ConvBNLayer(in_channels=32, + out_channels=32, + kernel_size=3, + stride=1, + act='relu', + lr_mult=self.lr_mult_list[0], + name="conv1_2") + self.conv1_3 = ConvBNLayer(in_channels=32, + out_channels=64, + kernel_size=3, + stride=1, + act='relu', + lr_mult=self.lr_mult_list[0], + name="conv1_3") + self.pool2d_max = MaxPool2D(kernel_size=3, stride=2, padding=1) + + self.block_list = [] + if layers >= 50: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + if layers in [101, 152, 200] and block == 2: + if i == 0: + conv_name = "res" + str(block + 2) + "a" + else: + conv_name = "res" + str(block + 2) + "b" + str(i) + else: + conv_name = "res" + str(block + 2) + chr(97 + i) + bottleneck_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BottleneckBlock( + in_channels=num_channels[block] + if i == 0 else num_filters[block] * 4, + out_channels=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + shortcut=shortcut, + if_first=block == i == 0, + lr_mult=self.lr_mult_list[block + 1], + name=conv_name)) + self.block_list.append(bottleneck_block) + shortcut = True + else: + for block in range(len(depth)): + shortcut = False + for i in range(depth[block]): + conv_name = "res" + str(block + 2) + chr(97 + i) + basic_block = self.add_sublayer( + 'bb_%d_%d' % (block, i), + BasicBlock(in_channels=num_channels[block] + if i == 0 else num_filters[block], + out_channels=num_filters[block], + stride=2 if i == 0 and block != 0 else 1, + shortcut=shortcut, + if_first=block == i == 0, + name=conv_name, + lr_mult=self.lr_mult_list[block + 1])) + self.block_list.append(basic_block) + shortcut = True + + def init_weights(self): + """Initiate the parameters. + Note: + 1. when indicate pretrained loading path, will load it to initiate backbone. + 2. when not indicating pretrained loading path, will follow specific initialization initiate backbone. Always, Conv2D layer will be + initiated by KaimingNormal function, and BatchNorm2d will be initiated by Constant function. + Please refer to https://www.paddlepaddle.org.cn/documentation/docs/en/develop/api/paddle/nn/initializer/kaiming/KaimingNormal_en.html + """ + # XXX: check bias!!! check pretrained!!! + + if isinstance(self.pretrained, str) and self.pretrained.strip() != "": + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + # XXX: no bias + weight_init_(layer, 'KaimingNormal') + elif isinstance(layer, nn.BatchNorm2D): + weight_init_(layer, 'Constant', value=1) + + def forward(self, inputs): + y = self.conv1_1(inputs) + y = self.conv1_2(y) + y = self.conv1_3(y) + y = self.pool2d_max(y) + for block in self.block_list: + y = block(y) + return y diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnext101.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnext101.py new file mode 100644 index 0000000..deca671 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/resnext101.py @@ -0,0 +1,191 @@ +# Copyright (c) 2021 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. + +from paddle import ParamAttr +from paddle import fluid +import paddle.nn as nn +from paddle.nn import Conv3D, BatchNorm3D +from functools import partial + + +class ConvBNLayer(nn.Layer): + def __init__(self, + num_channels, + num_filters, + filter_size, + stride=1, + padding=0, + dilation=1, + groups=1, + padding_mode='zeros', + weight_attr=None, + bias_attr=None, + name=None, + data_format="NCDHW"): + super(ConvBNLayer, self).__init__() + self._conv = Conv3D( + in_channels=num_channels, + out_channels=num_filters, + kernel_size=filter_size, + stride=stride, + padding=padding, + dilation=dilation, + groups=groups, + padding_mode=padding_mode, + weight_attr=ParamAttr(initializer=nn.initializer.KaimingNormal( + fan_in=num_filters * filter_size * filter_size), name=name+'_weights'), + bias_attr=bias_attr, + data_format=data_format) + bn_name = "bn_" + name + self._batch_norm = BatchNorm3D( + num_filters, + momentum=0.9, + epsilon=1e-05, + weight_attr=ParamAttr(initializer=nn.initializer.Constant( + 1.), name=bn_name + '_scale'), + bias_attr=ParamAttr(initializer=nn.initializer.Constant( + 0.), name=bn_name + '_offset'), + data_format=data_format) + + def forward(self, inputs): + y = self._conv(inputs) + y = self._batch_norm(y) + return y + + +def _downsample_basic_block(self, x, planes, stride): + out = fluid.layers.pool3d( + x, pool_size=1, pool_stride=stride, pool_type='avg') + shape = out.shape + zero_pads = fluid.layers.zeros([shape[0], planes - shape[1], shape[2], shape[3], shape[4]], + dtype='float32') + out = fluid.layers.concat([out, zero_pads], axis=1) + + +class BottleneckBlock(nn.Layer): + expansion = 2 + + def __init__(self, inplanes, planes, cardinality, stride=1, downsample=None, name=None): + super(BottleneckBlock, self).__init__() + + mid_planes = cardinality * int(planes / 32) + self.conv0 = ConvBNLayer( + inplanes, mid_planes, filter_size=1, bias_attr=False, name=name+'_branch2a') + self.conv1 = ConvBNLayer(mid_planes, mid_planes, filter_size=3, stride=stride, + padding=1, groups=cardinality, bias_attr=False, name=name+'_branch2b') + self.conv2 = ConvBNLayer(mid_planes, planes * self.expansion, + filter_size=1, bias_attr=False, name=name+'_branch2c') + self.downsample = downsample + self.stride = stride + self.relu = nn.ReLU() + + def forward(self, x): + residual = x + + out = self.conv0(x) + out = self.relu(out) + out = self.conv1(out) + out = self.relu(out) + out = self.conv2(out) + + if self.downsample is not None: + residual = self.downsample(x) + + out += residual + out = self.relu(out) + + return out + + +class ResNeXt(nn.Layer): + def __init__(self, + block, + layers, + shortcut_type='B', + cardinality=32): + self.inplanes = 64 + super(ResNeXt, self).__init__() + self.conv = ConvBNLayer( + 3, + 64, + filter_size=7, + stride=(1, 2, 2), + padding=(3, 3, 3), + bias_attr=False, + name="res_conv1" + ) + self.relu = nn.ReLU() + self.maxpool = nn.MaxPool3D(kernel_size=(3, 3, 3), stride=2, padding=1) + self.layer1 = self._make_layer(block, 128, layers[0], shortcut_type, + cardinality, stride=1, name='layer1') + + self.layer2 = self._make_layer( + block, 256, layers[1], shortcut_type, cardinality, stride=2, name='layer2') + + self.layer3 = self._make_layer( + block, 512, layers[2], shortcut_type, cardinality, stride=2, name='layer3') + + self.layer4 = self._make_layer( + block, 1024, layers[3], shortcut_type, cardinality, stride=2, name='layer4') + self.avgpool = nn.AvgPool3D((2, 1, 1), stride=1, exclusive=False) + + def _make_layer(self, + block, + planes, + blocks, + shortcut_type, + cardinality, + stride=1, + name=None): + downsample = None + if stride != 1 or self.inplanes != planes * block.expansion: + if shortcut_type == 'A': + downsample = partial(self._downsample_basic_block, + planes=planes * block.expansion, + stride=stride) + else: + downsample = ConvBNLayer( + self.inplanes, + planes * block.expansion, + 1, + stride=stride, + bias_attr=False, + name=name+'downsample' + ) + layers = [] + layers.append( + block(self.inplanes, planes, cardinality, stride, downsample, name=name+'_downsample')) + self.inplanes = planes * block.expansion + for i in range(1, blocks): + layers.append(block(self.inplanes, planes, + cardinality, name=name+'_res_block'+str(i))) + + return nn.Sequential(*layers) + + def forward(self, x): + x = self.conv(x) + x = self.relu(x) + x = self.maxpool(x) + x = self.layer1(x) + x = self.layer2(x) + x = self.layer3(x) + x = self.layer4(x) + return x + + +def ResNext101(): + """Constructs a ResNext-101 model. + """ + model = ResNeXt(BottleneckBlock, [3, 4, 23, 3]) + return model diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/stgcn.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/stgcn.py new file mode 100644 index 0000000..40d9d0d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/stgcn.py @@ -0,0 +1,343 @@ +# Copyright (c) 2021 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 paddle +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np +from ..registry import BACKBONES +from ..weight_init import weight_init_ + + +def zero(x): + return 0 + + +def iden(x): + return x + + +def einsum(x, A): + """paddle.einsum will be implemented in release/2.2. + """ + x = x.transpose((0, 2, 3, 1, 4)) + n, c, t, k, v = x.shape + k2, v2, w = A.shape + assert (k == k2 and v == v2), "Args of einsum not match!" + x = x.reshape((n, c, t, k * v)) + A = A.reshape((k * v, w)) + y = paddle.matmul(x, A) + return y + + +def get_hop_distance(num_node, edge, max_hop=1): + A = np.zeros((num_node, num_node)) + for i, j in edge: + A[j, i] = 1 + A[i, j] = 1 + + # compute hop steps + hop_dis = np.zeros((num_node, num_node)) + np.inf + transfer_mat = [np.linalg.matrix_power(A, d) for d in range(max_hop + 1)] + arrive_mat = (np.stack(transfer_mat) > 0) + for d in range(max_hop, -1, -1): + hop_dis[arrive_mat[d]] = d + return hop_dis + + +def normalize_digraph(A): + Dl = np.sum(A, 0) + num_node = A.shape[0] + Dn = np.zeros((num_node, num_node)) + for i in range(num_node): + if Dl[i] > 0: + Dn[i, i] = Dl[i]**(-1) + AD = np.dot(A, Dn) + return AD + + +class Graph(): + + def __init__(self, + layout='openpose', + strategy='uniform', + max_hop=1, + dilation=1): + self.max_hop = max_hop + self.dilation = dilation + + self.get_edge(layout) + self.hop_dis = get_hop_distance(self.num_node, + self.edge, + max_hop=max_hop) + self.get_adjacency(strategy) + + def __str__(self): + return self.A + + def get_edge(self, layout): + # edge is a list of [child, parent] paris + + if layout == 'fsd10': + self.num_node = 25 + self_link = [(i, i) for i in range(self.num_node)] + neighbor_link = [(1, 8), (0, 1), (15, 0), (17, 15), (16, 0), + (18, 16), (5, 1), (6, 5), (7, 6), (2, 1), (3, 2), + (4, 3), (9, 8), (10, 9), (11, 10), (24, 11), + (22, 11), (23, 22), (12, 8), (13, 12), (14, 13), + (21, 14), (19, 14), (20, 19)] + self.edge = self_link + neighbor_link + self.center = 8 + elif layout == 'ntu-rgb+d': + self.num_node = 25 + self_link = [(i, i) for i in range(self.num_node)] + neighbor_1base = [(1, 2), (2, 21), (3, 21), (4, 3), (5, 21), (6, 5), + (7, 6), (8, 7), (9, 21), (10, 9), (11, 10), + (12, 11), (13, 1), (14, 13), (15, 14), (16, 15), + (17, 1), (18, 17), (19, 18), (20, 19), (22, 23), + (23, 8), (24, 25), (25, 12)] + neighbor_link = [(i - 1, j - 1) for (i, j) in neighbor_1base] + self.edge = self_link + neighbor_link + self.center = 21 - 1 + elif layout == 'coco_keypoint': + self.num_node = 17 + self_link = [(i, i) for i in range(self.num_node)] + neighbor_1base = [(0, 1), (0, 2), (1, 3), (2, 4), (3, 5), (4, 6), + (5, 7), (6, 8), (7, 9), (8, 10), (5, 11), (6, 12), + (11, 13), (12, 14), (13, 15), (14, 16), (11, 12)] + neighbor_link = [(i, j) for (i, j) in neighbor_1base] + self.edge = self_link + neighbor_link + self.center = 11 + else: + raise ValueError("Do Not Exist This Layout.") + + def get_adjacency(self, strategy): + valid_hop = range(0, self.max_hop + 1, self.dilation) + adjacency = np.zeros((self.num_node, self.num_node)) + for hop in valid_hop: + adjacency[self.hop_dis == hop] = 1 + normalize_adjacency = normalize_digraph(adjacency) + + if strategy == 'spatial': + A = [] + for hop in valid_hop: + a_root = np.zeros((self.num_node, self.num_node)) + a_close = np.zeros((self.num_node, self.num_node)) + a_further = np.zeros((self.num_node, self.num_node)) + for i in range(self.num_node): + for j in range(self.num_node): + if self.hop_dis[j, i] == hop: + if self.hop_dis[j, self.center] == self.hop_dis[ + i, self.center]: + a_root[j, i] = normalize_adjacency[j, i] + elif self.hop_dis[j, self.center] > self.hop_dis[ + i, self.center]: + a_close[j, i] = normalize_adjacency[j, i] + else: + a_further[j, i] = normalize_adjacency[j, i] + if hop == 0: + A.append(a_root) + else: + A.append(a_root + a_close) + A.append(a_further) + A = np.stack(A) + self.A = A + else: + raise ValueError("Do Not Exist This Strategy") + + +class ConvTemporalGraphical(nn.Layer): + + def __init__(self, + in_channels, + out_channels, + kernel_size, + t_kernel_size=1, + t_stride=1, + t_padding=0, + t_dilation=1): + super().__init__() + + self.kernel_size = kernel_size + self.conv = nn.Conv2D(in_channels, + out_channels * kernel_size, + kernel_size=(t_kernel_size, 1), + padding=(t_padding, 0), + stride=(t_stride, 1), + dilation=(t_dilation, 1)) + + def forward(self, x, A): + assert A.shape[0] == self.kernel_size + + x = self.conv(x) + n, kc, t, v = x.shape + x = x.reshape((n, self.kernel_size, kc // self.kernel_size, t, v)) + x = einsum(x, A) + + return x, A + + +class st_gcn_block(nn.Layer): + + def __init__(self, + in_channels, + out_channels, + kernel_size, + stride=1, + dropout=0, + residual=True): + super(st_gcn_block, self).__init__() + + assert len(kernel_size) == 2 + assert kernel_size[0] % 2 == 1 + padding = ((kernel_size[0] - 1) // 2, 0) + + self.gcn = ConvTemporalGraphical(in_channels, out_channels, + kernel_size[1]) + + self.tcn = nn.Sequential( + nn.BatchNorm2D(out_channels), + nn.ReLU(), + nn.Conv2D( + out_channels, + out_channels, + (kernel_size[0], 1), + (stride, 1), + padding, + ), + nn.BatchNorm2D(out_channels), + nn.Dropout(dropout), + ) + + if not residual: + self.residual = zero + + elif (in_channels == out_channels) and (stride == 1): + self.residual = iden + + else: + self.residual = nn.Sequential( + nn.Conv2D(in_channels, + out_channels, + kernel_size=1, + stride=(stride, 1)), + nn.BatchNorm2D(out_channels), + ) + + self.relu = nn.ReLU() + + def forward(self, x, A): + res = self.residual(x) + x, A = self.gcn(x, A) + x = self.tcn(x) + res + return self.relu(x), A + + +@BACKBONES.register() +class STGCN(nn.Layer): + """ + ST-GCN model from: + `"Spatial Temporal Graph Convolutional Networks for Skeleton-Based Action Recognition" `_ + Args: + in_channels: int, channels of vertex coordinate. 2 for (x,y), 3 for (x,y,z). Default 2. + edge_importance_weighting: bool, whether to use edge attention. Default True. + data_bn: bool, whether to use data BatchNorm. Default True. + """ + + def __init__(self, + in_channels=2, + edge_importance_weighting=True, + data_bn=True, + layout='fsd10', + strategy='spatial', + **kwargs): + super(STGCN, self).__init__() + self.data_bn = data_bn + # load graph + self.graph = Graph( + layout=layout, + strategy=strategy, + ) + A = paddle.to_tensor(self.graph.A, dtype='float32') + self.register_buffer('A', A) + + # build networks + spatial_kernel_size = A.shape[0] + temporal_kernel_size = 9 + kernel_size = (temporal_kernel_size, spatial_kernel_size) + self.data_bn = nn.BatchNorm1D(in_channels * + A.shape[1]) if self.data_bn else iden + kwargs0 = {k: v for k, v in kwargs.items() if k != 'dropout'} + self.st_gcn_networks = nn.LayerList(( + st_gcn_block(in_channels, + 64, + kernel_size, + 1, + residual=False, + **kwargs0), + st_gcn_block(64, 64, kernel_size, 1, **kwargs), + st_gcn_block(64, 64, kernel_size, 1, **kwargs), + st_gcn_block(64, 64, kernel_size, 1, **kwargs), + st_gcn_block(64, 128, kernel_size, 2, **kwargs), + st_gcn_block(128, 128, kernel_size, 1, **kwargs), + st_gcn_block(128, 128, kernel_size, 1, **kwargs), + st_gcn_block(128, 256, kernel_size, 2, **kwargs), + st_gcn_block(256, 256, kernel_size, 1, **kwargs), + st_gcn_block(256, 256, kernel_size, 1, **kwargs), + )) + + # initialize parameters for edge importance weighting + if edge_importance_weighting: + self.edge_importance = nn.ParameterList([ + self.create_parameter( + shape=self.A.shape, + default_initializer=nn.initializer.Constant(1)) + for i in self.st_gcn_networks + ]) + else: + self.edge_importance = [1] * len(self.st_gcn_networks) + + self.pool = nn.AdaptiveAvgPool2D(output_size=(1, 1)) + + def init_weights(self): + """Initiate the parameters. + """ + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + weight_init_(layer, 'Normal', mean=0.0, std=0.02) + elif isinstance(layer, nn.BatchNorm2D): + weight_init_(layer, 'Normal', mean=1.0, std=0.02) + elif isinstance(layer, nn.BatchNorm1D): + weight_init_(layer, 'Normal', mean=1.0, std=0.02) + + def forward(self, x): + # data normalization + N, C, T, V, M = x.shape + x = x.transpose((0, 4, 3, 1, 2)) # N, M, V, C, T + x = x.reshape((N * M, V * C, T)) + if self.data_bn: + x.stop_gradient = False + x = self.data_bn(x) + x = x.reshape((N, M, V, C, T)) + x = x.transpose((0, 1, 3, 4, 2)) # N, M, C, T, V + x = x.reshape((N * M, C, T, V)) + + # forward + for gcn, importance in zip(self.st_gcn_networks, self.edge_importance): + x, _ = gcn(x, paddle.multiply(self.A, importance)) + + x = self.pool(x) # NM,C,T,V --> NM,C,1,1 + C = x.shape[1] + x = paddle.reshape(x, (N, M, C, 1, 1)).mean(axis=1) # N,C,1,1 + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/swin_transformer.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/swin_transformer.py new file mode 100644 index 0000000..aaed217 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/swin_transformer.py @@ -0,0 +1,742 @@ +# Copyright (c) 2021 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. + +from functools import lru_cache, reduce +from operator import mul + +import numpy as np +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +from paddle.nn.initializer import Constant + +from ...utils import load_ckpt +from ..registry import BACKBONES +from ..weight_init import trunc_normal_ + +zeros_ = Constant(value=0.) +ones_ = Constant(value=1.) + + +def drop_path(x, drop_prob=0., training=False): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + the original name is misleading as 'Drop Connect' is a different form of dropout in a separate paper... + # issuecomment-532968956 ... + See discussion: https://github.com/tensorflow/tpu/issues/494 + """ + if drop_prob == 0. or not training: + return x + keep_prob = paddle.to_tensor(1 - drop_prob) + shape = (paddle.shape(x)[0], ) + (1, ) * (x.ndim - 1) + random_tensor = keep_prob + paddle.rand(shape, dtype=x.dtype) + random_tensor = paddle.floor(random_tensor) # binarize + output = x.divide(keep_prob) * random_tensor + + return output + + +class DropPath(nn.Layer): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + """ + def __init__(self, drop_prob=None): + super(DropPath, self).__init__() + self.drop_prob = drop_prob + + def forward(self, x): + return drop_path(x, self.drop_prob, self.training) + + +class Mlp(nn.Layer): + """ Multilayer perceptron.""" + def __init__(self, + in_features, + hidden_features=None, + out_features=None, + act_layer=nn.GELU, + drop=0.): + super().__init__() + out_features = out_features or in_features + hidden_features = hidden_features or in_features + self.fc1 = nn.Linear(in_features, hidden_features) + self.act = act_layer() + self.fc2 = nn.Linear(hidden_features, out_features) + self.drop = nn.Dropout(drop) + + def forward(self, x): + x = self.fc1(x) + x = self.act(x) + x = self.drop(x) + x = self.fc2(x) + x = self.drop(x) + return x + + +def window_partition(x, window_size): + """window_partition + Args: + x (Tensor): x.shape = [B, D, H, W, C] + window_size (tuple[int]): window_size + + Returns: + Tensor: (B*num_windows, window_size*window_size, C) + """ + B, D, H, W, C = x.shape + x = x.reshape([ + B, D // window_size[0], window_size[0], H // window_size[1], + window_size[1], W // window_size[2], window_size[2], C + ]) + windows = x.transpose([0, 1, 3, 5, 2, 4, 6, + 7]).reshape([-1, reduce(mul, window_size), C]) + return windows + + +class Identity(nn.Layer): + def __init__(self): + super(Identity, self).__init__() + + def forward(self, input): + return input + + +def window_reverse(windows, window_size, B, D, H, W): + """ + Args: + windows: (B*num_windows, window_size, window_size, C) + window_size (tuple[int]): Window size + H (int): Height of image + W (int): Width of image + + Returns: + x: (B, D, H, W, C) + """ + x = windows.reshape([ + B, D // window_size[0], H // window_size[1], W // window_size[2], + window_size[0], window_size[1], window_size[2], -1 + ]) + x = x.transpose([0, 1, 4, 2, 5, 3, 6, 7]).reshape([B, D, H, W, -1]) + return x + + +def get_window_size(x_size, window_size, shift_size=None): + use_window_size = list(window_size) + if shift_size is not None: + use_shift_size = list(shift_size) + for i in range(len(x_size)): + if x_size[i] <= window_size[i]: + use_window_size[i] = x_size[i] + if shift_size is not None: + use_shift_size[i] = 0 + + if shift_size is None: + return tuple(use_window_size) + else: + return tuple(use_window_size), tuple(use_shift_size) + + +class WindowAttention3D(nn.Layer): + """ Window based multi-head self attention (W-MSA) module with relative position bias. + It supports both of shifted and non-shifted window. + Args: + dim (int): Number of input channels. + window_size (tuple[int]): The temporal length, height and width of the window. + num_heads (int): Number of attention heads. + qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True + qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set + attn_drop (float, optional): Dropout ratio of attention weight. Default: 0.0 + proj_drop (float, optional): Dropout ratio of output. Default: 0.0 + """ + def __init__(self, + dim, + window_size, + num_heads, + qkv_bias=False, + qk_scale=None, + attn_drop=0., + proj_drop=0.): + + super().__init__() + self.dim = dim + self.window_size = window_size # Wd, Wh, Ww + self.num_heads = num_heads + head_dim = dim // num_heads + self.scale = qk_scale or head_dim**-0.5 + + # define a parameter table of relative position bias + self.relative_position_bias_table = self.create_parameter( + shape=((2 * window_size[0] - 1) * (2 * window_size[1] - 1) * + (2 * window_size[2] - 1), num_heads), + default_initializer=zeros_, + ) # 2*Wd-1 * 2*Wh-1 * 2*Ww-1, nH + self.add_parameter("relative_position_bias_table", + self.relative_position_bias_table) + # get pair-wise relative position index for each token inside the window + coords_d = paddle.arange(self.window_size[0]) + coords_h = paddle.arange(self.window_size[1]) + coords_w = paddle.arange(self.window_size[2]) + coords = paddle.stack(paddle.meshgrid(coords_d, coords_h, + coords_w)) # 3, Wd, Wh, Ww + coords_flatten = paddle.flatten(coords, 1) # 3, Wd*Wh*Ww + + relative_coords = coords_flatten.unsqueeze( + axis=2) - coords_flatten.unsqueeze(axis=1) # 3, Wd*Wh*Ww, Wd*Wh*Ww + + # relative_coords = coords_flatten.unsqueeze(2) - coords_flatten.unsqueeze(1) # 3, Wd*Wh*Ww, Wd*Wh*Ww + relative_coords = relative_coords.transpose([1, 2, 0 + ]) # Wd*Wh*Ww, Wd*Wh*Ww, 3 + relative_coords[:, :, + 0] += self.window_size[0] - 1 # shift to start from 0 + relative_coords[:, :, 1] += self.window_size[1] - 1 + relative_coords[:, :, 2] += self.window_size[2] - 1 + + relative_coords[:, :, 0] *= (2 * self.window_size[1] - + 1) * (2 * self.window_size[2] - 1) + relative_coords[:, :, 1] *= (2 * self.window_size[2] - 1) + relative_position_index = relative_coords.sum( + axis=-1) # Wd*Wh*Ww, Wd*Wh*Ww + self.register_buffer("relative_position_index", relative_position_index) + + self.qkv = nn.Linear(dim, dim * 3, bias_attr=qkv_bias) + self.attn_drop = nn.Dropout(attn_drop) + self.proj = nn.Linear(dim, dim) + self.proj_drop = nn.Dropout(proj_drop) + + trunc_normal_(self.relative_position_bias_table, std=0.02) + self.softmax = nn.Softmax(axis=-1) + + def forward(self, x, mask=None): + """ Forward function. + Args: + x: input features with shape of (num_windows*B, N, C) + mask: (0/-inf) mask with shape of (num_windows, N, N) or None + """ + B_, N, C = x.shape + qkv = self.qkv(x).reshape( + [B_, N, 3, self.num_heads, + C // self.num_heads]).transpose([2, 0, 3, 1, 4]) + q, k, v = qkv[0], qkv[1], qkv[2] # B_, nH, N, C + + q = q * self.scale + attn = q @ k.transpose([0, 1, 3, 2]) + + relative_position_bias = self.relative_position_bias_table[ + self.relative_position_index[:N, :N].reshape([-1])].reshape( + [N, N, -1]) # Wd*Wh*Ww,Wd*Wh*Ww,nH + relative_position_bias = relative_position_bias.transpose( + [2, 0, 1]) # nH, Wd*Wh*Ww, Wd*Wh*Ww + attn = attn + relative_position_bias.unsqueeze(0) # B_, nH, N, N + + if mask is not None: + nW = mask.shape[0] + attn = attn.reshape([B_ // nW, nW, self.num_heads, N, N + ]) + mask.unsqueeze(1).unsqueeze(0) + attn = attn.reshape([-1, self.num_heads, N, N]) + attn = self.softmax(attn) + else: + attn = self.softmax(attn) + + attn = self.attn_drop(attn) + + x = (attn @ v).transpose([0, 2, 1, 3]).reshape([B_, N, C]) + x = self.proj(x) + x = self.proj_drop(x) + return x + + +class SwinTransformerBlock3D(nn.Layer): + """ Swin Transformer Block. + + Args: + dim (int): Number of input channels. + num_heads (int): Number of attention heads. + window_size (tuple[int]): Window size. + shift_size (tuple[int]): Shift size for SW-MSA. + mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. + qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True + qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set. + drop (float, optional): Dropout rate. Default: 0.0 + attn_drop (float, optional): Attention dropout rate. Default: 0.0 + drop_path (float, optional): Stochastic depth rate. Default: 0.0 + act_layer (nn.Layer, optional): Activation layer. Default: nn.GELU + norm_layer (nn.Layer, optional): Normalization layer. Default: nn.LayerNorm + """ + def __init__(self, + dim, + num_heads, + window_size=(2, 7, 7), + shift_size=(0, 0, 0), + mlp_ratio=4., + qkv_bias=True, + qk_scale=None, + drop=0., + attn_drop=0., + drop_path=0., + act_layer=nn.GELU, + norm_layer=nn.LayerNorm, + use_checkpoint=False): + super().__init__() + self.dim = dim + self.num_heads = num_heads + self.window_size = window_size + self.shift_size = shift_size + self.mlp_ratio = mlp_ratio + # self.use_checkpoint=use_checkpoint + + assert 0 <= self.shift_size[0] < self.window_size[ + 0], "shift_size must in 0-window_size" + assert 0 <= self.shift_size[1] < self.window_size[ + 1], "shift_size must in 0-window_size" + assert 0 <= self.shift_size[2] < self.window_size[ + 2], "shift_size must in 0-window_size" + + self.norm1 = norm_layer(dim) + self.attn = WindowAttention3D(dim, + window_size=self.window_size, + num_heads=num_heads, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + attn_drop=attn_drop, + proj_drop=drop) + + self.drop_path = DropPath(drop_path) if drop_path > 0. else Identity() + self.norm2 = norm_layer(dim) + mlp_hidden_dim = int(dim * mlp_ratio) + self.mlp = Mlp(in_features=dim, + hidden_features=mlp_hidden_dim, + act_layer=act_layer, + drop=drop) + + def forward_part1(self, x, mask_matrix): + B = paddle.shape(x)[0] + _, D, H, W, C = x.shape + window_size, shift_size = get_window_size((D, H, W), self.window_size, + self.shift_size) + + x = self.norm1(x) + # pad feature maps to multiples of window size + pad_l = pad_t = pad_d0 = 0 + pad_d1 = (window_size[0] - D % window_size[0]) % window_size[0] + pad_b = (window_size[1] - H % window_size[1]) % window_size[1] + pad_r = (window_size[2] - W % window_size[2]) % window_size[2] + x = F.pad(x, (pad_l, pad_r, pad_t, pad_b, pad_d0, pad_d1), + data_format='NDHWC') + _, Dp, Hp, Wp, _ = x.shape + # cyclic shift + if any(i > 0 for i in shift_size): + shifted_x = paddle.roll(x, + shifts=(-shift_size[0], -shift_size[1], + -shift_size[2]), + axis=(1, 2, 3)) + attn_mask = mask_matrix + else: + shifted_x = x + attn_mask = None + # partition windows + x_windows = window_partition(shifted_x, + window_size) # B*nW, Wd*Wh*Ww, C + # W-MSA/SW-MSA + attn_windows = self.attn(x_windows, mask=attn_mask) # B*nW, Wd*Wh*Ww, C + # merge windows + attn_windows = attn_windows.reshape([-1, *(window_size + (C, ))]) + shifted_x = window_reverse(attn_windows, window_size, B, Dp, Hp, + Wp) # B D' H' W' C + # reverse cyclic shift + if any(i > 0 for i in shift_size): + x = paddle.roll(shifted_x, + shifts=(shift_size[0], shift_size[1], + shift_size[2]), + axis=(1, 2, 3)) + else: + x = shifted_x + + if pad_d1 > 0 or pad_r > 0 or pad_b > 0: + x = x[:, :D, :H, :W, :] + return x + + def forward_part2(self, x): + return self.drop_path(self.mlp(self.norm2(x))) + + def forward(self, x, mask_matrix): + """ Forward function. + + Args: + x: Input feature, tensor size (B, D, H, W, C). + mask_matrix: Attention mask for cyclic shift. + """ + + shortcut = x + x = self.forward_part1(x, mask_matrix) + x = shortcut + self.drop_path(x) + x = x + self.forward_part2(x) + + return x + + +class PatchMerging(nn.Layer): + """ Patch Merging Layer + + Args: + dim (int): Number of input channels. + norm_layer (nn.Layer, optional): Normalization layer. Default: nn.LayerNorm + """ + def __init__(self, dim, norm_layer=nn.LayerNorm): + super().__init__() + self.dim = dim + self.reduction = nn.Linear(4 * dim, 2 * dim, bias_attr=False) + self.norm = norm_layer(4 * dim) + + def forward(self, x): + """ Forward function. + + Args: + x: Input feature, tensor size (B, D, H, W, C). + """ + B, D, H, W, C = x.shape + + # padding + pad_input = (H % 2 == 1) or (W % 2 == 1) + if pad_input: + x = F.pad(x, (0, W % 2, 0, H % 2, 0, 0), data_format='NDHWC') + + x0 = x[:, :, 0::2, 0::2, :] # B D H/2 W/2 C + x1 = x[:, :, 1::2, 0::2, :] # B D H/2 W/2 C + x2 = x[:, :, 0::2, 1::2, :] # B D H/2 W/2 C + x3 = x[:, :, 1::2, 1::2, :] # B D H/2 W/2 C + x = paddle.concat([x0, x1, x2, x3], -1) # B D H/2 W/2 4*C + + x = self.norm(x) + x = self.reduction(x) + + return x + + +# cache each stage results +@lru_cache() +def compute_mask(D, H, W, window_size, shift_size): + img_mask = paddle.zeros((1, D, H, W, 1)) # 1 Dp Hp Wp 1 + cnt = 0 + for d in slice(-window_size[0]), slice(-window_size[0], + -shift_size[0]), slice( + -shift_size[0], None): + for h in slice(-window_size[1]), slice(-window_size[1], + -shift_size[1]), slice( + -shift_size[1], None): + for w in slice(-window_size[2]), slice(-window_size[2], + -shift_size[2]), slice( + -shift_size[2], None): + img_mask[:, d, h, w, :] = cnt + cnt += 1 + mask_windows = window_partition(img_mask, + window_size) # nW, ws[0]*ws[1]*ws[2], 1 + mask_windows = mask_windows.squeeze(-1) # nW, ws[0]*ws[1]*ws[2] + attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2) + # attn_mask = attn_mask.masked_fill(attn_mask != 0, float(-100.0)).masked_fill(attn_mask == 0, float(0.0)) + huns = -100.0 * paddle.ones_like(attn_mask) + attn_mask = huns * (attn_mask != 0).astype("float32") + return attn_mask + + +class BasicLayer(nn.Layer): + """ A basic Swin Transformer layer for one stage. + + Args: + dim (int): Number of feature channels + depth (int): Depths of this stage. + num_heads (int): Number of attention head. + window_size (tuple[int]): Local window size. Default: (1,7,7). + mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4. + qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: True + qk_scale (float | None, optional): Override default qk scale of head_dim ** -0.5 if set. + drop (float, optional): Dropout rate. Default: 0.0 + attn_drop (float, optional): Attention dropout rate. Default: 0.0 + drop_path (float | tuple[float], optional): Stochastic depth rate. Default: 0.0 + norm_layer (nn.Layer, optional): Normalization layer. Default: nn.LayerNorm + downsample (nn.Layer | None, optional): Downsample layer at the end of the layer. Default: None + """ + def __init__(self, + dim, + depth, + num_heads, + window_size=(1, 7, 7), + mlp_ratio=4., + qkv_bias=False, + qk_scale=None, + drop=0., + attn_drop=0., + drop_path=0., + norm_layer=nn.LayerNorm, + downsample=None, + use_checkpoint=False): + super().__init__() + self.window_size = window_size + self.shift_size = tuple(i // 2 for i in window_size) + self.depth = depth + self.use_checkpoint = use_checkpoint + + # build blocks + self.blocks = nn.LayerList([ + SwinTransformerBlock3D( + dim=dim, + num_heads=num_heads, + window_size=window_size, + shift_size=(0, 0, 0) if (i % 2 == 0) else self.shift_size, + mlp_ratio=mlp_ratio, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + drop=drop, + attn_drop=attn_drop, + drop_path=drop_path[i] + if isinstance(drop_path, list) else drop_path, + norm_layer=norm_layer, + use_checkpoint=use_checkpoint, + ) for i in range(depth) + ]) + + self.downsample = downsample + if self.downsample is not None: + self.downsample = downsample(dim=dim, norm_layer=norm_layer) + + def forward(self, x): + """ Forward function. + + Args: + x: Input feature, tensor size (B, C, D, H, W). + """ + # calculate attention mask for SW-MSA + B = paddle.shape(x)[0] + _, C, D, H, W = x.shape + window_size, shift_size = get_window_size((D, H, W), self.window_size, + self.shift_size) + # x = rearrange(x, 'b c d h w -> b d h w c') + x = x.transpose([0, 2, 3, 4, 1]) + Dp = int(np.ceil(D / window_size[0])) * window_size[0] + Hp = int(np.ceil(H / window_size[1])) * window_size[1] + Wp = int(np.ceil(W / window_size[2])) * window_size[2] + attn_mask = compute_mask(Dp, Hp, Wp, window_size, shift_size) + for blk in self.blocks: + x = blk(x, attn_mask) + x = x.reshape([B, D, H, W, C]) + + if self.downsample is not None: + x = self.downsample(x) + x = x.transpose([0, 4, 1, 2, 3]) + return x + + +class PatchEmbed3D(nn.Layer): + """ Video to Patch Embedding. + + Args: + patch_size (int): Patch token size. Default: (2,4,4). + in_chans (int): Number of input video channels. Default: 3. + embed_dim (int): Number of linear projection output channels. Default: 96. + norm_layer (nn.Layer, optional): Normalization layer. Default: None + """ + def __init__(self, + patch_size=(2, 4, 4), + in_chans=3, + embed_dim=96, + norm_layer=None): + super().__init__() + self.patch_size = patch_size + + self.in_chans = in_chans + self.embed_dim = embed_dim + + self.proj = nn.Conv3D(in_chans, + embed_dim, + kernel_size=patch_size, + stride=patch_size) + if norm_layer is not None: + self.norm = norm_layer(embed_dim) + else: + self.norm = None + + def forward(self, x): + _, _, D, H, W = x.shape + if W % self.patch_size[2] != 0: + x = F.pad( + x, (0, self.patch_size[2] - W % self.patch_size[2], 0, 0, 0, 0), + data_format='NCDHW') + if H % self.patch_size[1] != 0: + x = F.pad( + x, (0, 0, 0, self.patch_size[1] - H % self.patch_size[1], 0, 0), + data_format='NCDHW') + if D % self.patch_size[0] != 0: + x = F.pad( + x, (0, 0, 0, 0, 0, self.patch_size[0] - D % self.patch_size[0]), + data_format='NCDHW') + + x = self.proj(x) # B C D Wh Ww + if self.norm is not None: + D, Wh, Ww = x.shape[2], x.shape[3], x.shape[4] + x = x.flatten(2).transpose([0, 2, 1]) + x = self.norm(x) + x = x.transpose([0, 2, 1]).reshape([-1, self.embed_dim, D, Wh, Ww]) + + return x + + +@BACKBONES.register() +class SwinTransformer3D(nn.Layer): + """ Swin Transformer backbone. + A Paddle impl of : `Swin Transformer: Hierarchical Vision Transformer using Shifted Windows` - + https://arxiv.org/pdf/2103.14030 + + Args: + patch_size (int | tuple(int)): Patch size. Default: (4,4,4). + in_chans (int): Number of input image channels. Default: 3. + embed_dim (int): Number of linear projection output channels. Default: 96. + depths (tuple[int]): Depths of each Swin Transformer stage. + num_heads (tuple[int]): Number of attention head of each stage. + window_size (int): Window size. Default: 7. + mlp_ratio (float): Ratio of mlp hidden dim to embedding dim. Default: 4. + qkv_bias (bool): If True, add a learnable bias to query, key, value. Default: Truee + qk_scale (float): Override default qk scale of head_dim ** -0.5 if set. + drop_rate (float): Dropout rate. + attn_drop_rate (float): Attention dropout rate. Default: 0. + drop_path_rate (float): Stochastic depth rate. Default: 0.2. + norm_layer: Normalization layer. Default: nn.LayerNorm. + patch_norm (bool): If True, add normalization after patch embedding. Default: False. + frozen_stages (int): Stages to be frozen (stop grad and set eval mode). + -1 means not freezing any parameters. + """ + def __init__(self, + pretrained=None, + patch_size=(4, 4, 4), + in_chans=3, + embed_dim=96, + depths=[2, 2, 6, 2], + num_heads=[3, 6, 12, 24], + window_size=(2, 7, 7), + mlp_ratio=4., + qkv_bias=True, + qk_scale=None, + drop_rate=0., + attn_drop_rate=0., + drop_path_rate=0.2, + norm_layer=nn.LayerNorm, + patch_norm=False, + frozen_stages=-1, + use_checkpoint=False): + super().__init__() + + self.pretrained = pretrained + self.num_layers = len(depths) + self.embed_dim = embed_dim + self.patch_norm = patch_norm + self.frozen_stages = frozen_stages + self.window_size = window_size + self.patch_size = patch_size + + # split image into non-overlapping patches + self.patch_embed = PatchEmbed3D( + patch_size=patch_size, + in_chans=in_chans, + embed_dim=embed_dim, + norm_layer=norm_layer if self.patch_norm else None) + + self.pos_drop = nn.Dropout(p=drop_rate) + + # stochastic depth + dpr = [ + x.item() for x in paddle.linspace(0, drop_path_rate, sum(depths)) + ] # stochastic depth decay rule + + # build layers + self.layers = nn.LayerList() + for i_layer in range(self.num_layers): + layer = BasicLayer( + dim=int(embed_dim * 2**i_layer), + depth=depths[i_layer], + num_heads=num_heads[i_layer], + window_size=window_size, + mlp_ratio=mlp_ratio, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + drop=drop_rate, + attn_drop=attn_drop_rate, + drop_path=dpr[sum(depths[:i_layer]):sum(depths[:i_layer + 1])], + norm_layer=norm_layer, + downsample=PatchMerging + if i_layer < self.num_layers - 1 else None, + use_checkpoint=use_checkpoint) + self.layers.append(layer) + + self.num_features = int(embed_dim * 2**(self.num_layers - 1)) + + # add a norm layer for each output + self.norm = norm_layer(self.num_features) + + self._freeze_stages() + + def _freeze_stages(self): + if self.frozen_stages >= 0: + self.patch_embed.eval() + for param in self.patch_embed.parameters(): + param.stop_gradient = True + + if self.frozen_stages >= 1: + self.pos_drop.eval() + for i in range(0, self.frozen_stages): + m = self.layers[i] + m.eval() + for param in m.parameters(): + param.stop_gradient = True + + def _init_fn(self, m): + if isinstance(m, nn.Linear): + trunc_normal_(m.weight, std=0.02) + if m.bias is not None: + zeros_(m.bias) + elif isinstance(m, nn.LayerNorm): + zeros_(m.bias) + ones_(m.weight) + + def init_weights(self): + """Initialize the weights in backbone. + + Args: + pretrained (str, optional): Path to pre-trained weights. + Defaults to None. + """ + """First init model's weight""" + + self.apply(self._init_fn) + """Second, if provide pretrained ckpt, load it""" + if isinstance( + self.pretrained, str + ) and self.pretrained.strip() != "": # load pretrained weights + load_ckpt(self, self.pretrained) + elif self.pretrained is None or self.pretrained.strip() == "": + pass + else: + raise NotImplementedError + + def forward(self, x): + """Forward function.""" + x = self.patch_embed(x) + x = self.pos_drop(x) + + for layer in self.layers: + x = layer(x) + + x = x.transpose([0, 2, 3, 4, 1]) + x = self.norm(x) + x = x.transpose([0, 4, 1, 2, 3]) + return x + + def train(self, mode=True): + """Convert the model into training mode while keep layers freezed.""" + super(SwinTransformer3D, self).train(mode) + self._freeze_stages() diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/toshift_vit.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/toshift_vit.py new file mode 100644 index 0000000..a481996 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/toshift_vit.py @@ -0,0 +1,413 @@ +# 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. + +from collections.abc import Callable + +import numpy as np +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +from paddle.nn.initializer import Constant + +from ...utils import load_ckpt +from ..registry import BACKBONES +from ..weight_init import trunc_normal_ + +__all__ = ['VisionTransformer'] + +zeros_ = Constant(value=0.) +ones_ = Constant(value=1.) + + +def to_2tuple(x): + return tuple([x] * 2) + + +def drop_path(x, drop_prob=0., training=False): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + the original name is misleading as 'Drop Connect' is a different form of dropout in a separate paper... + # issuecomment-532968956 ... + See discussion: https://github.com/tensorflow/tpu/issues/494 + """ + if drop_prob == 0. or not training: + return x + keep_prob = paddle.to_tensor(1 - drop_prob) + shape = (paddle.shape(x)[0], ) + (1, ) * (x.ndim - 1) + random_tensor = keep_prob + paddle.rand(shape).astype(x.dtype) + random_tensor = paddle.floor(random_tensor) # binarize + output = x.divide(keep_prob) * random_tensor + + return output + + +class DropPath(nn.Layer): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + """ + def __init__(self, drop_prob=None): + super(DropPath, self).__init__() + self.drop_prob = drop_prob + + def forward(self, x): + return drop_path(x, self.drop_prob, self.training) + + +class Identity(nn.Layer): + def __init__(self): + super(Identity, self).__init__() + + def forward(self, input): + return input + + +class Mlp(nn.Layer): + def __init__(self, + in_features, + hidden_features=None, + out_features=None, + act_layer=nn.GELU, + drop=0.0): + super().__init__() + out_features = out_features or in_features + hidden_features = hidden_features or in_features + self.fc1 = nn.Linear(in_features, hidden_features) + self.act = act_layer() + self.fc2 = nn.Linear(hidden_features, out_features) + self.drop = nn.Dropout(drop) + + def forward(self, x): + x = self.fc1(x) + x = self.act(x) + x = self.drop(x) + x = self.fc2(x) + x = self.drop(x) + return x + + +class Attention(nn.Layer): + def __init__(self, + dim, + num_heads=8, + qkv_bias=False, + qk_scale=None, + attn_drop=0.0, + proj_drop=0.0): + super().__init__() + + self.num_heads = num_heads + head_dim = dim // num_heads + self.scale = qk_scale or head_dim**-0.5 + + self.qkv = nn.Linear(dim, dim * 3, bias_attr=qkv_bias) + self.proj = nn.Linear(dim, dim) + self.proj_drop = nn.Dropout(proj_drop) + self.attn_drop = nn.Dropout(attn_drop) + + def forward(self, x): + N, C = x.shape[1:] + qkv = self.qkv(x).reshape( + (-1, N, 3, self.num_heads, C // self.num_heads)).transpose( + (2, 0, 3, 1, 4)) + q, k, v = qkv[0], qkv[1], qkv[2] + + attn = (q.matmul(k.transpose((0, 1, 3, 2)))) * self.scale + attn = nn.functional.softmax(attn, axis=-1) + attn = self.attn_drop(attn) + + x = (attn.matmul(v)).transpose((0, 2, 1, 3)).reshape((-1, N, C)) + x = self.proj(x) + x = self.proj_drop(x) + return x + + +class Block(nn.Layer): + def __init__(self, + dim, + num_heads, + mlp_ratio=4.0, + qkv_bias=False, + qk_scale=None, + drop=0.0, + attn_drop=0.0, + drop_path=0.1, + act_layer=nn.GELU, + norm_layer='nn.LayerNorm', + epsilon=1e-5, + num_segments = 8, + fold_div = 4): + #attention_type='divided_space_time', + super().__init__() + self.n_seg = num_segments #ckk + self.foldP_div = fold_div #ckk + #self.attention_type = attention_type + if isinstance(norm_layer, str): + self.norm1 = eval(norm_layer)(dim, epsilon=epsilon) + elif isinstance(norm_layer, Callable): + self.norm1 = norm_layer(dim, epsilon=epsilon) + else: + raise TypeError( + "The norm_layer must be str or paddle.nn.layer.Layer class") + + self.attn = Attention(dim, + num_heads=num_heads, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + attn_drop=attn_drop, + proj_drop=drop) + + # Temporal Attention Parameters + ''' + if self.attention_type == 'divided_space_time': + if isinstance(norm_layer, str): + self.temporal_norm1 = eval(norm_layer)(dim, epsilon=epsilon) + elif isinstance(norm_layer, Callable): + self.temporal_norm1 = norm_layer(dim, epsilon=epsilon) + else: + raise TypeError( + "The norm_layer must be str or paddle.nn.layer.Layer class") + self.temporal_attn = Attention(dim, + num_heads=num_heads, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + attn_drop=attn_drop, + proj_drop=drop) + self.temporal_fc = nn.Linear(dim, dim) + ''' + # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here + self.drop_path = DropPath(drop_path) if drop_path > 0. else Identity() + if isinstance(norm_layer, str): + self.norm2 = eval(norm_layer)(dim, epsilon=epsilon) + elif isinstance(norm_layer, Callable): + self.norm2 = norm_layer(dim, epsilon=epsilon) + else: + raise TypeError( + "The norm_layer must be str or paddle.nn.layer.Layer class") + mlp_hidden_dim = int(dim * mlp_ratio) + self.mlp = Mlp(in_features=dim, + hidden_features=mlp_hidden_dim, + act_layer=act_layer, + drop=drop) + # token_shift + def shuift_tk(self, x): + t = self.n_seg + bt, n, c = x.shape + b = bt // t + x = x.reshape([b, t, n, c]) #B T N C + + fold = c // self.foldP_div + out = paddle.zeros_like(x) + out.stop_gradient = True + # print("#### fold ", fold) + # print(out.shape) + # print(x[:, 1:, 0, :fold].unsqueeze(2).shape) + # print(out[:, :-1, 0:1, :fold].shape) + # exit(0) + out[:, :-1, 0, :fold] = x[:, 1:, 0, :fold] # shift left + out[:, 1:, 0, fold:2*fold] = x[:,:-1:, 0, fold:2*fold] + + out[:, :, 1:, :2*fold] = x[:, :, 1:, :2*fold] + out[:, :, :, 2*fold:] = x[:, :, :, 2*fold:] + + return out.reshape([bt, n, c]) + + def forward(self, x): + x = self.shuift_tk(x) + x = x + self.drop_path(self.attn(self.norm1(x))) + x = self.shuift_tk(x) + x = x + self.drop_path(self.mlp(self.norm2(x))) + return x + + +class PatchEmbed(nn.Layer): + """ Image to Patch Embedding + """ + def __init__(self, + img_size=224, + patch_size=16, + in_channels=3, + embed_dim=768): + super().__init__() + img_size = to_2tuple(img_size) + patch_size = to_2tuple(patch_size) + num_patches = (img_size[1] // patch_size[1]) * (img_size[0] // + patch_size[0]) + self.img_size = img_size + self.patch_size = patch_size + self.num_patches = num_patches + + self.proj = nn.Conv2D(in_channels, + embed_dim, + kernel_size=patch_size, + stride=patch_size) + + def forward(self, x): + B, C, T, H, W = x.shape + + assert H == self.img_size[0] and W == self.img_size[1], \ + f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})." + x = x.transpose((0, 2, 1, 3, 4)) + x = x.reshape([-1, C, H, W]) + x = self.proj(x) + W = x.shape[-1] + x = x.flatten(2).transpose((0, 2, 1)) + return x, T, W + + +@BACKBONES.register() +class TokenShiftVisionTransformer(nn.Layer): + """ Vision Transformer with support for patch input + """ + def __init__(self, + pretrained=None, + img_size=224, + patch_size=16, + in_channels=3, + embed_dim=768, + depth=12, + num_heads=12, + mlp_ratio=4, + qkv_bias=False, + qk_scale=None, + drop_rate=0, + attn_drop_rate=0., + drop_path_rate=0.1, + norm_layer='nn.LayerNorm', + epsilon=1e-5, + num_seg=8, + attention_type='divided_space_time', + **args): + + super().__init__() + self.pretrained = pretrained + self.num_seg = num_seg + self.attention_type = attention_type + self.num_features = self.embed_dim = embed_dim + + self.patch_embed = PatchEmbed(img_size=img_size, + patch_size=patch_size, + in_channels=in_channels, + embed_dim=embed_dim) + num_patches = self.patch_embed.num_patches + + # Positional Embeddings + self.cls_token = self.create_parameter(shape=(1, 1, embed_dim), + default_initializer=zeros_) + self.pos_embed = self.create_parameter(shape=(1, num_patches + 1, + embed_dim), + default_initializer=zeros_) + self.pos_drop = nn.Dropout(p=drop_rate) + + if self.attention_type != 'space_only': + self.time_embed = self.create_parameter(shape=(1, num_seg, + embed_dim), + default_initializer=zeros_) + self.time_drop = nn.Dropout(p=drop_rate) + + self.add_parameter("pos_embed", self.pos_embed) + self.add_parameter("cls_token", self.cls_token) + + dpr = np.linspace(0, drop_path_rate, depth) + + self.blocks = nn.LayerList([ + Block(dim=embed_dim, + num_heads=num_heads, + mlp_ratio=mlp_ratio, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + drop=drop_rate, + attn_drop=attn_drop_rate, + drop_path=dpr[i], + norm_layer=norm_layer, + epsilon=epsilon, + num_segments= self.num_seg + ) for i in range(depth) + #attention_type=self.attention_type + ]) + + self.norm = eval(norm_layer)(embed_dim, epsilon=epsilon) + + def init_weights(self): + """First init model's weight""" + trunc_normal_(self.pos_embed, std=0.02) + trunc_normal_(self.cls_token, std=0.02) + self.apply(self._init_fn) + + if self.attention_type == 'divided_space_time': + i = 0 + for m in self.blocks.sublayers(include_self=True): + m_str = str(m) + if 'Block' in m_str: + if i > 0: + zeros_(m.temporal_fc.weight) + zeros_(m.temporal_fc.bias) + i += 1 + + """Second, if provide pretrained ckpt, load it""" + + if isinstance( + self.pretrained, str + ) and self.pretrained.strip() != "": # load pretrained weights + load_ckpt(self, + self.pretrained, + num_patches=self.patch_embed.num_patches, + num_seg=self.num_seg, + attention_type=self.attention_type) + + def _init_fn(self, m): + if isinstance(m, nn.Linear): + trunc_normal_(m.weight) + if m.bias is not None: + zeros_(m.bias) + elif isinstance(m, nn.LayerNorm): + ones_(m.weight) + zeros_(m.bias) + + def forward_features(self, x): + # B = x.shape[0] + B = paddle.shape(x)[0] + x, T, W = self.patch_embed(x) # [BT,nH*nW,F] + cls_tokens = self.cls_token.expand((B * T, -1, -1)) # [1,1,F]->[BT,1,F] + x = paddle.concat((cls_tokens, x), axis=1) + pos_interp = (x.shape[1] != self.pos_embed.shape[1]) + if pos_interp: + pos_embed = self.pos_embed + cls_pos_embed = pos_embed[0, 0, :].unsqueeze(0).unsqueeze(1) + other_pos_embed = pos_embed[0, 1:, :].unsqueeze(0).transpose( + (0, 2, 1)) + P = int(other_pos_embed.shape[2]**0.5) + H = x.shape[1] // W + other_pos_embed = other_pos_embed.reshape([1, x.shape[2], P, P]) + new_pos_embed = F.interpolate(other_pos_embed, + size=(H, W), + mode='nearest') + new_pos_embed = new_pos_embed.flatten(2) + new_pos_embed = new_pos_embed.transpose((0, 2, 1)) + new_pos_embed = paddle.concat((cls_pos_embed, new_pos_embed), + axis=1) + x = x + new_pos_embed + else: + x = x + self.pos_embed + + x = self.pos_drop(x) + + # Attention blocks + for blk in self.blocks: + x = blk(x) + + + x = self.norm(x) + return x[:, 0] # [B, embed_dim] -> [B*T, embed_dim] + + def forward(self, x): + x = self.forward_features(x) + return x \ No newline at end of file diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/transnetv2.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/transnetv2.py new file mode 100644 index 0000000..60603e2 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/transnetv2.py @@ -0,0 +1,582 @@ +# 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 numpy as np +import paddle +import paddle.nn as nn +import paddle.nn.functional as functional +import random +from paddle import ParamAttr + +from ..registry import BACKBONES + + +class OctConv3D(nn.Layer): + def __init__(self, in_filters, filters, kernel_size=3, dilation_rate=(1, 1, 1), alpha=0.25, + use_bias=True, kernel_initializer=nn.initializer.KaimingNormal()): + super(OctConv3D, self).__init__() + + self.low_channels = int(filters * alpha) + self.high_channels = filters - self.low_channels + + self.high_to_high = nn.Conv3D(in_filters, self.high_channels, kernel_size=kernel_size, + dilation=dilation_rate, padding=(dilation_rate[0], 1, 1), + weight_attr=ParamAttr(initializer=kernel_initializer), + bias_attr=ParamAttr( + initializer=nn.initializer.Constant(value=0.)) if use_bias else use_bias) + self.high_to_low = nn.Conv3D(self.high_channels, self.low_channels, kernel_size=kernel_size, + dilation=dilation_rate, padding=(dilation_rate[0], 1, 1), + weight_attr=ParamAttr(initializer=kernel_initializer), + bias_attr=False) + self.low_to_high = nn.Conv3D(in_filters, self.high_channels, kernel_size=kernel_size, + dilation=dilation_rate, padding=(dilation_rate[0], 1, 1), + weight_attr=ParamAttr(initializer=kernel_initializer), + bias_attr=False) + self.low_to_low = nn.Conv3D(self.high_channels, self.low_channels, kernel_size=kernel_size, + dilation=dilation_rate, padding=(dilation_rate[0], 1, 1), + weight_attr=ParamAttr(initializer=kernel_initializer), + bias_attr=ParamAttr( + initializer=nn.initializer.Constant(value=0.)) if use_bias else use_bias) + self.upsampler = nn.Upsample(size=(1, 2, 2), data_format='NCDHW') + self.downsampler = nn.AvgPool3D(kernel_size=(1, 2, 2), stride=(1, 2, 2), padding=(0, 1, 1)) + + @staticmethod + def pad_to(tensor, target_shape): + shape = tensor.shape + padding = [[0, tar - curr] for curr, tar in zip(shape, target_shape)] + return functional.pad(tensor, padding, "CONSTANT", data_format='NCDHW') + + @staticmethod + def crop_to(tensor, target_width, target_height): + return tensor[:, :, :target_height, :target_width] + + def forward(self, inputs): + low_inputs, high_inputs = inputs + + high_to_high = self.high_to_high(high_inputs) + high_to_low = self.high_to_low(self.downsampler(high_inputs)) + + low_to_high = self.upsampler(self.low_to_high(low_inputs)) + low_to_low = self.low_to_low(low_inputs) + + high_output = high_to_high[:, :, :, :low_to_high.shape[3], :low_to_high.shape[4]] + low_to_high + low_output = low_to_low + high_to_low[:, :, :, :low_to_low.shape[3], :low_to_low.shape[4]] + + return low_output, high_output + + +class Conv3DConfigurable(nn.Layer): + def __init__(self, + in_filters, + filters, + dilation_rate, + separable=True, + octave=False, + use_bias=True): + super(Conv3DConfigurable, self).__init__() + assert not (separable and octave) + + if separable: + conv1 = nn.Conv3D(in_filters, 2 * filters, kernel_size=(1, 3, 3), + dilation=(1, 1, 1), padding=(0, 1, 1), + weight_attr=ParamAttr(initializer=nn.initializer.KaimingNormal()), + bias_attr=False) + conv2 = nn.Conv3D(2 * filters, filters, kernel_size=(3, 1, 1), + dilation=(dilation_rate, 1, 1), padding=(dilation_rate, 0, 0), + weight_attr=ParamAttr(initializer=nn.initializer.KaimingNormal()), + bias_attr=ParamAttr( + initializer=nn.initializer.Constant(value=0.)) if use_bias else use_bias) + self.layers = nn.LayerList([conv1, conv2]) + elif octave: + conv = OctConv3D(in_filters, filters, kernel_size=3, dilation_rate=(dilation_rate, 1, 1), + use_bias=use_bias, + kernel_initializer=nn.initializer.KaimingNormal()) + self.layers = [conv] + else: + conv = nn.Conv3D(in_filters, filters, kernel_size=3, + dilation=(dilation_rate, 1, 1), padding=(dilation_rate, 1, 1), + weight_attr=ParamAttr(initializer=nn.initializer.KaimingNormal()), + bias_attr=ParamAttr( + initializer=nn.initializer.Constant(value=0.)) if use_bias else use_bias) + self.layers = nn.LayerList([conv]) + + def forward(self, inputs): + x = inputs + for layer in self.layers: + x = layer(x) + return x + + +class DilatedDCNNV2(nn.Layer): + def __init__(self, + in_filters, + filters, + batch_norm=True, + activation=None, + octave_conv=False): + super(DilatedDCNNV2, self).__init__() + assert not (octave_conv and batch_norm) + + self.Conv3D_1 = Conv3DConfigurable(in_filters, filters, 1, use_bias=not batch_norm, octave=octave_conv) + self.Conv3D_2 = Conv3DConfigurable(in_filters, filters, 2, use_bias=not batch_norm, octave=octave_conv) + self.Conv3D_4 = Conv3DConfigurable(in_filters, filters, 4, use_bias=not batch_norm, octave=octave_conv) + self.Conv3D_8 = Conv3DConfigurable(in_filters, filters, 8, use_bias=not batch_norm, octave=octave_conv) + self.octave = octave_conv + + self.bn = nn.BatchNorm3D(filters * 4, momentum=0.99, epsilon=1e-03, + weight_attr=ParamAttr(initializer=nn.initializer.Constant(value=1.)), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.)) + ) if batch_norm else None + self.activation = activation + + def forward(self, inputs): + conv1 = self.Conv3D_1(inputs) + conv2 = self.Conv3D_2(inputs) + conv3 = self.Conv3D_4(inputs) + conv4 = self.Conv3D_8(inputs) + + # shape of convi[j]/convi is [B, 3, T, H, W], concat in channel dimension + if self.octave: + x = [paddle.concat([conv1[0], conv2[0], conv3[0], conv4[0]], axis=1), + paddle.concat([conv1[1], conv2[1], conv3[1], conv4[1]], axis=1)] + else: + x = paddle.concat([conv1, conv2, conv3, conv4], axis=1) + + if self.bn is not None: + x = self.bn(x) + + if self.activation is not None: + if self.octave: + x = [self.activation(x[0]), self.activation(x[1])] + else: + x = self.activation(x) + return x + + +class StackedDDCNNV2(nn.Layer): + def __init__(self, + in_filters, + n_blocks, + filters, + shortcut=True, + use_octave_conv=False, + pool_type="avg", + stochastic_depth_drop_prob=0.0): + super(StackedDDCNNV2, self).__init__() + assert pool_type == "max" or pool_type == "avg" + if use_octave_conv and pool_type == "max": + print("WARN: Octave convolution was designed with average pooling, not max pooling.") + + self.shortcut = shortcut + self.DDCNN = nn.LayerList([ + DilatedDCNNV2(in_filters if i == 1 else filters * 4, filters, octave_conv=use_octave_conv, + activation=functional.relu if i != n_blocks else None) for i in range(1, n_blocks + 1) + ]) + self.pool = nn.MaxPool3D(kernel_size=(1, 2, 2)) if pool_type == "max" else nn.AvgPool3D(kernel_size=(1, 2, 2)) + self.octave = use_octave_conv + self.stochastic_depth_drop_prob = stochastic_depth_drop_prob + + def forward(self, inputs): + x = inputs + shortcut = None + + if self.octave: + x = [self.pool(x), x] + for block in self.DDCNN: + x = block(x) + if shortcut is None: + shortcut = x + # shape of x[i] is [B, 3, T, H, W], concat in channel dimension + if self.octave: + x = paddle.concat([x[0], self.pool(x[1])], axis=1) + + x = functional.relu(x) + + if self.shortcut is not None: + if self.stochastic_depth_drop_prob != 0.: + if self.training: + if random.random() < self.stochastic_depth_drop_prob: + x = shortcut + else: + x = x + shortcut + else: + x = (1 - self.stochastic_depth_drop_prob) * x + shortcut + else: + x += shortcut + + if not self.octave: + x = self.pool(x) + return x + + +class ResNetBlock(nn.Layer): + def __init__(self, in_filters, filters, strides=(1, 1)): + super(ResNetBlock, self).__init__() + + self.conv1 = nn.Conv2D(in_filters, filters, kernel_size=(3, 3), stride=strides, padding=(1, 1), + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=False) + self.bn1 = nn.BatchNorm2D(filters, + weight_attr=ParamAttr(initializer=nn.initializer.Constant(value=1.)), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.))) + + self.conv2 = nn.Conv2D(filters, filters, kernel_size=(3, 3), padding=(1, 1), + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=False) + self.bn2 = nn.BatchNorm2D(filters, + weight_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.)), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.))) + + def forward(self, inputs): + x = self.conv1(inputs) + x = self.bn1(x) + x = functional.relu(x) + + x = self.conv2(x) + x = self.bn2(x) + + shortcut = inputs + x += shortcut + + return functional.relu(x) + + +class ResNetFeatures(nn.Layer): + def __init__(self, in_filters=3, + mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]): + super(ResNetFeatures, self).__init__() + self.conv1 = nn.Conv2D(in_channels=in_filters, out_channels=64, kernel_size=(7, 7), + stride=(2, 2), padding=(3, 3), + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=False) + self.bn1 = nn.BatchNorm2D(num_features=64, momentum=0.99, epsilon=1e-03, + weight_attr=ParamAttr(initializer=nn.initializer.Constant(value=1.)), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.)) + ) + self.max_pool = nn.MaxPool2D(kernel_size=(3, 3), stride=(2, 2), padding=(1, 1)) + + self.layer2a = ResNetBlock(64, 64) + self.layer2b = ResNetBlock(64, 64) + + self.mean = paddle.to_tensor(mean) + self.std = paddle.to_tensor(std) + + def forward(self, inputs): + shape = inputs.shape + x = paddle.reshape(inputs, [shape[0] * shape[2], shape[1], shape[3], shape[4]]) + x = (x - self.mean) / self.std + + x = self.conv1(x) + x = self.bn1(x) + x = functional.relu(x) + x = self.max_pool(x) + x = self.layer2a(x) + x = self.layer2b(x) + + new_shape = x.shape + x = paddle.reshape(x, [shape[0], new_shape[1], shape[2], new_shape[2], new_shape[3]]) + return x + + +class FrameSimilarity(nn.Layer): + def __init__(self, + in_filters, + similarity_dim=128, + lookup_window=101, + output_dim=128, + stop_gradient=False, + use_bias=False): + super(FrameSimilarity, self).__init__() + self.projection = nn.Linear(in_filters, similarity_dim, + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=use_bias) + self.fc = nn.Linear(lookup_window, output_dim, + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.))) + + self.lookup_window = lookup_window + self.stop_gradient = stop_gradient + assert lookup_window % 2 == 1, "`lookup_window` must be odd integer" + + def forward(self, inputs): + x = paddle.concat([paddle.mean(x, axis=[3, 4]) for x in inputs], axis=1) + x = paddle.transpose(x, (0, 2, 1)) + + if self.stop_gradient: + x = x.stop_gradient + + x = self.projection(x) + x = functional.normalize(x, p=2, axis=2) + batch_size = paddle.slice(x.shape, starts=[0], ends=[1], axes=[0]) if x.shape[0] == -1 else x.shape[0] + time_window = x.shape[1] + similarities = paddle.bmm(x, x.transpose([0, 2, 1])) # [batch_size, time_window, time_window] + + similarities_padded = functional.pad(similarities, + [(self.lookup_window - 1) // 2, (self.lookup_window - 1) // 2], + data_format='NCL') + + batch_indices = paddle.arange(0, batch_size).reshape([batch_size, 1, 1]) + batch_indices = paddle.tile(batch_indices, [1, time_window, self.lookup_window]) + time_indices = paddle.arange(0, time_window).reshape([1, time_window, 1]) + time_indices = paddle.tile(time_indices, [batch_size, 1, self.lookup_window]) + lookup_indices = paddle.arange(0, self.lookup_window).reshape([1, 1, self.lookup_window]) + lookup_indices = paddle.tile(lookup_indices, [batch_size, time_window, 1]) + time_indices + indices = paddle.stack([batch_indices, time_indices, lookup_indices], -1) + similarities = paddle.gather_nd(similarities_padded, indices) + return functional.relu(self.fc(similarities)) + + +class ConvexCombinationRegularization(nn.Layer): + def __init__(self, in_filters, filters=32, delta_scale=10., loss_weight=0.01): + super(ConvexCombinationRegularization, self).__init__() + + self.projection = nn.Conv3D(in_filters, filters, kernel_size=1, dilation=1, padding=(0, 0, 0), + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.))) + self.features = nn.Conv3D((filters * 3), filters * 2, + kernel_size=(3, 3, 3), dilation=1, padding=(1, 1, 1), + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.))) + self.dense = nn.Linear(64, 1, weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), bias_attr=True) + self.loss = nn.SmoothL1Loss(reduction='none') + self.delta_scale = delta_scale + self.loss_weight = loss_weight + + def forward(self, image_inputs, feature_inputs): + x = feature_inputs + x = self.projection(x) + x = functional.relu(x) + batch_size = x.shape[0] + window_size = x.shape[2] + first_frame = paddle.tile(x[:, :, :1], [1, 1, window_size, 1, 1]) + last_frame = paddle.tile(x[:, :, -1:], [1, 1, window_size, 1, 1]) + x = paddle.concat([x, first_frame, last_frame], 1) + x = self.features(x) + x = functional.relu(x) + x = paddle.mean(x, axis=[3, 4]) + x = paddle.transpose(x, (0, 2, 1)) + alpha = self.dense(x) + alpha = paddle.transpose(alpha, (0, 2, 1)) + + first_img = paddle.tile(image_inputs[:, :, :1], [1, 1, window_size, 1, 1]) + last_img = paddle.tile(image_inputs[:, :, -1:], [1, 1, window_size, 1, 1]) + + alpha_ = functional.sigmoid(alpha) + alpha_ = paddle.reshape(alpha_, [batch_size, 1, window_size, 1, 1]) + predictions_ = (alpha_ * first_img + (1 - alpha_) * last_img) + loss_ = self.loss(label=image_inputs / self.delta_scale, input=predictions_ / self.delta_scale) + loss_ = self.loss_weight * paddle.mean(loss_) + return alpha, loss_ + + +class ColorHistograms(nn.Layer): + def __init__(self, + lookup_window=101, + output_dim=None): + super(ColorHistograms, self).__init__() + + self.fc = nn.Linear(lookup_window, output_dim, + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=ParamAttr( + initializer=nn.initializer.Constant(value=0.))) if output_dim is not None else None + self.lookup_window = lookup_window + assert lookup_window % 2 == 1, "`lookup_window` must be odd integer" + + def compute_color_histograms(self, frames): + frames = frames.astype('int32') + + def get_bin(frames): + # returns 0 .. 511 + R, G, B = frames[:, :, 0], frames[:, :, 1], frames[:, :, 2] + R, G, B = R // 32, G // 32, B // 32 + return (R * 64) + (G * 8) + B + + batch_size = paddle.slice(frames.shape, starts=[0], ends=[1], axes=[0]) if frames.shape[0] == -1 else frames.shape[0] + time_window, height, width, no_channels = frames.shape[1:] + + assert no_channels == 3 or no_channels == 6 + if no_channels == 3: + frames_flatten = frames.reshape([-1, height * width, 3]) + else: + frames_flatten = frames.reshape([-1, height * width * 2, 3]) + + binned_values = get_bin(frames_flatten) + + frame_bin_prefix = (paddle.arange(0, batch_size * time_window) * 512).reshape([-1, 1]) + binned_values = (binned_values + frame_bin_prefix).reshape([-1, 1]) + histograms = paddle.zeros_like(frame_bin_prefix, dtype='int32').tile([512]).reshape([-1]) + histograms = histograms.scatter_nd_add(binned_values, paddle.ones_like(binned_values, dtype='int32').reshape([-1])) + histograms = histograms.reshape([batch_size, time_window, 512]).astype('float32') + histograms_normalized = functional.normalize(histograms, p=2, axis=2) + return histograms_normalized + + def forward(self, inputs): + x = self.compute_color_histograms(inputs) + batch_size = paddle.slice(x.shape, starts=[0], ends=[1], axes=[0]) if x.shape[0] == -1 else x.shape[0] + time_window = x.shape[1] + similarities = paddle.bmm(x, x.transpose([0, 2, 1])) # [batch_size, time_window, time_window] + similarities_padded = functional.pad(similarities, + [(self.lookup_window - 1) // 2, (self.lookup_window - 1) // 2], + data_format='NCL') + + batch_indices = paddle.arange(0, batch_size).reshape([batch_size, 1, 1]) + batch_indices = paddle.tile(batch_indices, [1, time_window, self.lookup_window]) + time_indices = paddle.arange(0, time_window).reshape([1, time_window, 1]) + time_indices = paddle.tile(time_indices, [batch_size, 1, self.lookup_window]) + lookup_indices = paddle.arange(0, self.lookup_window).reshape([1, 1, self.lookup_window]) + lookup_indices = paddle.tile(lookup_indices, [batch_size, time_window, 1]) + time_indices + + indices = paddle.stack([batch_indices, time_indices, lookup_indices], -1) + similarities = paddle.gather_nd(similarities_padded, indices) + + if self.fc is not None: + return functional.relu(self.fc(similarities)) + return similarities + + +@BACKBONES.register() +class TransNetV2(nn.Layer): + """TransNetV2 model from + `"TransNet V2: An effective deep network architecture for fast shot transition detection" `_ + """ + def __init__(self, + F=16, L=3, S=2, D=1024, + use_many_hot_targets=True, + use_frame_similarity=True, + use_color_histograms=True, + use_mean_pooling=False, + dropout_rate=0.5, + use_convex_comb_reg=False, + use_resnet_features=False, + use_resnet_like_top=False, + frame_similarity_on_last_layer=False, + mean=[0.485, 0.456, 0.406], + std=[0.229, 0.224, 0.225]): + super(TransNetV2, self).__init__() + + self.mean = np.array(mean, np.float32).reshape([1, 3, 1, 1]) * 255 + self.std = np.array(std, np.float32).reshape([1, 3, 1, 1]) * 255 + + self.use_resnet_features = use_resnet_features + self.resnet_layers = ResNetFeatures(in_filters=3, mean=self.mean, std=self.std) if self.use_resnet_features else None + self.resnet_like_top = use_resnet_like_top + if self.resnet_like_top: + self.resnet_like_top_conv = nn.Conv3D(64 if self.use_resnet_features else 3, 32, kernel_size=(3, 7, 7), + stride=(1, 2, 2), + padding=(1, 3, 3), + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=False) + self.resnet_like_top_bn = nn.BatchNorm3D(32, momentum=0.99, epsilon=1e-03, + weight_attr=ParamAttr( + initializer=nn.initializer.Constant(value=1.)), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.))) + self.resnet_like_top_max_pool = nn.MaxPool3D(kernel_size=(1, 3, 3), stride=(1, 2, 2), + padding=(0, 1, 1)) + + if self.resnet_like_top: + in_filters = 32 + elif self.use_resnet_features: + in_filters = 64 + else: + in_filters = 3 + self.SDDCNN = nn.LayerList( + [StackedDDCNNV2(in_filters=in_filters, n_blocks=S, filters=F, + stochastic_depth_drop_prob=0.)] + + [StackedDDCNNV2(in_filters=(F * 2 ** (i - 1)) * 4, n_blocks=S, filters=F * 2 ** i) for i in range(1, L)] + ) + + self.frame_sim_layer = FrameSimilarity( + sum([(F * 2 ** i) * 4 for i in range(L)]), lookup_window=101, output_dim=128, similarity_dim=128, + use_bias=True + ) if use_frame_similarity else None + self.color_hist_layer = ColorHistograms( + lookup_window=101, output_dim=128 + ) if use_color_histograms else None + + self.dropout = nn.Dropout(dropout_rate) if dropout_rate is not None else None + + output_dim = ((F * 2 ** (L - 1)) * 4) * 3 * 6 # 3x6 for spatial dimensions + if use_frame_similarity: output_dim += 128 + if use_color_histograms: output_dim += 128 + + self.use_mean_pooling = use_mean_pooling + + self.has_downsample = False + if self.use_resnet_features or self.resnet_like_top or self.use_mean_pooling: + self.has_downsample = True + self.fc1 = nn.Linear(512 if self.has_downsample else output_dim, D, + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.)) + ) + self.frame_similarity_on_last_layer = frame_similarity_on_last_layer + self.cls_layer1 = nn.Linear(1152 if self.frame_similarity_on_last_layer else D, 1, + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.)) + ) + self.cls_layer2 = nn.Linear(1152 if self.frame_similarity_on_last_layer else D, 1, + weight_attr=ParamAttr(initializer=nn.initializer.XavierUniform()), + bias_attr=ParamAttr(initializer=nn.initializer.Constant(value=0.)) + ) if use_many_hot_targets else None + + self.convex_comb_reg = ConvexCombinationRegularization( + in_filters=(F * 2 ** (L - 1) * 4)) if use_convex_comb_reg else None + + def forward(self, inputs): + assert list(inputs.shape[2:]) == [27, 48, 3] and inputs.dtype == paddle.float32, \ + "incorrect input type and/or shape" + out_dict = {} + + # shape [B, T, H, W, 3] to shape [B, 3, T, H, W] + x = inputs.transpose([0, 4, 1, 2, 3]) + if self.use_resnet_features: + x = self.resnet_layers(x) + else: + x = x / 255. + inputs = inputs.clip(min=0).astype('uint8') + if self.resnet_like_top: + x = self.resnet_like_top_conv(x) + x = self.resnet_like_top_bn(x) + x = self.resnet_like_top_max_pool(x) + block_features = [] + for block in self.SDDCNN: + x = block(x) + block_features.append(x) + if self.convex_comb_reg is not None: + out_dict["alphas"], out_dict["comb_reg_loss"] = self.convex_comb_reg(inputs.transpose([0, 4, 1, 2, 3]), x) + if self.use_mean_pooling: + x = paddle.mean(x, axis=[3, 4]) + x = x.transpose([0, 2, 1]) + else: + x = x.transpose([0, 2, 3, 4, 1]) + x = x.reshape([x.shape[0], x.shape[1], x.shape[2]*x.shape[3]*x.shape[4]]) + if self.frame_sim_layer is not None: + x = paddle.concat([self.frame_sim_layer(block_features), x], 2) + if self.color_hist_layer is not None: + x = paddle.concat([self.color_hist_layer(inputs), x], 2) + x = self.fc1(x) + x = functional.relu(x) + if self.dropout is not None: + x = self.dropout(x) + if self.frame_sim_layer is not None and self.frame_similarity_on_last_layer: + x = paddle.concat([self.frame_sim_layer(block_features), x], 2) + one_hot = self.cls_layer1(x) + if self.cls_layer2 is not None: + out_dict["many_hot"] = self.cls_layer2(x) + + if len(out_dict) > 0: + return one_hot, out_dict + + return one_hot + diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/vit.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/vit.py new file mode 100644 index 0000000..84f434f --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/vit.py @@ -0,0 +1,465 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + +from collections.abc import Callable + +import numpy as np +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +from paddle.nn.initializer import Constant + +from ...utils import load_ckpt +from ..registry import BACKBONES +from ..weight_init import trunc_normal_ + +__all__ = ['VisionTransformer'] + +zeros_ = Constant(value=0.) +ones_ = Constant(value=1.) + + +def to_2tuple(x): + return tuple([x] * 2) + + +def drop_path(x, drop_prob=0., training=False): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + the original name is misleading as 'Drop Connect' is a different form of dropout in a separate paper... + # issuecomment-532968956 ... + See discussion: https://github.com/tensorflow/tpu/issues/494 + """ + if drop_prob == 0. or not training: + return x + keep_prob = paddle.to_tensor(1 - drop_prob, dtype=x.dtype) + shape = (paddle.shape(x)[0], ) + (1, ) * (x.ndim - 1) + random_tensor = keep_prob + paddle.rand(shape).astype(x.dtype) + random_tensor = paddle.floor(random_tensor) # binarize + output = x.divide(keep_prob) * random_tensor + + return output + + +class DropPath(nn.Layer): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + """ + def __init__(self, drop_prob=None): + super(DropPath, self).__init__() + self.drop_prob = drop_prob + + def forward(self, x): + return drop_path(x, self.drop_prob, self.training) + + +class Identity(nn.Layer): + def __init__(self): + super(Identity, self).__init__() + + def forward(self, input): + return input + + +class Mlp(nn.Layer): + def __init__(self, + in_features, + hidden_features=None, + out_features=None, + act_layer=nn.GELU, + drop=0.0): + super().__init__() + out_features = out_features or in_features + hidden_features = hidden_features or in_features + self.fc1 = nn.Linear(in_features, hidden_features) + self.act = act_layer() + self.fc2 = nn.Linear(hidden_features, out_features) + self.drop = nn.Dropout(drop) + + def forward(self, x): + x = self.fc1(x) + x = self.act(x) + x = self.drop(x) + x = self.fc2(x) + x = self.drop(x) + return x + + +class Attention(nn.Layer): + def __init__(self, + dim, + num_heads=8, + qkv_bias=False, + qk_scale=None, + attn_drop=0.0, + proj_drop=0.0): + super().__init__() + + self.num_heads = num_heads + head_dim = dim // num_heads + self.scale = qk_scale or head_dim**-0.5 + + self.qkv = nn.Linear(dim, dim * 3, bias_attr=qkv_bias) + self.proj = nn.Linear(dim, dim) + self.proj_drop = nn.Dropout(proj_drop) + self.attn_drop = nn.Dropout(attn_drop) + + def forward(self, x): + N, C = x.shape[1:] + qkv = self.qkv(x).reshape( + (-1, N, 3, self.num_heads, C // self.num_heads)).transpose( + (2, 0, 3, 1, 4)) + q, k, v = qkv[0], qkv[1], qkv[2] + + attn = (q.matmul(k.transpose((0, 1, 3, 2)))) * self.scale + attn = nn.functional.softmax(attn, axis=-1) + attn = self.attn_drop(attn) + + x = (attn.matmul(v)).transpose((0, 2, 1, 3)).reshape((-1, N, C)) + x = self.proj(x) + x = self.proj_drop(x) + return x + + +class Block(nn.Layer): + def __init__(self, + dim, + num_heads, + mlp_ratio=4.0, + qkv_bias=False, + qk_scale=None, + drop=0.0, + attn_drop=0.0, + drop_path=0.1, + act_layer=nn.GELU, + norm_layer='nn.LayerNorm', + epsilon=1e-5, + attention_type='divided_space_time'): + + super().__init__() + self.attention_type = attention_type + if isinstance(norm_layer, str): + self.norm1 = eval(norm_layer)(dim, epsilon=epsilon) + elif isinstance(norm_layer, Callable): + self.norm1 = norm_layer(dim, epsilon=epsilon) + else: + raise TypeError( + "The norm_layer must be str or paddle.nn.layer.Layer class") + + self.attn = Attention(dim, + num_heads=num_heads, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + attn_drop=attn_drop, + proj_drop=drop) + + # Temporal Attention Parameters + if self.attention_type == 'divided_space_time': + if isinstance(norm_layer, str): + self.temporal_norm1 = eval(norm_layer)(dim, epsilon=epsilon) + elif isinstance(norm_layer, Callable): + self.temporal_norm1 = norm_layer(dim, epsilon=epsilon) + else: + raise TypeError( + "The norm_layer must be str or paddle.nn.layer.Layer class") + self.temporal_attn = Attention(dim, + num_heads=num_heads, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + attn_drop=attn_drop, + proj_drop=drop) + self.temporal_fc = nn.Linear(dim, dim) + + # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here + self.drop_path = DropPath(drop_path) if drop_path > 0. else Identity() + if isinstance(norm_layer, str): + self.norm2 = eval(norm_layer)(dim, epsilon=epsilon) + elif isinstance(norm_layer, Callable): + self.norm2 = norm_layer(dim, epsilon=epsilon) + else: + raise TypeError( + "The norm_layer must be str or paddle.nn.layer.Layer class") + mlp_hidden_dim = int(dim * mlp_ratio) + self.mlp = Mlp(in_features=dim, + hidden_features=mlp_hidden_dim, + act_layer=act_layer, + drop=drop) + + def forward(self, x, B, T, W): + num_spatial_tokens = (x.shape[1] - 1) // T + H = num_spatial_tokens // W + if self.attention_type in ['space_only', 'joint_space_time']: + x = x + self.drop_path(self.attn(self.norm1(x))) + x = x + self.drop_path(self.mlp(self.norm2(x))) + return x + elif self.attention_type == 'divided_space_time': + ########## Temporal ########## + xt = x[:, 1:, :] + _, _, _, _t, _m = B, H, W, T, xt.shape[-1] + xt = xt.reshape([-1, _t, _m]) + + res_temporal = self.drop_path( + self.temporal_attn(self.temporal_norm1(xt))) + + _, _h, _w, _t, _m = B, H, W, T, res_temporal.shape[-1] + res_temporal = res_temporal.reshape([-1, _h * _w * _t, _m]) + + res_temporal = self.temporal_fc(res_temporal) + xt = x[:, 1:, :] + res_temporal + + ########## Spatial ########## + init_cls_token = x[:, 0, :].unsqueeze(1) + cls_token = init_cls_token.tile((1, T, 1)) + _b, _t, _m = cls_token.shape + cls_token = cls_token.reshape([-1, _m]).unsqueeze(1) + + xs = xt + _, _h, _w, _t, _m = B, H, W, T, xs.shape[-1] + xs = xs.reshape([-1, _h, _w, _t, _m]).transpose( + (0, 3, 1, 2, 4)).reshape([-1, _h * _w, _m]) + xs = paddle.concat((cls_token, xs), axis=1) + res_spatial = self.drop_path(self.attn(self.norm1(xs))) + + # Taking care of CLS token + cls_token = res_spatial[:, 0, :] + _, _t, _m = B, T, cls_token.shape[-1] + cls_token = cls_token.reshape([-1, _t, _m]) + # averaging for every frame + cls_token = paddle.mean(cls_token, axis=1, keepdim=True) + + res_spatial = res_spatial[:, 1:, :] + _, _t, _h, _w, _m = B, T, H, W, res_spatial.shape[-1] + res_spatial = res_spatial.reshape([-1, _t, _h, _w, _m]).transpose( + (0, 2, 3, 1, 4)).reshape([-1, _h * _w * _t, _m]) + + res = res_spatial + x = xt + x = paddle.concat((init_cls_token, x), axis=1) + paddle.concat( + (cls_token, res), axis=1) + + # Mlp + x = x + self.drop_path(self.mlp(self.norm2(x))) + return x + else: + raise NotImplementedError + + +class PatchEmbed(nn.Layer): + """ Image to Patch Embedding + """ + def __init__(self, + img_size=224, + patch_size=16, + in_channels=3, + embed_dim=768): + super().__init__() + img_size = to_2tuple(img_size) + patch_size = to_2tuple(patch_size) + num_patches = (img_size[1] // patch_size[1]) * (img_size[0] // + patch_size[0]) + self.img_size = img_size + self.patch_size = patch_size + self.num_patches = num_patches + + self.proj = nn.Conv2D(in_channels, + embed_dim, + kernel_size=patch_size, + stride=patch_size) + + def forward(self, x): + B, C, T, H, W = x.shape + + assert H == self.img_size[0] and W == self.img_size[1], \ + f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})." + x = x.transpose((0, 2, 1, 3, 4)) + x = x.reshape([-1, C, H, W]) + x = self.proj(x) + W = x.shape[-1] + x = x.flatten(2).transpose((0, 2, 1)) + return x, T, W + + +@BACKBONES.register() +class VisionTransformer(nn.Layer): + """ Vision Transformer with support for patch input + """ + def __init__(self, + pretrained=None, + img_size=224, + patch_size=16, + in_channels=3, + embed_dim=768, + depth=12, + num_heads=12, + mlp_ratio=4, + qkv_bias=False, + qk_scale=None, + drop_rate=0., + attn_drop_rate=0., + drop_path_rate=0.1, + norm_layer='nn.LayerNorm', + epsilon=1e-5, + num_seg=8, + attention_type='divided_space_time', + **args): + super().__init__() + self.pretrained = pretrained + self.num_seg = num_seg + self.attention_type = attention_type + self.num_features = self.embed_dim = embed_dim + + self.patch_embed = PatchEmbed(img_size=img_size, + patch_size=patch_size, + in_channels=in_channels, + embed_dim=embed_dim) + num_patches = self.patch_embed.num_patches + + # Positional Embeddings + self.cls_token = self.create_parameter(shape=(1, 1, embed_dim), + default_initializer=zeros_) + self.pos_embed = self.create_parameter(shape=(1, num_patches + 1, + embed_dim), + default_initializer=zeros_) + self.pos_drop = nn.Dropout(p=drop_rate) + + if self.attention_type != 'space_only': + self.time_embed = self.create_parameter(shape=(1, num_seg, + embed_dim), + default_initializer=zeros_) + self.time_drop = nn.Dropout(p=drop_rate) + + self.add_parameter("pos_embed", self.pos_embed) + self.add_parameter("cls_token", self.cls_token) + + dpr = np.linspace(0, drop_path_rate, depth) + + self.blocks = nn.LayerList([ + Block(dim=embed_dim, + num_heads=num_heads, + mlp_ratio=mlp_ratio, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + drop=drop_rate, + attn_drop=attn_drop_rate, + drop_path=dpr[i], + norm_layer=norm_layer, + epsilon=epsilon, + attention_type=self.attention_type) for i in range(depth) + ]) + + self.norm = eval(norm_layer)(embed_dim, epsilon=epsilon) + + def init_weights(self): + """First init model's weight""" + trunc_normal_(self.pos_embed, std=0.02) + trunc_normal_(self.cls_token, std=0.02) + self.apply(self._init_fn) + + if self.attention_type == 'divided_space_time': + i = 0 + for m in self.blocks.sublayers(include_self=True): + m_str = str(m) + if 'Block' in m_str: + if i > 0: + zeros_(m.temporal_fc.weight) + zeros_(m.temporal_fc.bias) + i += 1 + """Second, if provide pretrained ckpt, load it""" + if isinstance( + self.pretrained, str + ) and self.pretrained.strip() != "": # load pretrained weights + load_ckpt(self, + self.pretrained, + num_patches=self.patch_embed.num_patches, + num_seg=self.num_seg, + attention_type=self.attention_type) + + def _init_fn(self, m): + if isinstance(m, nn.Linear): + trunc_normal_(m.weight) + if m.bias is not None: + zeros_(m.bias) + elif isinstance(m, nn.LayerNorm): + ones_(m.weight) + zeros_(m.bias) + + def forward_features(self, x): + # B = x.shape[0] + B = paddle.shape(x)[0] + x, T, W = self.patch_embed(x) # [BT,nH*nW,F] + cls_tokens = self.cls_token.expand((B * T, -1, -1)) # [1,1,F]->[BT,1,F] + x = paddle.concat((cls_tokens, x), axis=1) + pos_interp = (x.shape[1] != self.pos_embed.shape[1]) + if pos_interp: + pos_embed = self.pos_embed + cls_pos_embed = pos_embed[0, 0, :].unsqueeze(0).unsqueeze(1) + other_pos_embed = pos_embed[0, 1:, :].unsqueeze(0).transpose( + (0, 2, 1)) + P = int(other_pos_embed.shape[2]**0.5) + H = x.shape[1] // W + other_pos_embed = other_pos_embed.reshape([1, x.shape[2], P, P]) + new_pos_embed = F.interpolate(other_pos_embed, + size=(H, W), + mode='nearest') + new_pos_embed = new_pos_embed.flatten(2) + new_pos_embed = new_pos_embed.transpose((0, 2, 1)) + new_pos_embed = paddle.concat((cls_pos_embed, new_pos_embed), + axis=1) + x = x + new_pos_embed + else: + x = x + self.pos_embed + + x = self.pos_drop(x) + + # Time Embeddings + if self.attention_type != 'space_only': + cls_tokens = x[:B, 0, :].unsqueeze(1) if B > 0 else x.split( + T)[0].index_select(paddle.to_tensor([0]), axis=1) + x = x[:, 1:] + _, _n, _m = x.shape + _t = T + x = x.reshape([-1, _t, _n, _m]).transpose( + (0, 2, 1, 3)).reshape([-1, _t, _m]) + # Resizing time embeddings in case they don't match + time_interp = (T != self.time_embed.shape[1]) + if time_interp: # T' != T + time_embed = self.time_embed.transpose((0, 2, 1)).unsqueeze(0) + new_time_embed = F.interpolate(time_embed, + size=(T, x.shape[-1]), + mode='nearest').squeeze(0) + new_time_embed = new_time_embed.transpose((0, 2, 1)) + x = x + new_time_embed + else: + x = x + self.time_embed + + x = self.time_drop(x) + _, _t, _m = x.shape + x = x.reshape([-1, W * W * T, _m]) + x = paddle.concat((cls_tokens, x), axis=1) + + # Attention blocks + for blk in self.blocks: + x = blk(x, B, T, W) + + # Predictions for space-only baseline + if self.attention_type == 'space_only': + _, _n, _m = x.shape + _t = T + x = x.reshape([-1, _t, _n, _m]) + x = paddle.mean(x, 1) # averaging predictions for every frame + + x = self.norm(x) + return x[:, 0] # [B, embed_dim] + + def forward(self, x): + x = self.forward_features(x) + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/vit_tweaks.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/vit_tweaks.py new file mode 100644 index 0000000..a20af30 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/vit_tweaks.py @@ -0,0 +1,515 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + +from collections.abc import Callable + +import numpy as np +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +from paddle import ParamAttr +from paddle.nn.initializer import Constant +from paddle.regularizer import L2Decay + +from ...utils import load_ckpt +from ..registry import BACKBONES +from ..weight_init import trunc_normal_ + +__all__ = ['VisionTransformer_tweaks'] + +zeros_ = Constant(value=0.) +ones_ = Constant(value=1.) + + +def to_2tuple(x): + return tuple([x] * 2) + + +def rand_bbox(size, lam): + """ rand_bbox """ + w = size[2] + h = size[3] + cut_rat = np.sqrt(1. - lam) + cut_w = np.int(w * cut_rat) + cut_h = np.int(h * cut_rat) + + # uniform + cx = np.random.randint(w) + cy = np.random.randint(h) + + bbx1 = np.clip(cx - cut_w // 2, 0, w) + bby1 = np.clip(cy - cut_h // 2, 0, h) + bbx2 = np.clip(cx + cut_w // 2, 0, w) + bby2 = np.clip(cy + cut_h // 2, 0, h) + + return bbx1, bby1, bbx2, bby2 + + +def drop_path(x, drop_prob=0., training=False): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + the original name is misleading as 'Drop Connect' is a different form of dropout in a separate paper... + # issuecomment-532968956 ... + See discussion: https://github.com/tensorflow/tpu/issues/494 + """ + if drop_prob == 0. or not training: + return x + keep_prob = paddle.to_tensor(1 - drop_prob) + shape = (paddle.shape(x)[0], ) + (1, ) * (x.ndim - 1) + random_tensor = keep_prob + paddle.rand(shape, dtype=x.dtype) + random_tensor = paddle.floor(random_tensor) # binarize + output = x.divide(keep_prob) * random_tensor + + return output + + +class DropPath(nn.Layer): + """Drop paths (Stochastic Depth) per sample (when applied in main path of residual blocks). + """ + def __init__(self, drop_prob=None): + super(DropPath, self).__init__() + self.drop_prob = drop_prob + + def forward(self, x): + return drop_path(x, self.drop_prob, self.training) + + +class Identity(nn.Layer): + def __init__(self): + super(Identity, self).__init__() + + def forward(self, input): + return input + + +class Mlp(nn.Layer): + def __init__(self, + in_features, + hidden_features=None, + out_features=None, + act_layer=nn.GELU, + drop=0., + wd_bias=True, + lr_mult=1.0): + super().__init__() + out_features = out_features or in_features + hidden_features = hidden_features or in_features + self.fc1 = nn.Linear(in_features, hidden_features) + self.act = act_layer() + self.fc2 = nn.Linear(hidden_features, out_features) + self.drop = nn.Dropout(drop) + + def forward(self, x): + x = self.fc1(x) + x = self.act(x) + x = self.drop(x) + x = self.fc2(x) + x = self.drop(x) + return x + + +class Attention(nn.Layer): + def __init__(self, + dim, + num_heads=8, + qkv_bias=False, + qk_scale=None, + attn_drop=0., + proj_drop=0., + wd_bias=True, + lr_mult=1.0): + super().__init__() + + self.num_heads = num_heads + head_dim = dim // num_heads + self.scale = qk_scale or head_dim**-0.5 + self.qkv = nn.Linear(dim, dim * 3, bias_attr=qkv_bias) + self.proj = nn.Linear(dim, dim) + self.proj_drop = nn.Dropout(proj_drop) + self.attn_drop = nn.Dropout(attn_drop) + + def forward(self, x): + N, C = x.shape[1:] + qkv = self.qkv(x).reshape( + (-1, N, 3, self.num_heads, C // self.num_heads)).transpose( + (2, 0, 3, 1, 4)) + q, k, v = qkv[0], qkv[1], qkv[2] + + attn = (q.matmul(k.transpose((0, 1, 3, 2)))) * self.scale + attn = nn.functional.softmax(attn, axis=-1) + attn = self.attn_drop(attn) + + x = (attn.matmul(v)).transpose((0, 2, 1, 3)).reshape((-1, N, C)) + x = self.proj(x) + x = self.proj_drop(x) + return x + + +class Block(nn.Layer): + def __init__(self, + dim, + num_heads, + mlp_ratio=4.0, + qkv_bias=False, + qk_scale=None, + drop=0.0, + attn_drop=0.0, + drop_path=0.1, + act_layer=nn.GELU, + norm_layer='nn.LayerNorm', + epsilon=1e-5, + attention_type='divided_space_time', + wd_bias=True, + lr_mult=1.0): + + super().__init__() + self.attention_type = attention_type + if isinstance(norm_layer, str): + self.norm1 = eval(norm_layer)(dim, epsilon=epsilon) + elif isinstance(norm_layer, Callable): + self.norm1 = norm_layer(dim, epsilon=epsilon) + else: + raise TypeError( + "The norm_layer must be str or paddle.nn.layer.Layer class") + + self.attn = Attention(dim, + num_heads=num_heads, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + attn_drop=attn_drop, + proj_drop=drop, + wd_bias=wd_bias, + lr_mult=lr_mult) + + # Temporal Attention Parameters + if self.attention_type == 'divided_space_time': + if isinstance(norm_layer, str): + self.temporal_norm1 = eval(norm_layer)(dim, epsilon=epsilon) + elif isinstance(norm_layer, Callable): + self.temporal_norm1 = norm_layer(dim, epsilon=epsilon) + else: + raise TypeError( + "The norm_layer must be str or paddle.nn.layer.Layer class") + self.temporal_attn = Attention(dim, + num_heads=num_heads, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + attn_drop=attn_drop, + proj_drop=drop, + wd_bias=wd_bias, + lr_mult=lr_mult) + self.temporal_fc = nn.Linear(dim, dim) + + # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here + self.drop_path = DropPath(drop_path) if drop_path > 0. else Identity() + if isinstance(norm_layer, str): + self.norm2 = eval(norm_layer)(dim, epsilon=epsilon) + elif isinstance(norm_layer, Callable): + self.norm2 = norm_layer(dim, epsilon=epsilon) + else: + raise TypeError( + "The norm_layer must be str or paddle.nn.layer.Layer class") + + mlp_hidden_dim = int(dim * mlp_ratio) + self.mlp = Mlp(in_features=dim, + hidden_features=mlp_hidden_dim, + act_layer=act_layer, + drop=drop, + wd_bias=wd_bias, + lr_mult=lr_mult) + + def forward(self, x, B, T, W): + num_spatial_tokens = (x.shape[1] - 1) // T + H = num_spatial_tokens // W + if self.attention_type in ['space_only', 'joint_space_time']: + x = paddle.add(x, self.drop_path(self.attn(self.norm1(x)))) + x = paddle.add(x, self.drop_path(self.mlp(self.norm2(x)))) + return x + elif self.attention_type == 'divided_space_time': + ########## Temporal ########## + xt = x[:, 1:, :] + _, _, _, _t, _m = B, H, W, T, xt.shape[-1] + xt = xt.reshape([-1, _t, _m]) + + res_temporal = self.drop_path( + self.temporal_attn(self.temporal_norm1(xt))) + + _, _h, _w, _t, _m = B, H, W, T, res_temporal.shape[-1] + res_temporal = res_temporal.reshape([-1, _h * _w * _t, _m]) + + res_temporal = self.temporal_fc(res_temporal) + xt = paddle.add(x[:, 1:, :], res_temporal) + + ########## Spatial ########## + init_cls_token = x[:, 0, :].unsqueeze(1) + cls_token = init_cls_token.tile((1, T, 1)) + _b, _t, _m = cls_token.shape + cls_token = cls_token.reshape([-1, _m]).unsqueeze(1) + + xs = xt + _, _h, _w, _t, _m = B, H, W, T, xs.shape[-1] + xs = xs.reshape([-1, _h, _w, _t, _m]).transpose( + (0, 3, 1, 2, 4)).reshape([-1, _h * _w, _m]) + xs = paddle.concat((cls_token, xs), axis=1) + res_spatial = self.drop_path(self.attn(self.norm1(xs))) + + # Taking care of CLS token + cls_token = res_spatial[:, 0, :] + _, _t, _m = B, T, cls_token.shape[-1] + cls_token = cls_token.reshape([-1, _t, _m]) + # averaging for every frame + cls_token = paddle.mean(cls_token, axis=1, keepdim=True) + + res_spatial = res_spatial[:, 1:, :] + _, _t, _h, _w, _m = B, T, H, W, res_spatial.shape[-1] + res_spatial = res_spatial.reshape([-1, _t, _h, _w, _m]).transpose( + (0, 2, 3, 1, 4)).reshape([-1, _h * _w * _t, _m]) + + res = res_spatial + x = xt + x = paddle.add(paddle.concat((init_cls_token, x), axis=1), + paddle.concat((cls_token, res), axis=1)) + # Mlp + x = paddle.add(x, self.drop_path(self.mlp(self.norm2(x)))) + return x + else: + raise NotImplementedError + + +class PatchEmbed(nn.Layer): + """ Image to Patch Embedding + """ + def __init__(self, + img_size=224, + patch_size=16, + in_channels=3, + embed_dim=768, + wd_bias=True, + lr_mult=1.0): + super().__init__() + img_size = to_2tuple(img_size) + patch_size = to_2tuple(patch_size) + num_patches = (img_size[1] // patch_size[1]) * (img_size[0] // + patch_size[0]) + self.img_size = img_size + self.patch_size = patch_size + self.num_patches = num_patches + + self.proj = nn.Conv2D(in_channels, + embed_dim, + kernel_size=patch_size, + stride=patch_size) + + def forward(self, x): + B, C, T, H, W = x.shape + + assert H == self.img_size[0] and W == self.img_size[1], \ + f"Input image size ({H}*{W}) doesn't match model ({self.img_size[0]}*{self.img_size[1]})." + x = x.transpose((0, 2, 1, 3, 4)) # [B,T,C,H,W] + x = x.reshape([-1, C, H, W]) # [BT,C,H,W] + x = self.proj(x) # [BT,F,nH,nW] + W = x.shape[-1] + x = x.flatten(2).transpose((0, 2, 1)) # [BT,F,nHnW] + return x, T, W + + +@BACKBONES.register() +class VisionTransformer_tweaks(nn.Layer): + """ Vision Transformer with support for patch input + """ + def __init__(self, + pretrained=None, + img_size=224, + patch_size=16, + in_channels=3, + embed_dim=768, + depth=12, + num_heads=12, + mlp_ratio=4, + qkv_bias=False, + qk_scale=None, + drop_rate=0., + attn_drop_rate=0., + drop_path_rate=0.1, + norm_layer='nn.LayerNorm', + epsilon=1e-5, + num_seg=8, + attention_type='divided_space_time', + wd_bias=True, + lr_mult_list=[1.0, 1.0, 1.0, 1.0, 1.0], + **args): + super().__init__() + self.pretrained = pretrained + self.num_seg = num_seg + self.attention_type = attention_type + self.lr_mult_list = lr_mult_list + self.num_features = self.embed_dim = embed_dim + + self.patch_embed = PatchEmbed(img_size=img_size, + patch_size=patch_size, + in_channels=in_channels, + embed_dim=embed_dim, + wd_bias=wd_bias, + lr_mult=self.lr_mult_list[0]) + num_patches = self.patch_embed.num_patches + + # Positional Embeddings + self.cls_token = self.create_parameter( + shape=(1, 1, embed_dim), + default_initializer=zeros_, + attr=ParamAttr(regularizer=L2Decay(0.0))) + self.pos_embed = self.create_parameter( + shape=(1, num_patches + 1, embed_dim), + default_initializer=zeros_, + attr=ParamAttr(regularizer=L2Decay(0.0))) + self.pos_drop = nn.Dropout(p=drop_rate) + + if self.attention_type != 'space_only': + self.time_embed = self.create_parameter( + shape=(1, num_seg, embed_dim), + default_initializer=zeros_, + attr=ParamAttr(regularizer=L2Decay(0.0))) + self.time_drop = nn.Dropout(p=drop_rate) + + self.add_parameter("pos_embed", self.pos_embed) + self.add_parameter("cls_token", self.cls_token) + + dpr = np.linspace(0, drop_path_rate, depth) + + self.blocks = nn.LayerList([ + Block(dim=embed_dim, + num_heads=num_heads, + mlp_ratio=mlp_ratio, + qkv_bias=qkv_bias, + qk_scale=qk_scale, + drop=drop_rate, + attn_drop=attn_drop_rate, + drop_path=dpr[i], + norm_layer=norm_layer, + epsilon=epsilon, + attention_type=self.attention_type, + wd_bias=wd_bias, + lr_mult=self.lr_mult_list[(i // 4) + 1]) for i in range(depth) + ]) + + self.norm = eval(norm_layer)(embed_dim, epsilon=epsilon) + + def init_weights(self): + """First init model's weight""" + trunc_normal_(self.pos_embed, std=0.02) + trunc_normal_(self.cls_token, std=0.02) + self.apply(self._init_fn) + + if self.attention_type == 'divided_space_time': + i = 0 + for m in self.blocks.sublayers(include_self=True): + m_str = str(m) + if 'Block' in m_str: + if i > 0: + zeros_(m.temporal_fc.weight) + zeros_(m.temporal_fc.bias) + i += 1 + """Second, if provide pretrained ckpt, load it""" + if isinstance( + self.pretrained, str + ) and self.pretrained.strip() != "": # load pretrained weights + load_ckpt(self, + self.pretrained, + num_patches=self.patch_embed.num_patches, + num_seg=self.num_seg, + attention_type=self.attention_type) + elif self.pretrained is None or self.pretrained.strip() == "": + pass + else: + raise NotImplementedError + + def _init_fn(self, m): + if isinstance(m, nn.Linear): + trunc_normal_(m.weight) + if m.bias is not None: + zeros_(m.bias) + elif isinstance(m, nn.LayerNorm): + ones_(m.weight) + zeros_(m.bias) + + def forward_features(self, x): + # B = x.shape[0] + B = paddle.shape(x)[0] + x, T, W = self.patch_embed(x) # [BT,nH*nW,F] + cls_tokens = self.cls_token.expand((B * T, -1, -1)) # [1,1,F]->[BT,1,F] + x = paddle.concat((cls_tokens, x), axis=1) + pos_interp = (x.shape[1] != self.pos_embed.shape[1]) + if pos_interp: + pos_embed = self.pos_embed + cls_pos_embed = pos_embed[0, 0, :].unsqueeze(0).unsqueeze(1) + other_pos_embed = pos_embed[0, 1:, :].unsqueeze(0).transpose( + (0, 2, 1)) + P = int(other_pos_embed.shape[2]**0.5) + H = x.shape[1] // W + other_pos_embed = other_pos_embed.reshape([1, x.shape[2], P, P]) + new_pos_embed = F.interpolate(other_pos_embed, + size=(H, W), + mode='nearest') + new_pos_embed = new_pos_embed.flatten(2) + new_pos_embed = new_pos_embed.transpose((0, 2, 1)) + new_pos_embed = paddle.concat((cls_pos_embed, new_pos_embed), + axis=1) + x = paddle.add(x, new_pos_embed) + else: + x = paddle.add(x, self.pos_embed) + + x = self.pos_drop(x) + + # Time Embeddings + if self.attention_type != 'space_only': + cls_tokens = x[:B, 0, :].unsqueeze(1) if B > 0 else x.split( + T)[0].index_select(paddle.to_tensor([0]), axis=1) + x = x[:, 1:] + _, _n, _m = x.shape + _t = T + x = x.reshape([-1, _t, _n, _m]).transpose( + (0, 2, 1, 3)).reshape([-1, _t, _m]) + # Resizing time embeddings in case they don't match + time_interp = (T != self.time_embed.shape[1]) + if time_interp: # T' != T + time_embed = self.time_embed.transpose((0, 2, 1)).unsqueeze(0) + new_time_embed = F.interpolate(time_embed, + size=(T, x.shape[-1]), + mode='nearest').squeeze(0) + new_time_embed = new_time_embed.transpose((0, 2, 1)) + x = paddle.add(x, new_time_embed) + else: + x = paddle.add(x, self.time_embed) + + x = self.time_drop(x) + _, _t, _m = x.shape + x = x.reshape([-1, W * W * T, _m]) + x = paddle.concat((cls_tokens, x), axis=1) + + # Attention blocks + for blk in self.blocks: + x = blk(x, B, T, W) + + # Predictions for space-only baseline + if self.attention_type == 'space_only': + _, _n, _m = x.shape + _t = T + x = x.reshape([-1, _t, _n, _m]) + x = paddle.mean(x, 1) # averaging predictions for every frame + + x = self.norm(x) + return x[:, 0] # [B, embed_dim] + + def forward(self, x): + x = self.forward_features(x) + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/backbones/yowo.py b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/yowo.py new file mode 100644 index 0000000..5e6b88d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/backbones/yowo.py @@ -0,0 +1,150 @@ +# Copyright (c) 2021 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. + +from ..registry import BACKBONES +from .darknet import Darknet +from .resnext101 import ResNext101 +import paddle.nn as nn +import paddle + + +class CAM_Module(nn.Layer): + def __init__(self, in_dim): + super(CAM_Module, self).__init__() + self.chanel_in = in_dim + temp = paddle.zeros([1], dtype='float32') + self.gamma = paddle.create_parameter(shape=temp.shape, dtype=str(temp.numpy().dtype), + default_initializer=paddle.nn.initializer.Assign(temp)) + self.softmax = nn.Softmax(axis=-1) + + def forward(self, x): + m_batchsize, C, height, width = x.shape + proj_query = paddle.reshape(x, [m_batchsize, C, -1]) + proj_key = paddle.transpose(paddle.reshape( + x, [m_batchsize, C, -1]), perm=[0, 2, 1]) + energy = paddle.bmm(proj_query, proj_key) + energy_new = paddle.expand_as(paddle.max( + energy, axis=-1, keepdim=True), energy) - energy + attention = self.softmax(energy_new) + proj_value = paddle.reshape(x, [m_batchsize, C, -1]) + + out = paddle.bmm(attention, proj_value) + out = out.reshape([m_batchsize, C, height, width]) + out = self.gamma * out + x + return out + + +class CFAMBlock(nn.Layer): + def __init__(self, in_channels, out_channels): + super(CFAMBlock, self).__init__() + inter_channels = 1024 + self.conv_bn_relu1 = nn.Sequential(nn.Conv2D(in_channels, inter_channels, kernel_size=1, bias_attr=False), + nn.BatchNorm2D(inter_channels), + nn.ReLU()) + self.conv_bn_relu2 = nn.Sequential(nn.Conv2D(inter_channels, inter_channels, 3, padding=1, bias_attr=False), + nn.BatchNorm2D(inter_channels), + nn.ReLU()) + + self.sc = CAM_Module(inter_channels) + + self.conv_bn_relu3 = nn.Sequential(nn.Conv2D(inter_channels, inter_channels, 3, padding=1, bias_attr=False), + nn.BatchNorm2D(inter_channels), + nn.ReLU()) + self.conv_out = nn.Sequential(nn.Dropout2D(0.1), nn.Conv2D( + inter_channels, out_channels, 1, bias_attr=True)) + + def forward(self, x): + x = self.conv_bn_relu1(x) + x = self.conv_bn_relu2(x) + x = self.sc(x) + x = self.conv_bn_relu3(x) + output = self.conv_out(x) + + return output + + +@BACKBONES.register() +class YOWO(nn.Layer): + def __init__(self, num_class, pretrained_2d=None, pretrained_3d=None): + super(YOWO, self).__init__() + + self.pretrained_2d = pretrained_2d + self.pretrained_3d = pretrained_3d + self.backbone_2d = Darknet() + self.backbone_3d = ResNext101() + self.num_ch_2d = 425 + self.num_ch_3d = 2048 + self.num_class = num_class + self.cfam = CFAMBlock(self.num_ch_2d + self.num_ch_3d, 1024) + self.conv_final = nn.Conv2D( + 1024, 5 * (self.num_class + 4 + 1), kernel_size=1, bias_attr=False) + self.seen = 0 + + def init_weights(self): + if self.pretrained_2d is not None: + self.backbone_2d = self.load_pretrain_weight( + self.backbone_2d, self.pretrained_2d) + if self.pretrained_3d is not None: + self.backbone_3d = self.load_pretrain_weight( + self.backbone_3d, self.pretrained_3d) + + def load_pretrain_weight(self, model, weights_path): + model_dict = model.state_dict() + + param_state_dict = paddle.load(weights_path) + ignore_weights = set() + + # hack: fit for faster rcnn. Pretrain weights contain prefix of 'backbone' + # while res5 module is located in bbox_head.head. Replace the prefix of + # res5 with 'bbox_head.head' to load pretrain weights correctly. + for k in list(param_state_dict.keys()): + if 'backbone.res5' in k: + new_k = k.replace('backbone', 'bbox_head.head') + if new_k in model_dict.keys(): + value = param_state_dict.pop(k) + param_state_dict[new_k] = value + + for name, weight in param_state_dict.items(): + if name in model_dict.keys(): + if list(weight.shape) != list(model_dict[name].shape): + print( + '{} not used, shape {} unmatched with {} in model.'.format( + name, weight.shape, list(model_dict[name].shape))) + ignore_weights.add(name) + else: + print('Redundant weight {} and ignore it.'.format(name)) + ignore_weights.add(name) + + for weight in ignore_weights: + param_state_dict.pop(weight, None) + + model.set_dict(param_state_dict) + print('Finish loading model weights: {}'.format(weights_path)) + return model + + def forward(self, input): + x_3d = input # Input clip + x_2d = input[:, :, -1, :, :] # Last frame of the clip that is read + + x_2d = self.backbone_2d(x_2d) + + x_3d = self.backbone_3d(x_3d) + + x_3d = paddle.squeeze(x_3d, axis=2) + + x = paddle.concat([x_3d, x_2d], axis=1) + x = self.cfam(x) + out = self.conv_final(x) + + return out diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/bbox_utils.py b/Bank_second_part/detect_process/paddlevideo/modeling/bbox_utils.py new file mode 100644 index 0000000..23b4555 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/bbox_utils.py @@ -0,0 +1,528 @@ +# Copyright (c) 2021 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 math +import paddle +import paddle.nn.functional as F +import math +import numpy as np + + +def bbox2delta(src_boxes, tgt_boxes, weights): + src_w = src_boxes[:, 2] - src_boxes[:, 0] + src_h = src_boxes[:, 3] - src_boxes[:, 1] + src_ctr_x = src_boxes[:, 0] + 0.5 * src_w + src_ctr_y = src_boxes[:, 1] + 0.5 * src_h + + tgt_w = tgt_boxes[:, 2] - tgt_boxes[:, 0] + tgt_h = tgt_boxes[:, 3] - tgt_boxes[:, 1] + tgt_ctr_x = tgt_boxes[:, 0] + 0.5 * tgt_w + tgt_ctr_y = tgt_boxes[:, 1] + 0.5 * tgt_h + + wx, wy, ww, wh = weights + dx = wx * (tgt_ctr_x - src_ctr_x) / src_w + dy = wy * (tgt_ctr_y - src_ctr_y) / src_h + dw = ww * paddle.log(tgt_w / src_w) + dh = wh * paddle.log(tgt_h / src_h) + + deltas = paddle.stack((dx, dy, dw, dh), axis=1) + return deltas + + +def delta2bbox(deltas, boxes, weights): + clip_scale = math.log(1000.0 / 16) + + widths = boxes[:, 2] - boxes[:, 0] + heights = boxes[:, 3] - boxes[:, 1] + ctr_x = boxes[:, 0] + 0.5 * widths + ctr_y = boxes[:, 1] + 0.5 * heights + + wx, wy, ww, wh = weights + dx = deltas[:, 0::4] / wx + dy = deltas[:, 1::4] / wy + dw = deltas[:, 2::4] / ww + dh = deltas[:, 3::4] / wh + # Prevent sending too large values into paddle.exp() + dw = paddle.clip(dw, max=clip_scale) + dh = paddle.clip(dh, max=clip_scale) + + pred_ctr_x = dx * widths.unsqueeze(1) + ctr_x.unsqueeze(1) + pred_ctr_y = dy * heights.unsqueeze(1) + ctr_y.unsqueeze(1) + pred_w = paddle.exp(dw) * widths.unsqueeze(1) + pred_h = paddle.exp(dh) * heights.unsqueeze(1) + + pred_boxes = [] + pred_boxes.append(pred_ctr_x - 0.5 * pred_w) + pred_boxes.append(pred_ctr_y - 0.5 * pred_h) + pred_boxes.append(pred_ctr_x + 0.5 * pred_w) + pred_boxes.append(pred_ctr_y + 0.5 * pred_h) + pred_boxes = paddle.stack(pred_boxes, axis=-1) + + return pred_boxes + + +def expand_bbox(bboxes, scale): + w_half = (bboxes[:, 2] - bboxes[:, 0]) * .5 + h_half = (bboxes[:, 3] - bboxes[:, 1]) * .5 + x_c = (bboxes[:, 2] + bboxes[:, 0]) * .5 + y_c = (bboxes[:, 3] + bboxes[:, 1]) * .5 + + w_half *= scale + h_half *= scale + + bboxes_exp = np.zeros(bboxes.shape, dtype=np.float32) + bboxes_exp[:, 0] = x_c - w_half + bboxes_exp[:, 2] = x_c + w_half + bboxes_exp[:, 1] = y_c - h_half + bboxes_exp[:, 3] = y_c + h_half + + return bboxes_exp + + +def clip_bbox(boxes, im_shape): + h, w = im_shape[0], im_shape[1] + x1 = boxes[:, 0].clip(0, w) + y1 = boxes[:, 1].clip(0, h) + x2 = boxes[:, 2].clip(0, w) + y2 = boxes[:, 3].clip(0, h) + return paddle.stack([x1, y1, x2, y2], axis=1) + + +def nonempty_bbox(boxes, min_size=0, return_mask=False): + w = boxes[:, 2] - boxes[:, 0] + h = boxes[:, 3] - boxes[:, 1] + mask = paddle.logical_and(w > min_size, w > min_size) + if return_mask: + return mask + keep = paddle.nonzero(mask).flatten() + return keep + + +def bbox_area(boxes): + return (boxes[:, 2] - boxes[:, 0]) * (boxes[:, 3] - boxes[:, 1]) + + +def bbox_overlaps(boxes1, boxes2): + """ + Calculate overlaps between boxes1 and boxes2 + + Args: + boxes1 (Tensor): boxes with shape [M, 4] + boxes2 (Tensor): boxes with shape [N, 4] + + Return: + overlaps (Tensor): overlaps between boxes1 and boxes2 with shape [M, N] + """ + area1 = bbox_area(boxes1) + area2 = bbox_area(boxes2) + + xy_max = paddle.minimum( + paddle.unsqueeze(boxes1, 1)[:, :, 2:], boxes2[:, 2:]) + xy_min = paddle.maximum( + paddle.unsqueeze(boxes1, 1)[:, :, :2], boxes2[:, :2]) + width_height = xy_max - xy_min + width_height = width_height.clip(min=0) + inter = width_height.prod(axis=2) + + overlaps = paddle.where(inter > 0, inter / + (paddle.unsqueeze(area1, 1) + area2 - inter), + paddle.zeros_like(inter)) + return overlaps + + +def xywh2xyxy(box): + x, y, w, h = box + x1 = x - w * 0.5 + y1 = y - h * 0.5 + x2 = x + w * 0.5 + y2 = y + h * 0.5 + return [x1, y1, x2, y2] + + +def make_grid(h, w, dtype): + yv, xv = paddle.meshgrid([paddle.arange(h), paddle.arange(w)]) + return paddle.stack((xv, yv), 2).cast(dtype=dtype) + + +def decode_yolo(box, anchor, downsample_ratio): + """decode yolo box + + Args: + box (list): [x, y, w, h], all have the shape [b, na, h, w, 1] + anchor (list): anchor with the shape [na, 2] + downsample_ratio (int): downsample ratio, default 32 + scale (float): scale, default 1. + + Return: + box (list): decoded box, [x, y, w, h], all have the shape [b, na, h, w, 1] + """ + x, y, w, h = box + na, grid_h, grid_w = x.shape[1:4] + grid = make_grid(grid_h, grid_w, x.dtype).reshape((1, 1, grid_h, grid_w, 2)) + x1 = (x + grid[:, :, :, :, 0:1]) / grid_w + y1 = (y + grid[:, :, :, :, 1:2]) / grid_h + + anchor = paddle.to_tensor(anchor) + anchor = paddle.cast(anchor, x.dtype) + anchor = anchor.reshape((1, na, 1, 1, 2)) + w1 = paddle.exp(w) * anchor[:, :, :, :, 0:1] / (downsample_ratio * grid_w) + h1 = paddle.exp(h) * anchor[:, :, :, :, 1:2] / (downsample_ratio * grid_h) + + return [x1, y1, w1, h1] + + +def iou_similarity(box1, box2, eps=1e-9): + """Calculate iou of box1 and box2 + + Args: + box1 (Tensor): box with the shape [N, M1, 4] + box2 (Tensor): box with the shape [N, M2, 4] + + Return: + iou (Tensor): iou between box1 and box2 with the shape [N, M1, M2] + """ + box1 = box1.unsqueeze(2) # [N, M1, 4] -> [N, M1, 1, 4] + box2 = box2.unsqueeze(1) # [N, M2, 4] -> [N, 1, M2, 4] + px1y1, px2y2 = box1[:, :, :, 0:2], box1[:, :, :, 2:4] + gx1y1, gx2y2 = box2[:, :, :, 0:2], box2[:, :, :, 2:4] + x1y1 = paddle.maximum(px1y1, gx1y1) + x2y2 = paddle.minimum(px2y2, gx2y2) + overlap = (x2y2 - x1y1).clip(0).prod(-1) + area1 = (px2y2 - px1y1).clip(0).prod(-1) + area2 = (gx2y2 - gx1y1).clip(0).prod(-1) + union = area1 + area2 - overlap + eps + return overlap / union + + +def bbox_iou(box1, box2, giou=False, diou=False, ciou=False, eps=1e-9): + """calculate the iou of box1 and box2 + + Args: + box1 (list): [x, y, w, h], all have the shape [b, na, h, w, 1] + box2 (list): [x, y, w, h], all have the shape [b, na, h, w, 1] + giou (bool): whether use giou or not, default False + diou (bool): whether use diou or not, default False + ciou (bool): whether use ciou or not, default False + eps (float): epsilon to avoid divide by zero + + Return: + iou (Tensor): iou of box1 and box1, with the shape [b, na, h, w, 1] + """ + px1, py1, px2, py2 = box1 + gx1, gy1, gx2, gy2 = box2 + x1 = paddle.maximum(px1, gx1) + y1 = paddle.maximum(py1, gy1) + x2 = paddle.minimum(px2, gx2) + y2 = paddle.minimum(py2, gy2) + + overlap = ((x2 - x1).clip(0)) * ((y2 - y1).clip(0)) + + area1 = (px2 - px1) * (py2 - py1) + area1 = area1.clip(0) + + area2 = (gx2 - gx1) * (gy2 - gy1) + area2 = area2.clip(0) + + union = area1 + area2 - overlap + eps + iou = overlap / union + + if giou or ciou or diou: + # convex w, h + cw = paddle.maximum(px2, gx2) - paddle.minimum(px1, gx1) + ch = paddle.maximum(py2, gy2) - paddle.minimum(py1, gy1) + if giou: + c_area = cw * ch + eps + return iou - (c_area - union) / c_area + else: + # convex diagonal squared + c2 = cw**2 + ch**2 + eps + # center distance + rho2 = ((px1 + px2 - gx1 - gx2)**2 + (py1 + py2 - gy1 - gy2)**2) / 4 + if diou: + return iou - rho2 / c2 + else: + w1, h1 = px2 - px1, py2 - py1 + eps + w2, h2 = gx2 - gx1, gy2 - gy1 + eps + delta = paddle.atan(w1 / h1) - paddle.atan(w2 / h2) + v = (4 / math.pi**2) * paddle.pow(delta, 2) + alpha = v / (1 + eps - iou + v) + alpha.stop_gradient = True + return iou - (rho2 / c2 + v * alpha) + else: + return iou + + +def rect2rbox(bboxes): + """ + :param bboxes: shape (n, 4) (xmin, ymin, xmax, ymax) + :return: dbboxes: shape (n, 5) (x_ctr, y_ctr, w, h, angle) + """ + bboxes = bboxes.reshape(-1, 4) + num_boxes = bboxes.shape[0] + + x_ctr = (bboxes[:, 2] + bboxes[:, 0]) / 2.0 + y_ctr = (bboxes[:, 3] + bboxes[:, 1]) / 2.0 + edges1 = np.abs(bboxes[:, 2] - bboxes[:, 0]) + edges2 = np.abs(bboxes[:, 3] - bboxes[:, 1]) + angles = np.zeros([num_boxes], dtype=bboxes.dtype) + + inds = edges1 < edges2 + + rboxes = np.stack((x_ctr, y_ctr, edges1, edges2, angles), axis=1) + rboxes[inds, 2] = edges2[inds] + rboxes[inds, 3] = edges1[inds] + rboxes[inds, 4] = np.pi / 2.0 + return rboxes + + +def delta2rbox(Rrois, + deltas, + means=[0, 0, 0, 0, 0], + stds=[1, 1, 1, 1, 1], + wh_ratio_clip=1e-6): + """ + :param Rrois: (cx, cy, w, h, theta) + :param deltas: (dx, dy, dw, dh, dtheta) + :param means: + :param stds: + :param wh_ratio_clip: + :return: + """ + means = paddle.to_tensor(means) + stds = paddle.to_tensor(stds) + deltas = paddle.reshape(deltas, [-1, deltas.shape[-1]]) + denorm_deltas = deltas * stds + means + + dx = denorm_deltas[:, 0] + dy = denorm_deltas[:, 1] + dw = denorm_deltas[:, 2] + dh = denorm_deltas[:, 3] + dangle = denorm_deltas[:, 4] + + max_ratio = np.abs(np.log(wh_ratio_clip)) + dw = paddle.clip(dw, min=-max_ratio, max=max_ratio) + dh = paddle.clip(dh, min=-max_ratio, max=max_ratio) + + Rroi_x = Rrois[:, 0] + Rroi_y = Rrois[:, 1] + Rroi_w = Rrois[:, 2] + Rroi_h = Rrois[:, 3] + Rroi_angle = Rrois[:, 4] + + gx = dx * Rroi_w * paddle.cos(Rroi_angle) - dy * Rroi_h * paddle.sin( + Rroi_angle) + Rroi_x + gy = dx * Rroi_w * paddle.sin(Rroi_angle) + dy * Rroi_h * paddle.cos( + Rroi_angle) + Rroi_y + gw = Rroi_w * dw.exp() + gh = Rroi_h * dh.exp() + ga = np.pi * dangle + Rroi_angle + ga = (ga + np.pi / 4) % np.pi - np.pi / 4 + ga = paddle.to_tensor(ga) + + gw = paddle.to_tensor(gw, dtype='float32') + gh = paddle.to_tensor(gh, dtype='float32') + bboxes = paddle.stack([gx, gy, gw, gh, ga], axis=-1) + return bboxes + + +def rbox2delta(proposals, gt, means=[0, 0, 0, 0, 0], stds=[1, 1, 1, 1, 1]): + """ + + Args: + proposals: + gt: + means: 1x5 + stds: 1x5 + + Returns: + + """ + proposals = proposals.astype(np.float64) + + PI = np.pi + + gt_widths = gt[..., 2] + gt_heights = gt[..., 3] + gt_angle = gt[..., 4] + + proposals_widths = proposals[..., 2] + proposals_heights = proposals[..., 3] + proposals_angle = proposals[..., 4] + + coord = gt[..., 0:2] - proposals[..., 0:2] + dx = (np.cos(proposals[..., 4]) * coord[..., 0] + np.sin(proposals[..., 4]) + * coord[..., 1]) / proposals_widths + dy = (-np.sin(proposals[..., 4]) * coord[..., 0] + np.cos(proposals[..., 4]) + * coord[..., 1]) / proposals_heights + dw = np.log(gt_widths / proposals_widths) + dh = np.log(gt_heights / proposals_heights) + da = (gt_angle - proposals_angle) + + da = (da + PI / 4) % PI - PI / 4 + da /= PI + + deltas = np.stack([dx, dy, dw, dh, da], axis=-1) + means = np.array(means, dtype=deltas.dtype) + stds = np.array(stds, dtype=deltas.dtype) + deltas = (deltas - means) / stds + deltas = deltas.astype(np.float32) + return deltas + + +def bbox_decode(bbox_preds, + anchors, + means=[0, 0, 0, 0, 0], + stds=[1, 1, 1, 1, 1]): + """decode bbox from deltas + Args: + bbox_preds: [N,H,W,5] + anchors: [H*W,5] + return: + bboxes: [N,H,W,5] + """ + means = paddle.to_tensor(means) + stds = paddle.to_tensor(stds) + num_imgs, H, W, _ = bbox_preds.shape + bboxes_list = [] + for img_id in range(num_imgs): + bbox_pred = bbox_preds[img_id] + # bbox_pred.shape=[5,H,W] + bbox_delta = bbox_pred + anchors = paddle.to_tensor(anchors) + bboxes = delta2rbox( + anchors, bbox_delta, means, stds, wh_ratio_clip=1e-6) + bboxes = paddle.reshape(bboxes, [H, W, 5]) + bboxes_list.append(bboxes) + return paddle.stack(bboxes_list, axis=0) + + +def poly_to_rbox(polys): + """ + poly:[x0,y0,x1,y1,x2,y2,x3,y3] + to + rotated_boxes:[x_ctr,y_ctr,w,h,angle] + """ + rotated_boxes = [] + for poly in polys: + poly = np.array(poly[:8], dtype=np.float32) + + pt1 = (poly[0], poly[1]) + pt2 = (poly[2], poly[3]) + pt3 = (poly[4], poly[5]) + pt4 = (poly[6], poly[7]) + + edge1 = np.sqrt((pt1[0] - pt2[0]) * (pt1[0] - pt2[0]) + (pt1[1] - pt2[ + 1]) * (pt1[1] - pt2[1])) + edge2 = np.sqrt((pt2[0] - pt3[0]) * (pt2[0] - pt3[0]) + (pt2[1] - pt3[ + 1]) * (pt2[1] - pt3[1])) + + width = max(edge1, edge2) + height = min(edge1, edge2) + + rbox_angle = 0 + if edge1 > edge2: + rbox_angle = np.arctan2( + np.float(pt2[1] - pt1[1]), np.float(pt2[0] - pt1[0])) + elif edge2 >= edge1: + rbox_angle = np.arctan2( + np.float(pt4[1] - pt1[1]), np.float(pt4[0] - pt1[0])) + + def norm_angle(angle, range=[-np.pi / 4, np.pi]): + return (angle - range[0]) % range[1] + range[0] + + rbox_angle = norm_angle(rbox_angle) + + x_ctr = np.float(pt1[0] + pt3[0]) / 2 + y_ctr = np.float(pt1[1] + pt3[1]) / 2 + rotated_box = np.array([x_ctr, y_ctr, width, height, rbox_angle]) + rotated_boxes.append(rotated_box) + ret_rotated_boxes = np.array(rotated_boxes) + assert ret_rotated_boxes.shape[1] == 5 + return ret_rotated_boxes + + +def cal_line_length(point1, point2): + import math + return math.sqrt( + math.pow(point1[0] - point2[0], 2) + math.pow(point1[1] - point2[1], 2)) + + +def get_best_begin_point_single(coordinate): + x1, y1, x2, y2, x3, y3, x4, y4 = coordinate + xmin = min(x1, x2, x3, x4) + ymin = min(y1, y2, y3, y4) + xmax = max(x1, x2, x3, x4) + ymax = max(y1, y2, y3, y4) + combinate = [[[x1, y1], [x2, y2], [x3, y3], [x4, y4]], + [[x4, y4], [x1, y1], [x2, y2], [x3, y3]], + [[x3, y3], [x4, y4], [x1, y1], [x2, y2]], + [[x2, y2], [x3, y3], [x4, y4], [x1, y1]]] + dst_coordinate = [[xmin, ymin], [xmax, ymin], [xmax, ymax], [xmin, ymax]] + force = 100000000.0 + force_flag = 0 + for i in range(4): + temp_force = cal_line_length(combinate[i][0], dst_coordinate[0]) \ + + cal_line_length(combinate[i][1], dst_coordinate[1]) \ + + cal_line_length(combinate[i][2], dst_coordinate[2]) \ + + cal_line_length(combinate[i][3], dst_coordinate[3]) + if temp_force < force: + force = temp_force + force_flag = i + if force_flag != 0: + pass + return np.array(combinate[force_flag]).reshape(8) + + +def rbox2poly_single(rrect): + """ + rrect:[x_ctr,y_ctr,w,h,angle] + to + poly:[x0,y0,x1,y1,x2,y2,x3,y3] + """ + x_ctr, y_ctr, width, height, angle = rrect[:5] + tl_x, tl_y, br_x, br_y = -width / 2, -height / 2, width / 2, height / 2 + # rect 2x4 + rect = np.array([[tl_x, br_x, br_x, tl_x], [tl_y, tl_y, br_y, br_y]]) + R = np.array([[np.cos(angle), -np.sin(angle)], + [np.sin(angle), np.cos(angle)]]) + # poly + poly = R.dot(rect) + x0, x1, x2, x3 = poly[0, :4] + x_ctr + y0, y1, y2, y3 = poly[1, :4] + y_ctr + poly = np.array([x0, y0, x1, y1, x2, y2, x3, y3], dtype=np.float32) + poly = get_best_begin_point_single(poly) + return poly + + +def rbox2poly(rrects): + """ + rrect:[x_ctr,y_ctr,w,h,angle] + to + poly:[x0,y0,x1,y1,x2,y2,x3,y3] + """ + polys = [] + for rrect in rrects: + x_ctr, y_ctr, width, height, angle = rrect[:5] + tl_x, tl_y, br_x, br_y = -width / 2, -height / 2, width / 2, height / 2 + rect = np.array([[tl_x, br_x, br_x, tl_x], [tl_y, tl_y, br_y, br_y]]) + R = np.array([[np.cos(angle), -np.sin(angle)], + [np.sin(angle), np.cos(angle)]]) + poly = R.dot(rect) + x0, x1, x2, x3 = poly[0, :4] + x_ctr + y0, y1, y2, y3 = poly[1, :4] + y_ctr + poly = np.array([x0, y0, x1, y1, x2, y2, x3, y3], dtype=np.float32) + poly = get_best_begin_point_single(poly) + polys.append(poly) + polys = np.array(polys) + return polys diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/builder.py b/Bank_second_part/detect_process/paddlevideo/modeling/builder.py new file mode 100644 index 0000000..71503eb --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/builder.py @@ -0,0 +1,127 @@ +# 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. + +from .registry import BACKBONES, HEADS, LOSSES, RECOGNIZERS, LOCALIZERS, ROI_EXTRACTORS, DETECTORS, BBOX_ASSIGNERS, BBOX_SAMPLERS, BBOX_CODERS, PARTITIONERS, MULTIMODAL, SEGMENT, SEGMENTERS +from ..utils import build +from .registry import (BACKBONES, BBOX_ASSIGNERS, BBOX_CODERS, BBOX_SAMPLERS, + DETECTORS, ESTIMATORS, HEADS, LOCALIZERS, LOSSES, + MULTIMODAL, PARTITIONERS, RECOGNIZERS, ROI_EXTRACTORS) + + +def build_backbone(cfg): + """Build backbone.""" + return build(cfg, BACKBONES) + + +def build_roi_extractor(cfg): + """Build roi extractor.""" + return build(cfg, ROI_EXTRACTORS) + + +def build_assigner(cfg, **default_args): + """Builder of box assigner.""" + return build(cfg, BBOX_ASSIGNERS) + + +def build_sampler(cfg, **default_args): + """Builder of box sampler.""" + return build(cfg, BBOX_SAMPLERS) + + +def build_roi_extractor(cfg): + """Build roi extractor.""" + return build(cfg, ROI_EXTRACTORS) + + +def build_assigner(cfg, **default_args): + """Builder of box assigner.""" + return build(cfg, BBOX_ASSIGNERS) + + +def build_sampler(cfg, **default_args): + """Builder of box sampler.""" + return build(cfg, BBOX_SAMPLERS) + + +def build_head(cfg): + """Build head.""" + return build(cfg, HEADS) + + +def build_loss(cfg): + """Build loss.""" + return build(cfg, LOSSES) + + +def build_recognizer(cfg): + """Build recognizer.""" + return build(cfg, RECOGNIZERS, key='framework') + + +def build_segmenter(cfg): + """Build segmenter.""" + return build(cfg, SEGMENTERS, key='framework') + + +def build_localizer(cfg): + """Build localizer.""" + return build(cfg, LOCALIZERS, key='framework') + + +def build_detector(cfg, train_cfg=None, test_cfg=None): + """Build detector.""" + return build(cfg, DETECTORS, key='framework') + + +def build_partitioner(cfg): + """Build partitioner.""" + return build(cfg, PARTITIONERS, key='framework') + + +def build_estimator(cfg): + """Build estimator.""" + return build(cfg, ESTIMATORS, key='framework') + + +def build_multimodal(cfg): + """Build multimodal.""" + return build(cfg, MULTIMODAL, key='framework') + + +def build_segment(cfg): + """Build segment.""" + return build(cfg, SEGMENT, key='framework') + + +def build_model(cfg): + cfg_copy = cfg.copy() + framework_type = cfg_copy.get('framework') + if framework_type in RECOGNIZERS: + return build_recognizer(cfg) + elif framework_type in LOCALIZERS: + return build_localizer(cfg) + elif framework_type in PARTITIONERS: + return build_partitioner(cfg) + elif framework_type in DETECTORS: + return build_detector(cfg) + elif framework_type in ESTIMATORS: + return build_estimator(cfg) + elif framework_type in MULTIMODAL: + return build_multimodal(cfg) + elif framework_type in SEGMENTERS: + return build_segmenter(cfg) + elif framework_type in SEGMENT: + return build_segment(cfg) + else: + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/__init__.py new file mode 100644 index 0000000..d68fe09 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/__init__.py @@ -0,0 +1,28 @@ +# 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. + +from .estimators import BaseEstimator, DepthEstimator +from .localizers import BaseLocalizer, BMNLocalizer +from .partitioners import BasePartitioner, TransNetV2Partitioner +from .recognizers import BaseRecognizer, Recognizer2D +from .multimodal import ActBert, BaseMultimodal +from .segment import BaseSegment, CFBI +from .segmenters import MSTCN + +__all__ = [ + 'BaseRecognizer', 'Recognizer2D', 'BaseLocalizer', 'BMNLocalizer', + 'BasePartitioner', 'TransNetV2Partitioner', 'BaseEstimator', + 'DepthEstimator', 'BaseMultimodal', 'ActBert', 'BaseSegment', 'CFBI', + 'MSTCN' +] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4d7bf2b2aad9b9dd5ec9478ae697218523f0f818 GIT binary patch literal 722 zcmYjP%Wl*#6ty$SB$HQDhJHjg2+a~91ZhF4#EcMAv9KaV*2Ep6+DT-)yncbdKw{Cq zVeM^K{RLL|Cd{Oca^&NCuJ5@w>5?QwcKz{w*1uhZ?twgBjwP?{tG-#NQH?ngm|)=$ z2LpHbOt{1q9`Ob~<8$E?Uj!r=xXTwJB%z2%G;oi{A|Z)LNjmU3KM@(p#3?x)xX+)6 zC0Sy$M|JQElc)7!i}LUR+w!?%l7cGsR_R7i-AR*PuwH*Y@`K=gx1+rI!K8_c_2$TI z_yqDlP^lZ;bgdPfT}j%i4bz`ikB+S}1?5M!>-Oz<)3je**tq{@rwb#3_L zx1k79w`?z1tBrg9uDHyx@z&d`^G%+}z;+@R0CwI;dH{0(9{}bpX8;iZd>k1ABmk*} zO@3xVb{K)0GDye|eXHqi68BTPYN|vcd2CKirc5Y~t&G*dhw;_e&g6xJ|BskdgD>M( z73I9D?vPx9S%AN5_M$9kdsAIEoT+j9d{y?c+cBkv)3T>^&DocxW?gA#$avH4%WFvm m``XEyvZ|W4(N*=V|89bpR&dMNEBGH&W+6*6e0X9UJO2PdMZS3e literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__init__.py new file mode 100644 index 0000000..74dcac0 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__init__.py @@ -0,0 +1,17 @@ +# 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. + +from .base import BaseDetector +from .fast_rcnn import FastRCNN +from .two_stage import TwoStageDetector + +__all__ = ['BaseDetector', 'TwoStageDetector', 'FastRCNN'] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bdf6421175ea094ac27fed445e1bde26ed9563d9 GIT binary patch literal 349 zcmYjM%SyyB6ixb==|~6sjc#OcDIzk8%Pt&22!Rlr+fpWNN)j!8ga6>doqyxHTUY*q ztGTIy-jKt&=jNOwX1zWlSRd(&dW{JA49)*Sja=e(8w5oZ)uf}0(!e7fbuo))9_yq_ zSxQMmRPsjILZv%WEWRk(3OeOm>EIeXRNh$Zvm5FB?NwPKKfW8y&dcU+9@}uOO#;LS zWwD%+2TYiCwyM!AY}NPkl&$<|gbN9?Wm*a$wHD%?*ky! zU`++i%_<+HQW~CG1%`JN@W0m9^4F#rGn literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__pycache__/base.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b61c7f1a0e2dda569e151de232311d1a3ba3d9bf GIT binary patch literal 1956 zcmah~OK%%D5GMDbU9BZMwVgVy+hY3)po?4dSQJH(#3+IWDo`6eECjHtB_(aV50zZS zwcuWA139!m!an-n^vr8dIp@|>XSgdzQW2B}soCL>^L;bJaoOz#1jb+PAN)_3kiYR` zd4P_53sd!B;e^wSaiFY+i6-nD;2z9YQFy(_{! z;XZF)+Lts6xN}T;{wuhX^r+s9hpLisQsttWl>C)ltG(eY&A5<#Flj$IIyriL^23kE z2_9M=PV=FD20@UBauQjbMmFDmNk)|0+_`E;4tII$ibO8=xDUTAzQY5)aYZ9f_`Jir zR|J5yLEhwBMh-x}$KNsX#!KRmr~{yPb>~s6#1m18q$=h70KdW{iRwdP6XPa5L@qEbXeY?Nj~)#4Xl4yLk9gi=O3n8uuE;zi0uImk;cva}cv zMl#ODSt(BkcgP1rpmaDrmp*`OBU*&LY0d91Ge2BFOepLw2Fhst7^Zpv%LRGfkOawU z=u)6-%^yAmifNpsa}ib(5gJTkAu5Cuo{4lksUVE~o-MIRb;pFH(aQ}`^{7OA5~Eo! zTPWRwr3+JGX$00Lo$s$8U%qE0MQD%dG3fEq3vx{^=nehNzOXSx^M^;jno12vBCcjq zC_paD*?1Dh;UYtjc>soxdyc`UoiraS?WdKHteEB6Yfi5L*IS~#oi+R0a7RPJq4W1w zNUWJ^H!Vg&uFyd$cXXa19e5X~mTWI*9izqq%{FK#5;YndGzXxu?lcZ)J_U_kYbxh= z+H?Ebg;=D8c3(gexppc6&-gy_c6DI3n5x87`>zG>|@VJWEFs_n`cCbX&gXY1rJBuaX18ap5^Jzerr(?}`S3=huNU%^B1LK6n z`#sFpSO*mWj�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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/base.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/base.py new file mode 100644 index 0000000..4d5ccb8 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/base.py @@ -0,0 +1,51 @@ +from abc import abstractmethod +from ... import builder +import paddle.nn as nn +from ...registry import DETECTORS + +@DETECTORS.register() +class BaseDetector(nn.Layer): + """Base class for detectors. """ + def __init__(self, backbone=None, head=None): + + super().__init__() + + def init_weights(self): + """Initialize the model network weights. """ + self.backbone.init_weights() + self.head.init_weights() + + def extract_feature(self, imgs, iter_num): + """Extract features through a backbone. """ + feature = self.backbone(imgs) + return feature + + def forward(self, data_batch, mode='infer'): + if mode == 'train': + return self.train_step(data_batch) + elif mode == 'valid': + return self.val_step(data_batch) + elif mode == 'test': + return self.test_step(data_batch) + elif mode == 'infer': + return self.infer_step(data_batch) + else: + raise NotImplementedError + + @abstractmethod + def train_step(self, data_batch, **kwargs): + """Training step. + """ + raise NotImplementedError + + @abstractmethod + def val_step(self, data_batch, **kwargs): + """Validating step. + """ + raise NotImplementedError + + @abstractmethod + def test_step(self, data_batch, **kwargs): + """Test step. + """ + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/fast_rcnn.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/fast_rcnn.py new file mode 100644 index 0000000..e8f912d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/fast_rcnn.py @@ -0,0 +1,34 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + +from .two_stage import TwoStageDetector +from ...registry import DETECTORS + +@DETECTORS.register() +class FastRCNN(TwoStageDetector): + + def __init__(self, + backbone, + head=None, + train_cfg=None, + test_cfg=None, + neck=None, + pretrained=None): + super(FastRCNN, self).__init__( + backbone=backbone, + neck=neck, + roi_head=head, + train_cfg=train_cfg, + test_cfg=test_cfg, + pretrained=pretrained) diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/two_stage.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/two_stage.py new file mode 100644 index 0000000..f9deb1d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/detectors/two_stage.py @@ -0,0 +1,186 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 paddle +import paddle.nn as nn +from ... import builder +import paddle.distributed as dist +from ...registry import DETECTORS +from .base import BaseDetector + + +@DETECTORS.register() +class TwoStageDetector(BaseDetector): + """Base class for two-stage detectors. """ + + def __init__(self, + backbone, + neck=None, + rpn_head=None, + roi_head=None, + train_cfg=None, + test_cfg=None, + pretrained=None): + super(TwoStageDetector, self).__init__() + self.backbone = builder.build_backbone(backbone) + + if neck is not None: + self.neck = neck # useless + + if rpn_head is not None: + rpn_train_cfg = train_cfg.rpn if train_cfg is not None else None + rpn_head_ = rpn_head.copy() + rpn_head_.update(train_cfg=rpn_train_cfg, test_cfg=test_cfg.rpn) + self.rpn_head = builder.build_head(rpn_head_) + + if roi_head is not None: + self.roi_head = builder.build_head(roi_head) + + self.train_cfg = train_cfg + self.test_cfg = test_cfg + + if pretrained is not None: + self.init_weights(pretrained=pretrained) + + @property + def with_rpn(self): + """whether the detector has RPN""" + return hasattr(self, 'rpn_head') and self.rpn_head is not None + + @property + def with_roi_head(self): + """whether the detector has a RoI head""" + return hasattr(self, 'roi_head') and self.roi_head is not None + + def init_weights(self, pretrained=None): + """Initialize the weights in detector. """ + super(TwoStageDetector, self).init_weights(pretrained) + self.backbone.init_weights(pretrained=pretrained) + if self.with_rpn: + self.rpn_head.init_weights() + if self.with_roi_head: + self.roi_head.init_weights(pretrained) + + def extract_feat(self, img): + """Directly extract features from the backbone.""" + x = self.backbone(img) + return x + + def train_step(self, data, **kwargs): + img_slow = data[0] + img_fast = data[1] + proposals, gt_bboxes, gt_labels, scores, entity_ids = self.get_unpad_datas( + data) + img_shape = data[7] + img_idx = data[8] + img_metas = scores, entity_ids + x = self.extract_feat(img=[img_slow, img_fast]) + roi_losses = self.roi_head.train_step(x, img_metas, proposals, + gt_bboxes, gt_labels, **kwargs) + losses = dict() + losses.update(roi_losses) + + return losses + + def val_step(self, data, rescale=False): + img_slow = data[0] + img_fast = data[1] + proposals, gt_bboxes, gt_labels, scores, entity_ids = self.get_unpad_datas( + data) + img_shape = data[7] + img_metas = scores, entity_ids + x = self.extract_feat(img=[img_slow, img_fast]) + + return self.roi_head.simple_test(x, + proposals[0], + img_shape, + rescale=rescale) + + def test_step(self, data, rescale=False): + return self.val_step(data, rescale) + + def infer_step(self, data, rescale=False): + ''' model inference''' + + img_slow = data[0] + img_fast = data[1] + proposals = data[2] + img_shape = data[3] + + # using slowfast model to extract spatio-temporal features + x = self.extract_feat(img=[img_slow, img_fast]) + + ret = self.roi_head.simple_test(x, + proposals[0], + img_shape, + rescale=rescale) + return ret + + def get_unpad_datas(self, data): + ''' get original datas padded in dataset ''' + pad_proposals = data[2] + pad_gt_bboxes = data[3] + pad_gt_labels = data[4] + pad_scores, pad_entity_ids = data[5], data[6] + len_proposals = data[9] + len_gt_bboxes = data[10] + len_gt_labels = data[11] + len_scores = data[12] + len_entity_ids = data[13] + N = pad_proposals.shape[0] + proposals = [] + gt_bboxes = [] + gt_labels = [] + scores = [] + entity_ids = [] + for bi in range(N): + pad_proposal = pad_proposals[bi] + len_proposal = len_proposals[bi] + index_proposal = paddle.arange(len_proposal) + proposal = paddle.index_select(x=pad_proposal, + index=index_proposal, + axis=0) + proposals.append(proposal) + + pad_gt_bbox = pad_gt_bboxes[bi] + len_gt_bbox = len_gt_bboxes[bi] + index_gt_bbox = paddle.arange(len_gt_bbox) + gt_bbox = paddle.index_select(x=pad_gt_bbox, + index=index_gt_bbox, + axis=0) + gt_bboxes.append(gt_bbox) + + pad_gt_label = pad_gt_labels[bi] + len_gt_label = len_gt_labels[bi] + index_gt_label = paddle.arange(len_gt_label) + gt_label = paddle.index_select(x=pad_gt_label, + index=index_gt_label, + axis=0) + gt_labels.append(gt_label) + + pad_score = pad_scores[bi] + len_score = len_scores[bi] + index_score = paddle.arange(len_score) + score = paddle.index_select(x=pad_score, index=index_score, axis=0) + scores.append(score) + + pad_entity_id = pad_entity_ids[bi] + len_entity_id = len_entity_ids[bi] + index_entity_id = paddle.arange(len_entity_id) + entity_id = paddle.index_select(x=pad_entity_id, + index=index_entity_id, + axis=0) + entity_ids.append(entity_id) + + return proposals, gt_bboxes, gt_labels, scores, entity_ids diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/__init__.py new file mode 100644 index 0000000..e2bda93 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/__init__.py @@ -0,0 +1,4 @@ +from .base import BaseEstimator +from .depth_estimator import DepthEstimator + +__all__ = ['DepthEstimator', 'BaseEstimator'] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72d1ff9735c0c5abe02084d23bc03e3adce8fd42 GIT binary patch literal 306 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 W^9}k+BSAk5A;rOu`OI_f(*FP}FwTAe literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/base.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/base.py new file mode 100644 index 0000000..cdddd67 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/base.py @@ -0,0 +1,82 @@ +# 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. + +from abc import abstractmethod + +import paddle +import paddle.nn as nn +from paddlevideo.modeling.registry import ESTIMATORS +from paddlevideo.utils import get_logger + +from ... import builder + +logger = get_logger("paddlevideo") + + +@ESTIMATORS.register() +class BaseEstimator(nn.Layer): + """BaseEstimator + + """ + def __init__(self, backbone=None, head=None): + super().__init__() + if backbone is not None: + self.backbone = builder.build_backbone(backbone) + if hasattr(self.backbone, 'init_weights'): + self.backbone.init_weights() + else: + self.backbone = None + + if head is not None: + self.head_name = head.name + self.head = builder.build_head(head) + if hasattr(self.head, 'init_weights'): + self.head.init_weights() + else: + self.head = None + + def forward(self, data_batch, mode='infer'): + """ + 1. Define how the model is going to run, from input to output. + 2. Console of train, valid, test or infer step + """ + if mode == 'train': + return self.train_step(data_batch) + elif mode == 'valid': + return self.val_step(data_batch) + elif mode == 'test': + return self.test_step(data_batch) + elif mode == 'infer': + return self.infer_step(data_batch) + else: + raise NotImplementedError + + @abstractmethod + def train_step(self, data_batch): + """Define how the model is going to train, from input to output. + """ + raise NotImplementedError + + @abstractmethod + def val_step(self, data_batch): + """Define how the model is going to valid, from input to output.""" + raise NotImplementedError + + @abstractmethod + def test_step(self, data_batch): + """Define how the model is going to test, from input to output.""" + raise NotImplementedError + + @abstractmethod + def infer_step(self, data_batch): + """Define how the model is going to infer, from input to output.""" + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/depth_estimator.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/depth_estimator.py new file mode 100644 index 0000000..13ee877 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/estimators/depth_estimator.py @@ -0,0 +1,59 @@ +# 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. + +import paddle +from paddlevideo.modeling.framework.estimators.base import BaseEstimator +from paddlevideo.modeling.registry import ESTIMATORS +from paddlevideo.utils import get_logger + +from ... import builder + +logger = get_logger("paddlevideo") + + +@ESTIMATORS.register() +class DepthEstimator(BaseEstimator): + """DepthEstimator + """ + def forward_net(self, inputs, day_or_night='day_and_night'): + if self.backbone is not None: + outputs = self.backbone(inputs, day_or_night) + else: + outputs = inputs + return outputs + + def train_step(self, data_batch): + """Define how the model is going to train, from input to output. + """ + inputs, _ = data_batch + outputs = self.forward_net(inputs, day_or_night='day_and_night') + loss_metrics = self.head.loss(inputs, outputs) + return loss_metrics + + def val_step(self, data_batch): + inputs, day_or_night = data_batch + outputs = self.forward_net(inputs, day_or_night=day_or_night) + loss_metrics = self.head.loss(inputs, outputs) + return loss_metrics + + def test_step(self, data_batch): + """Define how the model is going to test, from input to output.""" + inputs, day_or_night = data_batch + outputs = self.forward_net(inputs, day_or_night=day_or_night) + loss_metrics = self.head.loss(inputs, outputs) + return loss_metrics + + def infer_step(self, data_batch): + """Define how the model is going to infer, from input to output.""" + inputs = data_batch[0] + outputs = self.forward_net(inputs, day_or_night='day') + return outputs diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__init__.py new file mode 100644 index 0000000..323a72c --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__init__.py @@ -0,0 +1,19 @@ +# 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. + +from .base import BaseLocalizer +from .bmn_localizer import BMNLocalizer +from .yowo_localizer import YOWOLocalizer + +__all__ = ['BaseLocalizer', 'BMNLocalizer', 'YOWOLocalizer'] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4e79cd8c1fdbf4614881667ee9095da7ac1c626d GIT binary patch literal 361 zcmYjMyG{c!5VY@+i_l#P{^A-GQ6hxU)sPevfMv;YVkfe)KA&tL3ctW#(D66a*HZBd zRICpHx0XjUqup8CRn-x}de2|faZ1QX6yr)zT;dIL1Vt1DVkx6E@&po_vUK1nWHx6x zC0nAhSIQK&aU%9me^Q=7@Wplk4>*{`ayZkp&9~XOk5%C$qqAvPu zg&Bj-s+Da8{KgG!Y<6&aH!|Z`UkD)qgm@#qh*=T7?(`XNWV;g^13LWB`6=(bTk8-8 zmv>Sr&`(Bb$E{NuOuOY9FRk7?zvF+q0~f-y=0S*)?$A%qvG)=5Mf`S{B9ya|;z_;% D8aQ8| literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/base.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7e5ceff18f8c2f67a8d07ab8ee4a09dff909eeb GIT binary patch literal 2406 zcma)7&2Jk;6rb4-f5i@M3TdGTh7VC$at)LN5J6R1psEPDBJW@ela zD<=}E2mXolnE!_JT#=A^?u`@g&Dt9$q=Jd&<@vq&_|5NqtZcO!1jZlX@BB;9{=^@P zBY+Y(OleDWZ zVLxe8yBrU+QE_5M!t6@E@zO8s)xjjqxKIhMTO8=ep`U^fq(?dFd7SqA=VVB^$NiI9 zFW>USA{(kY9HW*%oKahkA{VGAIwOB?iM9U2INytgX(n``es-@v zRx%M`@SfeU3sv;L#o-1gorUCnVRGsHdJ!N(tJEIXp$2HT2TXd%)Ksq zBy%k@!Q`;0k`8mV)L}0Dp(D6wx;iLt|Dww_g<(kjw|AWX4uhK~T5#7ybi9ukoJZt| za4WM8Qvw)697f7ae=2?*OJyP#K}e+XcpJKUwV^{|14N>30G;j7HqJ}g*1+#7*VfA- zwheb{VZN~;&6CkM6C;ru!GBOnsr1EdIdzS z(x5eZJ_B$1*2Vmo?MOUWJs+48nCCyie1!#W2*i?3zuLl{gfzKc$BH0D=cw4-`_Olx zEa4NP(xhbPjH=sk%vtdcg_UP3dw_IDUwVSN2|oOyy+S}iFuipV?m3mOMXcV3oq+c1 zr`USotAKcg8F&9TT*cr7^#O`Y1$PT<577P*h|B$A9@_sz_IOJeJ;MZ<1=Y^tBmsCu z0wbSSgDq;Ir1kYU-v)R;mN;)-;&A@;fUe?Fw2A#Zhjtl7wh>`+Pcqb-QS{3s&Ssu! z6mgkA%g5&FT90}UH4Kysn?iOJUTs^m7M_SKgB|BAF5?o{yF$?3gsE3S)JQ;^Rmj$= zcfCQq5a$Y2xCTBtemqFrHMU-~`fi?E4<;!-KjC_OD3n{haFx3hud=moiYML2q;@U8 Kxr{A;)&BRD9CbRCyY8D!Jc;6 zXmaY__$S(9{~OM}a_X5I7kF=`Nt4y$k)Pk2_s0Ic-+SY-+l>i~KZ8HiJ}2ZaG}cD| z#&ekV0E8lnW+bNrN{R9m%e zutlG``1r@8Z;xLLzWeFrEp1eOP^10~ORv5RiT&1A*Mp+PkJhwg?x|f`jeVVI9@HX0=}j z*WqHTVpo2>1^mWUa7h-OI<7k^JRo%k*pB8qr$(j)WZkosp53!-ux$-i>K4mqu+2`L zpOx13L)W!cITKSORjP~1bTQ&R5H4&9b$+g8;e3^jtA1iIO&2R!NimYu_*WPHF3@uE zv=V7~E^;|@9CTYrQ@Ic{T__h}ImIYdhaWYFoXl2X1In-kWd@={D?Yc2RtU;$sx}%dHWzBE)a!GQ0CcLa1^qMBDpVOS6aKa}-~oxF@91 zuni5;@Case^Ks&P+~XnN=0OrQzJBDm(bLpc=C#3+JAVZCy1}c(ypQ&sTbm~SU57Y+ U&|-du|E$HPOp=6hFJzDDfAD&Y-~a#s literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/yowo_localizer.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/__pycache__/yowo_localizer.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f3c15dbf8287fcf138c4c98e17e19ef486e78b82 GIT binary patch literal 3358 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 loss_metric + """ + raise NotImplementedError + + @abstractmethod + def val_step(self, data_batch, **kwargs): + """Validating setp. input_data_batch -> loss_metric + """ + raise NotImplementedError + + @abstractmethod + def test_step(self, data_batch, **kwargs): + """Tets setp. to get acc in test data. input_data_batch -> output + """ + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/bmn_localizer.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/bmn_localizer.py new file mode 100644 index 0000000..5afbd3a --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/bmn_localizer.py @@ -0,0 +1,69 @@ +# 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. + +from ...registry import LOCALIZERS +from .base import BaseLocalizer + +import paddle + + +@LOCALIZERS.register() +class BMNLocalizer(BaseLocalizer): + """BMN Localization framework + """ + def forward_net(self, imgs): + """Call backbone forward. + """ + preds = self.backbone(imgs) + return preds + + def train_step(self, data_batch): + """Training step. + """ + x_data = data_batch[0] + gt_iou_map = data_batch[1] + gt_start = data_batch[2] + gt_end = data_batch[3] + gt_iou_map.stop_gradient = True + gt_start.stop_gradient = True + gt_end.stop_gradient = True + + # call Model forward + pred_bm, pred_start, pred_end = self.forward_net(x_data) + # call Loss forward + loss = self.loss(pred_bm, pred_start, pred_end, gt_iou_map, gt_start, + gt_end) + avg_loss = paddle.mean(loss) + loss_metrics = dict() + loss_metrics['loss'] = avg_loss + return loss_metrics + + def val_step(self, data_batch): + """Validating setp. + """ + return self.train_step(data_batch) + + def test_step(self, data_batch): + """Test step. + """ + x_data = data_batch[0] + pred_bm, pred_start, pred_end = self.forward_net(x_data) + return pred_bm, pred_start, pred_end + + def infer_step(self, data_batch): + """Infer step + """ + x_data = data_batch[0] + + # call Model forward + pred_bm, pred_start, pred_end = self.forward_net(x_data) + return pred_bm, pred_start, pred_end diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/yowo_localizer.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/yowo_localizer.py new file mode 100644 index 0000000..c3613c6 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/yowo_localizer.py @@ -0,0 +1,161 @@ +# 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. + +from ...registry import LOCALIZERS +from .base import BaseLocalizer +from .yowo_utils import truths_length, nms, get_region_boxes, bbox_iou + + +@LOCALIZERS.register() +class YOWOLocalizer(BaseLocalizer): + """YOWO Localization framework + """ + + def forward_net(self, imgs): + """Call backbone forward. + """ + # imgs.shape=[N,C,T,H,W], for YOWO + preds = self.backbone(imgs) + return preds + + def train_step(self, data_batch): + """Training step. + """ + x_data = data_batch[0] + target = data_batch[1].squeeze(1) # indeed do squeeze to adapt to paddle tensor + target.stop_gradient = True + + # call Model forward + out = self.forward_net(x_data) + # call Loss forward + loss, nCorrect = self.loss(out, target) + loss_metrics = dict() + loss_metrics['loss'] = loss + loss_metrics['nCorrect'] = nCorrect + return loss_metrics + + def val_step(self, data_batch): + """Validating setp. + """ + total = 0.0 + proposals = 0.0 + correct = 0.0 + fscore = 0.0 + eps = 1e-5 + nms_thresh = 0.4 + iou_thresh = 0.5 + + x_data = data_batch[0] + target = data_batch[1].squeeze(1) # indeed do squeeze to adapt to paddle tensor + frame_idx = data_batch[2] + target.stop_gradient = True + # call Model forward + out = self.forward_net(x_data) + all_boxes = get_region_boxes(out) + out_boxes = [] + + for i in range(out.shape[0]): + boxes = all_boxes[i] + boxes = nms(boxes, nms_thresh) + out_boxes.append(boxes) + truths = target[i].reshape([-1, 5]) + num_gts = truths_length(truths) + total = total + num_gts + pred_list = [] + for i in range(len(boxes)): + if boxes[i][4] > 0.25: + proposals = proposals + 1 + pred_list.append(i) + for i in range(num_gts): + box_gt = [truths[i][1], truths[i][2], truths[i][3], truths[i][4], 1.0, 1.0, truths[i][0]] + best_iou = 0 + best_j = -1 + for j in pred_list: # ITERATE THROUGH ONLY CONFIDENT BOXES + iou = bbox_iou(box_gt, boxes[j], x1y1x2y2=False) + if iou > best_iou: + best_j = j + best_iou = iou + if best_iou > iou_thresh and int(boxes[best_j][6]) == box_gt[6]: + correct = correct + 1 + + precision = 1.0 * correct / (proposals + eps) + recall = 1.0 * correct / (total + eps) + fscore = 2.0 * precision * recall / (precision + recall + eps) + + outs = dict() + outs['precision'] = precision + outs['recall'] = recall + outs['fscore'] = fscore + outs['frame_idx'] = frame_idx + return outs + + def test_step(self, data_batch): + """Test step. + """ + total = 0.0 + proposals = 0.0 + correct = 0.0 + fscore = 0.0 + eps = 1e-5 + nms_thresh = 0.4 + iou_thresh = 0.5 + + x_data = data_batch[0] + target = data_batch[1].squeeze(1) # indeed do squeeze to adapt to paddle tensor + frame_idx = data_batch[2] + target.stop_gradient = True + # call Model forward + out = self.forward_net(x_data) + all_boxes = get_region_boxes(out) + out_boxes = [] + + for i in range(out.shape[0]): + boxes = all_boxes[i] + boxes = nms(boxes, nms_thresh) + out_boxes.append(boxes) + truths = target[i].reshape([-1, 5]) + num_gts = truths_length(truths) + total = total + num_gts + pred_list = [] + for i in range(len(boxes)): + if boxes[i][4] > 0.25: + proposals = proposals + 1 + pred_list.append(i) + for i in range(num_gts): + box_gt = [truths[i][1], truths[i][2], truths[i][3], truths[i][4], 1.0, 1.0, truths[i][0]] + best_iou = 0 + best_j = -1 + for j in pred_list: # ITERATE THROUGH ONLY CONFIDENT BOXES + iou = bbox_iou(box_gt, boxes[j], x1y1x2y2=False) + if iou > best_iou: + best_j = j + best_iou = iou + if best_iou > iou_thresh and int(boxes[best_j][6]) == box_gt[6]: + correct = correct + 1 + + precision = 1.0 * correct / (proposals + eps) + recall = 1.0 * correct / (total + eps) + fscore = 2.0 * precision * recall / (precision + recall + eps) + + outs = dict() + outs['boxes'] = out_boxes + outs['precision'] = precision + outs['recall'] = recall + outs['fscore'] = fscore + outs['frame_idx'] = frame_idx + return outs + + def infer_step(self, data_batch): + """Infer step. + """ + out = self.forward_net(data_batch[0]) + return out \ No newline at end of file diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/yowo_utils.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/yowo_utils.py new file mode 100644 index 0000000..9f0e016 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/localizers/yowo_utils.py @@ -0,0 +1,359 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 math +import paddle +import paddle.nn as nn +import numpy as np +from builtins import range as xrange + + +def truths_length(truths): + for i in range(50): + if truths[i][1] == 0: + return i + + +def nms(boxes, nms_thresh): + if len(boxes) == 0: + return boxes + + det_confs = paddle.zeros([len(boxes)]) + for i in range(len(boxes)): + det_confs[i] = 1 - boxes[i][4] + + sortIds = paddle.argsort(det_confs) + out_boxes = [] + for i in range(len(boxes)): + box_i = boxes[sortIds[i]] + if box_i[4] > 0: + out_boxes.append(box_i) + for j in range(i + 1, len(boxes)): + box_j = boxes[sortIds[j]] + if bbox_iou(box_i, box_j, x1y1x2y2=False) > nms_thresh: + box_j[4] = 0 + return out_boxes + + +def convert2cpu(gpu_matrix): + float_32_g = gpu_matrix.astype('float32') + return float_32_g.cpu() + + +def convert2cpu_long(gpu_matrix): + int_64_g = gpu_matrix.astype('int64') + return int_64_g.cpu() + + +def get_region_boxes(output, conf_thresh=0.005, num_classes=24, + anchors=[0.70458, 1.18803, 1.26654, 2.55121, 1.59382, + 4.08321, 2.30548, 4.94180, 3.52332, 5.91979], + num_anchors=5, only_objectness=1, validation=False): + anchor_step = len(anchors) // num_anchors + if output.dim() == 3: + output = output.unsqueeze(0) + batch = output.shape[0] + assert (output.shape[1] == (5 + num_classes) * num_anchors) + h = output.shape[2] + w = output.shape[3] + all_boxes = [] + output = paddle.reshape( + output, [batch * num_anchors, 5 + num_classes, h * w]) + output = paddle.transpose(output, (1, 0, 2)) + output = paddle.reshape( + output, [5 + num_classes, batch * num_anchors * h * w]) + + grid_x = paddle.linspace(0, w - 1, w) + grid_x = paddle.tile(grid_x, [h, 1]) + grid_x = paddle.tile(grid_x, [batch * num_anchors, 1, 1]) + grid_x = paddle.reshape(grid_x, [batch * num_anchors * h * w]).cuda() + + grid_y = paddle.linspace(0, h - 1, h) + grid_y = paddle.tile(grid_y, [w, 1]).t() + grid_y = paddle.tile(grid_y, [batch * num_anchors, 1, 1]) + grid_y = paddle.reshape(grid_y, [batch * num_anchors * h * w]).cuda() + + sigmoid = nn.Sigmoid() + xs = sigmoid(output[0]) + grid_x + ys = sigmoid(output[1]) + grid_y + + anchor_w = paddle.to_tensor(anchors) + anchor_w = paddle.reshape(anchor_w, [num_anchors, anchor_step]) + anchor_w = paddle.index_select(anchor_w, index=paddle.to_tensor( + np.array([0]).astype('int32')), axis=1) + + anchor_h = paddle.to_tensor(anchors) + anchor_h = paddle.reshape(anchor_h, [num_anchors, anchor_step]) + anchor_h = paddle.index_select(anchor_h, index=paddle.to_tensor( + np.array([1]).astype('int32')), axis=1) + + anchor_w = paddle.tile(anchor_w, [batch, 1]) + anchor_w = paddle.tile(anchor_w, [1, 1, h * w]) + anchor_w = paddle.reshape(anchor_w, [batch * num_anchors * h * w]).cuda() + + anchor_h = paddle.tile(anchor_h, [batch, 1]) + anchor_h = paddle.tile(anchor_h, [1, 1, h * w]) + anchor_h = paddle.reshape(anchor_h, [batch * num_anchors * h * w]).cuda() + + ws = paddle.exp(output[2]) * anchor_w + hs = paddle.exp(output[3]) * anchor_h + + det_confs = sigmoid(output[4]) + + cls_confs = paddle.to_tensor(output[5:5 + num_classes], stop_gradient=True) + cls_confs = paddle.transpose(cls_confs, [1, 0]) + s = nn.Softmax() + cls_confs = paddle.to_tensor(s(cls_confs)) + + cls_max_confs = paddle.max(cls_confs, axis=1) + cls_max_ids = paddle.argmax(cls_confs, axis=1) + + cls_max_confs = paddle.reshape(cls_max_confs, [-1]) + cls_max_ids = paddle.reshape(cls_max_ids, [-1]) + + sz_hw = h * w + sz_hwa = sz_hw * num_anchors + + det_confs = convert2cpu(det_confs) + cls_max_confs = convert2cpu(cls_max_confs) + cls_max_ids = convert2cpu_long(cls_max_ids) + xs = convert2cpu(xs) + ys = convert2cpu(ys) + ws = convert2cpu(ws) + hs = convert2cpu(hs) + if validation: + cls_confs = convert2cpu(cls_confs.reshape([-1, num_classes])) + for b in range(batch): + boxes = [] + for cy in range(h): + for cx in range(w): + for i in range(num_anchors): + ind = b * sz_hwa + i * sz_hw + cy * w + cx + det_conf = det_confs[ind] + if only_objectness: + conf = det_confs[ind] + else: + conf = det_confs[ind] * cls_max_confs[ind] + + if conf > conf_thresh: + bcx = xs[ind] + bcy = ys[ind] + bw = ws[ind] + bh = hs[ind] + cls_max_conf = cls_max_confs[ind] + cls_max_id = cls_max_ids[ind] + box = [bcx / w, bcy / h, bw / w, bh / h, + det_conf, cls_max_conf, cls_max_id] + if (not only_objectness) and validation: + for c in range(num_classes): + tmp_conf = cls_confs[ind][c] + if c != cls_max_id and det_confs[ind] * tmp_conf > conf_thresh: + box.append(tmp_conf) + box.append(c) + boxes.append(box) + all_boxes.append(boxes) + return all_boxes + + +def bbox_iou(box1, box2, x1y1x2y2=True): + if x1y1x2y2: + mx = min(box1[0], box2[0]) + Mx = max(box1[2], box2[2]) + my = min(box1[1], box2[1]) + My = max(box1[3], box2[3]) + w1 = box1[2] - box1[0] + h1 = box1[3] - box1[1] + w2 = box2[2] - box2[0] + h2 = box2[3] - box2[1] + else: + mx = min(float(box1[0] - box1[2] / 2.0), + float(box2[0] - box2[2] / 2.0)) + Mx = max(float(box1[0] + box1[2] / 2.0), + float(box2[0] + box2[2] / 2.0)) + my = min(float(box1[1] - box1[3] / 2.0), + float(box2[1] - box2[3] / 2.0)) + My = max(float(box1[1] + box1[3] / 2.0), + float(box2[1] + box2[3] / 2.0)) + w1 = box1[2] + h1 = box1[3] + w2 = box2[2] + h2 = box2[3] + uw = Mx - mx + uh = My - my + cw = w1 + w2 - uw + ch = h1 + h2 - uh + carea = 0 + if cw <= 0 or ch <= 0: + return paddle.to_tensor(0.0) + + area1 = w1 * h1 + area2 = w2 * h2 + carea = cw * ch + uarea = area1 + area2 - carea + return carea / uarea + + +def bbox_ious(boxes1, boxes2, x1y1x2y2=True): + if x1y1x2y2: + mx = paddle.min(boxes1[0], boxes2[0]) + Mx = paddle.max(boxes1[2], boxes2[2]) + my = paddle.min(boxes1[1], boxes2[1]) + My = paddle.max(boxes1[3], boxes2[3]) + w1 = boxes1[2] - boxes1[0] + h1 = boxes1[3] - boxes1[1] + w2 = boxes2[2] - boxes2[0] + h2 = boxes2[3] - boxes2[1] + else: + mx = paddle.min(paddle.stack( + [boxes1[0] - boxes1[2] / 2.0, boxes2[0] - boxes2[2] / 2.0], axis=0), axis=0) + Mx = paddle.max(paddle.stack( + [boxes1[0] + boxes1[2] / 2.0, boxes2[0] + boxes2[2] / 2.0], axis=0), axis=0) + my = paddle.min(paddle.stack( + [boxes1[1] - boxes1[3] / 2.0, boxes2[1] - boxes2[3] / 2.0], axis=0), axis=0) + My = paddle.max(paddle.stack( + [boxes1[1] + boxes1[3] / 2.0, boxes2[1] + boxes2[3] / 2.0], axis=0), axis=0) + w1 = boxes1[2] + h1 = boxes1[3] + w2 = boxes2[2] + h2 = boxes2[3] + uw = Mx - mx + uh = My - my + cw = w1 + w2 - uw + ch = h1 + h2 - uh + mask = paddle.cast(cw <= 0, dtype="int32") + \ + paddle.cast(ch <= 0, dtype="int32") > 0 + area1 = w1 * h1 + area2 = w2 * h2 + carea = cw * ch + carea[mask] = 0 + uarea = area1 + area2 - carea + return carea / uarea + + +# this function works for building the groud truth +def build_targets(pred_boxes, target, anchors, num_anchors, num_classes, nH, nW, noobject_scale, object_scale, + sil_thresh): + # nH, nW here are number of grids in y and x directions (7, 7 here) + nB = target.shape[0] # batch size + nA = num_anchors # 5 for our case + nC = num_classes + anchor_step = len(anchors) // num_anchors + conf_mask = paddle.ones([nB, nA, nH, nW]) * noobject_scale + coord_mask = paddle.zeros([nB, nA, nH, nW]) + cls_mask = paddle.zeros([nB, nA, nH, nW]) + tx = paddle.zeros([nB, nA, nH, nW]) + ty = paddle.zeros([nB, nA, nH, nW]) + tw = paddle.zeros([nB, nA, nH, nW]) + th = paddle.zeros([nB, nA, nH, nW]) + tconf = paddle.zeros([nB, nA, nH, nW]) + tcls = paddle.zeros([nB, nA, nH, nW]) + + # for each grid there are nA anchors + # nAnchors is the number of anchor for one image + nAnchors = nA * nH * nW + nPixels = nH * nW + # for each image + for b in xrange(nB): + # get all anchor boxes in one image + # (4 * nAnchors) + cur_pred_boxes = pred_boxes[b * nAnchors:(b + 1) * nAnchors].t() + # initialize iou score for each anchor + cur_ious = paddle.zeros([nAnchors]) + for t in xrange(50): + # for each anchor 4 coordinate parameters, already in the coordinate system for the whole image + # this loop is for anchors in each image + # for each anchor 5 parameters are available (class, x, y, w, h) + if target[b][t * 5 + 1] == 0: + break + gx = target[b][t * 5 + 1] * nW + gy = target[b][t * 5 + 2] * nH + gw = target[b][t * 5 + 3] * nW + gh = target[b][t * 5 + 4] * nH + # groud truth boxes + cur_gt_boxes = paddle.tile(paddle.to_tensor( + [gx, gy, gw, gh], dtype='float32').t(), [nAnchors, 1]).t() + # bbox_ious is the iou value between orediction and groud truth + cur_ious = paddle.max( + paddle.stack([cur_ious, bbox_ious(cur_pred_boxes, cur_gt_boxes, x1y1x2y2=False)], axis=0), axis=0) + # if iou > a given threshold, it is seen as it includes an object + # conf_mask[b][cur_ious>sil_thresh] = 0 + conf_mask_t = paddle.reshape(conf_mask, [nB, -1]) + conf_mask_t[b, cur_ious > sil_thresh] = 0 + conf_mask_tt = paddle.reshape(conf_mask_t[b], [nA, nH, nW]) + conf_mask[b] = conf_mask_tt + + # number of ground truth + nGT = 0 + nCorrect = 0 + for b in xrange(nB): + # anchors for one batch (at least batch size, and for some specific classes, there might exist more than one anchor) + for t in xrange(50): + if target[b][t * 5 + 1] == 0: + break + nGT = nGT + 1 + best_iou = 0.0 + best_n = -1 + min_dist = 10000 + # the values saved in target is ratios + # times by the width and height of the output feature maps nW and nH + gx = target[b][t * 5 + 1] * nW + gy = target[b][t * 5 + 2] * nH + gi = int(gx) + gj = int(gy) + + gw = target[b][t * 5 + 3] * nW + gh = target[b][t * 5 + 4] * nH + gt_box = [0, 0, gw, gh] + for n in xrange(nA): + # get anchor parameters (2 values) + aw = anchors[anchor_step * n] + ah = anchors[anchor_step * n + 1] + anchor_box = [0, 0, aw, ah] + # only consider the size (width and height) of the anchor box + iou = bbox_iou(anchor_box, gt_box, x1y1x2y2=False) + # get the best anchor form with the highest iou + if iou > best_iou: + best_iou = iou + best_n = n + + # then we determine the parameters for an anchor (4 values together) + gt_box = [gx, gy, gw, gh] + # find corresponding prediction box + pred_box = pred_boxes[b * nAnchors + + best_n * nPixels + gj * nW + gi] + + # only consider the best anchor box, for each image + coord_mask[b, best_n, gj, gi] = 1 + cls_mask[b, best_n, gj, gi] = 1 + + # in this cell of the output feature map, there exists an object + conf_mask[b, best_n, gj, gi] = object_scale + tx[b, best_n, gj, gi] = paddle.cast( + target[b][t * 5 + 1] * nW - gi, dtype='float32') + ty[b, best_n, gj, gi] = paddle.cast( + target[b][t * 5 + 2] * nH - gj, dtype='float32') + tw[b, best_n, gj, gi] = math.log( + gw / anchors[anchor_step * best_n]) + th[b, best_n, gj, gi] = math.log( + gh / anchors[anchor_step * best_n + 1]) + iou = bbox_iou(gt_box, pred_box, x1y1x2y2=False) # best_iou + # confidence equals to iou of the corresponding anchor + tconf[b, best_n, gj, gi] = paddle.cast(iou, dtype='float32') + tcls[b, best_n, gj, gi] = paddle.cast( + target[b][t * 5], dtype='float32') + # if ious larger than 0.5, we justify it as a correct prediction + if iou > 0.5: + nCorrect = nCorrect + 1 + # true values are returned + return nGT, nCorrect, coord_mask, conf_mask, cls_mask, tx, ty, tw, th, tconf, tcls diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__init__.py new file mode 100644 index 0000000..e1efec3 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) 2021 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. + +from .base import BaseMultimodal +from .actbert import ActBert + +__all__ = ['BaseMultimodal', 'ActBert'] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..107d9c8fc3aeb43ad341d0730f9d2a31b89dc758 GIT binary patch literal 292 zcmYjL%}T^D5Khu|E7J8Ty!0aCQAD(Ny?Bul2x&9Bgq<`c=_)>hPvYBn&efBz;K|7f ziv#oV%{Slt`1SgfQG8bKW)O^h<>G&k#_lNNIe}q@BXhjxJad7<6@5XxFy&VCrKz4+ zyZYv2ZFxHDbcBaJF4lRYk(By=TsjC#$Xi1}@Yq(V9LRT&Qmw~j$cEfYwNe^UsSg(F zJdok%8Lnlgr=8kZg!o4EwpIdxYEke_RnXO~V`U3kd2=p#T5? literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__pycache__/actbert.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__pycache__/actbert.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4f09ee51eede765fdeb71d13c8efeaf56cf2c9e4 GIT binary patch literal 2259 zcmbVNOK;mo5Z>iWBt^+@H!X@n=mV{Q#3*tqil9x>phbZ=eK>7VRRBSAS2AIWly_Hl zEi6w?PyG}2G5@A#UVHLi=%MZmNjXa3qK_4JG&9THo&DyU-MrKB3AEqrUl|Js`5ler zW`l7by8IdhBaEhGLI;!*W-v1~Cg#8d-C}lX4J`O~QhVYI97?#uT4!|7;`H3TAYTyX zGVd8-9yiZS@O#YOBYpqUgk}4*^mo5|{PfG+uO2;kd`W9p_hBUY?krWwBxg~2310F9 zKOJ)wrulfxMcJN4jHUcIVLXrVgXLy`aUZ(;2m~hs%E-WAbYNoW&qx)n4gWTSP~qRH zLmaf2&)Q(SEPxO@W$Qt#9&(}Pw;H7f0r9jq648X8^-!$`5%Ks?#a2=6KcYNhA*!Gb(+tRApFG!P#>nwjjbke&8PuA4b_> zI7(73YxTps!>Pz)E@kB%Epub{0xzg?-)mZFrMZ-SyR=vmD}mGz2vzCSh?mxcM_GScw9)A^*gf2jRD2+yUWq_> zL>I*hid7VADArMIfEctZI;7D)Ph}Z2e5%ZHBSW4^o++NiJglAVhFLhF3~EC~0_v^| zFxGIwl}KVKHevO01BnEYBS~eP3ob)-lk@l{XH;%WeiRCxM!0}HNT&57rLS@orBLWn zRvfJb5(0)0*H9`xeGBZW$PC;6)1^LjXh4x&ff0aZU3CqM&es<_dol4Pnjz)zBC2SH z38+i5()Ze*@o>%PVLCU#7lMw&c-_^EnrsC+0))E@0}{*AG7P$XPS8>e(g^@iX@Byj!``}uuVyFq9WFs!B{Xd1_iU!NHelh%{@0D&CX7DnFVd;k< z+|;ua^&kw7W>MOVw8D_(aTr#pRU{OB-1s&Mq}mb!*Kr8EywQ?KF&7|ksq45at{rr$ zF?haQ!N-YI;#A;4OKTslN`c1|Z=k)l^os1vRFX>JpxF}LYo`8G@P literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__pycache__/base.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a2e4620723ee47e470cffd7aac0e7a8285176a35 GIT binary patch literal 2586 zcma)7OK%%D5GMDb$40heC(WbjgJ@HvDqOWq4=vmWnxsVbmsK|W47Q{!G? zndnxjTneX3`JRybGSOnAxbS24z@|oRY;QxRk}OnOjJCJe;kwZ%mpaLIn9ebp{YY}Q zKM)zSif~Z4Ieo=mlqURjuCR&`-u~hxS}6TGcc7lVpm?p^Q5%-SMD?P0x0h#veaMqo zH#gYrnE-M&PKClpiAT0MSYJeXEJYCsS`S3TOUobe1GGmnj|CQHQ9I3*nz^|TJnN6M zSSNWlEm}LCwH3A&^4N#C)gM4KIV8vQDWPNn?KYo_a%v?_JbmCZxFDK5!Dty<#vOaOFWne7>YxxCO24^gT3ETj_?t;a+iEAwyoNU5) z!9A91I&ITPvP6gbBH0;e)m$<@bcK+n7KZj9l=vF6Z09MQ<=oUtt~!WRq_vb4)bp}v zC`=u*8(KCf3{hY_OQ#Y{sqv6DJ>w~n_9a4xTtTu5&W_q9788O zrJE>mK(YoBT1s4yTmy+yN<5HU2Z`;OO`^TuXwyIVx15E~TI_q#Phc1Z`99MFF~yBU zv7H=pfXyw(**fdXe8`e)G}b7}#~Qf#P~2>>J9(z^RIt2XV8A-FbG*)Q6d3@PeI`Q) zDZPK*Vw*x+m*3p5=QkL59xK5u#;IrzW3VS8i>JY@Gbtcr7>CaDRDB{IAsU6YZcv)? zdgEI(GQN$(co>Pi4C!q8CYU3dslmAg6;m(q#RS%CA->Sg^}XRJ6+@9}!GDl4mrYl$ z!Br;Uk&d9hbv!U0h9KVnaY3*@Om&KnAHj!0lUfDaWxhS<;L<{KOif}3)MpEu0{#Zb zPq3fkY-s|;qz9L`5SuYinA>?xPN;krv`&gRB?I16b^)n()Ix~z8k~Iv`#Jjayo0L? z;mmXO(um~yU<%P({TX52qW3~P@;Ye950ISAkbDbdw@`iq$P0rqE6yujU)aJjk2=vdlQJ{rk~lA+7c)XV$G9 VlG@kBqrSxsSBR|*f`EF-{U0##o16du literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/actbert.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/actbert.py new file mode 100644 index 0000000..4f2c074 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/actbert.py @@ -0,0 +1,64 @@ +# 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. + +from ...registry import MULTIMODAL +from .base import BaseMultimodal +import paddle +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +@MULTIMODAL.register() +class ActBert(BaseMultimodal): + """ActBert model framework.""" + def forward_net(self, text_ids, action_feat, image_feat, image_loc, + token_type_ids, text_mask, image_mask, action_mask): + pred = self.backbone(text_ids, action_feat, image_feat, image_loc, + token_type_ids, text_mask, image_mask, action_mask) + return pred + + def train_step(self, data_batch): + """For ActBert Dataset. Define how the model is going to train, from input to output. + """ + text_ids, action_feat, image_feat, image_loc, \ + token_type_ids, text_mask, image_mask, action_mask, \ + text_labels, action_label, next_sentence_label, image_label, image_target = data_batch + loss_metrics = dict() + pred = self.backbone(text_ids, action_feat, image_feat, image_loc, + token_type_ids, text_mask, image_mask, action_mask) + prediction_scores_t, prediction_scores_v, prediction_scores_a, seq_relationship_score = pred + total_loss = self.loss(prediction_scores_t, prediction_scores_v, prediction_scores_a, seq_relationship_score, \ + text_labels, image_label, image_target, action_label, next_sentence_label) + loss_metrics['loss'] = paddle.mean(total_loss) + return loss_metrics + + def val_step(self, data_batch): + """For ActBert Dataset. Define how the model is going to val, from input to output. + """ + return self.train_step(data_batch) + + def test_step(self, data_batch): + """For MSR-VTT Dataset. Define how the model is going to test, from input to output.""" + text_ids, action_feat, image_feat, image_loc, token_type_ids, text_mask, image_mask, action_mask = data_batch[: + -1] + action_feat = action_feat.squeeze(0) + image_feat = image_feat.squeeze(0) + image_loc = image_loc.squeeze(0) + image_mask = image_mask.squeeze(0) + action_mask = action_mask.squeeze(0) + prediction_scores_t, prediction_scores_v, prediction_scores_a, seq_relationship_score = self.forward_net(text_ids, \ + action_feat, image_feat, image_loc, token_type_ids, text_mask, image_mask, action_mask) + return prediction_scores_t, prediction_scores_v, prediction_scores_a, seq_relationship_score + + def infer_step(self, data_batch): + pass diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/base.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/base.py new file mode 100644 index 0000000..bc57f97 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/multimodal/base.py @@ -0,0 +1,81 @@ +from abc import abstractmethod +from ... import builder +import paddle.nn as nn + + +class BaseMultimodal(nn.Layer): + """Base class for Multimodal. + + All Multimodal model should subclass it. + All subclass should overwrite: + + - Methods:``train_step``, supporting to forward when training. + - Methods:``valid_step``, supporting to forward when validating. + - Methods:``test_step``, supporting to forward when testing. + + Args: + backbone (dict): Backbone modules to extract feature. + head (dict): Head to process feature. + loss(dict): Loss function. + + """ + def __init__(self, backbone=None, head=None, loss=None): + super().__init__() + if backbone is not None: + self.backbone = builder.build_backbone(backbone) + if hasattr(self.backbone, 'init_weights'): + self.backbone.init_weights() + else: + self.backbone = None + if head is not None: + self.head_name = head.name + self.head = builder.build_head(head) + if hasattr(self.head, 'init_weights'): + self.head.init_weights() + else: + self.head = None + if loss is not None: + self.loss = builder.build_loss(loss) + else: + self.loss = None + + def forward(self, data_batch, mode='infer'): + """ + 1. Define how the model is going to run, from input to output. + 2. Console of train, valid, test or infer step + 3. Set mode='infer' is used for saving inference model, refer to tools/export_model.py + """ + if mode == 'train': + return self.train_step(data_batch) + elif mode == 'valid': + return self.val_step(data_batch) + elif mode == 'test': + return self.test_step(data_batch) + elif mode == 'infer': + return self.infer_step(data_batch) + else: + raise NotImplementedError + + @abstractmethod + def train_step(self, data_batch, **kwargs): + """Training step. + """ + raise NotImplementedError + + @abstractmethod + def val_step(self, data_batch, **kwargs): + """Validating step. + """ + raise NotImplementedError + + @abstractmethod + def test_step(self, data_batch, **kwargs): + """Test step. + """ + raise NotImplementedError + + @abstractmethod + def infer_step(self, data_batch, **kwargs): + """Infer step. + """ + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__init__.py new file mode 100644 index 0000000..0c6de50 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__init__.py @@ -0,0 +1,18 @@ +# 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. + +from .base import BasePartitioner +from .transnetv2_partitioner import TransNetV2Partitioner + +__all__ = ['BasePartitioner', 'TransNetV2Partitioner'] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ac5d9bc3a7e6b4e706864bb03d9789074d6e6c6f GIT binary patch literal 324 zcmYjMOG*SW5Ka0siuCA8PvE9EBE1w5nF9=h;vxi!XljNq>7+^Gh-dI5-o|xrU3mc) zuB^16Q;^5Yt5-iipC2%a_xe?T6^wo4&u);$uIa^70?jnHtmlIB%nMuer6`G)x>^^a z()BHCXP=y`Egz2-D&ma_$t2?)29l2Nf^u<*>Au@Zgghja1k1J_s|PBZByp0m-C^2x zF#I=~tm7VlvKHWtg;}o8@GbB{E|lBA%2qg<-qM$ zxwB4M)t8`8TGTY7p3*Xk^-$`oR?L|@ zkrIz1sS};#nUK+^ln~^xIE|EI{amtA+zA+r@6wcw<{C^5@^Q+U8utp7M9=q?%#%&| zu8?~&(PGseb)Efa|+t0_6SqVc)aqyznZj>hcjapV> zwc0F7_o98p^gu8b4F!vUF3r7us1{1U@k|sfIIQsYq)nE4a_gAbO@g5D^b885D}hFdnWg*LX^#eTfAo&%km_O+5@PG{W$h{QXp{ zZrq8oov@#zLKWoaH#SBxkA+f}yD^G5PsMJ+MZPi2xk!_2Yojm0_+Bn|KwRQgZS(-F zozcFmfvw9h6)pj-(FXhi>O8ABwUe(V_5KOm$$O_T- zT}O@soE6~ElH&sB5^$W7;{oRia4eYDiS~Y_Er0Ttt!Zo#Uv${LqJRha-a;f2#kO+D zCDS>Rj%S8DuyD{f`2b%E?ch6 zzX^DxBPd864~&N{oI-@DLTBEKB)Pq0H`pls)5MVi97U+nsAmgZ2h@TSQmF5`1d1HNvl zQ7CKpdTJP+qveU=}CF8F)vDLw^}wjK*T>ilnq2nEW!Wj+x;g(E2gYhfG?43X5y_9x5T?u~P-2uM zI$)Mh8htF%6g1}1JcnCsC-Z?qLZJ&a;?ZWcb~dOw=b%;lI9I5|J*}E?qh4&yn0oOb qbh6AiFiG)h`H!M~A?@x3Q`RV2Ftx9XE8RwTD|{asO?(tCxc>raqnWV) literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__pycache__/transnetv2_partitioner.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/__pycache__/transnetv2_partitioner.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d9faf4a56beedbd67f28007ca5cd5f6b994c877a GIT binary patch literal 1935 zcmb7FOK%)S5bmD0$Fqq65ip=+63D>@fB2LLcw275nz+)U5Yvd6G-cVD>$X-vbd-kDfhT0piTW3FfCwfIC(m{Qa>VZftC~2Y6 zehtv1x=sOxqWTO{Sr5~q8jUp?>#+uH+oly$E0OOK^Vv4hFt1KAJEqmGhlfmxJ}Yab zOf(-(X%^3|LQMnNf{i9FR8c9NS6yLzJsy?9xP76GHxM~D9v(4`Wn`D~T<7dC*WH1+ zW7Ef!csUlhHJ)>$ue0@eD6Fp~f^B?WbT!LbiwR_qyo*x_dSFALWzkiZQZtcQj}``| zv>1H|WAy=u$lair^_WI9fgkDt4gT@mv-D;jEDw1D8jv@nfy>E)2Aa88I;wqG9)7K4s`p7N5pd?C-S0= z=uQ&axvkJdQ0#@$@>Jp%z<7u7&61d56U-ju`3fQJmYe*TXm=L&*ZAdASju;66? literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/base.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/base.py new file mode 100644 index 0000000..a7c9259 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/base.py @@ -0,0 +1,84 @@ +# 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. + +from abc import abstractmethod +import paddle.nn as nn +from ... import builder + + +class BasePartitioner(nn.Layer): + """Base class for Partition. + All partitioner should subclass it. + All subclass should overwrite: + - Methods:``train_step``, define your train step. + - Methods:``valid_step``, define your valid step, always the same as train_step. + - Methods:``test_step``, define your test step. + """ + def __init__(self, backbone=None, head=None): + super().__init__() + if backbone is not None: + self.backbone = builder.build_backbone(backbone) + if hasattr(self.backbone, 'init_weights'): + self.backbone.init_weights() + else: + self.backbone = None + if head is not None: + self.head_name = head.name + self.head = builder.build_head(head) + if hasattr(self.head, 'init_weights'): + self.head.init_weights() + else: + self.head = None + + def init_weights(self): + """Initialize the model network weights. """ + if getattr(self.backbone, 'init_weights'): + self.backbone.init_weights() + else: + pass + + def forward(self, data_batch, mode='infer'): + """ + 1. Define how the model is going to run, from input to output. + 2. Console of train, valid, test or infer step + 3. Set mode='infer' is used for saving inference model, refer to tools/export_model.py + """ + if mode == 'train': + return self.train_step(data_batch) + elif mode == 'valid': + return self.val_step(data_batch) + elif mode == 'test': + return self.test_step(data_batch) + elif mode == 'infer': + return self.infer_step(data_batch) + else: + raise NotImplementedError + + @abstractmethod + def train_step(self, data_batch, **kwargs): + """Training step. input_data_batch -> loss_metric + """ + raise NotImplementedError + + @abstractmethod + def val_step(self, data_batch, **kwargs): + """Validating setp. input_data_batch -> loss_metric + """ + raise NotImplementedError + + @abstractmethod + def test_step(self, data_batch, **kwargs): + """Tets setp. to get acc in test data. input_data_batch -> output + """ + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/transnetv2_partitioner.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/transnetv2_partitioner.py new file mode 100644 index 0000000..c329506 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/partitioners/transnetv2_partitioner.py @@ -0,0 +1,68 @@ +# 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. + +from ...registry import PARTITIONERS +from .base import BasePartitioner + +import paddle + + +@PARTITIONERS.register() +class TransNetV2Partitioner(BasePartitioner): + """TransNetV2 Partitioner framework + """ + def forward_net(self, imgs): + one_hot_pred = self.backbone(imgs) + return one_hot_pred + + def train_step(self, data_batch): + """Define how the model is going to train, from input to output. + """ + frame_sequence = data_batch[0] + one_hot_gt, many_hot_gt = data_batch[1:] + one_hot_pred = self.forward_net(frame_sequence) + dict_ = {} + if isinstance(one_hot_pred, tuple): + one_hot_pred, dict_ = one_hot_pred + many_hot_pred = dict_.get("many_hot", None) + comb_reg_loss = dict_.get("comb_reg_loss", None) + loss_metrics = self.head.loss(one_hot_pred, one_hot_gt, + many_hot_pred, many_hot_gt, + reg_losses={"comb_reg": comb_reg_loss}) + return loss_metrics + + def val_step(self, data_batch): + frame_sequence = data_batch[0] + one_hot_gt, many_hot_gt = data_batch[1:] + one_hot_pred = self.forward_net(frame_sequence) + dict_ = {} + if isinstance(one_hot_pred, tuple): + one_hot_pred, dict_ = one_hot_pred + many_hot_pred = dict_.get("many_hot", None) + comb_reg_loss = dict_.get("comb_reg_loss", None) + loss_metrics = self.head.loss(one_hot_pred, one_hot_gt, + many_hot_pred, many_hot_gt, + reg_losses={"comb_reg": comb_reg_loss}) + return loss_metrics + + def test_step(self, data_batch): + """Define how the model is going to test, from input to output.""" + # NOTE: (shipping) when testing, the net won't call head.loss, we deal with the test processing in /paddlevideo/metrics + frame_sequence = data_batch[0] + one_hot_pred = self.forward_net(frame_sequence) + return one_hot_pred + + def infer_step(self, data_batch): + """Define how the model is going to test, from input to output.""" + frame_sequence = data_batch[0] + one_hot_pred = self.forward_net(frame_sequence) + return one_hot_pred diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__init__.py new file mode 100644 index 0000000..764b37f --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__init__.py @@ -0,0 +1,30 @@ +# 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. + +from .base import BaseRecognizer +from .recognizer1d import Recognizer1D, RecognizerAction +from .recognizer2d import Recognizer2D +from .recognizer3d import Recognizer3D +from .recognizer_transformer import RecognizerTransformer +from .recognizer_gcn import RecognizerGCN +from .recognizerMRI import RecognizerMRI +from .recognizer3dMRI import Recognizer3DMRI +from .recognizer_transformer_MRI import RecognizerTransformer_MRI +from .recognizer_movinet_frame import MoViNetRecognizerFrame +from .recognizerDistillation import RecognizerDistillation + +__all__ = [ + 'BaseRecognizer', 'Recognizer1D', 'Recognizer2D', 'Recognizer3D', + 'RecognizerTransformer', 'RecognizerGCN', 'RecognizerMRI', + 'Recognizer3DMRI', 'RecognizerTransformer_MRI', 'MoViNetRecognizerFrame', + 'RecognizerAction', 'RecognizerDistillation' +] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f671541c9794435e2853234c8405632b623decd9 GIT binary patch literal 922 zcmZWn!H&}~5KYpwP1__5%Wf$AK{+6{y{*s+mI}mSdsq+>RwOIbZe^{VR8H6x`~p|L zfE$0qIaf~n0w+9E344X3JiU1ykDte`lVt3f@w5MxJ??wnF9_TbnBckjn{Nh~$9(B2 zpZGrTKnAKudMYF##y#0r12RA!%Atx#guE|DYD~t+2Xdlf5+fhVM5QD}9?7Z7NQQhQ z@2MklgnTUTt7CGEd?HU&PIBMdc`W|!lLst$>&?^OzOgpuG#$etB-Z~LcghYWA=T9v40my*CBr>QZdcRR_6fa^)S29ED)dGYE1Kh@ zRWh~Ol7R}|$s?<}wV`WxE;4fxRDB~V-qJ0!4o~cQbGwI4=!TS*Qd0WE(;0LI;Lits zR$P?THQfryn*)8iDE7ME@TNhv*q4k+ej^yK3so~NMYSt%*V|fO7uHf!P%0|XQu<{7 Yxr?5ewyGLIz+l`;(?u&&{d|;irbeB@E76VF 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 W>zKa6Uynr+h9UJK!FhAzJ)Z4=#v8XV;g)HVmF zpmw;&m!NjJ4=yg3{@jP{-O=W27?*~aX z7#7%-4-3$$opJZ3QM!jwd~%p)qBM_0#G7VmDv@?eGwJtK>2yU@45cU=ajHTU=Tck} z`5w6T*AL>$&Q6q_gxw?+s!~7wyfct_ER@o{of_sHeSC1OGee*wXAx61eVcC$&dQ~3 zE>9!L!%P$#h=&crV;(i>=>8nl?cJ@~#050b06&f9PoRv+F*&Bk5ZDt#J|0tUY!E<} za>mVHQDXx9^>EDy z*b0VfeIZnHyPG5R3oQ1oBXz7Jg_rtwHjS1y+W0O?697raOBA(u$=l##EkyDTw(p|2 z2jT!z&nq+zk@OPbksqMIi&MkVg-II4&!GPX6mKJn_ZCpRvRc3pbH|MB-$P>o!w+X{ zuNcmN;SV&!%_+knwIQFU47WAIttrE=SY72FXLRR4sNx!jYnUve(P}!Hv2q;`k6BIP zeU_Uj-baB1y)-o|))ugu8T?> z7hnz$Ty$%mjx|_S3c*BO8)@33yDze?kT;_>qfM)6Uk7RtBl!q%xyB(c!R0k3-_|kN zG$2*l{@)st#alSHXf+!;BBd81Rfj1i5kCxn97gFhr8r^8^EeEvH1ZL8@DRmg6d$9Q zJES!XigZEX!4xJFmzajjT*qB?SN#<|1{;^I6um?h@=Ri0E6qcA!zI$VT&=wuTf-uO oq=eLl3{}15Q%fQBTL0xh>3&t6=WG0jppa0$kLk%ZY_>-K1+vHh8UO$Q literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer3dMRI.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer3dMRI.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7e1f46b170e0913329fdd034723ef0622044e0b0 GIT binary patch literal 1975 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 WoeWgnd&q6q;kN5^^15wY(EbaVthQ|c literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizerMRI.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizerMRI.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..efac30d8f629277ae2f4de736046637f141e9d2d GIT binary patch literal 1984 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer_transformer_MRI.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/__pycache__/recognizer_transformer_MRI.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..197d6732a668683863b67b1853ed1b5cdd0e45d2 GIT binary patch literal 3028 zcma)8&u`o|7A7f5Bg#;6l)d99gy` zPDqZ^3?`R4ds_6+b5X!P`mfoZb=_0Wy)AZ|eNUPhPttW84)jDmQg7b--p5C(m6d=% z`^o)>_|GaK|H8pyb7AlqJf;sq5J7X&Yu>bAj8IZIJx)=>a<}k$9`qf-^H$;aeCWHv z%a@9v7f>QS(K?{LW$7QbkI3gl_+sfX5lb>Sa6rEz=oaY&PvC#ZW`|ZmDs7ajG?n^^ z13FMG-@9|`%g;CO_U_!dn~5doodJnT@5cmWQzrx!li$R0-NzY-r~*c+5=@ zlJuw`Jtk<+5llFbNskLITzG@mq6KfS@v+wufmnvIFV2V+vHFY9*I-!Cd zu}APeWP%-0=#gDVkUdAApO8amLP5t$HUSAUyq>uTGkk)por$vrIcnY=XR~SzauwT; zu4v3}$E~~uwTdUPvDMP3H1|hRj%DTd<7BU|N?Gw88H*0DxRLpw;#rXzFe76-(z04g zaub0Z9FJ=7|Z#?;#Fg;Z_Vm}F(TJ%?rc1TnMF zkLrMCsHidA%a~`=97l`AHH*U*8 zR?2WkJqYcNoN^*FVX6Ry(5evP%*snZ6IFy+IUHG3s*#0WHwdRq<2IIrtAhPF&qRa_)aT(}^s6Y|K!H?Vh|!0Yb%dXQ zz9yMZn+Sc%>Yw*t&c|<^9_h@$GjX=S8a^23&)`uS2fmm! z?9Y#dzrp}APxpyg{xdLS!hRq>vIF`pMLz5?{aSNq98n8Z>VW=%Y~gwiGwdRME%cgoUYg#e`}QifjOxm!%C6cN5Hu&<&lMtMd_7rulIY zzL#glcCLn77*TDe809t_=5lIfTFC0xi~;uHP=@ar3p7*1rfPwS8x23gB+ipj9-}^l zVzi?~Hw4zkVAo)cT(4bTKPi$OrauD2Dh{Vlf4p&Pq%n&8VW>(F807SiG0N%Jq0-?x zu3rzKD4Wr6sI-;hQrL$=oGKeOCY^XcO|S;f8gd^`i!FEzR+AKV;n%H4be56t*?qRv zkOgWF-GEJ@2DXU5ff4IouFd|6O4ks@L>0s9676D9^a!J?PsdkJr|}F;%vSeWt^hZ4 z9Xc~p9p0P|F5H-+vT|}+R%bVry<0$b3P4DTJ6bE{dN@HAI14} zrWHj(B~jEId?7fX-$HR2#T69j-Gaw;ZO8JUeGpjl4Hg=oaOP8g%@6!#zrEV7XFID6 zROgy2OSde$CkLv=X!QjYcrH{gFWhUoBb&kTiL9u6EmOc=Kh(I9E8d5jtHxBqDO=xj jXDg(x|MdU)TKU(S_^%`B8i(6!P}|yY)A5<-oTvW-=57ml literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/base.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/base.py new file mode 100644 index 0000000..bf31caf --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/base.py @@ -0,0 +1,81 @@ +from abc import abstractmethod +from ... import builder +import paddle.nn as nn + + +class BaseRecognizer(nn.Layer): + """Base class for recognizers. + + All recognizers should subclass it. + All subclass should overwrite: + + - Methods:``train_step``, supporting to forward when training. + - Methods:``valid_step``, supporting to forward when validating. + - Methods:``test_step``, supporting to forward when testing. + + Args: + backbone (dict): Backbone modules to extract feature. + head (dict): Classification head to process feature. + + """ + def __init__(self, backbone=None, head=None, runtime_cfg=None): + + super().__init__() + if backbone is not None: + self.backbone = builder.build_backbone(backbone) + if hasattr(self.backbone, 'init_weights'): + self.backbone.init_weights() + else: + self.backbone = None + if head is not None: + self.head_name = head.name + self.head = builder.build_head(head) + if hasattr(self.head, 'init_weights'): + self.head.init_weights() + else: + self.head = None + + # Settings when the model is running, + # such as 'avg_type' + self.runtime_cfg = runtime_cfg + + def forward(self, data_batch, mode='infer'): + """ + 1. Define how the model is going to run, from input to output. + 2. Console of train, valid, test or infer step + 3. Set mode='infer' is used for saving inference model, refer to tools/export_model.py + """ + if mode == 'train': + return self.train_step(data_batch) + elif mode == 'valid': + return self.val_step(data_batch) + elif mode == 'test': + return self.test_step(data_batch) + elif mode == 'infer': + return self.infer_step(data_batch) + else: + raise NotImplementedError + + @abstractmethod + def train_step(self, data_batch, **kwargs): + """Training step. + """ + raise NotImplementedError + + @abstractmethod + def val_step(self, data_batch, **kwargs): + """Validating step. + """ + raise NotImplementedError + + @abstractmethod + def test_step(self, data_batch, **kwargs): + """Test step. + """ + raise NotImplementedError + + @abstractmethod + def infer_step(self, data_batch, **kwargs): + """Infer step. + """ + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer1d.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer1d.py new file mode 100644 index 0000000..2c7fa94 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer1d.py @@ -0,0 +1,111 @@ +# 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. + +from ...registry import RECOGNIZERS +from .base import BaseRecognizer + + +@RECOGNIZERS.register() +class Recognizer1D(BaseRecognizer): + """1D recognizer model framework.""" + def forward_net(self, imgs): + """Define how the model is going to train, from input to output. + """ + lstm_logit, lstm_output = self.head(imgs) + return lstm_logit, lstm_output + + def train_step(self, data_batch): + """Training step. + """ + rgb_data, rgb_len, rgb_mask, audio_data, audio_len, audio_mask, labels = data_batch + imgs = [(rgb_data, rgb_len, rgb_mask), + (audio_data, audio_len, audio_mask)] + + # call forward + lstm_logit, lstm_output = self.forward_net(imgs) + loss = self.head.loss(lstm_logit, labels) + hit_at_one, perr, gap = self.head.metric(lstm_output, labels) + loss_metrics = dict() + loss_metrics['loss'] = loss + loss_metrics['hit_at_one'] = hit_at_one + loss_metrics['perr'] = perr + loss_metrics['gap'] = gap + + return loss_metrics + + def val_step(self, data_batch): + """Validating setp. + """ + return self.train_step(data_batch) + + def test_step(self, data_batch): + """Testing setp. + """ + return self.train_step(data_batch) + + def infer_step(self, data_batch): + """Infering setp. + """ + rgb_data, rgb_len, rgb_mask, audio_data, audio_len, audio_mask = data_batch + imgs = [(rgb_data, rgb_len, rgb_mask), + (audio_data, audio_len, audio_mask)] + # call forward + lstm_logit, _ = self.forward_net(imgs) + return lstm_logit + + +@RECOGNIZERS.register() +class RecognizerAction(BaseRecognizer): + """1D recognizer model framework.""" + def forward_net(self, imgs): + """Define how the model is going to train, from input to output. + """ + lstm_logit, lstm_output = self.head(imgs) + return lstm_logit, lstm_output + + def train_step(self, data_batch): + """Training step. + """ + rgb_data, rgb_len, rgb_mask, audio_data, audio_len, audio_mask, labels, labels_iou = data_batch + imgs = [(rgb_data, rgb_len, rgb_mask), + (audio_data, audio_len, audio_mask)] + + # call forward + output_logit, output_iou = self.forward_net(imgs) + loss = self.head.loss(output_logit, output_iou, labels, labels_iou) + top1, top5 = self.head.metric(output_logit, labels) + loss_metrics = dict() + loss_metrics['loss'] = loss + loss_metrics['top1'] = top1 + loss_metrics['top5'] = top5 + + return loss_metrics + + def val_step(self, data_batch): + """Validating setp. + """ + return self.train_step(data_batch) + + def test_step(self, data_batch): + """Testing setp. + """ + return self.train_step(data_batch) + + def infer_step(self, data_batch): + """Infering setp. + """ + rgb_data, rgb_len, rgb_mask, audio_data, audio_len, audio_mask = data_batch + imgs = [(rgb_data, rgb_len, rgb_mask), + (audio_data, audio_len, audio_mask)] + # call forward + output_logit, output_iou = self.forward_net(imgs) + return output_logit, output_iou diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer2d.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer2d.py new file mode 100644 index 0000000..d8aa661 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer2d.py @@ -0,0 +1,69 @@ +# 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. + +from ...registry import RECOGNIZERS +from .base import BaseRecognizer +import paddle +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +@RECOGNIZERS.register() +class Recognizer2D(BaseRecognizer): + """2D recognizer model framework.""" + def forward_net(self, imgs): + # NOTE: As the num_segs is an attribute of dataset phase, and didn't pass to build_head phase, should obtain it from imgs(paddle.Tensor) now, then call self.head method. + num_segs = imgs.shape[ + 1] # imgs.shape=[N,T,C,H,W], for most commonly case + imgs = paddle.reshape_(imgs, [-1] + list(imgs.shape[2:])) + + if self.backbone is not None: + feature = self.backbone(imgs) + else: + feature = imgs + + if self.head is not None: + cls_score = self.head(feature, num_segs) + else: + cls_score = None + + return cls_score + + def train_step(self, data_batch): + """Define how the model is going to train, from input to output. + """ + imgs = data_batch[0] + labels = data_batch[1:] + cls_score = self.forward_net(imgs) + loss_metrics = self.head.loss(cls_score, labels) + return loss_metrics + + def val_step(self, data_batch): + imgs = data_batch[0] + labels = data_batch[1:] + cls_score = self.forward_net(imgs) + loss_metrics = self.head.loss(cls_score, labels, valid_mode=True) + return loss_metrics + + def test_step(self, data_batch): + """Define how the model is going to test, from input to output.""" + # NOTE: (shipping) when testing, the net won't call head.loss, we deal with the test processing in /paddlevideo/metrics + imgs = data_batch[0] + cls_score = self.forward_net(imgs) + return cls_score + + def infer_step(self, data_batch): + """Define how the model is going to test, from input to output.""" + imgs = data_batch[0] + cls_score = self.forward_net(imgs) + return cls_score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer3d.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer3d.py new file mode 100644 index 0000000..f0ecff1 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer3d.py @@ -0,0 +1,93 @@ +# 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. + +from ...registry import RECOGNIZERS +from .base import BaseRecognizer +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +@RECOGNIZERS.register() +class Recognizer3D(BaseRecognizer): + """3D Recognizer model framework. + """ + + def forward_net(self, imgs): + """Define how the model is going to run, from input to output. + """ + feature = self.backbone(imgs) + cls_score = self.head(feature) + return cls_score + + def train_step(self, data_batch): + """Training step. + """ + if self.backbone.__class__.__name__ == 'ResNet3dSlowOnly': + imgs = data_batch[0] + labels = data_batch[1:] + if imgs.dim() == 6: + imgs = imgs.reshape([-1] + imgs.shape[2:]) + else: + imgs = data_batch[0:2] + labels = data_batch[2:] + + # call forward + cls_score = self.forward_net(imgs) + loss_metrics = self.head.loss(cls_score, labels) + return loss_metrics + + def val_step(self, data_batch): + """Validating setp. + """ + if self.backbone.__class__.__name__ == 'ResNet3dSlowOnly': + imgs = data_batch[0] + labels = data_batch[1:] + if imgs.dim() == 6: + imgs = imgs.reshape([-1] + imgs.shape[2:]) + else: + imgs = data_batch[0:2] + labels = data_batch[2:] + + # call forward + cls_score = self.forward_net(imgs) + loss_metrics = self.head.loss(cls_score, labels, valid_mode=True) + return loss_metrics + + def test_step(self, data_batch): + """Test step. + """ + if self.backbone.__class__.__name__ == 'ResNet3dSlowOnly': + imgs = data_batch[0] + if imgs.dim() == 6: + imgs = imgs.reshape([-1] + imgs.shape[2:]) + else: + imgs = data_batch[0:2] + # call forward + cls_score = self.forward_net(imgs) + + return cls_score + + def infer_step(self, data_batch): + """Infer step. + """ + if self.backbone.__class__.__name__ == 'ResNet3dSlowOnly': + imgs = data_batch[0] + # call forward + imgs = imgs.reshape([-1] + imgs.shape[2:]) + cls_score = self.forward_net(imgs) + else: + imgs = data_batch[0:2] + # call forward + cls_score = self.forward_net(imgs) + + return cls_score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer3dMRI.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer3dMRI.py new file mode 100644 index 0000000..9298491 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer3dMRI.py @@ -0,0 +1,81 @@ +# 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. + +from ...registry import RECOGNIZERS +from .base import BaseRecognizer +from paddlevideo.utils import get_logger +import paddle + +logger = get_logger("paddlevideo") + + +@RECOGNIZERS.register() +class Recognizer3DMRI(BaseRecognizer): + """3D Recognizer model framework. + """ + def forward_net(self, imgs): + """Define how the model is going to run, from input to output. + """ + + imgs[0] = paddle.cast(imgs[0], "float32") + imgs[1] = paddle.cast(imgs[1], "float32") + imgs[0] = imgs[0].unsqueeze(1) + imgs[1] = imgs[1].unsqueeze(1) + + feature = self.backbone(imgs) + cls_score = self.head(feature) + return cls_score + + def train_step(self, data_batch): + """Training step. + """ + imgs = data_batch[0:2] + labels = data_batch[2:] + + # call forward + cls_score = self.forward_net(imgs) + cls_score = paddle.nn.functional.sigmoid(cls_score) + loss_metrics = self.head.loss(cls_score, labels, if_top5=False) + return loss_metrics + + def val_step(self, data_batch): + """Validating setp. + """ + imgs = data_batch[0:2] + labels = data_batch[2:] + + # call forward + cls_score = self.forward_net(imgs) + cls_score = paddle.nn.functional.sigmoid(cls_score) + loss_metrics = self.head.loss(cls_score, + labels, + valid_mode=True, + if_top5=False) + return loss_metrics + + def test_step(self, data_batch): + """Test step. + """ + imgs = data_batch[0:2] + # call forward + cls_score = self.forward_net(imgs) + + return cls_score + + def infer_step(self, data_batch): + """Infer step. + """ + imgs = data_batch[0:2] + # call forward + cls_score = self.forward_net(imgs) + + return cls_score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizerDistillation.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizerDistillation.py new file mode 100644 index 0000000..6f48a08 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizerDistillation.py @@ -0,0 +1,231 @@ +# 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. + +from abc import abstractmethod +import paddle +import paddle.nn as nn + +from ...registry import RECOGNIZERS +from ... import builder +from paddlevideo.utils import get_logger, get_dist_info + +logger = get_logger("paddlevideo") + + +@RECOGNIZERS.register() +class RecognizerDistillation(nn.Layer): + """recognizer Distillation framework.""" + def __init__(self, + freeze_params_list=None, + models=None, + loss=None, + **kargs): + """ + Args: + freeze_params_list: list, set each model is trainable or not + models: config of distillaciton model. + loss: config of loss list + """ + super().__init__() + self.model_list = [] + self.model_name_list = [] + self.loss_cfgs = loss + + if freeze_params_list is None: + freeze_params_list = [False] * len(models) + assert len(freeze_params_list) == len(models) + + # build Teacher and Student model + for idx, model_config in enumerate(models): + assert len(model_config) == 1 + key = list(model_config.keys())[0] #Teacher or Student + model_config = model_config[key] + model_name = model_config['backbone']['name'] + + backbone, head = None, None + if model_config.get('backbone'): + backbone = builder.build_backbone(model_config['backbone']) + if hasattr(backbone, 'init_weights'): + backbone.init_weights() + if model_config.get('head'): + head = builder.build_head(model_config['head']) + if hasattr(head, 'init_weights'): + head.init_weights() + + model = nn.Sequential(backbone, head) + logger.info('build distillation {} model done'.format(key)) + # for add all parameters in nn.Layer class + self.model_list.append(self.add_sublayer(key, model)) + self.model_name_list.append({model_name: key}) + + # set model trainable or not + if freeze_params_list[idx]: + for param in model.parameters(): + param.trainable = False + + # build loss: support for loss list + self.loss_func_list = [] + mode_keys = list(loss.keys()) + for mode in mode_keys: + loss_cfgs = loss[mode] + for loss_cfg in loss_cfgs: + loss_func_dict = {} + model_name_pairs = loss_cfg.pop('model_name_pairs') + loss_func = builder.build_loss(loss_cfg) + loss_func_dict['mode'] = mode + loss_func_dict['loss_func'] = loss_func + loss_func_dict['model_name_pairs'] = model_name_pairs + self.loss_func_list.append(loss_func_dict) + + def forward(self, data_batch, mode='infer'): + """ + 1. Define how the model is going to run, from input to output. + 2. Console of train, valid, test or infer step + 3. Set mode='infer' is used for saving inference model, refer to tools/export_model.py + """ + if mode == 'train': + return self.train_step(data_batch) + elif mode == 'valid': + return self.val_step(data_batch) + elif mode == 'test': + return self.test_step(data_batch) + elif mode == 'infer': + return self.infer_step(data_batch) + else: + raise NotImplementedError + + def get_loss(self, output, labels, mode): + """ + Args: + output: dict, output name and its value + labels: label of data + mode: str, 'Train' or 'Val' + """ + output['GroundTruth'] = labels + loss_list = [] + + for loss_func_dict in self.loss_func_list: + if mode == loss_func_dict['mode']: + model_name_pairs = loss_func_dict['model_name_pairs'] + loss_func = loss_func_dict['loss_func'] + loss_val = loss_func(output[model_name_pairs[0]], + output[model_name_pairs[1]]) + loss_list.append(loss_val) + + total_loss = paddle.add_n(loss_list) + return total_loss + + def get_acc(self, scores, labels, mode='Train'): + def _get_acc(score, label, mode='Train'): + top1 = paddle.metric.accuracy(input=score, label=label, k=1) + top5 = paddle.metric.accuracy(input=score, label=label, k=5) + _, world_size = get_dist_info() + # Deal with multi cards validate + if world_size > 1 and mode == 'Val': #reduce sum when valid + top1 = paddle.distributed.all_reduce( + top1, op=paddle.distributed.ReduceOp.SUM) / world_size + top5 = paddle.distributed.all_reduce( + top5, op=paddle.distributed.ReduceOp.SUM) / world_size + return top1, top5 + + if len(labels) == 1: + label = labels[0] + return _get_acc(scores, label) + # Deal with VideoMix + elif len(labels) == 3: + label_a, label_b, lam = labels + top1a, top5a = _get_acc(scores, label_a, mode) + top1b, top5b = _get_acc(scores, label_b, mode) + top1 = lam * top1a + (1 - lam) * top1b + top5 = lam * top5a + (1 - lam) * top5b + return top1, top5 + + def forward_model(self, imgs, model_name, model): + if model_name in ['PPTSM_v2', 'ResNetTweaksTSM']: + # [N,T,C,H,W] -> [N*T,C,H,W] + imgs = paddle.reshape(imgs, [-1] + list(imgs.shape[2:])) + + return model(imgs) + + def train_step(self, data_batch): + """Define how the model is going to train, from input to output. + """ + out = {} + loss_metrics = {} + imgs = data_batch[0] + labels = data_batch[1:] + + for idx, item in enumerate(self.model_name_list): + model = self.model_list[idx] + model_name = list(item.keys())[0] + model_type = item[model_name] # Teacher or Student + out[model_type] = self.forward_model(imgs, model_name, model) + + # out_student, out_teacher + loss = self.get_loss(out, labels, 'Train') + loss_metrics['loss'] = loss + # calculate acc with student output + top1, top5 = self.get_acc(out['Student'], labels) + loss_metrics['top1'] = top1 + loss_metrics['top5'] = top5 + + return loss_metrics + + def val_step(self, data_batch): + out = {} + loss_metrics = {} + imgs = data_batch[0] + labels = data_batch[1:] + + for idx, item in enumerate(self.model_name_list): + model = self.model_list[idx] + model_name = list(item.keys())[0] + model_type = item[model_name] # Teacher or Student + out[model_type] = self.forward_model(imgs, model_name, model) + + # Loss of student with gt: out_student, label + loss = self.get_loss(out, labels, 'Val') + loss_metrics['loss'] = loss + + top1, top5 = self.get_acc(out['Student'], labels, 'Val') + loss_metrics['top1'] = top1 + loss_metrics['top5'] = top5 + + return loss_metrics + + def test_step(self, data_batch): + """Define how the model is going to test, from input to output.""" + imgs = data_batch[0] + + # Use Student to test + for idx, item in enumerate(self.model_name_list): + model = self.model_list[idx] + model_name = list(item.keys())[0] + model_type = item[model_name] # Teacher or Student + if model_type == "Student": + out = self.forward_model(imgs, model_name, model) + + return out + + def infer_step(self, data_batch): + """Define how the model is going to test, from input to output.""" + imgs = data_batch[0] + + # Use Student to infer + for idx, item in enumerate(self.model_name_list): + model = self.model_list[idx] + model_name = list(item.keys())[0] + model_type = item[model_name] # Teacher or Student + if model_type == "Student": + out = self.forward_model(imgs, model_name, model) + + return out diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizerMRI.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizerMRI.py new file mode 100644 index 0000000..4b1713e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizerMRI.py @@ -0,0 +1,76 @@ +# 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. + +from ...registry import RECOGNIZERS +from .base import BaseRecognizer +import paddle +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +@RECOGNIZERS.register() +class RecognizerMRI(BaseRecognizer): + """2D recognizer model framework.""" + def forward_net(self, imgs): + # NOTE: As the num_segs is an attribute of dataset phase, and didn't pass to build_head phase, should obtain it from imgs(paddle.Tensor) now, then call self.head method. + num_segs = imgs.shape[ + 1] # imgs.shape=[N,T,C,H,W], for most commonly case + imgs = paddle.reshape_(imgs, [-1] + list(imgs.shape[2:])) + imgs = paddle.cast(imgs, "float32") ############# + imgs = imgs.unsqueeze(1) + + if self.backbone != None: + feature = self.backbone(imgs) + else: + feature = imgs + + if self.head != None: + cls_score = self.head(feature, num_segs) + else: + cls_score = None + + return cls_score + + def train_step(self, data_batch): + """Define how the model is going to train, from input to output. + """ + imgs = data_batch[0] + labels = data_batch[1:] + cls_score = self.forward_net(imgs) + cls_score = paddle.nn.functional.sigmoid(cls_score) + loss_metrics = self.head.loss(cls_score, labels, if_top5=False) + return loss_metrics + + def val_step(self, data_batch): + imgs = data_batch[0] + labels = data_batch[1:] + cls_score = self.forward_net(imgs) + cls_score = paddle.nn.functional.sigmoid(cls_score) + loss_metrics = self.head.loss(cls_score, + labels, + valid_mode=True, + if_top5=False) + return loss_metrics + + def test_step(self, data_batch): + """Define how the model is going to test, from input to output.""" + # NOTE: (shipping) when testing, the net won't call head.loss, we deal with the test processing in /paddlevideo/metrics + imgs = data_batch[0] + cls_score = self.forward_net(imgs) + return cls_score + + def infer_step(self, data_batch): + """Define how the model is going to test, from input to output.""" + imgs = data_batch[0] + cls_score = self.forward_net(imgs) + return cls_score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_gcn.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_gcn.py new file mode 100644 index 0000000..281c5ac --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_gcn.py @@ -0,0 +1,87 @@ +# Copyright (c) 2021 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. + +from ...registry import RECOGNIZERS +from .base import BaseRecognizer +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +@RECOGNIZERS.register() +class RecognizerGCN(BaseRecognizer): + """GCN Recognizer model framework. + """ + + def __init__(self, + backbone=None, + head=None, + runtime_cfg=None, + if_top5=True): + """ + Args: + backbone (dict): Backbone modules to extract feature. + head (dict): Classification head to process feature. + is_top5 (bool): Whether to display top-5 accuracy during training/validation steps. + """ + super(RecognizerGCN, self).__init__(backbone, head, runtime_cfg) + self.if_top5 = if_top5 + + def forward_net(self, data): + """Define how the model is going to run, from input to output. + """ + feature = self.backbone(data) + cls_score = self.head(feature) + return cls_score + + def train_step(self, data_batch): + """Training step. + """ + data = data_batch[0] + label = data_batch[1:] + + # call forward + cls_score = self.forward_net(data) + loss_metrics = self.head.loss(cls_score, label, if_top5=self.if_top5) + return loss_metrics + + def val_step(self, data_batch): + """Validating setp. + """ + data = data_batch[0] + label = data_batch[1:] + + # call forward + cls_score = self.forward_net(data) + loss_metrics = self.head.loss(cls_score, + label, + valid_mode=True, + if_top5=self.if_top5) + return loss_metrics + + def test_step(self, data_batch): + """Test step. + """ + data = data_batch[0] + + # call forward + cls_score = self.forward_net(data) + return cls_score + + def infer_step(self, data_batch): + """Infer step. + """ + data = data_batch[0] + + # call forward + cls_score = self.forward_net(data) + return cls_score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_movinet_frame.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_movinet_frame.py new file mode 100644 index 0000000..1ad2e14 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_movinet_frame.py @@ -0,0 +1,78 @@ +# 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. + +import paddle + +from paddlevideo.utils import get_logger +from .base import BaseRecognizer +from ...registry import RECOGNIZERS + +logger = get_logger("paddlevideo") + + +@RECOGNIZERS.register() +class MoViNetRecognizerFrame(BaseRecognizer): + + def forward_net(self, imgs): + """Define how the model is going to run, from input to output. + """ + self.backbone.clean_activation_buffers() + outputs = self.backbone(imgs) + cls_score = self.head(outputs) + return cls_score + + def train_step(self, data_batch): + """Training step. + """ + imgs = data_batch[0] + labels = data_batch[1] #.astype("int64") + data = paddle.transpose(imgs, perm=[0, 2, 1, 3, 4]) + # call forward + cls_score = self.forward_net(data) + loss_metrics = self.head.loss_func(cls_score, labels) + top1 = paddle.metric.accuracy(input=cls_score, label=labels, k=1) + top5 = paddle.metric.accuracy(input=cls_score, label=labels, k=5) + output = {'loss': loss_metrics, 'top1': top1, 'top5': top5} + return output + + def val_step(self, data_batch): + """Validating setp. + """ + imgs = data_batch[0] + labels = data_batch[1] #.astype("int64") + data = paddle.transpose(imgs, perm=[0, 2, 1, 3, 4]) + # call forward + cls_score = self.forward_net(data) + loss_metrics = self.head.loss_func(cls_score, labels) + top1 = paddle.metric.accuracy(input=cls_score, label=labels, k=1) + top5 = paddle.metric.accuracy(input=cls_score, label=labels, k=5) + output = {'loss': loss_metrics, 'top1': top1, 'top5': top5} + return output + + def test_step(self, data_batch): + """Test step. + """ + imgs = data_batch[0] + data = paddle.transpose(imgs, perm=[0, 2, 1, 3, 4]) + # call forward + cls_score = self.forward_net(data) + return cls_score + + def infer_step(self, data_batch): + """Infer step. + """ + imgs = data_batch[0] + # call forward + data = paddle.transpose(imgs, perm=[0, 2, 1, 3, 4]) + cls_score = self.forward_net(data) + + return cls_score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_transformer.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_transformer.py new file mode 100644 index 0000000..4144eda --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_transformer.py @@ -0,0 +1,98 @@ +# 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. + +import paddle +import paddle.nn.functional as F +from paddlevideo.utils import get_logger + +from ...registry import RECOGNIZERS +from .base import BaseRecognizer + +logger = get_logger("paddlevideo") + + +@RECOGNIZERS.register() +class RecognizerTransformer(BaseRecognizer): + """Transformer's recognizer model framework.""" + def forward_net(self, imgs): + # imgs.shape=[N,C,T,H,W], for transformer case + if self.backbone is not None: + feature = self.backbone(imgs) + else: + feature = imgs + + if self.head is not None: + cls_score = self.head(feature) + else: + cls_score = None + + return cls_score + + def train_step(self, data_batch): + """Define how the model is going to train, from input to output. + """ + imgs = data_batch[0] + labels = data_batch[1:] + cls_score = self.forward_net(imgs) + loss_metrics = self.head.loss(cls_score, labels) + return loss_metrics + + def val_step(self, data_batch): + imgs = data_batch[0] + labels = data_batch[1:] + cls_score = self.forward_net(imgs) + loss_metrics = self.head.loss(cls_score, labels, valid_mode=True) + return loss_metrics + + def test_step(self, data_batch): + """Define how the model is going to infer, from input to output.""" + imgs = data_batch[0] + num_views = imgs.shape[2] // self.runtime_cfg.test.num_seg + cls_score = [] + for i in range(num_views): + view = imgs[:, :, i * self.runtime_cfg.test.num_seg:(i + 1) * + self.runtime_cfg.test.num_seg] + cls_score.append(self.forward_net(view)) + cls_score = self._average_view(cls_score, + self.runtime_cfg.test.avg_type) + return cls_score + + def infer_step(self, data_batch): + """Define how the model is going to infer, from input to output.""" + imgs = data_batch[0] + num_views = imgs.shape[2] // self.runtime_cfg.test.num_seg + cls_score = [] + for i in range(num_views): + view = imgs[:, :, i * self.runtime_cfg.test.num_seg:(i + 1) * + self.runtime_cfg.test.num_seg] + cls_score.append(self.forward_net(view)) + cls_score = self._average_view(cls_score, + self.runtime_cfg.test.avg_type) + return cls_score + + def _average_view(self, cls_score, avg_type='score'): + """Combine the predicted results of different views + + Args: + cls_score (list): results of multiple views + avg_type (str, optional): Average calculation method. Defaults to 'score'. + """ + assert avg_type in ['score', 'prob'], \ + f"Currently only the average of 'score' or 'prob' is supported, but got {avg_type}" + if avg_type == 'score': + return paddle.add_n(cls_score) / len(cls_score) + elif avg_type == 'prob': + return paddle.add_n( + [F.softmax(score, axis=-1) + for score in cls_score]) / len(cls_score) + else: + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_transformer_MRI.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_transformer_MRI.py new file mode 100644 index 0000000..e8696b4 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/recognizers/recognizer_transformer_MRI.py @@ -0,0 +1,104 @@ +# 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. + +import paddle +import paddle.nn.functional as F +from paddlevideo.utils import get_logger + +from ...registry import RECOGNIZERS +from .base import BaseRecognizer + +logger = get_logger("paddlevideo") + + +@RECOGNIZERS.register() +class RecognizerTransformer_MRI(BaseRecognizer): + """Transformer's recognizer model framework.""" + def forward_net(self, imgs): + # imgs.shape=[N,C,T,H,W], for transformer case + + imgs = paddle.cast(imgs, "float32") ############# + imgs = imgs.unsqueeze(1) + + if self.backbone != None: + feature = self.backbone(imgs) + else: + feature = imgs + + if self.head != None: + cls_score = self.head(feature) + else: + cls_score = None + + return cls_score + + def train_step(self, data_batch): + """Define how the model is going to train, from input to output. + """ + imgs = data_batch[0] + labels = data_batch[1:] + cls_score = self.forward_net(imgs) + cls_score = paddle.nn.functional.sigmoid(cls_score) + loss_metrics = self.head.loss(cls_score, labels, if_top5=False) + return loss_metrics + + def val_step(self, data_batch): + imgs = data_batch[0] + labels = data_batch[1:] + cls_score = self.forward_net(imgs) + cls_score = paddle.nn.functional.sigmoid(cls_score) + loss_metrics = self.head.loss(cls_score, + labels, + valid_mode=True, + if_top5=False) + return loss_metrics + + def test_step(self, data_batch): + """Define how the model is going to infer, from input to output.""" + imgs = data_batch[0] + num_views = imgs.shape[2] // self.backbone.seg_num + cls_score = [] + for i in range(num_views): + view = imgs[:, :, i * self.backbone.seg_num:(i + 1) * + self.backbone.seg_num] + cls_score.append(self.forward_net(view)) + cls_score = self.average_view(cls_score) + return cls_score + + def infer_step(self, data_batch): + """Define how the model is going to infer, from input to output.""" + imgs = data_batch[0] + num_views = imgs.shape[2] // self.backbone.seg_num + cls_score = [] + for i in range(num_views): + view = imgs[:, :, i * self.backbone.seg_num:(i + 1) * + self.backbone.seg_num] + cls_score.append(self.forward_net(view)) + cls_score = self.average_view(cls_score) + return cls_score + + def average_view(self, cls_score, average_type='score'): + """Combine the scores of different views + + Args: + cls_score (list): Scores of multiple views + average_type (str, optional): Average calculation method. Defaults to 'score'. + """ + assert average_type in ['score', 'prob'], \ + f"Currently only the average of 'score' or 'prob' is supported, but got {average_type}" + if average_type == 'score': + return paddle.add_n(cls_score) / len(cls_score) + elif average_type == 'avg': + return paddle.add_n([F.softmax(score) + for score in cls_score]) / len(cls_score) + else: + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__init__.py new file mode 100644 index 0000000..28a1d2e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__init__.py @@ -0,0 +1,16 @@ +# Copyright (c) 2021 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. + +from .base import BaseSegment +from .cfbi import CFBI + +__all__ = ['BaseSegment', 'CFBI'] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eadd9054564fa7d97cb6a5f751e1b35c0f270cae GIT binary patch literal 280 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 Ct^%h3 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__pycache__/utils.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/__pycache__/utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..740259a0420f5ca295d626b989f2bb1fbb192cfb GIT binary patch literal 18111 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/base.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/base.py new file mode 100644 index 0000000..0c5cb07 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/base.py @@ -0,0 +1,90 @@ +# Copyright (c) 2021 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. + +from abc import abstractmethod +from ... import builder +import paddle.nn as nn + + +class BaseSegment(nn.Layer): + """Base class for semi-Video Object Segmentation. + All subclass should overwrite: + + - Methods:``train_step``, supporting to forward when training. + - Methods:``valid_step``, supporting to forward when validating. + - Methods:``test_step``, supporting to forward when testing. + + Args: + backbone (dict): Backbone modules to extract feature. + head (dict): Head to process feature. + loss(dict): Loss function. + """ + def __init__(self, backbone=None, head=None, loss=None): + super().__init__() + if backbone is not None: + self.backbone = builder.build_backbone(backbone) + if hasattr(self.backbone, 'init_weights'): + self.backbone.init_weights() + else: + self.backbone = None + if head is not None: + self.head_name = head.name + self.head = builder.build_head(head) + if hasattr(self.head, 'init_weights'): + self.head.init_weights() + else: + self.head = None + if loss is not None: + self.loss = builder.build_loss(loss) + else: + self.loss = None + + def forward(self, data_batch, mode='infer'): + """ + 1. Define how the model is going to run, from input to output. + 2. Console of train, valid, test or infer step + 3. Set mode='infer' is used for saving inference model, refer to tools/export_model.py + """ + if mode == 'train': + return self.train_step(data_batch) + elif mode == 'valid': + return self.val_step(data_batch) + elif mode == 'test': + return self.test_step(data_batch) + elif mode == 'infer': + return self.infer_step(data_batch) + else: + raise NotImplementedError + + @abstractmethod + def train_step(self, data_batch, **kwargs): + """Training step. + """ + raise NotImplementedError + + @abstractmethod + def val_step(self, data_batch, **kwargs): + """Validating step. + """ + raise NotImplementedError + + @abstractmethod + def test_step(self, data_batch, **kwargs): + """Test step. + """ + raise NotImplementedError + + @abstractmethod + def infer_step(self, data_batch, **kwargs): + """Infer step. + """ + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/cfbi.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/cfbi.py new file mode 100644 index 0000000..dcdc512 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/cfbi.py @@ -0,0 +1,286 @@ +# Copyright (c) 2021 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. + +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np + +from .utils import foreground2background, global_matching_for_eval, local_matching, calculate_attention_head_for_eval +from ...registry import SEGMENT +from .base import BaseSegment +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") + + +@SEGMENT.register() +class CFBI(BaseSegment): + """CFBI model framework.""" + def __init__(self, backbone=None, head=None, loss=None): + super().__init__(backbone, head, loss) + x1 = paddle.zeros([3, 1, 1, 1]) + self.bg_bias = paddle.create_parameter( + shape=x1.shape, + dtype=x1.dtype, + default_initializer=nn.initializer.Assign(x1)) + self.fg_bias = paddle.create_parameter( + shape=x1.shape, + dtype=x1.dtype, + default_initializer=nn.initializer.Assign(x1)) + self.epsilon = 1e-05 + + def test_step(self, data_batch): + """Define how the model is going to test, from input to output. + """ + self.test_mode = True + ref_embeddings, ref_masks, prev_embedding, prev_mask, current_frame, pred_size, gt_ids = data_batch + current_frame_embedding_4x, current_frame_embedding_8x, current_frame_embedding_16x, \ + current_low_level = self.backbone(current_frame) + + current_frame_embedding = [ + current_frame_embedding_4x, current_frame_embedding_8x, + current_frame_embedding_16x + ] + + if prev_embedding is None: + return None, current_frame_embedding + else: + bs, c, h, w = current_frame_embedding_4x.shape + + tmp_dic, _ = self.before_seghead_process( + ref_embeddings, + prev_embedding, + current_frame_embedding, + ref_masks, + prev_mask, + gt_ids, + current_low_level=current_low_level, + ) + all_pred = [] + for i in range(bs): + pred = tmp_dic[i] + + pred = F.interpolate(pred, + size=[pred_size[0], pred_size[1]], + mode='bilinear', + align_corners=True) + all_pred.append(pred) + all_pred = paddle.concat(all_pred, axis=0) + all_pred = F.softmax(all_pred, axis=1) + return all_pred, current_frame_embedding + + def before_seghead_process(self, + ref_frame_embeddings=None, + previous_frame_embeddings=None, + current_frame_embeddings=None, + ref_frame_labels=None, + previous_frame_mask=None, + gt_ids=None, + current_low_level=None): + """ process befor segmentation head""" + TEST_GLOBAL_MATCHING_CHUNK = [4, 1, 1] + TEST_GLOBAL_ATROUS_RATE = [2, 1, 1] + TRAIN_LOCAL_ATROUS_RATE = [2, 1, 1] + TEST_LOCAL_ATROUS_RATE = [2, 1, 1] + MODEL_FLOAT16_MATCHING = False + TEST_GLOBAL_MATCHING_MIN_PIXEL = 100 + MODEL_MULTI_LOCAL_DISTANCE = [[4, 8, 12, 16, 20, 24], + [2, 4, 6, 8, 10, 12], [2, 4, 6, 8, 10]] + TRAIN_LOCAL_PARALLEL = True + TEST_LOCAL_PARALLEL = True + MODEL_MATCHING_BACKGROUND = True + MODEL_SEMANTIC_MATCHING_DIM = [32, 64, 128] + + dic_tmp = [] + boards = {} + scale_ref_frame_labels = [] + scale_previous_frame_labels = [] + for current_frame_embedding in current_frame_embeddings: + bs, c, h, w = current_frame_embedding.shape + if not self.test_mode: + raise NotImplementedError + else: + ref_frame_embeddings = list(zip(*ref_frame_embeddings)) + all_scale_ref_frame_label = [] + for ref_frame_label in ref_frame_labels: + scale_ref_frame_label = paddle.cast(F.interpolate( + paddle.cast(ref_frame_label, dtype="float32"), + size=(h, w), + mode='nearest'), + dtype="int32") + all_scale_ref_frame_label.append(scale_ref_frame_label) + scale_ref_frame_labels.append(all_scale_ref_frame_label) + scale_previous_frame_label = paddle.cast(F.interpolate( + paddle.cast(previous_frame_mask, dtype="float32"), + size=(h, w), + mode='nearest'), + dtype="int32") + scale_previous_frame_labels.append(scale_previous_frame_label) + for n in range(bs): + ref_obj_ids = paddle.reshape( + paddle.cast(paddle.arange(0, + np.array(gt_ids)[n] + 1), + dtype="int32"), [-1, 1, 1, 1]) + obj_num = ref_obj_ids.shape[0] + low_level_feat = paddle.unsqueeze(current_low_level[n], axis=0) + all_CE_input = [] + all_attention_head = [] + for scale_idx, current_frame_embedding, ref_frame_embedding, previous_frame_embedding, \ + scale_ref_frame_label, scale_previous_frame_label in zip(range(3), \ + current_frame_embeddings, ref_frame_embeddings, previous_frame_embeddings, \ + scale_ref_frame_labels, scale_previous_frame_labels): + #Prepare + seq_current_frame_embedding = current_frame_embedding[n] + seq_prev_frame_embedding = previous_frame_embedding[n] + seq_previous_frame_label = paddle.cast( + (paddle.cast(scale_previous_frame_label[n], dtype="int32") + == ref_obj_ids), + dtype="float32") + if np.array(gt_ids)[n] > 0: + dis_bias = paddle.concat([ + paddle.unsqueeze(self.bg_bias[scale_idx], axis=0), + paddle.expand( + paddle.unsqueeze(self.fg_bias[scale_idx], axis=0), + [np.array(gt_ids)[n], -1, -1, -1]) + ], + axis=0) + else: + dis_bias = paddle.unsqueeze(self.bg_bias[scale_idx], axis=0) + #Global FG map + matching_dim = MODEL_SEMANTIC_MATCHING_DIM[scale_idx] + seq_current_frame_embedding_for_matching = paddle.transpose( + seq_current_frame_embedding[:matching_dim], [1, 2, 0]) + + if not self.test_mode: + raise NotImplementedError + else: + all_scale_ref_frame_label = scale_ref_frame_label + all_ref_frame_embedding = ref_frame_embedding + all_reference_embeddings = [] + all_reference_labels = [] + seq_ref_frame_labels = [] + count = 0 + for idx in range(len(all_scale_ref_frame_label)): + + ref_frame_embedding = all_ref_frame_embedding[idx] + scale_ref_frame_label = all_scale_ref_frame_label[idx] + + seq_ref_frame_embedding = ref_frame_embedding[n] + seq_ref_frame_embedding = paddle.transpose( + seq_ref_frame_embedding, [1, 2, 0]) + seq_ref_frame_label = paddle.cast( + (paddle.cast(scale_ref_frame_label[n], + dtype="int32") == ref_obj_ids), + dtype="float32") + seq_ref_frame_labels.append(seq_ref_frame_label) + seq_ref_frame_label = paddle.transpose( + paddle.squeeze(seq_ref_frame_label, axis=1), + [1, 2, 0]) + all_reference_embeddings.append( + seq_ref_frame_embedding[:, :, :matching_dim]) + all_reference_labels.append(seq_ref_frame_label) + global_matching_fg = global_matching_for_eval( + all_reference_embeddings=all_reference_embeddings, + query_embeddings= + seq_current_frame_embedding_for_matching, + all_reference_labels=all_reference_labels, + n_chunks=TEST_GLOBAL_MATCHING_CHUNK[scale_idx], + dis_bias=dis_bias, + atrous_rate=TEST_GLOBAL_ATROUS_RATE[scale_idx], + use_float16=MODEL_FLOAT16_MATCHING, + atrous_obj_pixel_num=TEST_GLOBAL_MATCHING_MIN_PIXEL) + + # Local FG map + seq_prev_frame_embedding_for_matching = paddle.transpose( + seq_prev_frame_embedding[:matching_dim], [1, 2, 0]) + seq_previous_frame_label_for_matching = paddle.transpose( + paddle.squeeze(seq_previous_frame_label, axis=1), [1, 2, 0]) + local_matching_fg = local_matching( + prev_frame_embedding=seq_prev_frame_embedding_for_matching, + query_embedding=seq_current_frame_embedding_for_matching, + prev_frame_labels=seq_previous_frame_label_for_matching, + multi_local_distance=MODEL_MULTI_LOCAL_DISTANCE[scale_idx], + dis_bias=dis_bias, + atrous_rate=TRAIN_LOCAL_ATROUS_RATE[scale_idx] if + not self.test_mode else TEST_LOCAL_ATROUS_RATE[scale_idx], + use_float16=MODEL_FLOAT16_MATCHING, + allow_downsample=False, + allow_parallel=TRAIN_LOCAL_PARALLEL + if not self.test_mode else TEST_LOCAL_PARALLEL) + + #Aggregate Pixel-level Matching + to_cat_global_matching_fg = paddle.transpose( + paddle.squeeze(global_matching_fg, axis=0), [2, 3, 0, 1]) + to_cat_local_matching_fg = paddle.transpose( + paddle.squeeze(local_matching_fg, axis=0), [2, 3, 0, 1]) + all_to_cat = [ + to_cat_global_matching_fg, to_cat_local_matching_fg, + seq_previous_frame_label + ] + + #Global and Local BG map + if MODEL_MATCHING_BACKGROUND: + to_cat_global_matching_bg = foreground2background( + to_cat_global_matching_fg, + np.array(gt_ids)[n] + 1) + reshaped_prev_nn_feature_n = paddle.unsqueeze( + paddle.transpose(to_cat_local_matching_fg, + [0, 2, 3, 1]), + axis=1) + to_cat_local_matching_bg = foreground2background( + reshaped_prev_nn_feature_n, + np.array(gt_ids)[n] + 1) + to_cat_local_matching_bg = paddle.squeeze(paddle.transpose( + to_cat_local_matching_bg, [0, 4, 2, 3, 1]), + axis=-1) + all_to_cat += [ + to_cat_local_matching_bg, to_cat_global_matching_bg + ] + + to_cat_current_frame_embedding = paddle.expand( + paddle.unsqueeze(current_frame_embedding[n], axis=0), + [obj_num, -1, -1, -1]) + to_cat_prev_frame_embedding = paddle.expand( + paddle.unsqueeze(previous_frame_embedding[n], axis=0), + [obj_num, -1, -1, -1]) + to_cat_prev_frame_embedding_fg = to_cat_prev_frame_embedding * seq_previous_frame_label + to_cat_prev_frame_embedding_bg = to_cat_prev_frame_embedding * ( + 1 - seq_previous_frame_label) + all_to_cat += [ + to_cat_current_frame_embedding, + to_cat_prev_frame_embedding_fg, + to_cat_prev_frame_embedding_bg + ] + + CE_input = paddle.concat(all_to_cat, axis=1) + #Instance-level Attention + if not self.test_mode: + raise NotImplementedError + else: + attention_head = calculate_attention_head_for_eval( + all_ref_frame_embedding, + seq_ref_frame_labels, + paddle.expand( + paddle.unsqueeze(previous_frame_embedding[n], + axis=0), [obj_num, -1, -1, -1]), + seq_previous_frame_label, + epsilon=self.epsilon) + + all_CE_input.append(CE_input) + all_attention_head.append(attention_head) + + #Collaborative Ensembler + pred = self.head(all_CE_input, all_attention_head, low_level_feat) + dic_tmp.append(pred) + + return dic_tmp, boards diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/utils.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/utils.py new file mode 100644 index 0000000..1ec3be4 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segment/utils.py @@ -0,0 +1,754 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +import paddle +import paddle.nn as nn +import paddle.nn.functional as F + + +def foreground2background(dis, obj_num): + if obj_num == 1: + return dis + bg_dis = [] + for i in range(obj_num): + obj_back = [] + for j in range(obj_num): + if i == j: + continue + obj_back.append(paddle.unsqueeze(dis[j], axis=0)) + obj_back = paddle.concat(x=obj_back, axis=1) + obj_back = paddle.min(x=obj_back, axis=1, keepdim=True) + bg_dis.append(obj_back) + bg_dis = paddle.concat(x=bg_dis, axis=0) + return bg_dis + + +WRONG_LABEL_PADDING_DISTANCE = 5e4 + + +#GLOBAL_DIST_MAP +def _pairwise_distances(x, x2, y, y2): + """ + Computes pairwise squared l2 distances between tensors x and y. + Args: + x: [n, feature_dim]. + y: [m, feature_dim]. + Returns: + d: [n, m]. + """ + xs = x2 + ys = y2 + + xs = paddle.unsqueeze(xs, axis=1) + ys = paddle.unsqueeze(ys, axis=0) + d = xs + ys - 2. * paddle.matmul(x, y, transpose_y=True) + return d + + +def _flattened_pairwise_distances(reference_embeddings, ref_square, + query_embeddings, query_square): + """ + Calculates flattened tensor of pairwise distances between ref and query. + Args: + reference_embeddings: [..., embedding_dim], + the embedding vectors for the reference frame + query_embeddings: [..., embedding_dim], + the embedding vectors for the query frames. + Returns: + dists: [reference_embeddings.size / embedding_dim, query_embeddings.size / embedding_dim] + """ + dists = _pairwise_distances(query_embeddings, query_square, + reference_embeddings, ref_square) + return dists + + +def _nn_features_per_object_for_chunk(reference_embeddings, ref_square, + query_embeddings, query_square, + wrong_label_mask): + """Extracts features for each object using nearest neighbor attention. + Args: + reference_embeddings: [n_chunk, embedding_dim], + the embedding vectors for the reference frame. + query_embeddings: [m_chunk, embedding_dim], + the embedding vectors for the query frames. + wrong_label_mask: [n_objects, n_chunk], + the mask for pixels not used for matching. + Returns: + nn_features: A float32 tensor of nearest neighbor features of shape + [m_chunk, n_objects, n_chunk]. + """ + if reference_embeddings.dtype == "float16": + wrong_label_mask = paddle.cast(wrong_label_mask, dtype="float16") + else: + wrong_label_mask = paddle.cast(wrong_label_mask, dtype="float32") + + reference_embeddings_key = reference_embeddings + query_embeddings_key = query_embeddings + dists = _flattened_pairwise_distances(reference_embeddings_key, ref_square, + query_embeddings_key, query_square) + dists = (paddle.unsqueeze(dists, axis=1) + + paddle.unsqueeze(wrong_label_mask, axis=0) * + WRONG_LABEL_PADDING_DISTANCE) + features = paddle.min(dists, axis=2, keepdim=True) + return features + + +def _nearest_neighbor_features_per_object_in_chunks(reference_embeddings_flat, + query_embeddings_flat, + reference_labels_flat, + n_chunks): + """Calculates the nearest neighbor features per object in chunks to save mem. + Uses chunking to bound the memory use. + Args: + reference_embeddings_flat: [n, embedding_dim], + the embedding vectors for the reference frame. + query_embeddings_flat: [m, embedding_dim], + the embedding vectors for the query frames. + reference_labels_flat: [n, n_objects], + the class labels of the reference frame. + n_chunks: Integer, the number of chunks to use to save memory + (set to 1 for no chunking). + Returns: + nn_features: [m, n_objects, n]. + """ + + feature_dim, embedding_dim = query_embeddings_flat.shape + chunk_size = int(np.ceil(float(feature_dim) / n_chunks)) + wrong_label_mask = reference_labels_flat < 0.1 + + wrong_label_mask = paddle.transpose(x=wrong_label_mask, perm=[1, 0]) + ref_square = paddle.sum(paddle.pow(reference_embeddings_flat, 2), axis=1) + query_square = paddle.sum(paddle.pow(query_embeddings_flat, 2), axis=1) + + all_features = [] + for n in range(n_chunks): + if n_chunks == 1: + query_embeddings_flat_chunk = query_embeddings_flat + query_square_chunk = query_square + chunk_start = 0 + else: + chunk_start = n * chunk_size + chunk_end = (n + 1) * chunk_size + query_square_chunk = query_square[chunk_start:chunk_end] + if query_square_chunk.shape[0] == 0: + continue + query_embeddings_flat_chunk = query_embeddings_flat[ + chunk_start:chunk_end] + features = _nn_features_per_object_for_chunk( + reference_embeddings_flat, ref_square, query_embeddings_flat_chunk, + query_square_chunk, wrong_label_mask) + all_features.append(features) + if n_chunks == 1: + nn_features = all_features[0] + else: + nn_features = paddle.concat(all_features, axis=0) + + return nn_features + + +def global_matching(reference_embeddings, + query_embeddings, + reference_labels, + n_chunks=100, + dis_bias=0., + ori_size=None, + atrous_rate=1, + use_float16=True, + atrous_obj_pixel_num=0): + """ + Calculates the distance to the nearest neighbor per object. + For every pixel of query_embeddings calculate the distance to the + nearest neighbor in the (possibly subsampled) reference_embeddings per object. + Args: + reference_embeddings: [height, width, embedding_dim], + the embedding vectors for the reference frame. + query_embeddings: [height, width, + embedding_dim], the embedding vectors for the query frames. + reference_labels: [height, width, obj_nums], + the class labels of the reference frame. + n_chunks: Integer, the number of chunks to use to save memory + (set to 1 for no chunking). + dis_bias: [n_objects], foreground and background bias + ori_size: (ori_height, ori_width), + the original spatial size. If "None", (ori_height, ori_width) = (height, width). + atrous_rate: Integer, the atrous rate of reference_embeddings. + use_float16: Bool, if "True", use float16 type for matching. + Returns: + nn_features: [1, ori_height, ori_width, n_objects, feature_dim]. + """ + + assert (reference_embeddings.shape[:2] == reference_labels.shape[:2]) + if use_float16: + query_embeddings = paddle.cast(query_embeddings, dtype="float16") + reference_embeddings = paddle.cast(reference_embeddings, + dtype="float16") + h, w, embedding_dim = query_embeddings.shape + obj_nums = reference_labels.shape[2] + + if atrous_rate > 1: + h_pad = (atrous_rate - h % atrous_rate) % atrous_rate + w_pad = (atrous_rate - w % atrous_rate) % atrous_rate + selected_points = paddle.zeros([h + h_pad, w + w_pad]) + selected_points = selected_points.view( + (h + h_pad) // atrous_rate, atrous_rate, (w + w_pad) // atrous_rate, + atrous_rate) + selected_points[:, 0, :, 0] = 1. + selected_points = paddle.reshape(selected_points, + [h + h_pad, w + w_pad, 1])[:h, :w] + is_big_obj = (paddle.sum( + reference_labels, + axis=(0, 1))) > (atrous_obj_pixel_num * atrous_rate**2) + reference_labels[:, :, + is_big_obj] = reference_labels[:, :, + is_big_obj] * selected_points + + reference_embeddings_flat = paddle.reshape(reference_embeddings, + [-1, embedding_dim]) + reference_labels_flat = paddle.reshape(reference_labels, [-1, obj_nums]) + query_embeddings_flat = paddle.reshape(query_embeddings, + [-1, embedding_dim]) + + all_ref_fg = paddle.sum(reference_labels_flat, axis=1, keepdim=True) > 0.9 + reference_labels_flat = paddle.reshape( + paddle.masked_select(reference_labels_flat, + paddle.expand(all_ref_fg, [-1, obj_nums])), + [-1, obj_nums]) + if reference_labels_flat.shape[0] == 0: + return paddle.ones([1, h, w, obj_nums, 1]) + reference_embeddings_flat = paddle.reshape( + paddle.masked_select(reference_embeddings_flat, + paddle.expand(all_ref_fg, [-1, embedding_dim])), + [-1, embedding_dim]) + + nn_features = _nearest_neighbor_features_per_object_in_chunks( + reference_embeddings_flat, query_embeddings_flat, reference_labels_flat, + n_chunks) + + nn_features_reshape = paddle.reshape(nn_features, [1, h, w, obj_nums, 1]) + nn_features_reshape = ( + F.sigmoid(nn_features_reshape + + paddle.reshape(dis_bias, [1, 1, 1, -1, 1])) - 0.5) * 2 + + #TODO: ori_size is not None + + if use_float16: + nn_features_reshape = paddle.cast(nn_features_reshape, dtype="float32") + return nn_features_reshape + + +def global_matching_for_eval(all_reference_embeddings, + query_embeddings, + all_reference_labels, + n_chunks=20, + dis_bias=0., + ori_size=None, + atrous_rate=1, + use_float16=True, + atrous_obj_pixel_num=0): + """ + Calculates the distance to the nearest neighbor per object. + For every pixel of query_embeddings calculate the distance to the + nearest neighbor in the (possibly subsampled) reference_embeddings per object. + Args: + all_reference_embeddings: A list of reference_embeddings, + each with size [height, width, embedding_dim], + the embedding vectors for the reference frame. + query_embeddings: [n_query_images, height, width, + embedding_dim], the embedding vectors for the query frames. + all_reference_labels: A list of reference_labels, + each with size [height, width, obj_nums], + the class labels of the reference frame. + n_chunks: Integer, the number of chunks to use to save memory + (set to 1 for no chunking). + dis_bias: [n_objects], foreground and background bias + ori_size: (ori_height, ori_width), + the original spatial size. If "None", (ori_height, ori_width) = (height, width). + atrous_rate: Integer, the atrous rate of reference_embeddings. + use_float16: Bool, if "True", use float16 type for matching. + Returns: + nn_features: [n_query_images, ori_height, ori_width, n_objects, feature_dim]. + """ + + h, w, embedding_dim = query_embeddings.shape + obj_nums = all_reference_labels[0].shape[2] + all_reference_embeddings_flat = [] + all_reference_labels_flat = [] + ref_num = len(all_reference_labels) + n_chunks *= ref_num + if atrous_obj_pixel_num > 0: + if atrous_rate > 1: + h_pad = (atrous_rate - h % atrous_rate) % atrous_rate + w_pad = (atrous_rate - w % atrous_rate) % atrous_rate + selected_points = paddle.zeros([h + h_pad, w + w_pad]) + selected_points = paddle.reshape( + selected_points, [(h + h_pad) // atrous_rate, atrous_rate, + (w + w_pad) // atrous_rate, atrous_rate]) + selected_points[:, 0, :, 0] = 1. + selected_points = paddle.reshape(selected_points, + [h + h_pad, w + w_pad, 1])[:h, :w] + + for reference_embeddings, reference_labels, idx in zip( + all_reference_embeddings, all_reference_labels, range(ref_num)): + if atrous_rate > 1: + is_big_obj = paddle.sum( + reference_labels, + axis=(0, 1)) > (atrous_obj_pixel_num * atrous_rate**2) + is_big_obj = list(np.array(is_big_obj)) + for j in range(len(is_big_obj)): + if is_big_obj[j] == True: + reference_labels[:, :, j:j + + 1] = reference_labels[:, :, j:j + + 1] * selected_points + + reference_embeddings_flat = paddle.reshape(reference_embeddings, + [-1, embedding_dim]) + reference_labels_flat = paddle.reshape(reference_labels, + [-1, obj_nums]) + + all_reference_embeddings_flat.append(reference_embeddings_flat) + all_reference_labels_flat.append(reference_labels_flat) + + reference_embeddings_flat = paddle.concat( + x=all_reference_embeddings_flat, axis=0) + reference_labels_flat = paddle.concat(x=all_reference_labels_flat, + axis=0) + else: + if ref_num == 1: + reference_embeddings, reference_labels = all_reference_embeddings[ + 0], all_reference_labels[0] + if atrous_rate > 1: + h_pad = (atrous_rate - h % atrous_rate) % atrous_rate + w_pad = (atrous_rate - w % atrous_rate) % atrous_rate + if h_pad > 0 or w_pad > 0: + reference_embeddings = F.pad(reference_embeddings, + [0, h_pad, 0, w_pad, 0, 0]) + reference_labels = F.pad(reference_labels, + [0, h_pad, 0, w_pad, 0, 0]) + reference_embeddings = paddle.reshape( + reference_embeddings, + [(h + h_pad) // atrous_rate, atrous_rate, + (w + w_pad) // atrous_rate, atrous_rate, 32]) + reference_labels = paddle.reshape( + reference_labels, + [(h + h_pad) // atrous_rate, atrous_rate, + (w + w_pad) // atrous_rate, atrous_rate, -1]) + reference_embeddings = paddle.reshape( + reference_embeddings[:, 0, :, 0, :], + reference_embeddings[:, 0, :, 0, :].shape) + reference_labels = paddle.reshape( + reference_labels[:, 0, :, 0, :], + reference_labels[:, 0, :, 0, :].shape) + reference_embeddings_flat = paddle.reshape(reference_embeddings, + [-1, embedding_dim]) + reference_labels_flat = paddle.reshape(reference_labels, + [-1, obj_nums]) + else: + for reference_embeddings, reference_labels, idx in zip( + all_reference_embeddings, all_reference_labels, + range(ref_num)): + if atrous_rate > 1: + h_pad = (atrous_rate - h % atrous_rate) % atrous_rate + w_pad = (atrous_rate - w % atrous_rate) % atrous_rate + if h_pad > 0 or w_pad > 0: + reference_embeddings = F.pad(reference_embeddings, + [0, h_pad, 0, w_pad, 0, 0]) + reference_labels = F.pad(reference_labels, + [0, h_pad, 0, w_pad, 0, 0]) + + reference_embeddings = paddle.reshape( + reference_embeddings, + [(h + h_pad) // atrous_rate, atrous_rate, + (w + w_pad) // atrous_rate, atrous_rate, -1]) + reference_labels = paddle.reshape( + reference_labels, + [(h + h_pad) // atrous_rate, atrous_rate, + (w + w_pad) // atrous_rate, atrous_rate, -1]) + reference_embeddings = paddle.reshape( + reference_embeddings[:, 0, :, 0, :], + reference_embeddings[:, 0, :, 0, :].shape) + reference_labels = paddle.reshape( + reference_labels[:, 0, :, 0, :], + reference_labels[:, 0, :, 0, :].shape) + + reference_embeddings_flat = paddle.reshape( + reference_embeddings, [-1, embedding_dim]) + reference_labels_flat = paddle.reshape(reference_labels, + [-1, obj_nums]) + + all_reference_embeddings_flat.append(reference_embeddings_flat) + all_reference_labels_flat.append(reference_labels_flat) + + reference_embeddings_flat = paddle.concat( + all_reference_embeddings_flat, axis=0) + reference_labels_flat = paddle.concat(all_reference_labels_flat, + axis=0) + + query_embeddings_flat = paddle.reshape(query_embeddings, + [-1, embedding_dim]) + + all_ref_fg = paddle.sum(reference_labels_flat, axis=1, keepdim=True) > 0.9 + reference_labels_flat = paddle.reshape( + paddle.masked_select(reference_labels_flat, + paddle.expand(all_ref_fg, [-1, obj_nums])), + [-1, obj_nums]) + if reference_labels_flat.shape[0] == 0: + return paddle.ones([1, h, w, obj_nums, 1]) + reference_embeddings_flat = paddle.reshape( + paddle.masked_select(reference_embeddings_flat, + paddle.expand(all_ref_fg, [-1, embedding_dim])), + [-1, embedding_dim]) + if use_float16: + query_embeddings_flat = paddle.cast(query_embeddings_flat, + dtype="float16") + reference_embeddings_flat = paddle.cast(reference_embeddings_flat, + dtype="float16") + nn_features = _nearest_neighbor_features_per_object_in_chunks( + reference_embeddings_flat, query_embeddings_flat, reference_labels_flat, + n_chunks) + + nn_features_reshape = paddle.reshape(nn_features, [1, h, w, obj_nums, 1]) + nn_features_reshape = ( + F.sigmoid(nn_features_reshape + + paddle.reshape(dis_bias, [1, 1, 1, -1, 1])) - 0.5) * 2 + + # TODO: ori_size is not None + + if use_float16: + nn_features_reshape = paddle.cast(nn_features_reshape, dtype="float32") + return nn_features_reshape + + +#LOCAL_DIST_MAP +def local_pairwise_distances(x, + y, + max_distance=9, + atrous_rate=1, + allow_downsample=False): + """Computes pairwise squared l2 distances using a local search window. + Use for-loop for saving memory. + Args: + x: Float32 tensor of shape [height, width, feature_dim]. + y: Float32 tensor of shape [height, width, feature_dim]. + max_distance: Integer, the maximum distance in pixel coordinates + per dimension which is considered to be in the search window. + atrous_rate: Integer, the atrous rate of local matching. + allow_downsample: Bool, if "True", downsample x and y + with a stride of 2. + Returns: + Float32 distances tensor of shape [height, width, (2 * max_distance + 1) ** 2]. + """ + if allow_downsample: + ori_height = x.shape[0] + ori_width = x.shape[1] + x = paddle.unsqueeze(paddle.transpose(x, [2, 0, 1]), axis=0) + y = paddle.unsqueeze(paddle.transpose(y, [2, 0, 1]), axis=0) + down_size = (int(ori_height / 2) + 1, int(ori_width / 2) + 1) + x = F.interpolate(x, + size=down_size, + mode='bilinear', + align_corners=True) + y = F.interpolate(y, + size=down_size, + mode='bilinear', + align_corners=True) + x = paddle.unsqueeze(paddle.transpose(x, [1, 2, 0]), axis=0) + y = paddle.unsqueeze(paddle.transpose(y, [1, 2, 0]), axis=0) + + pad_max_distance = max_distance - max_distance % atrous_rate + # no change pad + padded_y = F.pad(y, (0, 0, pad_max_distance, pad_max_distance, + pad_max_distance, pad_max_distance), + value=WRONG_LABEL_PADDING_DISTANCE) + + height, width, _ = x.shape + dists = [] + for y in range(2 * pad_max_distance // atrous_rate + 1): + y_start = y * atrous_rate + y_end = y_start + height + y_slice = padded_y[y_start:y_end] + for x in range(2 * max_distance + 1): + x_start = x * atrous_rate + x_end = x_start + width + offset_y = y_slice[:, x_start:x_end] + dist = paddle.sum(paddle.pow((x - offset_y), 2), axis=2) + dists.append(dist) + dists = paddle.stack(dists, axis=2) + + return dists + + +def local_pairwise_distances_parallel(x, + y, + max_distance=9, + atrous_rate=1, + allow_downsample=True): + """Computes pairwise squared l2 distances using a local search window. + Args: + x: Float32 tensor of shape [height, width, feature_dim]. + y: Float32 tensor of shape [height, width, feature_dim]. + max_distance: Integer, the maximum distance in pixel coordinates + per dimension which is considered to be in the search window. + atrous_rate: Integer, the atrous rate of local matching. + allow_downsample: Bool, if "True", downsample x and y + with a stride of 2. + Returns: + Float32 distances tensor of shape [height, width, (2 * max_distance + 1) ** 2]. + """ + + ori_height, ori_width, _ = x.shape + x = paddle.unsqueeze(paddle.transpose(x, [2, 0, 1]), axis=0) + y = paddle.unsqueeze(paddle.transpose(y, [2, 0, 1]), axis=0) + if allow_downsample: + down_size = (int(ori_height / 2) + 1, int(ori_width / 2) + 1) + x = F.interpolate(x, + size=down_size, + mode='bilinear', + align_corners=True) + y = F.interpolate(y, + size=down_size, + mode='bilinear', + align_corners=True) + + _, channels, height, width = x.shape + + x2 = paddle.reshape(paddle.sum(paddle.pow(x, 2), axis=1), + [height, width, 1]) + y2 = paddle.reshape(paddle.sum(paddle.pow(y, 2), axis=1), + [1, 1, height, width]) + + pad_max_distance = max_distance - max_distance % atrous_rate + # no change pad + padded_y = F.pad(y, (pad_max_distance, pad_max_distance, pad_max_distance, + pad_max_distance)) + padded_y2 = F.pad(y2, (pad_max_distance, pad_max_distance, pad_max_distance, + pad_max_distance), + value=WRONG_LABEL_PADDING_DISTANCE) + + offset_y = paddle.transpose( + paddle.reshape( + F.unfold(x=padded_y, + kernel_sizes=[height, width], + strides=[atrous_rate, atrous_rate]), + [channels, height * width, -1]), [1, 0, 2]) + offset_y2 = paddle.reshape( + F.unfold(padded_y2, + kernel_sizes=[height, width], + strides=[atrous_rate, atrous_rate]), [height, width, -1]) + x = paddle.transpose(paddle.reshape(x, [channels, height * width, -1]), + [1, 2, 0]) + + dists = x2 + offset_y2 - 2. * paddle.reshape(paddle.matmul(x, offset_y), + [height, width, -1]) + + return dists + + +def local_matching(prev_frame_embedding, + query_embedding, + prev_frame_labels, + dis_bias=0., + multi_local_distance=[15], + ori_size=None, + atrous_rate=1, + use_float16=True, + allow_downsample=True, + allow_parallel=True): + """Computes nearest neighbor features while only allowing local matches. + Args: + prev_frame_embedding: [height, width, embedding_dim], + the embedding vectors for the last frame. + query_embedding: [height, width, embedding_dim], + the embedding vectors for the query frames. + prev_frame_labels: [height, width, n_objects], + the class labels of the previous frame. + multi_local_distance: A list of Integer, + a list of maximum distance allowed for local matching. + ori_size: (ori_height, ori_width), + the original spatial size. If "None", (ori_height, ori_width) = (height, width). + atrous_rate: Integer, the atrous rate of local matching. + use_float16: Bool, if "True", use float16 type for matching. + allow_downsample: Bool, if "True", downsample prev_frame_embedding and query_embedding + with a stride of 2. + allow_parallel: Bool, if "True", do matching in a parallel way. If "False", do matching in + a for-loop way, which will save GPU memory. + Returns: + nn_features: A float32 np.array of nearest neighbor features of shape + [1, height, width, n_objects, 1]. + """ + max_distance = multi_local_distance[-1] + + if ori_size is None: + height, width = prev_frame_embedding.shape[:2] + ori_size = (height, width) + + obj_num = prev_frame_labels.shape[2] + pad = paddle.ones([1]) * WRONG_LABEL_PADDING_DISTANCE + if use_float16: + query_embedding = paddle.cast(query_embedding, dtype="float16") + prev_frame_embedding = paddle.cast(prev_frame_embedding, + dtype="float16") + pad = paddle.cast(pad, dtype="float16") + + if allow_parallel: + d = local_pairwise_distances_parallel(query_embedding, + prev_frame_embedding, + max_distance=max_distance, + atrous_rate=atrous_rate, + allow_downsample=allow_downsample) + else: + d = local_pairwise_distances(query_embedding, + prev_frame_embedding, + max_distance=max_distance, + atrous_rate=atrous_rate, + allow_downsample=allow_downsample) + + height, width = d.shape[:2] + + labels = paddle.unsqueeze(paddle.transpose(prev_frame_labels, [2, 0, 1]), 1) + labels = paddle.unsqueeze(paddle.transpose(prev_frame_labels, [2, 0, 1]), + axis=1) + if (height, width) != ori_size: + labels = F.interpolate(labels, size=(height, width), mode='nearest') + + pad_max_distance = max_distance - max_distance % atrous_rate + atrous_max_distance = pad_max_distance // atrous_rate + #no change pad + padded_labels = F.pad(labels, ( + pad_max_distance, + pad_max_distance, + pad_max_distance, + pad_max_distance, + ), + mode='constant', + value=0) + + offset_masks = paddle.transpose( + paddle.reshape( + F.unfold(padded_labels, + kernel_sizes=[height, width], + strides=[atrous_rate, atrous_rate]), + [obj_num, height, width, -1]), [1, 2, 3, 0]) > 0.9 + + d_tiled = paddle.expand(paddle.unsqueeze( + d, axis=-1), [-1, -1, -1, obj_num]) # h, w, num_local_pos, obj_num + + d_masked = paddle.where(offset_masks, d_tiled, pad) + dists = paddle.min(d_masked, axis=2) + multi_dists = [ + paddle.unsqueeze(paddle.transpose(dists, [2, 0, 1]), axis=1) + ] # n_objects, num_multi_local, h, w + + reshaped_d_masked = paddle.reshape(d_masked, [ + height, width, 2 * atrous_max_distance + 1, 2 * atrous_max_distance + 1, + obj_num + ]) + for local_dis in multi_local_distance[:-1]: + local_dis = local_dis // atrous_rate + start_idx = atrous_max_distance - local_dis + end_idx = atrous_max_distance + local_dis + 1 + new_d_masked = paddle.reshape( + reshaped_d_masked[:, :, start_idx:end_idx, start_idx:end_idx, :], + reshaped_d_masked[:, :, start_idx:end_idx, + start_idx:end_idx, :].shape) + new_d_masked = paddle.reshape(new_d_masked, + [height, width, -1, obj_num]) + new_dists = paddle.min(new_d_masked, axis=2) + new_dists = paddle.unsqueeze(paddle.transpose(new_dists, [2, 0, 1]), + axis=1) + multi_dists.append(new_dists) + + multi_dists = paddle.concat(multi_dists, axis=1) + multi_dists = (F.sigmoid(multi_dists + + paddle.reshape(dis_bias, [-1, 1, 1, 1])) - 0.5) * 2 + + if use_float16: + multi_dists = paddle.cast(multi_dists, dtype="float32") + + if (height, width) != ori_size: + multi_dists = F.interpolate(multi_dists, + size=ori_size, + mode='bilinear', + align_corners=True) + multi_dists = paddle.transpose(multi_dists, perm=[2, 3, 0, 1]) + multi_dists = paddle.reshape(multi_dists, + [1, ori_size[0], ori_size[1], obj_num, -1]) + + return multi_dists + + +def calculate_attention_head(ref_embedding, + ref_label, + prev_embedding, + prev_label, + epsilon=1e-5): + + ref_head = ref_embedding * ref_label + ref_head_pos = paddle.sum(ref_head, axis=(2, 3)) + ref_head_neg = paddle.sum(ref_embedding, axis=(2, 3)) - ref_head_pos + ref_pos_num = paddle.sum(ref_label, axis=(2, 3)) + ref_neg_num = paddle.sum(1. - ref_label, axis=(2, 3)) + ref_head_pos = ref_head_pos / (ref_pos_num + epsilon) + ref_head_neg = ref_head_neg / (ref_neg_num + epsilon) + + prev_head = prev_embedding * prev_label + prev_head_pos = paddle.sum(prev_head, axis=(2, 3)) + prev_head_neg = paddle.sum(prev_embedding, axis=(2, 3)) - prev_head_pos + prev_pos_num = paddle.sum(prev_label, axis=(2, 3)) + prev_neg_num = paddle.sum(1. - prev_label, axis=(2, 3)) + prev_head_pos = prev_head_pos / (prev_pos_num + epsilon) + prev_head_neg = prev_head_neg / (prev_neg_num + epsilon) + + total_head = paddle.concat( + x=[ref_head_pos, ref_head_neg, prev_head_pos, prev_head_neg], axis=1) + + return total_head + + +def calculate_attention_head_for_eval(ref_embeddings, + ref_labels, + prev_embedding, + prev_label, + epsilon=1e-5): + total_ref_head_pos = 0. + total_ref_head_neg = 0. + total_ref_pos_num = 0. + total_ref_neg_num = 0. + + for idx in range(len(ref_embeddings)): + ref_embedding = ref_embeddings[idx] + ref_label = ref_labels[idx] + ref_head = ref_embedding * ref_label + ref_head_pos = paddle.sum(ref_head, axis=(2, 3)) + ref_head_neg = paddle.sum(ref_embedding, axis=(2, 3)) - ref_head_pos + ref_pos_num = paddle.sum(ref_label, axis=(2, 3)) + ref_neg_num = paddle.sum(1. - ref_label, axis=(2, 3)) + total_ref_head_pos = total_ref_head_pos + ref_head_pos + total_ref_head_neg = total_ref_head_neg + ref_head_neg + total_ref_pos_num = total_ref_pos_num + ref_pos_num + total_ref_neg_num = total_ref_neg_num + ref_neg_num + ref_head_pos = total_ref_head_pos / (total_ref_pos_num + epsilon) + ref_head_neg = total_ref_head_neg / (total_ref_neg_num + epsilon) + + prev_head = prev_embedding * prev_label + prev_head_pos = paddle.sum(prev_head, axis=(2, 3)) + prev_head_neg = paddle.sum(prev_embedding, axis=(2, 3)) - prev_head_pos + prev_pos_num = paddle.sum(prev_label, axis=(2, 3)) + prev_neg_num = paddle.sum(1. - prev_label, axis=(2, 3)) + prev_head_pos = prev_head_pos / (prev_pos_num + epsilon) + prev_head_neg = prev_head_neg / (prev_neg_num + epsilon) + + total_head = paddle.concat( + x=[ref_head_pos, ref_head_neg, prev_head_pos, prev_head_neg], axis=1) + return total_head diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__init__.py new file mode 100644 index 0000000..de4bf57 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__init__.py @@ -0,0 +1,17 @@ +# 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. + +from .base import BaseSegmenter +from .ms_tcn import MSTCN +from .asrf import ASRF + +__all__ = ['BaseSegmenter', 'MSTCN', 'ASRF'] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c427464e6954d0737bf3040c800a666a0a35f37c GIT binary patch literal 328 zcmYk1!Ait15QdW`?XJ>3NH4PNQABhFZ|=c*kP--SGc9G4wj@>2SMV*o`8J+&_2esf za#9g?LO%ZdGe1d&qBtg4pXr-^O$hmlhr>dTT;TRAgeICAVrflj)QL$ftJ$oX;Wn*P zN?M}%JFPRFR;0|nDaJ|~ijDG6L2IF(z@d@eRCiZf6#TNfy)K!H7daNe5!-SR_ycBU zKV;U+Y1hyFz?FB+JQWsFDr2PlAnqteBYy7TRBTkgmrZBD|H;)_jBeP0_p>WTrL}>l xPQxJVpuu!~D;lRPJP&R!{Qpb6kh1H$Ny?M)B`nWy_R+w3{FPrK@;s-wl3ydtQwsn9 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__pycache__/asrf.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/__pycache__/asrf.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a035c2c57a18683d1509a766306dbcecb112f287 GIT binary patch literal 2679 zcmaJ@OOF#r5bnpkZSSs@09g_u=SiH9)slz{LWq#CQ4X;Xi*m3mjb`2L-GT9p=^lfy z#!{pu;t(ajVfVjtlKHZVW2qh!G7g#SZ3rA5eqD0dD z#sT?(2wwzGi3lX$<9oE%6z&%3gfBRJphHcxb^C{(Zg=n9zPt5;)~eR6M9VF?Gm?2J z)eBIPE_kkfyLET-PNB;?su)PE(|l)uw&RyGpXfUW@H_WRKjZ6|bDi74&z2v7!};S;atdL12B>?Qj!pCxZvuMJ|oA zD-&UytkAmS7*|imQkfu*(>yKX*qj{$7UM%K;*l(O3t?8bi%BjL^&~ELmDIaMCOV#R zw9JO81#ze)6ak751@hrJHDMeNvPA1ReokKAlh^vUlKeqDOf#wL;l|hf`NyobKTd?m zU%Vz(-uOxzSz@%fn{-FE)l)& z;MUhbROCJoaza(3BKv^e0iCg&RUpAatz``?v|?c472g8y`q^RA&F|$f&1HMHc-$^` zj{()R3C0c>F+;4RJ6}$Y{qAfMG3Izvza^dkacT-&HJu+)lVbu`)I%X%>538u+2Mjb0Xd1w2 zcY6LF0*fH)QjU+HeDNBtuI1lLfAh-CjrFS=&m(mX_F&w6G6KdRHx;tQGS_%D=Zvo( zPNbYdg@|-eS{j??jx6KNE3qCFN_LucVj_{0NxYqugI#sjuA3#>GJ_hM*NAD%Qv>AJ zW@RxsG%qbQV2<;#IkT8AJWx4bBgR5C;aEwGN($3N1(u~s2mi@^Wa$SGkhQ}ro|&rn=K@i_?7TtH)Ua*FA}qa?F?#lF1Q zEC1iUE_%b_%@aFCVjwSUZzy4K$a;=_)^gwWffL+k$GDH<-~_Wn%j^&jI>CQsL$*c^ zXa$GdbyE8KL0vyq;{vxG;I=nCcTeiKL94L+ca1+Mgb8bafH9p=eE>E~b@d*O4mqyg zhp7q6A}(dF3uWjg&^_H56{+Y%meohOF*H_R;_Gk93?}7t!wE|W*XCgaR*j_=agPD( zSd-RVyTE{Fbh=dYY~g+ad^|f2!M_2M3Yza4!8QzSxo$Yvez*V#XD&d9PiR1uS5jy( zR)0WuI5Z+3VC2*DKjuTJ-at`=(DJmyYqT~{aRo#tI0eR=KrsHCl&67+Qv9Gr;ul!V zHr{|Q@c`<~!3O-waptvlL2bp{1CcPvDkt$;X;xr{Qp^iR+TmV=AI z#g#MGr_(Zlk~^s`)f0v1sByO8f0V*wv}V;ib^Bb;^Y!5*ACzg4Cz)Y+Zla^PLWGSw qDbq|_S}sZ1)+-KOQH%{mNx61vAxZD*UXHQ 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 M;%89%bz}bj0JVrp{{R30 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/asrf.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/asrf.py new file mode 100644 index 0000000..3d962c7 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/asrf.py @@ -0,0 +1,143 @@ +# 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. + +from ...registry import SEGMENTERS +from .base import BaseSegmenter + +import paddle +import paddle.nn.functional as F +from .utils import ASRFPostProcessing + + +@SEGMENTERS.register() +class ASRF(BaseSegmenter): + """ASRF model framework.""" + + def __init__(self, + postprocessing_method, + boundary_threshold, + backbone=None, + head=None, + loss=None): + + super().__init__(backbone=backbone, head=head, loss=loss) + self.postprocessing_method = postprocessing_method + self.boundary_threshold = boundary_threshold + + def forward_net(self, video_feature): + """Define how the model is going to train, from input to output. + """ + if self.backbone is not None: + feature = self.backbone(video_feature) + else: + feature = video_feature + + if self.head is not None: + network_outputs = self.head(feature) + else: + network_outputs = None + + return network_outputs + + def train_step(self, data_batch): + """Training step. + """ + feature, label, boundary = data_batch + # call forward + outputs_cls, outputs_boundary = self.forward_net(feature) + + # transfer data + outputs_cls_np = outputs_cls[-1].numpy() + outputs_boundary_np = outputs_boundary[-1].numpy() + + # caculate loss + if self.loss is not None: + output_loss = self.loss(feature, outputs_cls, label, + outputs_boundary, boundary) + else: + output_loss = None + + # predict post process + predicted = ASRFPostProcessing(outputs_cls_np, outputs_boundary_np, + self.postprocessing_method) + predicted = paddle.squeeze(predicted) + + loss_metrics = dict() + loss_metrics['loss'] = output_loss + loss_metrics['F1@0.50'] = self.head.get_F1_score(predicted, label) + + return loss_metrics + + def val_step(self, data_batch): + """Validating setp. + """ + feature, label, boundary = data_batch + + # call forward + outputs_cls, outputs_boundary = self.forward_net(feature) + + # transfer data + outputs_cls_np = outputs_cls[-1].numpy() + outputs_boundary_np = outputs_boundary[-1].numpy() + + ## caculate loss + if self.loss is not None: + output_loss = self.loss(feature, outputs_cls, label, + outputs_boundary, boundary) + else: + output_loss = None + + # predict post process + predicted = ASRFPostProcessing(outputs_cls_np, outputs_boundary_np, + self.postprocessing_method) + predicted = paddle.squeeze(predicted) + + outputs_dict = dict() + outputs_dict['loss'] = output_loss + outputs_dict['F1@0.50'] = self.head.get_F1_score(predicted, label) + return outputs_dict + + def test_step(self, data_batch): + """Testing setp. + """ + feature, _, _ = data_batch + + outputs_dict = dict() + # call forward + outputs_cls, outputs_boundary = self.forward_net(feature) + # transfer data + outputs_cls_np = outputs_cls[-1].numpy() + outputs_boundary_np = outputs_boundary[-1].numpy() + + # predict post process + predicted = ASRFPostProcessing(outputs_cls_np, outputs_boundary_np, + self.postprocessing_method) + outputs_dict['predict'] = paddle.to_tensor(predicted[0, :]) + outputs_dict['output_np'] = F.sigmoid(outputs_cls[-1]) + return outputs_dict + + def infer_step(self, data_batch): + """Infering setp. + """ + feature = data_batch[0] + + # call forward + outputs_cls, outputs_boundary = self.forward_net(feature) + # transfer data + outputs_cls_np = outputs_cls[-1] + outputs_boundary_np = outputs_boundary[-1] + + outputs = [ + outputs_cls_np, outputs_boundary_np, + F.sigmoid(outputs_cls[-1]) + ] + return outputs diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/base.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/base.py new file mode 100644 index 0000000..e0856d9 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/base.py @@ -0,0 +1,100 @@ +# 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. + +from abc import abstractmethod +from ... import builder +import paddle.nn as nn + + +class BaseSegmenter(nn.Layer): + """Base class for segementers. + + All segementers should subclass it. + All subclass should overwrite: + + - Methods:``train_step``, supporting to forward when training. + - Methods:``valid_step``, supporting to forward when validating. + - Methods:``test_step``, supporting to forward when testing. + + Args: + backbone (dict): Backbone modules to extract feature. + head (dict): Classification head to process feature. + + """ + + def __init__(self, backbone=None, head=None, loss=None): + + super().__init__() + # build backbone + if backbone is not None: + self.backbone = builder.build_backbone(backbone) + if hasattr(self.backbone, 'init_weights'): + self.backbone.init_weights() + else: + self.backbone = None + # build head + if head is not None: + self.head_name = head.name + self.head = builder.build_head(head) + if hasattr(self.head, 'init_weights'): + self.head.init_weights() + else: + self.head = None + # build loss + if loss is not None: + self.loss_name = loss.name + self.loss = builder.build_loss(loss) + if hasattr(self.loss, 'init_weights'): + self.loss.init_weights() + else: + self.loss = None + + def forward(self, data_batch, mode='infer'): + """ + 1. Define how the model is going to run, from input to output. + 2. Console of train, valid, test or infer step + 3. Set mode='infer' is used for saving inference model, refer to tools/export_model.py + """ + if mode == 'train': + return self.train_step(data_batch) + elif mode == 'valid': + return self.val_step(data_batch) + elif mode == 'test': + return self.test_step(data_batch) + elif mode == 'infer': + return self.infer_step(data_batch) + else: + raise NotImplementedError + + @abstractmethod + def train_step(self, data_batch, **kwargs): + """Training step. + """ + raise NotImplementedError + + @abstractmethod + def val_step(self, data_batch, **kwargs): + """Validating step. + """ + raise NotImplementedError + + @abstractmethod + def test_step(self, data_batch, **kwargs): + """Test step. + """ + raise NotImplementedError + + @abstractmethod + def infer_step(self, data_batch, **kwargs): + """Infer step. + """ + raise NotImplementedError diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/ms_tcn.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/ms_tcn.py new file mode 100644 index 0000000..a5982a7 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/ms_tcn.py @@ -0,0 +1,101 @@ +# 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. + +from ...registry import SEGMENTERS +from .base import BaseSegmenter + +import paddle +import paddle.nn.functional as F + + +@SEGMENTERS.register() +class MSTCN(BaseSegmenter): + """MS-TCN model framework.""" + + def forward_net(self, video_feature): + """Define how the model is going to train, from input to output. + """ + if self.backbone is not None: + feature = self.backbone(video_feature) + else: + feature = video_feature + + if self.head is not None: + cls_score = self.head(feature) + else: + cls_score = None + + return cls_score + + def train_step(self, data_batch): + """Training step. + """ + video_feat, video_gt = data_batch + + # call forward + output = self.forward_net(video_feat) + loss = 0. + for i in range(len(output)): + loss += self.head.loss(output[i], video_gt) + + predicted = paddle.argmax(output[-1], axis=1) + predicted = paddle.squeeze(predicted) + + loss_metrics = dict() + loss_metrics['loss'] = loss + loss_metrics['F1@0.50'] = self.head.get_F1_score(predicted, video_gt) + return loss_metrics + + def val_step(self, data_batch): + """Validating setp. + """ + video_feat, video_gt = data_batch + + # call forward + output = self.forward_net(video_feat) + loss = 0. + for i in range(len(output)): + loss += self.head.loss(output[i], video_gt) + + predicted = paddle.argmax(output[-1], axis=1) + predicted = paddle.squeeze(predicted) + + outputs_dict = dict() + outputs_dict['loss'] = loss + outputs_dict['F1@0.50'] = self.head.get_F1_score(predicted, video_gt) + return outputs_dict + + def test_step(self, data_batch): + """Testing setp. + """ + video_feat, _ = data_batch + + outputs_dict = dict() + # call forward + output = self.forward_net(video_feat) + predicted = paddle.argmax(output[-1], axis=1) + predicted = paddle.squeeze(predicted) + outputs_dict['predict'] = predicted + outputs_dict['output_np'] = F.sigmoid(output[-1]) + return outputs_dict + + def infer_step(self, data_batch): + """Infering setp. + """ + video_feat = data_batch[0] + + # call forward + output = self.forward_net(video_feat) + predicted = paddle.argmax(output[-1], axis=1) + predicted = paddle.squeeze(predicted) + output_np = F.sigmoid(output[-1]) + return predicted, output_np diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/utils.py b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/utils.py new file mode 100644 index 0000000..9c21cbb --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/framework/segmenters/utils.py @@ -0,0 +1,343 @@ +# 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. + +# https://github.com/yiskw713/asrf/libs/postprocess.py + +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np +import math + + +class GaussianSmoothing(nn.Layer): + """ + Apply gaussian smoothing on a 1d tensor. + Filtering is performed seperately for each channel + in the input using a depthwise convolution. + Arguments: + channels (int, sequence): Number of channels of the input tensors. Output will + have this number of channels as well. + kernel_size (int, sequence): Size of the gaussian kernel. + sigma (float, sequence): Standard deviation of the gaussian kernel. + """ + + def __init__(self, kernel_size=15, sigma=1.0): + super().__init__() + self.kernel_size = kernel_size + + # The gaussian kernel is the product of the + # gaussian function of each dimension. + kernel = 1 + meshgrid = paddle.arange(kernel_size) + + meshgrid = paddle.cast(meshgrid, dtype='float32') + + mean = (kernel_size - 1) / 2 + kernel = kernel / (sigma * math.sqrt(2 * math.pi)) + kernel = kernel * paddle.exp(-(((meshgrid - mean) / sigma)**2) / 2) + + # Make sure sum of values in gaussian kernel equals 1. + # kernel = kernel / paddle.max(kernel) + + self.kernel = paddle.reshape(kernel, [1, 1, -1]) + + def forward(self, inputs): + """ + Apply gaussian filter to input. + Arguments: + input (paddle.Tensor): Input to apply gaussian filter on. + Returns: + filtered (paddle.Tensor): Filtered output. + """ + _, c, _ = inputs.shape + inputs = F.pad(inputs, + pad=((self.kernel_size - 1) // 2, + (self.kernel_size - 1) // 2), + mode="reflect", + data_format='NCL') + + kernel = paddle.expand(self.kernel, shape=[c, 1, self.kernel_size]) + return F.conv1d(inputs, weight=kernel, groups=c) + + +def argrelmax(prob, threshold=0.7): + """ + Calculate arguments of relative maxima. + prob: np.array. boundary probability maps distributerd in [0, 1] + prob shape is (T) + ignore the peak whose value is under threshold + + Return: + Index of peaks for each batch + """ + # ignore the values under threshold + prob[prob < threshold] = 0.0 + + # calculate the relative maxima of boundary maps + # treat the first frame as boundary + peak = np.concatenate( + [ + np.ones((1), dtype=np.bool), + (prob[:-2] < prob[1:-1]) & (prob[2:] < prob[1:-1]), + np.zeros((1), dtype=np.bool), + ], + axis=0, + ) + + peak_idx = np.where(peak)[0].tolist() + + return peak_idx + + +def is_probability(x): + assert x.ndim == 3 + + if x.shape[1] == 1: + # sigmoid + if x.min() >= 0 and x.max() <= 1: + return True + else: + return False + else: + # softmax + _sum = np.sum(x, axis=1).astype(np.float32) + _ones = np.ones_like(_sum, dtype=np.float32) + return np.allclose(_sum, _ones) + + +def convert2probability(x): + """ + Args: x (N, C, T) + """ + assert x.ndim == 3 + + if is_probability(x): + return x + else: + if x.shape[1] == 1: + # sigmoid + prob = 1 / (1 + np.exp(-x)) + else: + # softmax + prob = np.exp(x) / np.sum(np.exp(x), axis=1) + return prob.astype(np.float32) + + +def convert2label(x): + assert x.ndim == 2 or x.ndim == 3 + + if x.ndim == 2: + return x.astype(np.int64) + else: + if not is_probability(x): + x = convert2probability(x) + + label = np.argmax(x, axis=1) + return label.astype(np.int64) + + +def refinement_with_boundary(outputs, boundaries, boundary_threshold): + """ + Get segments which is defined as the span b/w two boundaries, + and decide their classes by majority vote. + Args: + outputs: numpy array. shape (N, C, T) + the model output for frame-level class prediction. + boundaries: numpy array. shape (N, 1, T) + boundary prediction. + boundary_threshold: the threshold of the size of action segments. float(default=0.7) + Return: + preds: np.array. shape (N, T) + final class prediction considering boundaries. + """ + + preds = convert2label(outputs) + boundaries = convert2probability(boundaries) + + for i, (output, pred, boundary) in enumerate(zip(outputs, preds, + boundaries)): + idx = argrelmax(boundary[0, :], threshold=boundary_threshold) + + # add the index of the last action ending + T = pred.shape[0] + idx.append(T) + + # majority vote + for j in range(len(idx) - 1): + count = np.bincount(pred[idx[j]:idx[j + 1]]) + modes = np.where(count == count.max())[0] + if len(modes) == 1: + mode = modes + else: + if outputs.ndim == 3: + # if more than one majority class exist + prob_sum_max = 0 + for m in modes: + prob_sum = output[m, idx[j]:idx[j + 1]].sum() + if prob_sum_max < prob_sum: + mode = m + prob_sum_max = prob_sum + else: + # decide first mode when more than one majority class + # have the same number during oracle experiment + mode = modes[0] + + preds[i, idx[j]:idx[j + 1]] = mode + return preds + + +def relabeling(outputs, theta_t): + """ + Relabeling small action segments with their previous action segment + Args: + output: the results of action segmentation. (N, T) or (N, C, T) + theta_t: the threshold of the size of action segments. + Return: + relabeled output. (N, T) + """ + + preds = convert2label(outputs) + + for i in range(preds.shape[0]): + # shape (T,) + last = preds[i][0] + cnt = 1 + for j in range(1, preds.shape[1]): + if last == preds[i][j]: + cnt += 1 + else: + if cnt > theta_t: + cnt = 1 + last = preds[i][j] + else: + preds[i][j - cnt:j] = preds[i][j - cnt - 1] + cnt = 1 + last = preds[i][j] + + if cnt <= theta_t: + preds[i][j - cnt:j] = preds[i][j - cnt - 1] + + return preds + + +def smoothing(outputs, filter_func): + """ + Smoothing action probabilities with gaussian filter. + Args: + outputs: frame-wise action probabilities. (N, C, T) + Return: + predictions: final prediction. (N, T) + """ + + outputs = convert2probability(outputs) + outputs = filter_func(paddle.to_tensor(outputs)).numpy() + + preds = convert2label(outputs) + return preds + + +def ASRFPostProcessing(outputs_cls, + outputs_boundary, + refinement_method, + boundary_threshold=0.7, + theta_t=15, + kernel_size=15): + """ + ASRF post processing is to refine action boundary + Args: + outputs_cls: the results of action segmentation. (N, T) or (N, C, T) + outputs_boundary: action boundary probability. (N, 1, T) + refinement_method: the way of refine predict boundary and classification. str + boundary_threshold: the threshold of the size of action segments. float(default=0.7) + theta_t: the threshold of the size of action segments. int(default=15) + kernel_size: Size of the gaussian kernel. int(default=15) + Return: + preds output. (N, T) + """ + func = [ + "refinement_with_boundary", + "relabeling", + "smoothing", + ] + + if refinement_method == "smoothing": + filter_func = GaussianSmoothing(kernel_size) + preds = smoothing(outputs_cls, filter_func) + elif refinement_method == "relabeling": + preds = relabeling(outputs_cls, theta_t) + elif refinement_method == "refinement_with_boundary": + preds = refinement_with_boundary(outputs_cls, outputs_boundary, + boundary_threshold) + else: + preds = np.zeros((1, 1)) + assert refinement_method in func + + return paddle.to_tensor(preds) + + +def _calculate_fan_in_and_fan_out(tensor): + dimensions = len(tensor.shape) + if dimensions < 2: + raise ValueError("Fan in and fan out can not be computed \ + for tensor with fewer than 2 dimensions") + + if dimensions == 2: # Linear + fan_in = tensor.shape[1] + fan_out = tensor.shape[0] + else: + num_input_fmaps = tensor.shape[1] + num_output_fmaps = tensor.shape[0] + receptive_field_size = 1 + if tensor.dim() > 2: + receptive_field_size = tensor[0][0].numel() + fan_in = num_input_fmaps * receptive_field_size + fan_out = num_output_fmaps * receptive_field_size + + return fan_in, fan_out + + +def calculate_gain(nonlinearity=None, a=None): + if nonlinearity == 'tanh': + return 5.0 / 3 + elif nonlinearity == 'relu': + return math.sqrt(2.0) + elif nonlinearity == 'leaky_relu': + if a is not None: + return math.sqrt(2.0 / (1 + a**2)) + else: + return math.sqrt(2.0 / (1 + 0.01**2)) + elif nonlinearity == 'selu': + return 3.0 / 4 + else: + return 1 + + +def KaimingUniform_like_torch(weight_npy, + mode='fan_in', + nonlinearity='leaky_relu'): + fan_in, fan_out = _calculate_fan_in_and_fan_out(weight_npy) + if mode == 'fan_in': + fan_mode = fan_in + else: + fan_mode = fan_out + a = math.sqrt(5.0) + gain = calculate_gain(nonlinearity=nonlinearity, a=a) + std = gain / math.sqrt(fan_mode) + bound = math.sqrt(3.0) * std + return np.random.uniform(-bound, bound, weight_npy.shape) + + +def init_bias(weight_npy, bias_npy): + fan_in, fan_out = _calculate_fan_in_and_fan_out(weight_npy) + bound = 1.0 / math.sqrt(fan_in) + return np.random.uniform(-bound, bound, bias_npy.shape) diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__init__.py new file mode 100644 index 0000000..49f71cc --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__init__.py @@ -0,0 +1,49 @@ +# 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. + +from .adds_head import AddsHead +from .asrf_head import ASRFHead +from .attention_lstm_head import AttentionLstmHead, ActionAttentionLstmHead +from .base import BaseHead +from .bbox_head import BBoxHeadAVA +from .cfbi_head import CollaborativeEnsemblerMS +from .i3d_head import I3DHead +from .movinet_head import MoViNetHead +from .ms_tcn_head import MSTCNHead +from .pptimesformer_head import ppTimeSformerHead +from .pptsm_head import ppTSMHead +from .pptsn_head import ppTSNHead +from .roi_head import AVARoIHead +from .single_straight3d import SingleRoIExtractor3D +from .slowfast_head import SlowFastHead +from .stgcn_head import STGCNHead +from .timesformer_head import TimeSformerHead +from .transnetv2_head import TransNetV2Head +from .tsm_head import TSMHead +from .tsn_head import TSNHead +from .ms_tcn_head import MSTCNHead +from .asrf_head import ASRFHead +from .ctrgcn_head import CTRGCNHead +from .movinet_head import MoViNetHead +from .agcn2s_head import AGCN2sHead +from .token_shift_head import TokenShiftHead + +__all__ = [ + 'BaseHead', 'TSNHead', 'TSMHead', 'ppTSMHead', 'ppTSNHead', 'SlowFastHead', + 'AttentionLstmHead', 'TimeSformerHead', 'STGCNHead', 'TransNetV2Head', + 'I3DHead', 'SingleRoIExtractor3D', 'AVARoIHead', 'BBoxHeadAVA', 'AddsHead', + 'ppTimeSformerHead', 'CollaborativeEnsemblerMS', 'MSTCNHead', 'ASRFHead', + 'MoViNetHead', 'CTRGCNHead', 'TokenShiftHead', 'ActionAttentionLstmHead', + 'AGCN2sHead' +] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b559ad203225e46f5a8a847246cf435193e143f8 GIT binary patch literal 1485 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/agcn2s_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/agcn2s_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6fc341ad49e34baef7d9b607929351d808e7a0b0 GIT binary patch literal 1829 zcmZ8iOK%%D5GMDf)x(C7xNh7R7VSx`YZyk+gV7Xrk|IG78wJwSRs}&Xxzft}P{>sr z3-YB7kVE1AfuMj5^pbzmGp{}AFZ2+1W><=gQs8KYGegb}zi+o#S!od%f4jen6Q7WO z(6~KZF!o{U9tc4MO-We)(~wrSmD!<9iLiv7I++`~pgY1%y{r*7D&0%{tQj^bk&Ua? zHF-=#L-?+-E~E`p#~?~_ zL56f{O=)Z;Wa|7y|Dcpi>69>QYJ;>(XXpwF(i=90zOc&XRZG}Y>tk|Fg>z{M_tH9d zOK;eolA$HMbprpLsVf?nn7<+j+>(D}R?;MwT(KGjeK@-s3uV7+87GrGH?}SX8adCT zX(L(^o+cBiX80rkr1l(0yew6B)wp^*lFIn3Mi#@I_jhXOq47psh*X;9Ph9cr0J4mg z=V}#pGu~05GM>WGyc`%uKUbyko>rBb_N~h`RvdLb2#{&4?n0*e1jTx_$H^%NOsO?6 z-cr+KH6j>$Oa6T-_j(U_e!}7;mAY1Uc6%dLL{jT&wO5z-A`!CaRX9!Zes2H();->j z@?Fi)*dCp!J8;71F!g63HmCV z0!$&YY~l8uYkCgRSGMr3QPwuOa;EeeUm=aj*FY|4dN3$XE9T$>2Z;{)1@s~)i$IO@ zB{dYjYbM3dK(RPcx(q~;$y_HzjD*d*XbH&{tya4owTTfQfH2J(*V{m~57Bmx;me?~X~tKwpXgGZDf~{o rCp2?6j`+Kt_O*_pB`}k(&?R>m> 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/attention_lstm_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/attention_lstm_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ec7441350fad89746481c462e94d6c3b8a05e201 GIT binary patch literal 6904 zcmbtZTXP&o6`r2k&d%OfH_Mkq0g7U|80-WHfg-WvgaAeXY@k>S!)SUWjXXQM>6wi! zd6r9*R30c71rHQe6d-YV@V}t=1-#P5164dwdgci~*nFpFR$9vzmts|W_Vnq~_wLi* z*BUk&u7=N_tRL~$KBj4Zqr~jTLgFQS)89aFjk8$m)2|+D1J-AZbR*UWM&D4n8Jh#E zZz-L{_MoC`OdB};Dl8VaV|P&N*P&Oq6E_CUepBhyxHV|^+t6KJi#vmEzst0+xi`13 zeNN+b-gsN%jj+3G?6Us+p}omlu(wM40%zB>Ui$$3)K+^;R=?~Ee{dxA09r_QqKhALxa}dhL}T?}zvb}*_i$)aI$HO&UpnVt7PW;*Y#;B!fAq%W*o zfBnkqDj6-dG)+{{!2?vM9sEFP82EwaXqs%lEQV?NN|K4;X!|PEdrX>%KL`Wl9)23o zs0y0FbPMy6X&KA4U42i_S#IZ*ee4BjnrGw&q?wzLR&GJsStZxD%w5WLvMO|EmtE1m zy*hC+cdNElr`+6G*6?d_c2}RkXRpEay=Lz0v%I>mGfjE6$OB)SCiku}ah0D{`nlxC z?MaP%_u6?4Wi_vJ*oMt3^BR_cT0om)rExB)woa*1%S9PpX9%qy4>lPnWeQ@zz5> z8;dZN_2D=>Ox>@q2h+rziEOMzJQ86*Tg8v>8PbiC5!};gCzQ3#i1RQh64gV$`_;9` zi?OfnO#WUh`CngDJ4R5XxbOHGnhWks4zPc)ZB{g`bkj8Ing}<>u`keopngVK^iL|dqN$3k%hsjIFYq7tL9^2~_ zCo*YXy>|UevT_CI0Mjcge5zaq59ho~-uVoiLQ#79V+hfu2?Z2CzO#;J5- zoK7!T-;gZoyGM&IE9L6RD)reDeui-uYlg#I^@{2AynEXH>){JGF8j$%Z#{~`v`{~G z@y19DgAkRI^+qvcZ$>;E-WUvd7-Pb3Y$D>MH&AI2gw$^F$asFVEk208uHc(~7ozFt z%zS9;Hlx2fYvRvj_QS63>L$~f{h(`@I;=W$SPKn0yvzsAgSzFw>nQD5s#KZVwsuZm zn)YHE3eQh>Pe2iS`XQaZFXQ_US}rhq3jH1vWLJ72zJ#Q#tH57e0_ina{y~dv zvYn?MZ*Quy0qH}$mj1zf2Jn@H`$`WD;JCVFNRJ}NN& zdSYYO zcx}=|ZH>H*h<)PC=W?PeEH&^SBJ{G;H(vX=rDl zE#zmQoz2hWXV-Ov;QH$Q-sdTdu3-PCL$Sh#VY-qGvz1_&WPX&a+?lLQ!?Rezx(nKQ zf_8$6p$L<aFrQsXnFbP5rF>52+6i<^AU9NQV`nRJL&g`~i+XoNv=`D(nl7k8l zpCIi5gsg0Y8BU`R7b#_CezGY(MXC|r9!YZ$`iZQLlN3#b2>i}q9B0ue-j+s+;Ao77 zx1y7S)e$z`nLmf^EI%Hh$`%8( zq4nw0%xG?)@*p{s{x2$6g7@p&QFM<#`!F5M6+V$<%=*`BtqO$@{p`ZY6( z*hX$5npw~Zia5H?C>obyR_wu>eFy+p@Eb9Wh=DpC5RGFcVRb%6aU^ z0H7%gy-f_w#}-RM`GF(r2oNqxf#E0*0Rw~u7C*)hUGI$}&kcXnbBYNq&R4npeuzFu z6ZLRusmYb@Oj9O7FKM9g@rksHKK=~F(>8>|9Bet-s^-JG?y{Xzk56b(z+p=D03>F$A^LEiSMCyg&o9KNV`Mg9TGo*kc|?z1R)0P&GhmMi0VNgbBQCT{2X$4o0Yv@5R;huInyyD0V~R(C*K zw!rALNP-BO0MXM#heQ|R5dudjdwTTKHx(xNzX{xnPatrL$Z^JX(6fTZ8M8Ewn?M&t z&sw>w=viA)q7KkdQPKk00#O5ssNo)NaHlL?+b>DrF^bmVRyI$icNt1nvxRJtyP#=H zplLPGw7Q~cr&KG;yb9_@q)-vDy%slB9~9-<>L9myLiw|0`DR)ETrq~S{8PmkcoY3F zsPAau>8Y(44J<2)%(Yg>B5D2|>#g9r( zASi(Mo)JBA_&EuJ;su|0luFEi2*M9X@mYM5k{>6b(8cql5t0zkk$8c`r%BN9IZl0y z_27c6UiPzKlU`e-v6ftrPI=v5kjTDBHn5=5hU9wiEQ#lO^#W0xM1I5-YVZ{jgfhhE zNW4bk^CVOhAS7Re0vh-4@lC%2@gxdDq+&`vx`)(*v?Hp~wweeV$1N04Oy)eW5nOau zf3UN1!fF1`G(^z7uWpATo_(2;Y7j>wp;-85vVRp~=Y1!&bt3y9^m)iW{-{p+|HMAt z`uFUk#N#G-fu*>G1$dzC0W1J9R}{CfAK?}ia0@51!9MVq1FUavIb|Ic)Io7oM@+E6 zINX_(n^T(DL=Aa0umQZFAywz@q=DMNHu45;;HE0sEK5>~N;Xx=R^FnPVL{u<(pIT< zS#t-eTHYyZ?&7X*Tj+R*YpaU&t2~|ER4BBBMpXz>=1+;yP)E^g(=slHVk8 z1EP0k=FA@w2k~vnSLa(nG>?+sCE=4;BcV<@CvBa?28myg_$7p7uNM5^S7iA$i9Hhg zBz{9eMT_5(rijDR5pfWkWL2j*BJC!Ln8biYLSjf_MB)t+f<#IpBQYlNCW%`lZj;z1 z@hu2x0{Y+?2J+(ZQ*{UVf5A7UBX&z`-g)?aOho-KYyIgNl`c|G8BdgcY|OS5etK(z&Exn&1T(HEfyR5%n0VE5bt zR04?;a0gu+j>Qkj*DbKRM~1h^VEOTA)9=?y&Q&7yK}yIyP5TP7lXiSj-a+97Z0EEN zg=mh;78TaqIeXHCJ_g-sCh7Y!zUhY{GCZto(W|sx!Vo;I99r-&4`8AoyE<6rs=9T1 zhO`tt7k5#EWH%3}%AQe7&`-$b_(3ohez4uM%6UnHAs%CkDKSBTu=5~4eteKr`Wy|C zf^wI2al_y>>B)HTd;z4zPvJUKkGks=;-x!&58sm!?{fI=@Di^%YoiWfJ>vu|WbN-O-2pY0@ms)pFbp+P7 zEeN>E+RXo11mSRLuHm07qBi4Oz6}?+M%|A`f+j;cpD7r|XED3wj5LWJ*D=X;z0hm} M|5p0GZ7s5Y0Yezf;{X5v literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/base.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/base.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ca7372ee150e02d4eb043bfe210ea23191675c3 GIT binary patch literal 4224 zcma)9&2JmW72nw}E|;XfEI3ZwCfiSmfg{94-GdOPwcVsGny5gm0tKUDz2Xd|m6yBB z?9#G?CD2v|awyzCpytB2qg?!0L_B)V41+pB zKZ)`@7-TZo2R#@?ve@wb0Np68h7>v_?5ohUC zUAdQUYQ0FebUX~TwjvMKWqA*U3XY3R{RXV}@R&Jtq+I5tji)0`d zFfJE~$(tUpTt@dZrkY`O>0$Vp@%%lpxpOy4ABKZC5qZ^o`#U=$ne_#3g{V7oPPsG8 zxJYnvJLCxY&Mv%TV{{}t5PbvxoUqFGUFI^M`R4KR)R#7@X-`k=pCxJlMq1J@IC|b3C=44e0rKY3^7Pf6|(?%eL0I zJ*Tk=jek{Z>(6Q1scEe_+CsWo@8B{g?dk$&*)BV)h)8Aono%yS8m}0W26p<_T6e$R z>EdLmrnG9x@?-^b7iV*q^;{3Mr5SBS)4t3ZVI6%&i|4E8{_;!Ln4bCkIl8b)FPh-$ z??p*}oJ57tc1f-kME$VyHQ6fAP(KSJ!~A>FEK#DkD@RPIBB+Pxf1dhhae2#{Z);;Sfn zUNtw2X02T)6%BiuALOduRSs<-($%f1x>*r#?OuW|y@UqJZLH94d%)NQc9pG~Hd|qy z{@Kpbf2d`%w&|lL6kgRltEg>r1)S8XxtmMRm+GEv+U9X*286V$J{{)tYoI~#O=I96 z&?peuI6GzX%_ee9AcA?#D6D51*-p(>V}jUrKy>Fi(cO}9>(qSKK*^qY+&*P316&jX z9pHjXmZf0`N1 zm-nELw{Fa*M8BMg_5lg>F`>K+$7bu;+*=8f|S%0f=GSDo@dzkl`upEhvBv__qr z$moANI$2kqtwRY`QNhH(>9p z4zLPw9Z{0fC7mXy7LxIh#15m!%F4$>We-J^sz#QIa6c| zk>7-l@>^7_qv$pFk%($X>$S&ejJP_i+)n$+#h5I=jv2qkKgaXN@I8}Vb$oV>*)KfP zb{GD=1T#mE9lv&Np0xdWcfJs>n-D{`s-5M}Xdvd?f%P!hBjPJ(+grJ!T<*YxW&iK$ zm)GK0i`UY=V6DDbG3@((kK z2VNe-DlT2_H^BUR{BueV38_|qNo|vm$;AavYtLK(Vx7~0M(1f+jnZB7{p~K>?zSmI zrZgNGvL6yKj}vOQ!|;=Fl++`QFyvW34CU8IT}n_T<$IEhtb%K@J4yPfPMs3>1&$(| z+rlcbP~s>(6tw4@3J*ImmrX`L`-N#Qd~Ply-*voqS6R((C{g}-TYe8qs)l|F30bB7%he?PQr;LBags~A{pxxVT=eVO q`5-#N1X6u&Px^v%GVHxmo!z?>Qgh0fy@fXO%r-8mZ7!j8)%q{Mc}h$G literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/bbox_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/bbox_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e862576f0d3f4999bc5c8804976974fa0932080b GIT binary patch literal 6688 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/ctrgcn_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/ctrgcn_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..77001ca4d33806c519387c45b3294f8d84102f2e GIT binary patch literal 1983 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/movinet_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/movinet_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..981fd7a86054b8baa62190c0f172bbec8facde3d GIT binary patch literal 849 zcmYjPy>1gh5T3o?^>0u>JORx$7NSH5K?F*gxUocWva~wiuFb*v&g`B8iRf%8MP4E) z{WjFwQu!6Am^s_hjkTlsX4mt5GdI;>&;_(V;e$*Vz+VDw3lV(4W5?(uNTwlWihc7^ zUwYEl!7@xk1~QPLj+Sv6W9-RD^JORPFi_!R_X#dR#*%MAausj<4NH5HO(5y)u_lc7 z9{Pm2@apr&Pm?{WAjB^+tFBarvRrqzF0>T7vNor`w9P*P`w9bv;v}TrJC0dXX>bn#q#@FVu6JF1DaNX%@;ULHjABwlMePt>4I6l5Pk>#)1a@qkcrLW-l`@VC zQIth31PTnS((@g29U*d^Su4a2{#~oL(~GS9F6M<+_7J{)GhLY~SNMdo(^V#=RyT!I z)pS`&rHgVg{fe?I!keO0wIDQF-5UB%J<>%2hwSb}tBKJ`OHP+3qb{hUOFT9}_Zz2f zI0lA#OMFB19Q);h%q(n^Jh(H;$Meek%#5VB4Qascp0`Pl_en&vD6^#!!gYnfKGvGz zz7RjwnLgY!`pr2N9vr8XE3JiS(f0Ay5VwiZb@12-9f!X6%x`i@-<{=^)+(=ysfoSqQ~t>Z>53R|07LnCp)3|Gt0X1loAEM*MwoZcZM{+2KrK_krZ WcZc@g(_otw;ShO!M!(2^$^HXALC8b^ literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/ms_tcn_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/ms_tcn_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..69bf0c630a32e2283f6de48e15a10274e9d37546 GIT binary patch literal 4314 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/pptimesformer_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/pptimesformer_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..966829f0fec131b5cd1f901869c0eed9548c378b GIT binary patch literal 2160 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/pptsn_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/pptsn_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..90b5293cc4fd05b66b460a5a7cafad5ebf24d51b GIT binary patch literal 2874 zcmZ`*&2QYs73Yv#lKUY=F@(TLla@%@NE;*z#YuY*+SrPe#zkBqhy)m56c8iMa7CFP zn;}=S)a}Uzd??gYFYU<&dda1S{w2MZwbgRbV=X)jv}mY5;CkC&eq9~z<~x(^M}mF)-C0~S0d z*q+hvU1Dcrx6kVK$6WDjtEyDrs-NEyd{iYTa_eOHaZ#iC(EwvVp%NV?Iu+O`mkvbDqiHtZge;_#m%vMQ3-wuJz}}1%#pERZ^_S zX~D@niF_?uFt;&ycm7gYi7V|r@Ou$YW#2#H=~$8@d7(0%f=j9-P0qRcfuW7J=avMo zcnC)_Uagl%GVBfsxdsV^xQR(6^Ag^|^rvgP+qdtoz3H#*-oCrN_Su5vW@To@h^{okl9U7qsJ&FbGt3`=)YnI!)kVcj5BY6fD?i2n~$YTT|xS zo5Q!ZU;fWmzk2Cr->jEr_eD7?>#mZ+amp29siyirzx7RH0pMfS-6_OyAXwc#On4a* z+h49*<#;4j?S&2egmq_L3blm{R~GElZGJKw5!MMsfKbGmVlxeJfO43(I>dmTJy-2c`h^&AFEuFTt)1=iGfZ(tJp)mZy`0qz@^Wc4+ z-wWdepwX}!Hx5Rsh$K*gqz5A|L@G}bA&Y~o5Hdx29~=SX%7f9UD)W%|!RSm~$9`*g z%2z?IcO2%hWvgSZFvm2RjZY5}`}>}$>C^LTSLivIMJ=Lxn+@VA54Z7@FN0Lbons~# z;k7^}Ajeu44jPezd~nbG-w{Ai-BHo~cDt!Fe?%=uR#KI4`dV{jU7Ou55w zL#<*1+_0TVp6mGS_ANyvpngV#BHCxlC;k^#>mL=TI)Zesep33wf&dLj zr^fjdVyGAWu(^@szQ5ii%V1vvEI?}?H_>1&Rp%T`NuBb$l!SFnGu*vugpd-tm2>@1 zB$`;h&`ild85K%yKD(*jQ@2ty&xl%4-e{J(#WklXc{W1E&o{XI9%BY2Hou>g^nayQ z9`TXvd+H~+h}vnqt6e3vT)hRUS|>v3sVh-uOW)RsQnUNDJM|K#=(Nw~j*Hd=z!$&A z`y~}@r+3|4HaljAt%BOt`SbI{nd%}9-+(4i0BA$79s+H`5Vbi@iSLEs=VP8uSKKfZ zMFg=;EnF9=>eFf80jZa!Xb{OX4a0@gy+$gO-l_*erCm~mc!q6yE3?dA{?2>lT3c)M zSJZ&C38?VDNMptz&o%04aBJ}H+H_?BXd76w579yuRYUDzF+uk}Q}oC73UjG!bV1G( kq|!St99kEqu1W9LO*q~o5Gk*Lc*{Mu3J7XGj`afjKY>I6NB{r; literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/roi_extractor.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/roi_extractor.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e70db2971d23fa9c0f8652eced55307e1d8e63be GIT binary patch literal 1151 zcma)5J8#rL5Z;%4_9b@^lm-cbC`}QeAWcP7nT zWj5*q6GDu25R1WvK}d1->4&uij~k0W%NB)!g9NW(j?Y2tX8=bUc1RW76=ucJ6V|X( zS^|BFT__PkKN;L(-=aNDR^kSvl>^MI*Mz z4w(o4cQOe^=UDl+{65G_cW*PHK2YwU*2${pg)V*A@#Vv;Dznu2*j3W$(pJWcEVa&u z`? zw92eNeO1bLv$W`T+72<8haX%vVx}>*rJPsMCnnxLhHIc${Go_2j@dFg{CRby-AlN^ gZu4RFW~wvSt}QugY3LYu*roFb%V#m^Xt>UQ0kEtLqyPW_ literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/roi_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/roi_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..194ca51517a9e856346453447ccd9b830f44dc95 GIT binary patch literal 4722 zcmaJ^TXP&o74Gi2?9A-NiYz-4BxXWU6q|qu4g^StWtIozkSZus#SfrL;sx@;Z{fM$C>~ON`r+(-h@=inYo2*^Gj}_R)eF56$x^`=CFqD}B z>%H-VtJiLR`ty}Pzy8O#p&vEx)iidF1f zIz0z{SGxDaAy%v~w#KHc;!|EZQ?K%~~O57I3ha`=&x`&WJ{}Yr*W)Jww`aN-U?wB2O&OZ266++*Q$&0Uz@((jr#xg6jZaEm`vC4|QVOhlG zC{E+ypeW-}FV6RN#|Lq$RC-XX$FYKz*?mLE639Sgc`(kjH^|EuE^jEZp!*N;w1wvT zG%U0I`>vIB)BQowUeeAm%e6~OXpxV#H_6nf(6!!hlwuO?k5eg!nRdG=B)nof#RAcw z801Bn=3OjiB(KFVnZ-7t$KMK;8Vw4aX0SuVBT9p&8=^O&QwTiU;MYqXyg z+8?I3vSFd?c#(96X;EM>9PIWJyP{KWt4`yjpU_UJw{8FKXus%=0GjqKa+(jccV|0O zS*K~2m~Exgw1TtlCrmvHJpOqjduj9gX?{ED4Tf1^+2=2Bj@77}6@?kyv`Bn7klAQ+ zcOmO-M>=k^!y zfQ;hdwA*pt<xXxsC z0h`kwE!IF(!TD$gnk_J>MZ{gy3D-~wO+D!>^xy{uHi|F=3)|sG6qOu`Mmx^2I}Oa3 zi+aaJtq>fGX;{_ZL!tEUA$uDj{mIpL_VT!APZ0O^a+|)%eY)weyEjbBEFO-Ef@EUE zmzc~X9^|nJ6UZRzryQD6wu5#P&4AH|e&6>{nDHIqO-3^>v&rTEg=Atjw0>nc!p4i2!OTDZuMLtpnhmakF&hl*26s>q zug$iJ9a3~^3$sy0nNaTUXtTuaycS(%in z!e3!xGD;T+YJYDm0d+fCFwi9vlmKxuvp*g7OEV?a7GQ17p>ELZZxVS6q+?BXzQ&Jf z{PdRf`BNrnf!l?gwO(ZL7LQ=T?!#r#fGtlh{eR56WV7?935HzU*zm8xpteO#y+#)7 zqpq!$yz)&=`z2$c6yu!=wKMFNs7DkQ9m0CuBUtNW-nyuUYe#++nJN^uE;22zYM8-; z-PgCjdCP4Ze{?r9cNl)=9^@2fJ)pj@?r-tFphy6lHxb)K)Q<)qJOwvJo@>Z; zT(R8Va4^=bF3dRjU=PK>9#k{alnr4|KwNv~0%yZni^AC>+}o`MJ&}rZICqMfUP)zV z0+!9T+w`JOL=wq}oDN&+7RG*$X6hlowuCShpi#1=L~DQ1XF+Z9^y3vavkn|-ou>af z$OfJ^zus<8Ii9Dx8Ore}NpL;dgIOlJkq{I^`^MC}>P7mNN+64g2@YG-?Gd3(qA;+< zayJ_e=LNGl%=bvdl+IrRcNMLOK>{ZH`2hrP{UcZoYJnd_K|Q)CR+c|gB#neb#R9_5 zCHyJUg<1gt#^#E${||Z~gHr$i literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/single_straight3d.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/single_straight3d.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e3ab758f7d0b9648111f88957b889e67e9e0a413 GIT binary patch literal 2260 zcmaJ?OK%)S5bmD$%s%2cfrLE7!il|DQ6lkDWXKbOP(ZeY(8|%Mv)x{gJv+1Ro=t3P z_JSkjfO6m;*vI@E&VA*S8z+R25PUUjgNY)#)iu@K)m@LS`ljr35{CA(|D$ZT8T*AM zr<;$-=NM)ML^8>9Hkg0;*cmu{&btFoI?~PkaWDw5=1D&f$I&3-Oa+JW5&MG4K!(ql z43)E$9JmL3(2{(W^`lp~mpy#tfcClVu6*+#z4!gv%B?$V->j^@;`8NbrF?KJ&ql?N zq)#{Rcw%mYQEb2^8#s~=+}Md-bT9Vf06mo5=WK(^NXE}%SewY!GdA#LTXygbo->aP zLfCW0o?p$1QLdoz-fpGEuqyS9yZav+Wlb+{-hBfV7M4YgH-H*9r7c_S$Vg`6 z32aKoB_ujDUwoQXn`x!SlTyPD+O@4_ZIqXf#oT-w|D&uQThFL`LpQH*7FXy+B6PVv zM})4`=ZU-p@{-#)O^3NKCQV$gR*oo-~gGIRFY_4SD^hYBLJx;_z7;`!l4 zxlWc+MAkQzkY;_J9OR?OMw`_Qxis0+XQ1aIhUtMMalpGg;BAak-SIf}_MiJ#-;|O| zCvhE8Vx2VNY23juR23;Q}CJsw1$)lx0Ra6Z2X_sBC!x-6~kNs z8KIybCGZq6f~UY+>AY}%a&{ct>o(V}>8lV#xd!v3v))*V0&{2Sn&rE%KW=g}&rCHe z$CKq{(n2b)u>EUqeAqvzzJn z=@8!=G^jvQ#&THMXt0SCl>kUV+aTG{VysdU8PF9CXI-tT*8>|K2kS#zZI(dVJVE(- zJVIYYL3hC~@&%OjqLc6iC*Teb{^~ky-bHEeU-`cm=tm6*Yf6qep`z9i$lBWdenhBR zkfEtfQo_b*PJBB}ccvmg-U-uGmcuk{&_+{wX-WaxIYzgk%5&@zGRz4fk|s#dRK|pb zhBhPSIcPBd-`@Q_y0qXma{acZ1OQGqAh=W%c+JB4h&_;wB7?_JBP5dE)AWE t`MWlro`~Rw;eSoPi00~3wl!8Za24I0`@2jbF$6kMr;V7m2|(S8{BQDEIaB}u literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/slowfast_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/slowfast_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f7c5b6105e48539d1054f05059e00e71195afa93 GIT binary patch literal 3625 zcmbVP-ESMm5x>1J9*-wVmSxp;oAv_qLu?h*u2Gs+bRB5B%*)-bYrfvd zw=H6g8r=X!EavCUQP>TM#mSS_Q|mp8HCXV-VgYwfom0|{nD@ZyG|y~UphL8G|J^&= z56(#43*MoU-{+K_LEqYe@#v6e{eeodB2!5Zxr>iG?Z^+H!L2S~R@Y{v>-53k&&ib9 z++_}P9~0)K&SzFin9mxInq7|ttog|5`YdEE_%=SXT&o*^d6AAD+wlN~wha3>gG|ObJ>nv+xJXMek}-|bah@N&)hmmF_Y`MwCCVYR zva*QTSY$;%R)WIDivDJNIN(LB2HdF2ifXK4nH}>O^xk|3zpeOvwWu4k9+deQmC^il znz>Y<*r=Q7jxXxXspx~jYCwzm8Y$XP%fSu=k5f^O;?X!)S(Vquu`Erw;02gN)!>jG z$<4({hgqJ-dprgMdsOiPUKZ0-;n9?34mQU>_<$B2NgGEM5$Uy2f^O5`NeB@5&8_OcKq?SNabV|&(bxH>IDPiuuE&u!h zgybptv>pKo*hyP04_AhlU`CTQ9wTSfa4xGg;K6L5J_{b>uCFi~!-E1YY(Bl`08yob73HiBS}H}XuX z&TZpa*o@0G?t!NkJVy~;Nbr1#Ty$7m076E_s>J>Ug)a<7TWjY-9zMl*l=N~cC78dF z6|)8Z*Fxo3{XZ+A?in`f)FH7Rhm4b0`@!%N5D4awhAiU#^G%qQh-IN<67XT}b`Nw12LmA)L zy0JNfuec~*S$;b6#Uf`hg!hiXd{jdOW{Bf&Pa$W~1rVi*QX$|-a1;QhEdUNub!^?r ziX`P!jRluFLVIVu&bs#G7_eFgNu65~y=-8vFEWM`?pjBS=cJeCPJri@mD;bJT{q_g+R1sLBh)rSSM67n zv7BqWD0E}HK6u@jYS#XTS;48$jvSA4_#(wX4s#{XQ?ZIico_*Kd`nzGvX0~{NUkEe z21ExrKyK1Y`{ELI{ryA85Aqq&&7_WzBzb0ivBPigzC(-sB+YUz>*kFg?83S|4%3ml zTibh(F<$PDO2!fNcQIMYT?tt=g{+#G+*uuo62C;y-V@SM7DO zPV6sN{rc;FvA$#z|J)|-d1SBJz8w&kM9+_}EN1Sl+3ohwe`XK18}QzRSK1v(TS}v?Lcqa`sh0+*oM>yDa9ItnaUgbkTkJhpM-Pb z7H!}*YVKUxgLCp9yC?3%eiBUFr-WD^udC)ToY>5Rv|^ul&}&Uhk%c{&8L@ER6~CQW zPnIU$Q-ZuF?OAKMEDKm?1!lBZG@XBG;z1F&^f{SxRv~qJ!^^A<7A~hYTQRz^ro6Os zyz#!NoB#x5DPmRvnoglXL7^3YaxzO%B7l?9-p<|a`@e&GBoB3~2KG8`TZ}52U>!%5 zfuD{mZsCkp4X?G7FBO0V7e9m%xN{@m(ubMscr|dLpPgZqbB2X#t!O3(s4^07A^SEE zaFZY5XId2DMDb%J2!Lnj@BpTHazHEISrcEwkvD*7zqV0(f)-HBeHD4+p1uq2RU#)2iYH6JIw<>RL@Vp&Tt_RZ3pN!kf4ZIcp57Z&@Qph z-E$W}piM#(9KrL@4NS}bGIHBC@STu^whuC^)G3~hnIh?pV~+5*e9 z+skNf`(MGGm4+GZEa^b-J|rt~BrujCqrm?jVVuO=$XX4dTSc*zjtldbf#%{HC>ky> u-bO}i;UAL0otbhj%xVip8W1x06a2K^{?F0VWE)7-j!0myk_ZlRo%|O*uhYQ* literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/stgcn_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/stgcn_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6acc1c5e3a1a9cbafe7308279965c39fd2d715b9 GIT binary patch literal 1541 zcmZ8h&2Qv16t|s^$$Yf?0Tj4Ekl--V?r5n5hYA6^E$SkqxwNNfkd?;HOxjE`YbRSe zWF@3l+5=in`~e+_%U<|fIQxb;&A-55;k{&r8R00;&+ple-|zQx@|~Ryf%b>lFhK)LbY7B};?Zu}fh}Cox*>rhJkf^UeMxK*wBQ(B(>^&p zJ{;nw=ZlUH4P8IZm49;j5HkKW7cw2xsmE%p4{8r5CK-<=VV22MAHbk^0A^Meek{YH zRMKB32mXmhO`mA?vZt^4#*vusHKuO)I9Sz9n5 z3P@QOUi|<}L9WR;tyo24mXON&js8L@DcHGHK~zw|URf34wjh9kHB>d|mg#PlWO{iC zfUgQP-3zIpQm&J^>^sKMEz?-xVNG|dR^wh= zh5+PiYTCR3fb-Yn@9*Tn=t-De@Hk1OZrn%vqnXMhsdXJ4%|ank`8*LaAJx1h*?2So z!t_WN<0#|k4`x?t7ry!-qJf{^qb_Ce^xn+x|Ht-Vee?(=xNZmpTnKUqZ;fO{Zpnfi zk?-%kparccVtCEeTZLUw#8FtUEJ~i)!UiOr`A6S^Op~yXeld~$EL7oC7E&6}C zY8s~FAK(7{_|N&TUxCIgU5Fu|+ScV+8eYMC(@Aua=_1S`sqVmG)Lk@qv_4b!p)*cB zQ@xAv+PsI+UVTrRJEK2=NR2?x>d{@wezM=p_cjP@PmQqhbweNZRHN`QIEX?;7ZfqL z1yxn_+!FMC_zlEt!Ct@^bu@nnLQgX3Px8yUeq_T>v_H;)C%?#jRc0F`6av5e2U_1& z_rN!9!>{p_)RS-~Ip_@gb;iwbHID0+?PbgVsUv-!PEm8%)BhX;Ap2GjRY zxfyW7x#@5YQYusQdz?Qj!*rEtaW3+R^IA>n16++@n4OhuBbla<-7xSDPC*(}3k=3< z^gUv;UDtE(w(5Alt9(eAc2n&j%W8&=eFpzPh4&f(7$>?=R|;t`-K~FMt%3Cfsp=iK bj<8XJ_eE3Imk6`Q3*qhdXpg~5T|ntyR2hPJ literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/timesformer_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/timesformer_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a8276cf8d6f21ce78d7cfa2fdcf7a47b5bef451d GIT binary patch literal 1997 zcmZ`)&2Jnv6t`z)XJ^0CfJ&M}B`hw@O0ZgbBPt(hT3Vzk0+Q1xlI4s&n@Q$lv1gm^ zvYZmB2NX_RxU~|OUie42aGo3Dlz#y@@SbNwmX+|v&a?ge{QP^r_onFe+63BfjqhdF zBIFO8EVl+sK7($)gh3KXQTil>4gn znmi%0DT50l0~MUR=QM1~);{UCufQtl)5?FA-*>8BsV8~F^Fn7L zn{TW;QBVjh5?NJu3K9Z5r1dFcKnm0s+;Br!#Y zFIr)vb~5y3OSUga*nCMm5(eOCr@D2JWNJSKN0i3P#7}Vj${NFsLA%YM?dXx&wi3?r zNyej87^4i^O7gP5%?^$gE*~k)ikMw*mIXUf^(=`K1=jF5wj}4#vB-0k{+|ilP2qwh zhrjWpWU&(EM5`McX<-bH;t|`DNrX=97I~bE7(9y|O_Ee5`G`e!ZNMI>SWMD#o1yMj zE;9A;yKQ)(?X!#eUSGfk*Yp>F4BoYpXwljl$1%D%!FRL zVmKIncw_1GOaOYdlkc-)TqZ>>QZT!dPuZ!Oo)ua$P?=;ZFBw2)Z3-|7Z?%9`>#Lpu z$vk|+=-b=BJo$b03os5c^sj-aj1cB2o}+Ts<5MDO2@4 zk*YY%3aL^E^WiaY)f|?)jhcGJ?I8e*=+jsHl1y*PqtbfkajK+R|Zgu#q`f%FiiVkP9q=esNwQ^=69 z&=9*)X#^<#o~;VAAddKOaK?uV>4*(1MzR6jV4MQtIYG~% zYkvow^{(C9gAYV&fpwnO=^kh`N=&Jz8lO>hmOfpUZ$FRKcZ2=|0o4+V literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/token_shift_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/token_shift_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..141da044adaf5e6631b818eacc66d33de21235bd GIT binary patch literal 2325 zcmZ`)OK%)S5bmD$uGfwUQGy7FIe_97Xl23$SwJ36NRT2+U<;wuO0D*E&+gds*mTe0 zcp0B;DF@^mKfpfb!XM$nd2Wc4|3WxGRnMB;SkQL&RzIq`x~jf!isj`tf%d!mvuH07 z@+VFfn+ucs(De^62qI`oGTNsUWh=G%mav7B+L_aLV9ge8>SkWw%ly6%b5HnbkhS_P zN~CkvJ||Cz2t@0Ih?Z;}+sCxOB&==HZC`+O(xtWcEXgHTTNhR{cb`6f@Mybh)yt)t z%Sxp=?CELa=o%s?8|(6l*A?8$KL~Y=S$&^ z;<=8&RjESU@3q?@vHnF)-4rfJa`+!l$}pC^oG3ZBfo^Cy{7(;HJ(GEKMs$H_2+mxsHPBo#?M3?s9)U;)pr)&U#Vtt49|+wf}`zcd{?HS&WfTOp?bgr*UF<0I$#oBhn zQ`rr_=jlXZJepDhDJhdQnR4}}sk?Ji`v)8{*SzwRuo#y~k@FOMdXOK6`||LhP$GmQ z6AV@e=`uDs7=<{SXk7$QclGMk_d>xt7>VIeH-3Hc$ModhO!(zq<#$`hpwKk#a9tbgdHN;C9mH^6lp?V5JMb1b?&*_m> zS$lL~9oa`FJV$P2o!Np`ZsiPZ+%KIoSQFN{h4P+mPc18`=A~aD^i8}vD*^3T7%$JhN&f+* Cl5>v$ literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/transnetv2_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/transnetv2_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c993c178f61231618157dfcc8428f54f7f484248 GIT binary patch literal 1337 zcmZuxTWb_C6izai&CKo=@h*79r$H#%Cn+Lcu@ABc6(5F$Fix`D(YdV2Y^7!T)PfJ9 zzo7+R`fq&Bt55w4f|qkB=emw-%Qo-hXmSJ@1wly6Y>owCz}V82hh!P zFp@}`lY+*S63L{Kv%-m;)^~Ha@L~^qPx`rEbm9&r%Gu`!n5_dijm&6<}_fA4W$lK=@5U*okIlK-{BW+NCTPB4{=Lir8`k2I0%vmrs*(Lk5 zp$%)C1LTsdLyd!oS#_}9! z66t6RECph=MuN$HoR@RfB>c7X^9=FxXxNYTBr3G0{rea6TK? zwqGRW)*{vYGlg8J)mY%`+IO_0z5vJR^JwsfXXYGwn79Gm^uYM+EbTE)Id$pwnSY4G z6H^q)ydhsWZ#hG}H9=l>*^bjV>qK`Uq&r|Dw=G9s#lST*|3h*G61SimJU2uH7ym)9 z;KvyZ22p@QL^%s#Lm@yQ(;WSt5bvf*ew^tDA*)mfjnZf}G9v?DXZy#BOjVx4k_9)X zadAr!Dg)yNE9Asw+*|s=!tmFrP-AWoh1SI{UgN*Qav(o5wcgTLhQ5ggzpnUFp=zC_ qX8DA2XCaMxoo`gSJ@o{X78F9U{NAj_`}mt`FRZuJqxksjJpB#*r%D0< literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/tsm_head.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/heads/__pycache__/tsm_head.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..991d912ede739cc10efb81287b0f5d140318ec74 GIT binary patch literal 2714 zcmZ`*UvCsQ5VyU1yL)?=kWxf}(#lmUC0D^IAoY);wm<_kR1l#C3F#DR<*a>|P4>^# z-b+Yyyc8%875xHjC6M~U*XSpx`nXS3`+%Z8^|hd;GrO1EfmA0uJ7dp|?eYA6zHDmB zC(wSaeJ4MfCge{vCR+`Ri}09lK}aHLOghz@b|}~^rU~mXihWjWC3eRybsECSYi*W)9}OlO7?HU0RtC*%tvec8BAWJ5LY zS@&q?sH7{T)!c)%kmVLF>NkZJ$)!BkU^v&KR0-7F>*p`4Q0(kc@I(97%JPyDa*tJZ zZRyIT%PTO@+*VOsfzzE1dhfqL6pLOe~|O868S)@af~=K zCJ4JdJ}09P7qOV7-KfXAndWPQD3(#$<6+s?=9g7h4B~u&qwicQ67}iqqJ{`p(p+c# zo$H{^w#LCFbOu`FQ8w3&GlAi;iPj6X8DJoH`xeI*pJYVj=*4-{@B&2%DS z(4stwqg|n23N$}|ZX9ZJTR_gMt)1an9~P2|7*=s9-Qk;RXFJo9gUcXMY0e?hWl#Z8 zM;UrnmBsHDp1pYb_is1WZeA$t<;A7jp)*lDF6bUS4S0+Ok&}C5gAVDCb=lAw+QXWp zKUzcQXZk&*BxggiVZmePHOX>ELbXf#5d*6RmQz{MePj<@ zY{9yro++n>{cg3~!Zs@I>XYbj0tFBq(MM2}ZcbGaPk~Q@3VuQGl>Bo|Ev$Yn(#@b7 z0bD9|{`_iRXQ2XoVDD;QNExfGNUCf#$)t)QZL8~mZnK)3BtWg*-_dWtT(j_)HVDsU zlSvs@x+*XxGCe0w{X zA8BjBe2bPjgQC)Pm`LMn`b`ipa2j=fDBc0BXqK#66^FSDJqC~H6x%&^u%k(b5Rdnu z;V~ZW>MSK~^GR<@Au?-lb8-OlpJzyuv6Ly!T&6oNC zSr4pg1Y$U446F38WNirOgs+{Gq-Vjm(7)jhE$IOED$527khbCVnDnr3XhCl40`58j zTnKj%U(dG71Vag&#S-9=fvQH*1Uk`!v|VvOGXBf_k3DzzTvb)=TPih~9^C;IRU?YV zREF*d0i%%6s{3O3@UDPfq%bq~|4ISRrxW)L1~6f!)xxWjmiJD1+ra%2B3q}GrzvlN zYBfeAeSpSzg5?tO8jo%d&vS1dn#SJ{aM{}8PGsO+GwY(STJ@qXwtD?6i_go#MV872 z`3R6z0t#2F(pMvP%6cp8M2WP7a?38OuAp}cca#JOjhlJ35M3ZUAbq(6QOw&Q{D#kb z>a!E{1iWoJ1DKlzJcwdy#4@3ZV;JQ)Pzqd|M(k+(QHIbmNKhWJ8Jj}7n11fP zHDi~ft=AzJB45|(hSY2Ew)Mau?lW1@xN20ghyiDRcpfItZ100jsE#G1R5X;Y-S zOWCoio@^k8!o9br1n4D~K183O*YZ~M_ zEjw9r;DsI~!hPC$M(z;q^5!YwO<|vyCp2txxfmvPH)VxmKg|V`m9s62VKFMtDcAetzS__duJX|!iZiB^Q2tt)m%)brXiuPeS4h7|{Mlw% z_`9NBrAaEl8$OOB&7*ja<+;fI&js#g@Pagl|KX_g6T!-n6muV0p;QzneSeLoF&<*8 z$dk11Cx!HPM`^~>yzj?a*YUSS!bVxS;iK(Z&IaP^Yg-aL+|Em=$MJm-uLX1G9F&n{ zWm>EyS;5dfs(h_laJSz1V*ZdS`77%kkauF1iNHT(*+^g@c_9ZZ11T-jEFClXnxpm4 z=bjFZ7^J+8>@&XrC>1%&;1HYnv40?rj|$0sFc}R*Uiy${?UR91NRZBQwen_ofG7(C z@BjJ>j=yg7e^~wf&fnwH8Os?g37r@dGci*#aekve zQ%WY*gha-q0kc_JoK9?RoEfkJ%|77pz?7eqwwA3k3VJ6uIl+7Bg0=~lcY^jUP5_6E zZeU34SUtg!Tbz|Ff|?FkDW@$%he5k)sL@c!%8ly&h$?Shv&w{0NbIMo$qxHN>_9Ft zp2|ThXg_JfXU=88_^@V$W&SjOyly zqUYqrJ+aZd#qxtFNde5YxPHAiltnB6y{PRC8RwZeOt~m}gMy0;aNFC1=2N{=~FXHj2%O3519n~ltQY??rJQL-6W3IJ4ey_RN9T! z``}-Xz^JT&V7X2cu%c{&T3*Hp6Bkf<1?Bf&O&@?%wKd(<)Th1#jlu-mra|jJi+V4| ztFv$yjbkk7Y+$hw&^qLYAWX^))K7wBYss9L2-fjS;1!^Cf3G;wslsCUsq*^;k`MHy9Od(_ew{{<2Os-u zb@@AwM6L=srP7-55c%_m(HsG)1QJ6{yWLlm3tFTCHMf5#fG+a|+C~Q|E~MCa^QD@; zHE9D)$4Gj4ZK*Vw)~8WyFa!+GUvT~}j9Hsn>~X5Pfg@KT)s&2T0$zwBXsc0%ayyE?AF*t@<3tfJVo+Q7tDrkfUd7XW3RAT-ZRA*FSrjcC2^&Zv zRwaITAUP;x1D9BayIg~G`GtFF#nb!2lKdEUtLC)Od9H~`^G{7l)-HSjNE?k@Df+1@ w<*~$ety&9T0J?i-2107z3y0EOq#MZnst)%X?0TIocX^ezjW%sl+q_8s0}Fy}AOHXW literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/adds_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/adds_head.py new file mode 100644 index 0000000..3b1cd24 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/adds_head.py @@ -0,0 +1,146 @@ +# 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 cv2 +import numpy as np +import paddle.nn as nn +from paddlevideo.utils import get_dist_info +import paddle +from ..builder import build_loss +from ..registry import HEADS + +MIN_DEPTH = 1e-3 +MAX_DEPTH = 80 + + +@HEADS.register() +class AddsHead(nn.Layer): + """TimeSformerHead Head. + + Args: + num_classes (int): The number of classes to be classified. + in_channels (int): The number of channles in input feature. + loss_cfg (dict): Config for building config. Default: dict(name='CrossEntropyLoss'). + std(float): Std(Scale) value in normal initilizar. Default: 0.01. + kwargs (dict, optional): Any keyword argument to initialize. + + """ + def __init__(self, + avg_reprojection, + disparity_smoothness, + no_ssim, + loss_cfg=dict(name='ADDSLoss'), + max_gt_depth=60, + pred_depth_scale_factor=1): + + super(AddsHead, self).__init__() + loss_cfg['avg_reprojection'] = avg_reprojection + loss_cfg['disparity_smoothness'] = disparity_smoothness + loss_cfg['no_ssim'] = no_ssim + self.max_gt_depth = max_gt_depth + self.pred_depth_scale_factor = pred_depth_scale_factor + self.loss_func = build_loss(loss_cfg) + + def forward(self): + raise NotImplemented + + def loss(self, inputs, outputs): + if self.training: + return self.loss_func(inputs, outputs) + else: + abs_rel, sq_rel, rmse, rmse_log, a1, a2, a3 = self.get_metrics( + outputs['pred_disp'], outputs['gt']) + outputs['abs_rel'] = abs_rel + outputs['sq_rel'] = sq_rel + outputs['rmse'] = rmse + outputs['rmse_log'] = rmse_log + outputs['a1'] = a1 + outputs['a2'] = a2 + outputs['a3'] = a3 + return outputs + + def get_metrics(self, pred_disp, gt_depth): + gt_height, gt_width = gt_depth.shape[:2] + + pred_disp = cv2.resize(pred_disp, (gt_width, gt_height)) + pred_depth = 1 / pred_disp + + mask = gt_depth > 0 + + pred_depth = pred_depth[mask] + gt_depth = gt_depth[mask] + + pred_depth *= self.pred_depth_scale_factor + ratio = np.median(gt_depth) / np.median(pred_depth) + pred_depth *= ratio + + pred_depth[pred_depth < MIN_DEPTH] = MIN_DEPTH + pred_depth[pred_depth > MAX_DEPTH] = MAX_DEPTH + + mask2 = gt_depth <= self.max_gt_depth + pred_depth = pred_depth[mask2] + gt_depth = gt_depth[mask2] + + abs_rel, sq_rel, rmse, rmse_log, a1, a2, a3 = self.compute_errors( + gt_depth, pred_depth) + + _, world_size = get_dist_info() + if world_size > 1: + # educe sum when valid + # TODO: there are some problems with multi gpu gather code. + abs_rel = paddle.to_tensor(abs_rel) + sq_rel = paddle.to_tensor(sq_rel) + rmse = paddle.to_tensor(rmse) + rmse_log = paddle.to_tensor(rmse_log) + a1 = paddle.to_tensor(a1) + a2 = paddle.to_tensor(a2) + a3 = paddle.to_tensor(a3) + abs_rel = paddle.distributed.all_reduce( + abs_rel, op=paddle.distributed.ReduceOp.SUM) / world_size + sq_rel = paddle.distributed.all_reduce( + sq_rel, op=paddle.distributed.ReduceOp.SUM) / world_size + rmse = paddle.distributed.all_reduce( + rmse, op=paddle.distributed.ReduceOp.SUM) / world_size + rmse_log = paddle.distributed.all_reduce( + rmse_log, op=paddle.distributed.ReduceOp.SUM) / world_size + a1 = paddle.distributed.all_reduce( + a1, op=paddle.distributed.ReduceOp.SUM) / world_size + a2 = paddle.distributed.all_reduce( + a2, op=paddle.distributed.ReduceOp.SUM) / world_size + a3 = paddle.distributed.all_reduce( + a3, op=paddle.distributed.ReduceOp.SUM) / world_size + return abs_rel.item(), sq_rel.item(), rmse.item(), rmse_log.item( + ), a1.item(), a2.item(), a3.item() + + return abs_rel, sq_rel, rmse, rmse_log, a1, a2, a3 + + def compute_errors(self, gt, pred): + """Computation of error metrics between predicted and ground truth depths + """ + thresh = np.maximum((gt / pred), (pred / gt)) + a1 = (thresh < 1.25).mean() + a2 = (thresh < 1.25**2).mean() + a3 = (thresh < 1.25**3).mean() + + rmse = (gt - pred)**2 + rmse = np.sqrt(rmse.mean()) + + rmse_log = (np.log(gt) - np.log(pred))**2 + rmse_log = np.sqrt(rmse_log.mean()) + + abs_rel = np.mean(np.abs(gt - pred) / gt) + + sq_rel = np.mean(((gt - pred)**2) / gt) + + return abs_rel, sq_rel, rmse, rmse_log, a1, a2, a3 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/agcn2s_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/agcn2s_head.py new file mode 100644 index 0000000..92cb5e4 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/agcn2s_head.py @@ -0,0 +1,59 @@ +# Copyright (c) 2021 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 math +import paddle +import paddle.nn as nn + +from .base import BaseHead +from ..registry import HEADS +from ..weight_init import weight_init_ + + +@HEADS.register() +class AGCN2sHead(BaseHead): + """ + Head for AGCN2s model. + Args: + in_channels: int, input feature channels. Default: 64. + num_classes: int, output the number of classes. + M: int, number of people. + drop_out: float, dropout ratio of layer. Default: 0. + """ + def __init__(self, in_channels=64, num_classes=10, M=2, **kwargs): + super().__init__(num_classes, in_channels, **kwargs) + self.in_channels = in_channels + self.M = M + weight_attr = paddle.ParamAttr( + name="linear_weight", + initializer=paddle.nn.initializer.Normal(mean=0.0, + std=math.sqrt( + 2. / num_classes))) + + self.fc = nn.Linear(self.in_channels * 4, + self.num_classes, + weight_attr=weight_attr) + + def forward(self, x): + """Define how the head is going to run. + """ + assert x.shape[ + 0] % self.M == 0, f'The first dimension of the output must be an integer multiple of the number of people M, but recieved shape[0]={x.shape[0]}, M={self.M}' + # N*M,C,T,V + N = x.shape[0] // self.M + c_new = x.shape[1] + x = x.reshape([N, self.M, c_new, -1]) + x = x.mean(3).mean(1) + + return self.fc(x) diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/asrf_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/asrf_head.py new file mode 100644 index 0000000..c3aab77 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/asrf_head.py @@ -0,0 +1,212 @@ +# Copyright (c) 2021 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. + +# https://github.com/yiskw713/asrf/libs/models/tcn.py +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np + +from paddle import ParamAttr + +from ..backbones.ms_tcn import SingleStageModel + +from .base import BaseHead +from ..registry import HEADS +from ..weight_init import weight_init_ +from ..framework.segmenters.utils import init_bias, KaimingUniform_like_torch + + +@HEADS.register() +class ASRFHead(BaseHead): + + def __init__(self, + num_classes, + num_features, + num_stages, + num_layers, + num_stages_asb=None, + num_stages_brb=None): + super().__init__(num_classes=num_classes, in_channels=num_features) + if not isinstance(num_stages_asb, int): + num_stages_asb = num_stages + + if not isinstance(num_stages_brb, int): + num_stages_brb = num_stages + + self.num_layers = num_layers + self.num_stages_asb = num_stages_asb + self.num_stages_brb = num_stages_brb + self.num_features = num_features + + # cls score + self.overlap = 0.5 + + self.conv_cls = nn.Conv1D(self.num_features, self.num_classes, 1) + self.conv_boundary = nn.Conv1D(self.num_features, 1, 1) + + # action segmentation branch + asb = [ + SingleStageModel(self.num_layers, self.num_features, + self.num_classes, self.num_classes) + for _ in range(self.num_stages_asb - 1) + ] + + # boundary regression branch + brb = [ + SingleStageModel(self.num_layers, self.num_features, 1, 1) + for _ in range(self.num_stages_brb - 1) + ] + self.brb = nn.LayerList(brb) + self.asb = nn.LayerList(asb) + + self.activation_asb = nn.Softmax(axis=1) + self.activation_brb = nn.Sigmoid() + + def init_weights(self): + """ + initialize model layers' weight + """ + # init weight + for layer in self.sublayers(): + if isinstance(layer, nn.Conv1D): + layer.weight.set_value( + KaimingUniform_like_torch(layer.weight).astype('float32')) + if layer.bias is not None: + layer.bias.set_value( + init_bias(layer.weight, layer.bias).astype('float32')) + + def forward(self, x): + """ + ASRF head + """ + out_cls = self.conv_cls(x) + out_boundary = self.conv_boundary(x) + + outputs_cls = [out_cls] + outputs_boundary = [out_boundary] + + for as_stage in self.asb: + out_cls = as_stage(self.activation_asb(out_cls)) + outputs_cls.append(out_cls) + + for br_stage in self.brb: + out_boundary = br_stage(self.activation_brb(out_boundary)) + outputs_boundary.append(out_boundary) + + return outputs_cls, outputs_boundary + + def get_F1_score(self, predicted, groundTruth): + recog_content = list(predicted.numpy()) + gt_content = list(groundTruth[0].numpy()) + + # cls score + correct = 0 + total = 0 + edit = 0 + + for i in range(len(gt_content)): + total += 1 + + if gt_content[i] == recog_content[i]: + correct += 1 + + edit_num = self.edit_score(recog_content, gt_content) + edit += edit_num + + tp, fp, fn = self.f_score(recog_content, gt_content, self.overlap) + + # cls metric + + precision = tp / float(tp + fp) + recall = tp / float(fp + fn) + + if precision + recall > 0.0: + f1 = 2.0 * (precision * recall) / (precision + recall) + else: + f1 = 0.0 + f1 = np.nan_to_num(f1) + return f1 + + def get_labels_start_end_time(self, frame_wise_labels): + labels = [] + starts = [] + ends = [] + last_label = frame_wise_labels[0] + labels.append(frame_wise_labels[0]) + starts.append(0) + for i in range(len(frame_wise_labels)): + if frame_wise_labels[i] != last_label: + labels.append(frame_wise_labels[i]) + starts.append(i) + ends.append(i) + last_label = frame_wise_labels[i] + ends.append(i + 1) + return labels, starts, ends + + def levenstein(self, p, y, norm=False): + m_row = len(p) + n_col = len(y) + D = np.zeros([m_row + 1, n_col + 1], np.float) + for i in range(m_row + 1): + D[i, 0] = i + for i in range(n_col + 1): + D[0, i] = i + + for j in range(1, n_col + 1): + for i in range(1, m_row + 1): + if y[j - 1] == p[i - 1]: + D[i, j] = D[i - 1, j - 1] + else: + D[i, j] = min(D[i - 1, j] + 1, D[i, j - 1] + 1, + D[i - 1, j - 1] + 1) + + if norm: + score = (1 - D[-1, -1] / max(m_row, n_col)) * 100 + else: + score = D[-1, -1] + + return score + + def edit_score(self, recognized, ground_truth, norm=True): + P, _, _ = self.get_labels_start_end_time(recognized) + Y, _, _ = self.get_labels_start_end_time(ground_truth) + return self.levenstein(P, Y, norm) + + def f_score(self, recognized, ground_truth, overlap): + p_label, p_start, p_end = self.get_labels_start_end_time(recognized) + y_label, y_start, y_end = self.get_labels_start_end_time(ground_truth) + + tp = 0 + fp = 0 + + hits = np.zeros(len(y_label)) + + for j in range(len(p_label)): + intersection = np.minimum(p_end[j], y_end) - np.maximum( + p_start[j], y_start) + union = np.maximum(p_end[j], y_end) - np.minimum( + p_start[j], y_start) + IoU = (1.0 * intersection / union) * ( + [p_label[j] == y_label[x] for x in range(len(y_label))]) + # Get the best scoring segment + idx = np.array(IoU).argmax() + + if IoU[idx] >= overlap and not hits[idx]: + tp += 1 + hits[idx] = 1 + else: + fp += 1 + fn = len(y_label) - sum(hits) + return float(tp), float(fp), float(fn) diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/attention_lstm_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/attention_lstm_head.py new file mode 100644 index 0000000..24c31ad --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/attention_lstm_head.py @@ -0,0 +1,288 @@ +# 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 paddle +from paddle import ParamAttr +from paddle.nn.initializer import Normal +from paddle.regularizer import L2Decay +import paddle.nn.functional as F + +from ...metrics.youtube8m import eval_util as youtube8m_metrics +from ..registry import HEADS +from ..weight_init import weight_init_ +from .base import BaseHead + + +@HEADS.register() +class AttentionLstmHead(BaseHead): + """AttentionLstmHead. + Args: TODO + """ + def __init__(self, + num_classes=3862, + feature_num=2, + feature_dims=[1024, 128], + embedding_size=512, + lstm_size=1024, + in_channels=2048, + loss_cfg=dict(name='CrossEntropyLoss')): + super(AttentionLstmHead, self).__init__(num_classes, in_channels, + loss_cfg) + self.num_classes = num_classes + self.feature_dims = feature_dims + self.embedding_size = embedding_size + self.lstm_size = lstm_size + self.feature_num = len(self.feature_dims) + for i in range(self.feature_num): # 0:rgb, 1:audio + fc_feature = paddle.nn.Linear(in_features=self.feature_dims[i], + out_features=self.embedding_size) + self.add_sublayer("fc_feature{}".format(i), fc_feature) + + bi_lstm = paddle.nn.LSTM(input_size=self.embedding_size, + hidden_size=self.lstm_size, + direction="bidirectional") + self.add_sublayer("bi_lstm{}".format(i), bi_lstm) + + drop_rate = 0.5 + self.dropout = paddle.nn.Dropout(drop_rate) + + att_fc = paddle.nn.Linear(in_features=self.lstm_size * 2, + out_features=1) + self.add_sublayer("att_fc{}".format(i), att_fc) + self.softmax = paddle.nn.Softmax() + + self.fc_out1 = paddle.nn.Linear(in_features=self.lstm_size * 4, + out_features=8192, + bias_attr=ParamAttr( + regularizer=L2Decay(0.0), + initializer=Normal())) + self.relu = paddle.nn.ReLU() + self.fc_out2 = paddle.nn.Linear(in_features=8192, + out_features=4096, + bias_attr=ParamAttr( + regularizer=L2Decay(0.0), + initializer=Normal())) + self.fc_logit = paddle.nn.Linear(in_features=4096, + out_features=self.num_classes, + bias_attr=ParamAttr( + regularizer=L2Decay(0.0), + initializer=Normal())) + self.sigmoid = paddle.nn.Sigmoid() + + def init_weights(self): + pass + + def forward(self, inputs): + # inputs = [(rgb_data, rgb_len, rgb_mask), (audio_data, audio_len, audio_mask)] + # deal with features with different length + # 1. padding to same lenght, make a tensor + # 2. make a mask tensor with the same shpae with 1 + # 3. compute output using mask tensor, s.t. output is nothing todo with padding + assert (len(inputs) == self.feature_num + ), "Input tensor does not contain {} features".format( + self.feature_num) + att_outs = [] + for i in range(len(inputs)): + # 1. fc + m = getattr(self, "fc_feature{}".format(i)) + output_fc = m(inputs[i][0]) + output_fc = paddle.tanh(output_fc) + + # 2. bi_lstm + m = getattr(self, "bi_lstm{}".format(i)) + lstm_out, _ = m(inputs=output_fc, sequence_length=inputs[i][1]) + + lstm_dropout = self.dropout(lstm_out) + + # 3. att_fc + m = getattr(self, "att_fc{}".format(i)) + lstm_weight = m(lstm_dropout) + + # 4. softmax replace start, for it's relevant to sum in time step + lstm_exp = paddle.exp(lstm_weight) + lstm_mask = paddle.mean(inputs[i][2], axis=2) + lstm_mask = paddle.unsqueeze(lstm_mask, axis=2) + lstm_exp_with_mask = paddle.multiply(x=lstm_exp, y=lstm_mask) + lstm_sum_with_mask = paddle.sum(lstm_exp_with_mask, axis=1) + exponent = -1 + lstm_denominator = paddle.pow(lstm_sum_with_mask, exponent) + lstm_denominator = paddle.unsqueeze(lstm_denominator, axis=2) + lstm_softmax = paddle.multiply(x=lstm_exp, y=lstm_denominator) + lstm_weight = lstm_softmax + # softmax replace end + + lstm_scale = paddle.multiply(x=lstm_dropout, y=lstm_weight) + + # 5. sequence_pool's replace start, for it's relevant to sum in time step + lstm_scale_with_mask = paddle.multiply(x=lstm_scale, y=lstm_mask) + fea_lens = inputs[i][1] + fea_len = int(fea_lens[0]) + lstm_pool = paddle.sum(lstm_scale_with_mask, axis=1) + # sequence_pool's replace end + att_outs.append(lstm_pool) + att_out = paddle.concat(att_outs, axis=1) + fc_out1 = self.fc_out1(att_out) + fc_out1_act = self.relu(fc_out1) + fc_out2 = self.fc_out2(fc_out1_act) + fc_out2_act = paddle.tanh(fc_out2) + fc_logit = self.fc_logit(fc_out2_act) + output = self.sigmoid(fc_logit) + return fc_logit, output + + def loss(self, lstm_logit, labels, **kwargs): + labels.stop_gradient = True + losses = dict() + bce_logit_loss = paddle.nn.BCEWithLogitsLoss(reduction='sum') + sum_cost = bce_logit_loss(lstm_logit, labels) + return sum_cost + + def metric(self, lstm_output, labels): + pred = lstm_output.numpy() + label = labels.numpy() + hit_at_one = youtube8m_metrics.calculate_hit_at_one(pred, label) + perr = youtube8m_metrics.calculate_precision_at_equal_recall_rate( + pred, label) + gap = youtube8m_metrics.calculate_gap(pred, label) + return hit_at_one, perr, gap + + +@HEADS.register() +class ActionAttentionLstmHead(BaseHead): + """AttentionLstmHead for FootballAction + Args: TODO + """ + def __init__(self, + num_classes=8, + feature_num=2, + feature_dims=[2048, 1024], + embedding_size=512, + lstm_size=1024, + in_channels=2048, + loss_cfg=dict(name='CrossEntropyLoss')): + super(ActionAttentionLstmHead, self).__init__(num_classes, in_channels, + loss_cfg) + self.num_classes = num_classes + self.feature_dims = feature_dims + self.embedding_size = embedding_size + self.lstm_size = lstm_size + self.feature_num = len(self.feature_dims) + for i in range(self.feature_num): # 0:rgb, 1:audio + bi_lstm = paddle.nn.LSTM(input_size=self.feature_dims[i], + hidden_size=self.feature_dims[i], + direction="bidirectional") + self.add_sublayer("bi_lstm{}".format(i), bi_lstm) + + drop_rate = 0.5 + self.dropout = paddle.nn.Dropout(drop_rate) + + att_fc = paddle.nn.Linear(in_features=self.feature_dims[i] * 2, + out_features=1) + self.add_sublayer("att_fc{}".format(i), att_fc) + self.softmax = paddle.nn.Softmax() + + self.fc1 = paddle.nn.Linear(in_features=2 * sum(self.feature_dims), + out_features=8192, + bias_attr=ParamAttr( + regularizer=L2Decay(0.0), + initializer=Normal())) + self.bn1 = paddle.nn.BatchNorm(num_channels=8192) + self.dropout1 = paddle.nn.Dropout(0.5) + self.fc2 = paddle.nn.Linear(in_features=8192, + out_features=4096, + bias_attr=ParamAttr( + regularizer=L2Decay(0.0), + initializer=Normal())) + self.bn2 = paddle.nn.BatchNorm(num_channels=4096) + self.dropout2 = paddle.nn.Dropout(0.5) + self.fc3 = paddle.nn.Linear( + in_features=4096, + out_features=self.num_classes, + ) + self.fc4 = paddle.nn.Linear( + in_features=4096, + out_features=1, + ) + + def init_weights(self): + pass + + def forward(self, inputs): + # inputs = [(rgb_data, rgb_len, rgb_mask), (audio_data, audio_len, audio_mask)] + # deal with features with different length + # 1. padding to same lenght, make a tensor + # 2. make a mask tensor with the same shpae with 1 + # 3. compute output using mask tensor, s.t. output is nothing todo with padding + assert (len(inputs) == self.feature_num + ), "Input tensor does not contain {} features".format( + self.feature_num) + att_outs = [] + for i in range(len(inputs)): + m = getattr(self, "bi_lstm{}".format(i)) + lstm_out, _ = m(inputs=inputs[i][0], sequence_length=inputs[i][1]) + + lstm_dropout = self.dropout(lstm_out) + + # 3. att_fc + m = getattr(self, "att_fc{}".format(i)) + lstm_weight = m(lstm_dropout) + + # 4. softmax replace start, for it's relevant to sum in time step + lstm_exp = paddle.exp(lstm_weight) + lstm_mask = paddle.mean(inputs[i][2], axis=2) + lstm_mask = paddle.unsqueeze(lstm_mask, axis=2) + lstm_exp_with_mask = paddle.multiply(x=lstm_exp, y=lstm_mask) + lstm_sum_with_mask = paddle.sum(lstm_exp_with_mask, axis=1) + exponent = -1 + lstm_denominator = paddle.pow(lstm_sum_with_mask, exponent) + lstm_denominator = paddle.unsqueeze(lstm_denominator, axis=2) + lstm_softmax = paddle.multiply(x=lstm_exp, y=lstm_denominator) + lstm_weight = lstm_softmax + # softmax replace end + + lstm_scale = paddle.multiply(x=lstm_dropout, y=lstm_weight) + + # 5. sequence_pool's replace start, for it's relevant to sum in time step + lstm_scale_with_mask = paddle.multiply(x=lstm_scale, y=lstm_mask) + # fea_lens = inputs[i][1] + # fea_len = int(fea_lens[0]) + lstm_pool = paddle.sum(lstm_scale_with_mask, axis=1) + # sequence_pool's replace end + att_outs.append(lstm_pool) + att_out = paddle.concat(att_outs, axis=1) + y = self.fc1(att_out) + y = self.bn1(y) + y = F.relu(y) + y = self.dropout1(y) + y = self.fc2(y) + y = self.bn2(y) + y = F.relu(y) + y = self.dropout2(y) + out1 = self.fc3(y) + out1 = F.softmax(out1) + out2 = self.fc4(y) + out2 = F.sigmoid(out2) + return out1, out2 + + def loss(self, logits, iou, labels, labels_iou, **kwargs): + alpha = 10 + softmax_loss = F.cross_entropy(logits, labels) + labels_iou = labels_iou.astype('float32') + mse_loss = paddle.sum(F.square_error_cost(iou, labels_iou), axis=-1) + sum_loss = softmax_loss + alpha * mse_loss + return sum_loss + + def metric(self, scores, labels): + top1 = paddle.metric.accuracy(input=scores, label=labels, k=1) + top5 = paddle.metric.accuracy(input=scores, label=labels, k=5) + return top1, top5 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/base.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/base.py new file mode 100644 index 0000000..99a1408 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/base.py @@ -0,0 +1,178 @@ +# 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 numpy as np +from abc import abstractmethod + +import paddle +import paddle.nn as nn +import paddle.nn.functional as F + +from ..builder import build_loss +from paddlevideo.utils import get_logger, get_dist_info + +logger = get_logger("paddlevideo") + + +class BaseHead(nn.Layer): + """Base class for head part. + + All head should subclass it. + All subclass should overwrite: + + - Methods: ```init_weights```, initializing weights. + - Methods: ```forward```, forward function. + + Args: + num_classes (int): The number of classes to be classified. + in_channels (int): The number of channels in input feature. + loss_cfg (dict): Config for building loss. Default: dict(type='CrossEntropyLoss'). + ls_eps (float): label smoothing epsilon. Default: 0. . + + """ + def __init__( + self, + num_classes=None, + in_channels=None, + loss_cfg=dict( + name="CrossEntropyLoss" + ), #TODO(shipping): only pass a name or standard build cfg format. + #multi_class=False, NOTE(shipping): not supported now. + ls_eps=0.): + + super().__init__() + self.num_classes = num_classes + self.in_channels = in_channels + self.loss_func = build_loss(loss_cfg) + #self.multi_class = multi_class NOTE(shipping): not supported now + self.ls_eps = ls_eps + + @abstractmethod + def forward(self, x): + """Define how the head is going to run. + """ + raise NotImplemented + + def loss(self, scores, labels, valid_mode=False, if_top5=True, **kwargs): + """Calculate the loss accroding to the model output ```scores```, + and the target ```labels```. + + Args: + scores (paddle.Tensor): The output of the model. + labels (paddle.Tensor): The target output of the model. + + Returns: + losses (dict): A dict containing field 'loss'(mandatory) and 'top1_acc', 'top5_acc'(optional). + + """ + if len(labels) == 1: #commonly case + labels = labels[0] + losses = dict() + if self.ls_eps != 0. and not valid_mode: # label_smooth + loss = self.label_smooth_loss(scores, labels, **kwargs) + else: + loss = self.loss_func(scores, labels, **kwargs) + if if_top5: + top1, top5 = self.get_acc(scores, labels, valid_mode) + losses['top1'] = top1 + losses['top5'] = top5 + losses['loss'] = loss + else: + top1 = self.get_acc(scores, labels, valid_mode, if_top5) + losses['top1'] = top1 + losses['loss'] = loss + return losses + # MRI目前二分类无top5 + elif len(labels) == 3: # mix_up + labels_a, labels_b, lam = labels + lam = lam[0] # get lam value + losses = dict() + if self.ls_eps != 0: + loss_a = self.label_smooth_loss(scores, labels_a, **kwargs) + loss_b = self.label_smooth_loss(scores, labels_b, **kwargs) + else: + loss_a = self.loss_func(scores, labels_a, **kwargs) + loss_b = self.loss_func(scores, labels_b, **kwargs) + loss = lam * loss_a + (1 - lam) * loss_b + + if if_top5: + top1a, top5a = self.get_acc(scores, labels_a, valid_mode) + top1b, top5b = self.get_acc(scores, labels_b, valid_mode) + top1 = lam * top1a + (1 - lam) * top1b + top5 = lam * top5a + (1 - lam) * top5b + losses['top1'] = top1 + losses['top5'] = top5 + losses['loss'] = loss + + else: + top1a = self.get_acc(scores, labels_a, valid_mode, if_top5) + top1b = self.get_acc(scores, labels_b, valid_mode, if_top5) + top1 = lam * top1a + (1 - lam) * top1b + losses['top1'] = top1 + losses['loss'] = loss + + return losses + else: + raise NotImplemented + + def label_smooth_loss(self, scores, labels, **kwargs): + """ + Args: + scores (paddle.Tensor): [N, num_classes] + labels (paddle.Tensor): [N, ] + Returns: + paddle.Tensor: [1,] + """ + if paddle.is_compiled_with_custom_device('npu'): + """ + Designed for the lack of temporary operators of NPU, + main idea is to split smooth loss into uniform distribution loss + and hard label calculation + """ + hard_loss = (1.0 - self.ls_eps) * F.cross_entropy(scores, labels) + uniform_loss = (self.ls_eps / self.num_classes) * ( + -F.log_softmax(scores, -1).sum(-1).mean(0)) + loss = hard_loss + uniform_loss + else: + labels = F.one_hot(labels, self.num_classes) + labels = F.label_smooth(labels, epsilon=self.ls_eps) + labels = paddle.squeeze(labels, axis=1) + loss = self.loss_func(scores, labels, soft_label=True, **kwargs) + return loss + + def get_acc(self, scores, labels, valid_mode, if_top5=True): + if if_top5: + top1 = paddle.metric.accuracy(input=scores, label=labels, k=1) + top5 = paddle.metric.accuracy(input=scores, label=labels, k=5) + _, world_size = get_dist_info() + #NOTE(shipping): deal with multi cards validate + if world_size > 1 and valid_mode: #reduce sum when valid + paddle.distributed.all_reduce( + top1, op=paddle.distributed.ReduceOp.SUM) + top1 = top1 / world_size + paddle.distributed.all_reduce( + top5, op=paddle.distributed.ReduceOp.SUM) + top5 = top5 / world_size + + return top1, top5 + else: + top1 = paddle.metric.accuracy(input=scores, label=labels, k=1) + _, world_size = get_dist_info() + #NOTE(shipping): deal with multi cards validate + if world_size > 1 and valid_mode: #reduce sum when valid + paddle.distributed.all_reduce( + top1, op=paddle.distributed.ReduceOp.SUM) + top1 = top1 / world_size + + return top1 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/bbox_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/bbox_head.py new file mode 100644 index 0000000..688251e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/bbox_head.py @@ -0,0 +1,225 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 paddle +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np +from .. import builder + +from ..registry import HEADS + +@HEADS.register() +class BBoxHeadAVA(nn.Layer): + """Simplest RoI head, with only two fc layers for classification and + regression respectively. """ + + def __init__( + self, + temporal_pool_type='avg', + spatial_pool_type='max', + in_channels=2048, + num_classes=81,# The first class is reserved, to classify bbox as pos / neg + dropout_ratio=0, + dropout_before_pool=True, + topk=(3, 5), + multilabel=True): + + super(BBoxHeadAVA, self).__init__() + assert temporal_pool_type in ['max', 'avg'] + assert spatial_pool_type in ['max', 'avg'] + self.temporal_pool_type = temporal_pool_type + self.spatial_pool_type = spatial_pool_type + + self.in_channels = in_channels + self.num_classes = num_classes + + self.dropout_ratio = dropout_ratio + self.dropout_before_pool = dropout_before_pool + + self.multilabel = multilabel + if topk is None: + self.topk = () + elif isinstance(topk, int): + self.topk = (topk, ) + elif isinstance(topk, tuple): + assert all([isinstance(k, int) for k in topk]) + self.topk = topk + else: + raise TypeError('topk should be int or tuple[int], ' + f'but get {type(topk)}') + # Class 0 is ignored when calculaing multilabel accuracy, + # so topk cannot be equal to num_classes + assert all([k < num_classes for k in self.topk]) + assert self.multilabel + + in_channels = self.in_channels + if self.temporal_pool_type == 'avg': + self.temporal_pool = nn.AdaptiveAvgPool3D((1, None, None)) + else: + self.temporal_pool = nn.AdaptiveMaxPool3D((1, None, None)) + if self.spatial_pool_type == 'avg': + self.spatial_pool = nn.AdaptiveAvgPool3D((None, 1, 1)) + else: + self.spatial_pool = nn.AdaptiveMaxPool3D((None, 1, 1)) + + if dropout_ratio > 0: + self.dropout = nn.Dropout(dropout_ratio) + + weight_attr = paddle.framework.ParamAttr(name="weight", + initializer=paddle.nn.initializer.Normal(mean=0.0, std=0.01)) + bias_attr = paddle.ParamAttr(name="bias", + initializer=paddle.nn.initializer.Constant(value=0.0)) + + self.fc_cls = nn.Linear(in_channels, num_classes, weight_attr=weight_attr, bias_attr=bias_attr) + + self.debug_imgs = None + + def forward(self, x,rois, rois_num): + roi = paddle.concat(rois) + roi_x1 = paddle.index_select(roi, index=paddle.to_tensor(0), axis=1) + roi_x2 = paddle.index_select(roi, index=paddle.to_tensor(2), axis=1) + roi_w = roi_x2 - roi_x1 + roi_y1 = paddle.index_select(roi, index=paddle.to_tensor(1), axis=1) + roi_y2 = paddle.index_select(roi, index=paddle.to_tensor(3), axis=1) + roi_h = roi_y2 - roi_y1 + roi_area = paddle.multiply(roi_w, roi_h) + A = roi_area + A1 = paddle.full(A.shape, 1, dtype='int32') + A2 = paddle.where(A == 0, paddle.zeros_like(A1), A1) + AE = paddle.expand(A2, [A.shape[0], x.shape[1]]) + rois_num = paddle.to_tensor(rois_num, dtype='int32') + if self.dropout_before_pool and self.dropout_ratio > 0 : + x = self.dropout(x) + x = self.temporal_pool(x) + x = self.spatial_pool(x) + if not self.dropout_before_pool and self.dropout_ratio > 0 : + x = self.dropout(x) + x = paddle.reshape(x, [x.shape[0], -1]) + x = paddle.multiply(x, paddle.cast(AE,"float32")) + cls_score = self.fc_cls(x) + # We do not predict bbox, so return None + return cls_score, None + + def get_targets(self, sampling_results, gt_bboxes, gt_labels, pos_weight): + pos_proposals = [res.pos_bboxes for res in sampling_results] + neg_proposals = [res.neg_bboxes for res in sampling_results] + pos_gt_labels = [res.pos_gt_labels for res in sampling_results] + cls_reg_targets = self.bbox_target(pos_proposals, neg_proposals, + pos_gt_labels, pos_weight) + return cls_reg_targets + + def bbox_target(self, pos_bboxes_list, neg_bboxes_list, gt_labels, pos_weight): + """Generate classification targets for bboxes. """ + labels, label_weights = [], [] + pos_weight = 1.0 if pos_weight <= 0 else pos_weight + + assert len(pos_bboxes_list) == len(neg_bboxes_list) == len(gt_labels) + length = len(pos_bboxes_list) + + for i in range(length): + pos_bboxes = pos_bboxes_list[i] + neg_bboxes = neg_bboxes_list[i] + gt_label = gt_labels[i] + num_pos = pos_bboxes.shape[0] + if neg_bboxes is not None: + num_neg = neg_bboxes.shape[0] + else: + num_neg = 0 + num_samples = num_pos + num_neg + neg_label = paddle.zeros([num_neg, gt_label.shape[1]]) + label = paddle.concat([gt_label,neg_label]) + labels.append(label) + + labels = paddle.concat(labels, 0) + return labels + + def recall_prec(self, pred_vec, target_vec): + correct = paddle.to_tensor(np.logical_and(pred_vec.numpy(), target_vec.numpy())) + correct = paddle.where(correct, + paddle.full(correct.shape,1,dtype='int32'), + paddle.full(correct.shape,0,dtype='int32')) + recall_correct = paddle.cast(paddle.sum(correct, axis=1), 'float32') + target_vec = paddle.where(target_vec, + paddle.full(target_vec.shape,1,dtype='int32'), + paddle.full(target_vec.shape,0,dtype='int32')) + recall_target = paddle.cast(paddle.sum(target_vec, axis=1),'float32') + recall = recall_correct / recall_target + pred_vec = paddle.where(pred_vec, + paddle.full(pred_vec.shape,1,dtype='int32'), + paddle.full(pred_vec.shape,0,dtype='int32')) + prec_target = paddle.cast(paddle.sum(pred_vec, axis=1) + 1e-6, 'float32') + prec = recall_correct / prec_target + recall_mean = paddle.mean(recall) + prec_mean = paddle.mean(prec) + return recall_mean, prec_mean + + def multilabel_accuracy(self, pred, target, thr=0.5): + pred = paddle.nn.functional.sigmoid(pred) + pred_vec = pred > thr + target_vec = target > 0.5 + recall_thr, prec_thr = self.recall_prec(pred_vec, target_vec) + recalls, precs = [], [] + for k in self.topk: + _, pred_label = paddle.topk(pred, k, 1, True, True) + pred_vec = paddle.full(pred.shape,0,dtype='bool') + num_sample = pred.shape[0] + for i in range(num_sample): + pred_vec[i, pred_label[i].numpy()] = 1 + recall_k, prec_k = self.recall_prec(pred_vec, target_vec) + recalls.append(recall_k) + precs.append(prec_k) + return recall_thr, prec_thr, recalls, precs + + def loss(self, + cls_score, + labels): + losses = dict() + if cls_score is not None: + # Only use the cls_score + labels = labels[:, 1:] + pos_inds_bool = paddle.sum(labels, axis=-1) > 0 + pos_inds = paddle.where(paddle.sum(labels, axis=-1) > 0, + paddle.full([labels.shape[0]],1,dtype='int32'), + paddle.full([labels.shape[0]],0,dtype='int32')) + pos_inds = paddle.nonzero(pos_inds, as_tuple=False) + cls_score = paddle.index_select(cls_score, pos_inds, axis=0) + cls_score = cls_score[:, 1:] + labels = paddle.index_select(labels, pos_inds, axis=0) + bce_loss = F.binary_cross_entropy_with_logits + loss = bce_loss(cls_score, labels, reduction='none') + losses['loss'] = paddle.mean(loss) + recall_thr, prec_thr, recall_k, prec_k = self.multilabel_accuracy( + cls_score, labels, thr=0.5) + losses['recall@thr=0.5'] = recall_thr + losses['prec@thr=0.5'] = prec_thr + for i, k in enumerate(self.topk): + losses[f'recall@top{k}'] = recall_k[i] + losses[f'prec@top{k}'] = prec_k[i] + return losses + + def get_det_bboxes(self, + rois, + cls_score, + img_shape, + flip=False, + crop_quadruple=None, + cfg=None): + if isinstance(cls_score, list): + cls_score = sum(cls_score) / float(len(cls_score)) + assert self.multilabel + m = paddle.nn.Sigmoid() + scores = m(cls_score) + bboxes = rois + return bboxes, scores diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/cfbi_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/cfbi_head.py new file mode 100644 index 0000000..f7cbd91 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/cfbi_head.py @@ -0,0 +1,448 @@ +# Copyright (c) 2021 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 paddle +import paddle.nn as nn +import paddle.nn.functional as F + +from .base import BaseHead +from ..registry import HEADS +from ..weight_init import weight_init_ + + +class IA_gate(nn.Layer): + def __init__(self, in_dim, out_dim): + super(IA_gate, self).__init__() + self.IA = nn.Linear(in_dim, out_dim) + + def forward(self, x, IA_head): + a = self.IA(IA_head) + a = 1. + paddle.tanh(a) + a = paddle.unsqueeze(paddle.unsqueeze(a, axis=-1), axis=-1) + x = a * x + return x + + +class GCT(nn.Layer): + def __init__(self, num_channels, epsilon=1e-5, mode='l2', after_relu=False): + super(GCT, self).__init__() + x1 = paddle.zeros([1, num_channels, 1, 1]) + x2 = paddle.ones([1, num_channels, 1, 1]) + self.alpha = paddle.create_parameter( + shape=x2.shape, + dtype=x2.dtype, + default_initializer=nn.initializer.Assign(x2)) + self.alpha.stop_gradient = False + self.gamma = paddle.create_parameter( + shape=x1.shape, + dtype=x1.dtype, + default_initializer=nn.initializer.Assign(x1)) + self.gamma.stop_gradient = False + self.beta = paddle.create_parameter( + shape=x1.shape, + dtype=x1.dtype, + default_initializer=nn.initializer.Assign(x1)) + self.beta.stop_gradient = False + + self.epsilon = epsilon + self.mode = mode + self.after_relu = after_relu + + def forward(self, x): + + if self.mode == 'l2': + embedding = paddle.pow( + paddle.sum(paddle.pow(x, 2), axis=[2, 3], keepdim=True) + + self.epsilon, 0.5) * self.alpha + norm = self.gamma / paddle.pow( + (paddle.mean(paddle.pow(embedding, 2), axis=1, keepdim=True) + + self.epsilon), 0.5) + elif self.mode == 'l1': + if not self.after_relu: + _x = paddle.abs(x) + else: + _x = x + embedding = paddle.sum(_x, axis=(2, 3), keepdim=True) * self.alpha + norm = self.gamma / (paddle.mean( + paddle.abs(embedding), axis=1, keepdim=True) + self.epsilon) + else: + print('Unknown mode!') + exit() + + gate = 1. + paddle.tanh(embedding * norm + self.beta) + + return x * gate + + +class Bottleneck(nn.Layer): + def __init__(self, inplanes, outplanes, stride=1, dilation=1): + super(Bottleneck, self).__init__() + expansion = 4 + planes = int(outplanes / expansion) + + self.GCT1 = GCT(inplanes) + self.conv1 = nn.Conv2D(inplanes, planes, kernel_size=1, bias_attr=False) + self.bn1 = nn.GroupNorm(num_groups=32, num_channels=planes) + + self.conv2 = nn.Conv2D(planes, + planes, + kernel_size=3, + stride=stride, + dilation=dilation, + padding=dilation, + bias_attr=False) + self.bn2 = nn.GroupNorm(num_groups=32, num_channels=planes) + + self.conv3 = nn.Conv2D(planes, + planes * expansion, + kernel_size=1, + bias_attr=False) + self.bn3 = nn.GroupNorm(num_groups=32, num_channels=planes * expansion) + self.relu = nn.ReLU() + if stride != 1 or inplanes != planes * expansion: + downsample = nn.Sequential( + nn.Conv2D(inplanes, + planes * expansion, + kernel_size=1, + stride=stride, + bias_attr=False), + nn.GroupNorm(num_groups=32, num_channels=planes * expansion), + ) + else: + downsample = None + self.downsample = downsample + + self.stride = stride + self.dilation = dilation + + for m in self.sublayers(): + if isinstance(m, nn.Conv2D): + nn.initializer.KaimingNormal() + + def forward(self, x): + residual = x + + out = self.GCT1(x) + out = self.conv1(out) + out = self.bn1(out) + out = self.relu(out) + + out = self.conv2(out) + out = self.bn2(out) + out = self.relu(out) + + out = self.conv3(out) + out = self.bn3(out) + if self.downsample is not None: + residual = self.downsample(x) + + out += residual + out = self.relu(out) + + return out + + +class _ASPPModule(nn.Layer): + def __init__(self, inplanes, planes, kernel_size, padding, dilation): + super(_ASPPModule, self).__init__() + self.GCT = GCT(inplanes) + self.atrous_conv = nn.Conv2D(inplanes, + planes, + kernel_size=kernel_size, + stride=1, + padding=padding, + dilation=dilation, + bias_attr=False) + self.bn = nn.GroupNorm(num_groups=int(planes / 4), num_channels=planes) + self.relu = nn.ReLU() + + self._init_weight() + + def forward(self, x): + x = self.GCT(x) + x = self.atrous_conv(x) + x = self.bn(x) + + return self.relu(x) + + def _init_weight(self): + for m in self.sublayers(): + if isinstance(m, nn.Conv2D): + nn.initializer.KaimingNormal() + elif isinstance(m, nn.GroupNorm): + m.weight.data = nn.initializer.Constant(1) + m.bias.data = nn.initializer.Constant(0) + + +class ASPP(nn.Layer): + def __init__(self): + super(ASPP, self).__init__() + + inplanes = 512 + dilations = [1, 6, 12, 18] + + self.aspp1 = _ASPPModule(inplanes, + 128, + 1, + padding=0, + dilation=dilations[0]) + self.aspp2 = _ASPPModule(inplanes, + 128, + 3, + padding=dilations[1], + dilation=dilations[1]) + self.aspp3 = _ASPPModule(inplanes, + 128, + 3, + padding=dilations[2], + dilation=dilations[2]) + self.aspp4 = _ASPPModule(inplanes, + 128, + 3, + padding=dilations[3], + dilation=dilations[3]) + + self.global_avg_pool = nn.Sequential( + nn.AdaptiveAvgPool2D((1, 1)), + nn.Conv2D(inplanes, 128, 1, stride=1, bias_attr=False), nn.ReLU()) + + self.GCT = GCT(640) + self.conv1 = nn.Conv2D(640, 256, 1, bias_attr=False) + self.bn1 = nn.GroupNorm(num_groups=32, num_channels=256) + self.relu = nn.ReLU() + self._init_weight() + + def forward(self, x): + x1 = self.aspp1(x) + x2 = self.aspp2(x) + x3 = self.aspp3(x) + x4 = self.aspp4(x) + x5 = self.global_avg_pool(x) + x5 = F.interpolate(x5, + size=x4.shape[2:], + mode='bilinear', + align_corners=True) + x = paddle.concat([x1, x2, x3, x4, x5], axis=1) + + x = self.GCT(x) + x = self.conv1(x) + x = self.bn1(x) + x = self.relu(x) + + return x + + def _init_weight(self): + for m in self.sublayers(): + if isinstance(m, nn.Conv2D): + nn.initializer.KaimingNormal() + elif isinstance(m, nn.GroupNorm): + m.weight.data = nn.initializer.Constant(1) + m.bias.data = nn.initializer.Constant(0) + + +@HEADS.register() +class CollaborativeEnsemblerMS(nn.Layer): + def __init__( + self, + model_semantic_embedding_dim=256, + model_multi_local_distance=[[4, 8, 12, 16, 20, 24], + [2, 4, 6, 8, 10, 12], [2, 4, 6, 8, 10]], + model_head_embedding_dim=256, + model_refine_channels=64, + model_low_level_inplanes=256, + ): + super(CollaborativeEnsemblerMS, self).__init__() + in_dim_4x = model_semantic_embedding_dim * 3 + 3 + 2 * len( + model_multi_local_distance[0]) + in_dim_8x = model_semantic_embedding_dim * 3 + 3 + 2 * len( + model_multi_local_distance[1]) + in_dim_16x = model_semantic_embedding_dim * 3 + 3 + 2 * len( + model_multi_local_distance[2]) + attention_dim = model_semantic_embedding_dim * 4 + embed_dim = model_head_embedding_dim + refine_dim = model_refine_channels + low_level_dim = model_low_level_inplanes + + IA_in_dim = attention_dim + + self.relu = nn.ReLU() + + # stage 1 + + self.S1_IA1 = IA_gate(IA_in_dim, in_dim_4x) + self.S1_layer1 = Bottleneck(in_dim_4x, embed_dim) + + self.S1_IA2 = IA_gate(IA_in_dim, embed_dim) + self.S1_layer2 = Bottleneck(embed_dim, embed_dim, 1, 2) + + # stage2 + self.S2_IA1 = IA_gate(IA_in_dim, embed_dim) + self.S2_layer1 = Bottleneck(embed_dim, embed_dim * 2, 2) + + self.S2_IA2 = IA_gate(IA_in_dim, embed_dim * 2 + in_dim_8x) + self.S2_layer2 = Bottleneck(embed_dim * 2 + in_dim_8x, embed_dim * 2, 1, + 2) + + self.S2_IA3 = IA_gate(IA_in_dim, embed_dim * 2) + self.S2_layer3 = Bottleneck(embed_dim * 2, embed_dim * 2, 1, 4) + + # stage3 + self.S3_IA1 = IA_gate(IA_in_dim, embed_dim * 2) + self.S3_layer1 = Bottleneck(embed_dim * 2, embed_dim * 2, 2) + + self.S3_IA2 = IA_gate(IA_in_dim, embed_dim * 2 + in_dim_16x) + self.S3_layer2 = Bottleneck(embed_dim * 2 + in_dim_16x, embed_dim * 2, + 1, 2) + + self.S3_IA3 = IA_gate(IA_in_dim, embed_dim * 2) + self.S3_layer3 = Bottleneck(embed_dim * 2, embed_dim * 2, 1, 4) + + self.ASPP_IA = IA_gate(IA_in_dim, embed_dim * 2) + self.ASPP = ASPP() + + # Decoder + self.GCT_sc = GCT(low_level_dim + embed_dim) + self.conv_sc = nn.Conv2D(low_level_dim + embed_dim, + refine_dim, + 1, + bias_attr=False) + self.bn_sc = nn.GroupNorm(num_groups=int(refine_dim / 4), + num_channels=refine_dim) + self.relu = nn.ReLU() + + self.IA10 = IA_gate(IA_in_dim, embed_dim + refine_dim) + self.conv1 = nn.Conv2D(embed_dim + refine_dim, + int(embed_dim / 2), + kernel_size=3, + padding=1, + bias_attr=False) + self.bn1 = nn.GroupNorm(num_groups=32, num_channels=int(embed_dim / 2)) + + self.IA11 = IA_gate(IA_in_dim, int(embed_dim / 2)) + self.conv2 = nn.Conv2D(int(embed_dim / 2), + int(embed_dim / 2), + kernel_size=3, + padding=1, + bias_attr=False) + self.bn2 = nn.GroupNorm(num_groups=32, num_channels=int(embed_dim / 2)) + + # Output + self.IA_final_fg = nn.Linear(IA_in_dim, int(embed_dim / 2) + 1) + self.IA_final_bg = nn.Linear(IA_in_dim, int(embed_dim / 2) + 1) + + self.conv_sc.weight.data = nn.initializer.KaimingNormal() + self.conv1.weight.data = nn.initializer.KaimingNormal() + self.conv2.weight.data = nn.initializer.KaimingNormal() + + def forward(self, all_x, all_IA_head=None, low_level_feat=None): + x_4x, x_8x, x_16x = all_x + IA_head = all_IA_head[0] + + # stage 1 + x = self.S1_IA1(x_4x, IA_head) + x = self.S1_layer1(x) + + x = self.S1_IA2(x, IA_head) + x = self.S1_layer2(x) + + low_level_feat = paddle.concat( + [paddle.expand(low_level_feat, [x.shape[0], -1, -1, -1]), x], + axis=1) + + # stage 2 + x = self.S2_IA1(x, IA_head) + x = self.S2_layer1(x) + + x = paddle.concat([x, x_8x], axis=1) + x = self.S2_IA2(x, IA_head) + x = self.S2_layer2(x) + + x = self.S2_IA3(x, IA_head) + x = self.S2_layer3(x) + + # stage 3 + x = self.S3_IA1(x, IA_head) + x = self.S3_layer1(x) + + x = paddle.concat([x, x_16x], axis=1) + x = self.S3_IA2(x, IA_head) + x = self.S3_layer2(x) + + x = self.S3_IA3(x, IA_head) + x = self.S3_layer3(x) + + # ASPP + Decoder + x = self.ASPP_IA(x, IA_head) + x = self.ASPP(x) + + x = self.decoder(x, low_level_feat, IA_head) + + fg_logit = self.IA_logit(x, IA_head, self.IA_final_fg) + bg_logit = self.IA_logit(x, IA_head, self.IA_final_bg) + + pred = self.augment_background_logit(fg_logit, bg_logit) + + return pred + + def IA_logit(self, x, IA_head, IA_final): + n, c, h, w = x.shape + x = paddle.reshape(x, [1, n * c, h, w]) + IA_output = IA_final(IA_head) + IA_weight = IA_output[:, :c] + IA_bias = IA_output[:, -1] + IA_weight = paddle.reshape(IA_weight, [n, c, 1, 1]) + + IA_bias = paddle.reshape(IA_bias, [-1]) + logit = paddle.reshape( + F.conv2d(x, weight=IA_weight, bias=IA_bias, groups=n), [n, 1, h, w]) + return logit + + def decoder(self, x, low_level_feat, IA_head): + x = F.interpolate(x, + size=low_level_feat.shape[2:], + mode='bicubic', + align_corners=True) + + low_level_feat = self.GCT_sc(low_level_feat) + low_level_feat = self.conv_sc(low_level_feat) + low_level_feat = self.bn_sc(low_level_feat) + low_level_feat = self.relu(low_level_feat) + + x = paddle.concat([x, low_level_feat], axis=1) + x = self.IA10(x, IA_head) + x = self.conv1(x) + x = self.bn1(x) + x = self.relu(x) + + x = self.IA11(x, IA_head) + x = self.conv2(x) + x = self.bn2(x) + x = self.relu(x) + + return x + + def augment_background_logit(self, fg_logit, bg_logit): + # We augment the logit of absolute background by using the relative background logit of all the + # foreground objects. + obj_num = fg_logit.shape[0] + pred = fg_logit + if obj_num > 1: + bg_logit = bg_logit[1:obj_num, :, :, :] + aug_bg_logit = paddle.min(bg_logit, axis=0, keepdim=True) + pad = paddle.expand(paddle.zeros(aug_bg_logit.shape), + [obj_num - 1, -1, -1, -1]) + aug_bg_logit = paddle.concat([aug_bg_logit, pad], axis=0) + pred = pred + aug_bg_logit + pred = paddle.transpose(pred, [1, 0, 2, 3]) + return pred diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/ctrgcn_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/ctrgcn_head.py new file mode 100644 index 0000000..c551d0d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/ctrgcn_head.py @@ -0,0 +1,65 @@ +# Copyright (c) 2021 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 math +import paddle +import paddle.nn as nn + +from .base import BaseHead +from ..registry import HEADS +from ..weight_init import weight_init_ + + +@HEADS.register() +class CTRGCNHead(BaseHead): + """ + Head for CTR-GCN model. + Args: + in_channels: int, input feature channels. Default: 64. + num_classes: int, output the number of classes. + drop_out: float, dropout ratio of layer. Default: 0. + """ + + def __init__(self, in_channels=64, num_classes=10, drop_out=0, **kwargs): + super().__init__(num_classes, in_channels, **kwargs) + self.in_channels = in_channels + self.drop_out = drop_out + + self.fc = nn.Linear(self.in_channels * 4, self.num_classes) + if drop_out: + self.drop_out = nn.Dropout(self.drop_out) + else: + self.drop_out = lambda x: x + + def init_weights(self): + """Initiate the parameters. + """ + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + weight_init_(layer.weight, + 'Normal', + mean=0.0, + std=math.sqrt(2. / self.num_classes)) + + def forward(self, output_patch): + """Define how the head is going to run. + """ + x, N, M = output_patch + # N*M,C,T,V + _, c_new, T, V = x.shape + x = paddle.reshape(x, shape=[N, M, c_new, T * V]) + x = x.mean(3).mean(1) + x = self.drop_out(x) + + return self.fc(x) diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/i3d_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/i3d_head.py new file mode 100644 index 0000000..269c818 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/i3d_head.py @@ -0,0 +1,95 @@ +# 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 paddle +import paddle.nn as nn +from paddle import ParamAttr + +from ..registry import HEADS +from ..weight_init import weight_init_ +from .base import BaseHead + + +@HEADS.register() +class I3DHead(BaseHead): + """Classification head for I3D. + + Args: + num_classes (int): Number of classes to be classified. + in_channels (int): Number of channels in input feature. + loss_cls (dict): Config for building loss. + Default: dict(name='CrossEntropyLoss') + spatial_type (str): Pooling type in spatial dimension. Default: 'avg'. + drop_ratio (float): Probability of dropout layer. Default: 0.5. + std (float): Std value for Initiation. Default: 0.01. + kwargs (dict, optional): Any keyword argument to be used to initialize + the head. + """ + def __init__(self, + num_classes, + in_channels, + loss_cfg=dict(name='CrossEntropyLoss'), + spatial_type='avg', + drop_ratio=0.5, + std=0.01, + **kwargs): + + super().__init__(num_classes, in_channels, loss_cfg, **kwargs) + + self.spatial_type = spatial_type + self.drop_ratio = drop_ratio + self.stdv = std + if self.drop_ratio != 0: + self.dropout = nn.Dropout(p=self.drop_ratio) + else: + self.dropout = None + self.fc = nn.Linear( + self.in_channels, + self.num_classes, + weight_attr=ParamAttr(learning_rate=10.0), + bias_attr=ParamAttr(learning_rate=10.0), + ) + + if self.spatial_type == 'avg': + # use `nn.AdaptiveAvgPool3d` to adaptively match the in_channels. + self.avg_pool = nn.AdaptiveAvgPool3D((1, 1, 1)) + else: + self.avg_pool = None + + def init_weights(self): + """Initiate the parameters from scratch.""" + weight_init_(self.fc, 'Normal', 'fc_0.w_0', 'fc_0.b_0', std=self.stdv) + + def forward(self, x): + """Defines the computation performed at every call. + + Args: + x (torch.Tensor): The input data. + + Returns: + torch.Tensor: The classification scores for input samples. + """ + # [N, in_channels, 4, 7, 7] + if self.avg_pool is not None: + x = self.avg_pool(x) + # [N, in_channels, 1, 1, 1] + if self.dropout is not None: + x = self.dropout(x) + # [N, in_channels, 1, 1, 1] + N = paddle.shape(x)[0] + x = x.reshape([N, -1]) + # [N, in_channels] + cls_score = self.fc(x) + # [N, num_classes] + return cls_score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/movinet_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/movinet_head.py new file mode 100644 index 0000000..924b014 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/movinet_head.py @@ -0,0 +1,15 @@ +import collections.abc + +container_abcs = collections.abc +from ..registry import HEADS +from .base import BaseHead +from ..builder import build_loss + + +@HEADS.register() +class MoViNetHead(BaseHead): + def __init__(self): + super().__init__() + + def forward(self, x, *args): + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/ms_tcn_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/ms_tcn_head.py new file mode 100644 index 0000000..e0f435f --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/ms_tcn_head.py @@ -0,0 +1,165 @@ +# Copyright (c) 2021 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 paddle +import paddle.nn as nn +import paddle.nn.functional as F +import numpy as np + +from paddle import ParamAttr + +from .base import BaseHead +from ..registry import HEADS +from ..weight_init import weight_init_ + + +@HEADS.register() +class MSTCNHead(BaseHead): + + def __init__(self, num_classes, in_channels): + super().__init__(num_classes, in_channels) + self.ce = nn.CrossEntropyLoss(ignore_index=-100) + self.mse = nn.MSELoss(reduction='none') + self.num_classes = num_classes + + # cls score + self.overlap = 0.5 + + def forward(self, x): + """MS-TCN no head + """ + return x + + def loss(self, output, video_gt): + """calculate loss + """ + output_transpose = paddle.transpose(output, [2, 0, 1]) + ce_x = paddle.reshape(output_transpose, + (output_transpose.shape[0] * + output_transpose.shape[1], self.num_classes)) + ce_y = video_gt[0, :] + ce_loss = self.ce(ce_x, ce_y) + loss = ce_loss + + mse = self.mse(F.log_softmax(output[:, :, 1:], axis=1), + F.log_softmax(output.detach()[:, :, :-1], axis=1)) + mse = paddle.clip(mse, min=0, max=16) + mse_loss = 0.15 * paddle.mean(mse) + loss += mse_loss + + return loss + + def get_F1_score(self, predicted, groundTruth): + recog_content = list(predicted.numpy()) + gt_content = list(groundTruth[0].numpy()) + + # cls score + correct = 0 + total = 0 + edit = 0 + + for i in range(len(gt_content)): + total += 1 + + if gt_content[i] == recog_content[i]: + correct += 1 + + edit_num = self.edit_score(recog_content, gt_content) + edit += edit_num + + tp, fp, fn = self.f_score(recog_content, gt_content, self.overlap) + + # cls metric + + precision = tp / float(tp + fp) + recall = tp / float(fp + fn) + + if precision + recall > 0.0: + f1 = 2.0 * (precision * recall) / (precision + recall) + else: + f1 = 0.0 + f1 = np.nan_to_num(f1) + return f1 + + def get_labels_start_end_time(self, frame_wise_labels): + labels = [] + starts = [] + ends = [] + last_label = frame_wise_labels[0] + labels.append(frame_wise_labels[0]) + starts.append(0) + for i in range(len(frame_wise_labels)): + if frame_wise_labels[i] != last_label: + labels.append(frame_wise_labels[i]) + starts.append(i) + ends.append(i) + last_label = frame_wise_labels[i] + ends.append(i + 1) + return labels, starts, ends + + def levenstein(self, p, y, norm=False): + m_row = len(p) + n_col = len(y) + D = np.zeros([m_row + 1, n_col + 1], np.float) + for i in range(m_row + 1): + D[i, 0] = i + for i in range(n_col + 1): + D[0, i] = i + + for j in range(1, n_col + 1): + for i in range(1, m_row + 1): + if y[j - 1] == p[i - 1]: + D[i, j] = D[i - 1, j - 1] + else: + D[i, j] = min(D[i - 1, j] + 1, D[i, j - 1] + 1, + D[i - 1, j - 1] + 1) + + if norm: + score = (1 - D[-1, -1] / max(m_row, n_col)) * 100 + else: + score = D[-1, -1] + + return score + + def edit_score(self, recognized, ground_truth, norm=True): + P, _, _ = self.get_labels_start_end_time(recognized) + Y, _, _ = self.get_labels_start_end_time(ground_truth) + return self.levenstein(P, Y, norm) + + def f_score(self, recognized, ground_truth, overlap): + p_label, p_start, p_end = self.get_labels_start_end_time(recognized) + y_label, y_start, y_end = self.get_labels_start_end_time(ground_truth) + + tp = 0 + fp = 0 + + hits = np.zeros(len(y_label)) + + for j in range(len(p_label)): + intersection = np.minimum(p_end[j], y_end) - np.maximum( + p_start[j], y_start) + union = np.maximum(p_end[j], y_end) - np.minimum( + p_start[j], y_start) + IoU = (1.0 * intersection / union) * ( + [p_label[j] == y_label[x] for x in range(len(y_label))]) + # Get the best scoring segment + idx = np.array(IoU).argmax() + + if IoU[idx] >= overlap and not hits[idx]: + tp += 1 + hits[idx] = 1 + else: + fp += 1 + fn = len(y_label) - sum(hits) + return float(tp), float(fp), float(fn) diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/pptimesformer_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/pptimesformer_head.py new file mode 100644 index 0000000..113bde8 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/pptimesformer_head.py @@ -0,0 +1,74 @@ +# 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. + +from paddle.nn import Linear + +from ..registry import HEADS +from ..weight_init import trunc_normal_, weight_init_ +from .base import BaseHead +from paddle import ParamAttr +from paddle.regularizer import L2Decay + + +@HEADS.register() +class ppTimeSformerHead(BaseHead): + """TimeSformerHead Head. + + Args: + num_classes (int): The number of classes to be classified. + in_channels (int): The number of channles in input feature. + loss_cfg (dict): Config for building config. Default: dict(name='CrossEntropyLoss'). + std(float): Std(Scale) value in normal initilizar. Default: 0.01. + kwargs (dict, optional): Any keyword argument to initialize. + + """ + def __init__(self, + num_classes, + in_channels, + loss_cfg=dict(name='CrossEntropyLoss'), + std=0.02, + **kwargs): + + super().__init__(num_classes, in_channels, loss_cfg, **kwargs) + self.std = std + self.fc = Linear(self.in_channels, + self.num_classes, + bias_attr=ParamAttr(regularizer=L2Decay(0.0))) + + def init_weights(self): + """Initiate the FC layer parameters""" + + weight_init_(self.fc, + 'TruncatedNormal', + 'fc_0.w_0', + 'fc_0.b_0', + mean=0.0, + std=self.std) + # NOTE: Temporarily use trunc_normal_ instead of TruncatedNormal + trunc_normal_(self.fc.weight, std=self.std) + + def forward(self, x): + """Define how the head is going to run. + Args: + x (paddle.Tensor): The input data. + Returns: + score: (paddle.Tensor) The classification scores for input samples. + """ + # XXX: check dropout location! + # x.shape = [N, embed_dim] + + score = self.fc(x) + # [N, num_class] + # x = F.softmax(x) # NOTE remove + return score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/pptsm_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/pptsm_head.py new file mode 100644 index 0000000..45f50fd --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/pptsm_head.py @@ -0,0 +1,92 @@ +# 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 paddle +from paddle import ParamAttr +from paddle.nn import Linear +from paddle.regularizer import L2Decay +from .tsn_head import TSNHead +from ..registry import HEADS + +from ..weight_init import weight_init_ + + +@HEADS.register() +class ppTSMHead(TSNHead): + """ ppTSM Head + Args: + num_classes (int): The number of classes to be classified. + in_channels (int): The number of channles in input feature. + loss_cfg (dict): Config for building config. Default: dict(name='CrossEntropyLoss'). + drop_ratio(float): drop ratio. Default: 0.8. + std(float): Std(Scale) value in normal initilizar. Default: 0.001. + kwargs (dict, optional): Any keyword argument to initialize. + """ + def __init__( + self, + num_classes, + in_channels, # NOTE: 2048 for >= R50, 512 for <= R34 + drop_ratio=0.8, + std=0.01, + data_format="NCHW", + num_seg=8, + **kwargs): + + super().__init__(num_classes, + in_channels, + drop_ratio=drop_ratio, + std=std, + data_format=data_format, + **kwargs) + + self.fc = Linear(self.in_channels, + self.num_classes, + weight_attr=ParamAttr(learning_rate=5.0, + regularizer=L2Decay(1e-4)), + bias_attr=ParamAttr(learning_rate=10.0, + regularizer=L2Decay(0.0))) + self.stdv = std + self.num_seg = num_seg + + def init_weights(self): + """Initiate the FC layer parameters""" + weight_init_(self.fc, 'Normal', 'fc_0.w_0', 'fc_0.b_0', std=self.stdv) + + def forward(self, x, num_seg=None): + """Define how the head is going to run. + Args: + x (paddle.Tensor): The input data. + num_segs (int): Number of segments. + Returns: + score: (paddle.Tensor) The classification scores for input samples. + """ + + #XXX: check dropout location! + # [N * num_segs, in_channels, 7, 7] + x = self.avgpool2d(x) + # [N * num_segs, in_channels, 1, 1] + if self.dropout is not None: + x = self.dropout(x) + # [N * num_seg, in_channels, 1, 1] + num_seg = num_seg if num_seg is not None else self.num_seg + x = paddle.reshape(x, [-1, num_seg, x.shape[1]]) + # [N, num_seg, in_channels] + x = paddle.mean(x, axis=1) + # [N, in_channels] + x = paddle.reshape(x, shape=[-1, self.in_channels]) + # [N, in_channels] + score = self.fc(x) + # [N, num_class] + #x = F.softmax(x) #NOTE remove + return score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/pptsn_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/pptsn_head.py new file mode 100644 index 0000000..2655c90 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/pptsn_head.py @@ -0,0 +1,103 @@ +# 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 paddle +from paddle import ParamAttr +from paddle.nn import AdaptiveAvgPool2D, Linear, Dropout +from paddle.regularizer import L2Decay +from .base import BaseHead +from ..registry import HEADS +from ..weight_init import weight_init_ + + +@HEADS.register() +class ppTSNHead(BaseHead): + """ppTSN Head. + + Args: + num_classes (int): The number of classes to be classified. + in_channels (int): The number of channles in input feature. + loss_cfg (dict): Config for building config. Default: dict(name='CrossEntropyLoss'). + drop_ratio(float): drop ratio. Default: 0.4. + std(float): Std(Scale) value in normal initilizar. Default: 0.01. + data_format(str): data format of input tensor in ['NCHW', 'NHWC']. Default: 'NCHW'. + fclr5(bool): Whether to increase the learning rate of the fully connected layer. Default: True + kwargs (dict, optional): Any keyword argument to initialize. + + """ + def __init__(self, + num_classes, + in_channels, + loss_cfg=dict(name='CrossEntropyLoss'), + drop_ratio=0.4, + std=0.01, + data_format="NCHW", + fclr5=True, + **kwargs): + + super().__init__(num_classes, in_channels, loss_cfg, **kwargs) + self.drop_ratio = drop_ratio + self.std = std + + # NOTE: global pool performance + self.avgpool2d = AdaptiveAvgPool2D((1, 1), data_format=data_format) + + if self.drop_ratio != 0: + self.dropout = Dropout(p=self.drop_ratio) + else: + self.dropout = None + self.fc = Linear( + self.in_channels, + self.num_classes, + weight_attr=ParamAttr(learning_rate=5.0 if fclr5 else 1.0, + regularizer=L2Decay(1e-4)), + bias_attr=ParamAttr(learning_rate=10.0 if fclr5 else 1.0, + regularizer=L2Decay(0.0))) + + def init_weights(self): + """Initiate the FC layer parameters""" + weight_init_(self.fc, + 'Normal', + 'fc_0.w_0', + 'fc_0.b_0', + mean=0., + std=self.std) + + def forward(self, x, num_seg=8): + """Define how the head is going to run. + + Args: + x (paddle.Tensor): The input data. + num_segs (int): Number of segments. + Returns: + score: (paddle.Tensor) The classification scores for input samples. + """ + + # XXX: check dropout location! + # [N * num_segs, in_channels, 7, 7] + x = self.avgpool2d(x) + # [N * num_segs, in_channels, 1, 1] + x = paddle.reshape(x, [-1, num_seg, x.shape[1]]) + # [N, num_seg, in_channels] + x = paddle.mean(x, axis=1) + # [N, in_channels] + if self.dropout is not None: + x = self.dropout(x) + # [N, in_channels] + x = paddle.reshape(x, shape=[-1, self.in_channels]) + # [N, in_channels] + score = self.fc(x) + # [N, num_class] + # x = F.softmax(x) # NOTE remove + return score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/roi_extractor.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/roi_extractor.py new file mode 100644 index 0000000..3aaef23 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/roi_extractor.py @@ -0,0 +1,53 @@ +# Copyright (c) 2021 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 paddle + +#@register +class RoIAlign(object): + + def __init__(self, + resolution=14, + spatial_scale=0.0625, + sampling_ratio=0, + aligned=False): + super(RoIAlign, self).__init__() + self.resolution = resolution + self.spatial_scale = spatial_scale + self.sampling_ratio = sampling_ratio + self.aligned = aligned + + def __call__(self, feats, roi, rois_num): + roi = paddle.concat(roi) if len(roi) > 1 else roi[0] + rois_num = paddle.to_tensor(rois_num, dtype='int32') + rois_num = paddle.cast(rois_num, dtype='int32') + if len(feats) == 1: + roi_feat = paddle.vision.ops.roi_align(feats, + roi, + rois_num, + self.resolution, + self.spatial_scale, + self.sampling_ratio, + self.aligned) + else: + rois_feat_list = [] + roi_feat = paddle.vision.ops.roi_align(feats, + roi, + rois_num, + self.resolution, + self.spatial_scale, + self.sampling_ratio, + self.aligned) + + return roi_feat diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/roi_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/roi_head.py new file mode 100644 index 0000000..be34a33 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/roi_head.py @@ -0,0 +1,177 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 numpy as np +import paddle +import paddle.nn as nn +from .. import builder +from ..registry import HEADS + + +def bbox2result(bboxes, labels, num_classes, img_shape, thr=0.01): + """Convert detection results to a list of numpy arrays. """ + if len(bboxes) == 0: + return list(np.zeros((num_classes - 1, 0, 5), dtype=np.float32)) + else: + bboxes = bboxes[0] + labels = labels + img_shape_np = img_shape + img_h, img_w = img_shape_np[0][0], img_shape_np[0][1] + + img_w = paddle.cast(img_w, dtype='int32') + img_h = paddle.cast(img_h, dtype='int32') + + bboxes[:, 0::2] /= img_w + bboxes[:, 1::2] /= img_h + + # We only handle multilabel now + assert labels.shape[-1] > 1 + + scores = labels # rename + thr = (thr, ) * num_classes if isinstance(thr, float) else thr + assert scores.shape[1] == num_classes + assert len(thr) == num_classes + + result = [] + for i in range(num_classes - 1): + #step1. 对该类, 每个bbox的得分是否大于阈值 + where = scores[:, i + 1] > thr[i + 1] + + where = paddle.nonzero(where) # index + bboxes_select = paddle.index_select(x=bboxes, index=where) + bboxes_select = bboxes_select[:, :4] + + scores_select = paddle.index_select(x=scores, index=where) + scores_select = scores_select[:, i + 1:i + 2] + + result.append( + #对于step1中得分大于阈值的bbox(可能为空), 将bbox及在该类的score放入result列表. + paddle.concat((bboxes_select, scores_select), axis=1).numpy()) + + return result + + +@HEADS.register() +class AVARoIHead(nn.Layer): + + def __init__(self, + assigner, + sampler, + pos_weight=1.0, + action_thr=0.0, + bbox_roi_extractor=None, + bbox_head=None, + train_cfg=None, + test_cfg=None): + super().__init__() + self.assigner = assigner + self.sampler = sampler + self.pos_weight = pos_weight + self.action_thr = action_thr + self.init_assigner_sampler() + if bbox_head is not None: + self.init_bbox_head(bbox_roi_extractor, bbox_head) + + def init_assigner_sampler(self): + """Initialize assigner and sampler.""" + self.bbox_assigner = None + self.bbox_sampler = None + self.bbox_assigner = builder.build_assigner(self.assigner) + self.bbox_sampler = builder.build_sampler(self.sampler, context=self) + + def init_bbox_head(self, bbox_roi_extractor, bbox_head): + """Initialize ``bbox_head``""" + self.bbox_roi_extractor = builder.build_roi_extractor( + bbox_roi_extractor) + self.bbox_head = builder.build_head(bbox_head) + + def _bbox_forward(self, x, rois, rois_num): + bbox_feat = self.bbox_roi_extractor(x, rois, rois_num) + cls_score, bbox_pred = self.bbox_head( + bbox_feat, rois, rois_num + ) #deal with: when roi's width or height = 0 , roi_align is wrong + bbox_results = dict(cls_score=cls_score, + bbox_pred=bbox_pred, + bbox_feats=bbox_feat) + return bbox_results + + def _bbox_forward_train(self, x, sampling_results, gt_bboxes, gt_labels): + """Run forward function and calculate loss for box head in training.""" + rois = [res.bboxes for res in sampling_results] + rois_num = [res.bboxes.shape[0] for res in sampling_results] + bbox_results = self._bbox_forward(x, rois, rois_num) + bbox_targets = self.bbox_head.get_targets(sampling_results, gt_bboxes, + gt_labels, self.pos_weight) + loss_bbox = self.bbox_head.loss(bbox_results['cls_score'], bbox_targets) + bbox_results.update(loss_bbox=loss_bbox) + return bbox_results + + def train_step(self, x, img_metas, proposal_list, gt_bboxes, gt_labels): + #1. assign gts and sample proposals + num_imgs = len(img_metas[0]) + sampling_results = [] + for i in range(num_imgs): + assign_result = self.bbox_assigner.assign(proposal_list[i], + gt_bboxes[i], + gt_labels[i]) + sampling_result = self.bbox_sampler.sample(assign_result, + proposal_list[i], + gt_bboxes[i], + gt_labels[i]) + sampling_results.append(sampling_result) + + #2. forward and loss + bbox_results = self._bbox_forward_train(x, sampling_results, gt_bboxes, + gt_labels) + losses = dict() + losses.update(bbox_results['loss_bbox']) + + return losses + + def simple_test(self, x, proposal_list, img_shape, rescale=False): + x_shape = x[0].shape + #assert x_shape[0] == 1, 'only accept 1 sample at test mode' + + det_bboxes, det_labels = self.simple_test_bboxes(x, + img_shape, + proposal_list, + self.action_thr, + rescale=rescale) + + bbox_results = bbox2result(det_bboxes, det_labels, + self.bbox_head.num_classes, img_shape, + self.action_thr) + return [bbox_results] + + def simple_test_bboxes(self, + x, + img_shape, + proposals, + action_thr, + rescale=False): + """Test only det bboxes without augmentation.""" + rois = [proposals] + rois_num = [rois[0].shape[0]] + bbox_results = self._bbox_forward(x, rois, rois_num) + cls_score = bbox_results['cls_score'] + crop_quadruple = np.array([0, 0, 1, 1]) + flip = False + det_bboxes, det_labels = self.bbox_head.get_det_bboxes( + rois, + cls_score, + img_shape, + flip=flip, + crop_quadruple=crop_quadruple) + + return det_bboxes, det_labels diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/single_straight3d.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/single_straight3d.py new file mode 100644 index 0000000..805d93e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/single_straight3d.py @@ -0,0 +1,79 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 paddle +import paddle.nn as nn +import numpy as np +from ..registry import ROI_EXTRACTORS +from .roi_extractor import RoIAlign + + +@ROI_EXTRACTORS.register() +class SingleRoIExtractor3D(nn.Layer): + """Extract RoI features from a single level feature map. """ + def __init__(self, + roi_layer_type='RoIAlign', + featmap_stride=16, + output_size=16, + sampling_ratio=0, + pool_mode='avg', + aligned=True, + with_temporal_pool=True, + with_global=False): + super().__init__() + self.roi_layer_type = roi_layer_type + assert self.roi_layer_type in ['RoIPool', 'RoIAlign'] + self.featmap_stride = featmap_stride + self.spatial_scale = 1. / self.featmap_stride + self.output_size = output_size + self.sampling_ratio = sampling_ratio + self.pool_mode = pool_mode + self.aligned = aligned + self.with_temporal_pool = with_temporal_pool + self.with_global = with_global + + self.roi_layer = RoIAlign(resolution=self.output_size, + spatial_scale=self.spatial_scale, + sampling_ratio=self.sampling_ratio, + aligned=self.aligned) + + def init_weights(self): + pass + + # The shape of feat is N, C, T, H, W + def forward(self, feat, rois, rois_num): + if len(feat) >= 2: + assert self.with_temporal_pool + if self.with_temporal_pool: + xi = 0 + for x in feat: + xi = xi + 1 + y = paddle.mean(x, 2, keepdim=True) + feat = [paddle.mean(x, 2, keepdim=True) for x in feat] + feat = paddle.concat(feat, axis=1) # merge slow and fast + roi_feats = [] + for t in range(feat.shape[2]): + if type(t) == paddle.static.Variable: + index = paddle.to_tensor(t) + else: + data_index = np.array([t]).astype('int32') + index = paddle.to_tensor(data_index) + + frame_feat = paddle.index_select(feat, index, axis=2) + frame_feat = paddle.squeeze(frame_feat, + axis=2) #axis=2,避免N=1时, 第一维度被删除. + roi_feat = self.roi_layer(frame_feat, rois, rois_num) + roi_feats.append(roi_feat) + + ret = paddle.stack(roi_feats, axis=2) + return ret diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/slowfast_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/slowfast_head.py new file mode 100644 index 0000000..bd18baf --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/slowfast_head.py @@ -0,0 +1,137 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + +from ..registry import HEADS +from .base import BaseHead + +import paddle +import paddle.nn.functional as F + +from ..weight_init import weight_init_ + + +@HEADS.register() +class SlowFastHead(BaseHead): + """ + ResNe(X)t 3D head. + This layer performs a fully-connected projection during training, when the + input size is 1x1x1. It performs a convolutional projection during testing + when the input size is larger than 1x1x1. If the inputs are from multiple + different pathways, the inputs will be concatenated after pooling. + """ + def __init__(self, + width_per_group, + alpha, + beta, + num_classes, + num_frames, + crop_size, + dropout_rate, + pool_size_ratio=[[1, 1, 1], [1, 1, 1]], + loss_cfg=dict(name='CrossEntropyLoss'), + multigrid_short=False, + **kwargs): + """ + ResNetBasicHead takes p pathways as input where p in [1, infty]. + + Args: + dim_in (list): the list of channel dimensions of the p inputs to the + ResNetHead. + num_classes (int): the channel dimensions of the p outputs to the + ResNetHead. + pool_size (list): the list of kernel sizes of p spatial temporal + poolings, temporal pool kernel size, spatial pool kernel size, + spatial pool kernel size in order. + dropout_rate (float): dropout rate. If equal to 0.0, perform no + dropout. + """ + super().__init__(num_classes, loss_cfg, **kwargs) + self.multigrid_short = multigrid_short + self.width_per_group = width_per_group + self.alpha = alpha + self.beta = beta + self.num_classes = num_classes + self.num_frames = num_frames + self.crop_size = crop_size + self.dropout_rate = dropout_rate + self.pool_size_ratio = pool_size_ratio + + self.dim_in = [ + self.width_per_group * 32, + self.width_per_group * 32 // self.beta, + ] + self.pool_size = [None, None] if self.multigrid_short else [ + [ + self.num_frames // self.alpha // self.pool_size_ratio[0][0], + self.crop_size // 32 // self.pool_size_ratio[0][1], + self.crop_size // 32 // self.pool_size_ratio[0][2], + ], + [ + self.num_frames // self.pool_size_ratio[1][0], + self.crop_size // 32 // self.pool_size_ratio[1][1], + self.crop_size // 32 // self.pool_size_ratio[1][2], + ], + ] + + assert (len({len(self.pool_size), len(self.dim_in) + }) == 1), "pathway dimensions are not consistent." + self.num_pathways = len(self.pool_size) + + self.dropout = paddle.nn.Dropout(p=self.dropout_rate) + + self.projection = paddle.nn.Linear( + in_features=sum(self.dim_in), + out_features=self.num_classes, + ) + + def init_weights(self): + weight_init_(self.projection, + "Normal", + bias_value=0.0, + mean=0.0, + std=0.01) + + def forward(self, inputs): + assert (len(inputs) == self.num_pathways + ), "Input tensor does not contain {} pathway".format( + self.num_pathways) + pool_out = [] + for pathway in range(self.num_pathways): + if self.pool_size[pathway] is None: + tmp_out = F.adaptive_avg_pool3d(x=inputs[pathway], + output_size=(1, 1, 1), + data_format="NCDHW") + else: + tmp_out = F.avg_pool3d(x=inputs[pathway], + kernel_size=self.pool_size[pathway], + stride=1, + data_format="NCDHW") + pool_out.append(tmp_out) + + x = paddle.concat(x=pool_out, axis=1) + x = paddle.transpose(x=x, perm=(0, 2, 3, 4, 1)) + + # Perform dropout. + if self.dropout_rate > 0.0: + x = self.dropout(x) + + x = self.projection(x) + + # Performs fully convlutional inference. + if not self.training: # attr of base class + x = F.softmax(x, axis=4) + x = paddle.mean(x, axis=[1, 2, 3]) + + x = paddle.reshape(x, shape=(x.shape[0], -1)) + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/stgcn_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/stgcn_head.py new file mode 100644 index 0000000..fc80d66 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/stgcn_head.py @@ -0,0 +1,50 @@ +# Copyright (c) 2021 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 paddle +import paddle.nn as nn + +from .base import BaseHead +from ..registry import HEADS +from ..weight_init import weight_init_ + + +@HEADS.register() +class STGCNHead(BaseHead): + """ + Head for ST-GCN model. + Args: + in_channels: int, input feature channels. Default: 256. + num_classes: int, number classes. Default: 10. + """ + def __init__(self, in_channels=256, num_classes=10, **kwargs): + super().__init__(num_classes, in_channels, **kwargs) + self.fcn = nn.Conv2D(in_channels=in_channels, + out_channels=num_classes, + kernel_size=1) + + def init_weights(self): + """Initiate the parameters. + """ + for layer in self.sublayers(): + if isinstance(layer, nn.Conv2D): + weight_init_(layer, 'Normal', std=0.02) + + def forward(self, x): + """Define how the head is going to run. + """ + x = self.fcn(x) + x = paddle.reshape_(x, (x.shape[0], -1)) # N,C,1,1 --> N,C + + return x diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/timesformer_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/timesformer_head.py new file mode 100644 index 0000000..d02a3cc --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/timesformer_head.py @@ -0,0 +1,70 @@ +# 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. + +from paddle.nn import Linear + +from ..registry import HEADS +from ..weight_init import trunc_normal_, weight_init_ +from .base import BaseHead + + +@HEADS.register() +class TimeSformerHead(BaseHead): + """TimeSformerHead Head. + + Args: + num_classes (int): The number of classes to be classified. + in_channels (int): The number of channles in input feature. + loss_cfg (dict): Config for building config. Default: dict(name='CrossEntropyLoss'). + std(float): Std(Scale) value in normal initilizar. Default: 0.01. + kwargs (dict, optional): Any keyword argument to initialize. + + """ + def __init__(self, + num_classes, + in_channels, + loss_cfg=dict(name='CrossEntropyLoss'), + std=0.02, + **kwargs): + + super().__init__(num_classes, in_channels, loss_cfg, **kwargs) + self.std = std + self.fc = Linear(self.in_channels, self.num_classes) + + def init_weights(self): + """Initiate the FC layer parameters""" + + weight_init_(self.fc, + 'TruncatedNormal', + 'fc_0.w_0', + 'fc_0.b_0', + mean=0.0, + std=self.std) + # NOTE: Temporarily use trunc_normal_ instead of TruncatedNormal + trunc_normal_(self.fc.weight, std=self.std) + + def forward(self, x): + """Define how the head is going to run. + Args: + x (paddle.Tensor): The input data. + Returns: + score: (paddle.Tensor) The classification scores for input samples. + """ + # XXX: check dropout location! + # x.shape = [N, embed_dim] + + score = self.fc(x) + # [N, num_class] + # x = F.softmax(x) # NOTE remove + return score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/token_shift_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/token_shift_head.py new file mode 100644 index 0000000..52e9309 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/token_shift_head.py @@ -0,0 +1,79 @@ +# 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. + +from paddle.nn import Linear +import paddle + +from ..registry import HEADS +from ..weight_init import trunc_normal_, weight_init_ +from .base import BaseHead + + +@HEADS.register() +class TokenShiftHead(BaseHead): + """TokenShift Transformer Head. + + Args: + num_classes (int): The number of classes to be classified. + in_channels (int): The number of channles in input feature. + num_seg(int): The number of segments. Default: 8. + loss_cfg (dict): Config for building config. Default: dict(name='CrossEntropyLoss'). + ls_eps (float): Label smoothing epsilon. Default: 0.01. + std (float): Std(Scale) Value in normal initilizar. Default: 0.02. + kwargs (dict, optional): Any keyword argument to initialize. + + """ + def __init__(self, + num_classes, + in_channels, + num_seg=8, + loss_cfg=dict(name='CrossEntropyLoss'), + ls_eps=0.01, + std=0.02, + **kwargs): + + super().__init__(num_classes, in_channels, loss_cfg, ls_eps) + self.num_seg = num_seg + self.std = std + self.fc = Linear(self.in_channels, self.num_classes) + + def init_weights(self): + """Initiate the FC layer parameters""" + + weight_init_(self.fc, + 'TruncatedNormal', + 'fc_0.w_0', + 'fc_0.b_0', + mean=0.0, + std=self.std) + # NOTE: Temporarily use trunc_normal_ instead of TruncatedNormal + trunc_normal_(self.fc.weight, std=self.std) + + def forward(self, x): + """Define how the head is going to run. + Args: + x (paddle.Tensor): The input data. + Returns: + score: (paddle.Tensor) The classification scores for input samples. + """ + # XXX: check dropout location! + # x.shape = [N, embed_dim] + score = self.fc(x) + # [N*T, num_class] + _, _m = score.shape + _t = self.num_seg + score = score.reshape([-1, _t, _m]) + score = paddle.mean(score, 1) # averaging predictions for every frame + score = paddle.squeeze(score, axis=1) + return score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/transnetv2_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/transnetv2_head.py new file mode 100644 index 0000000..2ea67d4 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/transnetv2_head.py @@ -0,0 +1,45 @@ +# 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. + +from .base import BaseHead +from ..registry import HEADS +from ..losses import TransNetV2Loss +from ...metrics.transnetv2_metric import create_scene_based_summaries + +@HEADS.register() +class TransNetV2Head(BaseHead): + """TransNetV2 Head. + """ + def __init__(self, + num_classes, + in_channels, + loss_cfg=dict(name="TransNetV2Loss") + ): + super().__init__(num_classes, + in_channels, + loss_cfg) + + def loss(self, one_hot_pred, one_hot_gt, + many_hot_pred=None, many_hot_gt=None, reg_losses=None): + losses = dict() + loss = self.loss_func(scores, labels, **kwargs) + + f1 = self.get_score(one_hot_pred, one_hot_gt) + losses['f1'] = f1 + losses['loss'] = loss + return losses + + def get_score(self, one_hot_pred, one_hot_gt): + f1 = create_scene_based_summaries(one_hot_pred, one_hot_gt) + return f1 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/tsm_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/tsm_head.py new file mode 100644 index 0000000..9559301 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/tsm_head.py @@ -0,0 +1,99 @@ +# 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 math +import paddle +from paddle import ParamAttr +from paddle.nn import Linear +import paddle.nn.functional as F +from paddle.regularizer import L2Decay +from .tsn_head import TSNHead +from ..registry import HEADS + +from ..weight_init import weight_init_ + + +@HEADS.register() +class TSMHead(TSNHead): + """ TSM Head + + Args: + num_classes (int): The number of classes to be classified. + in_channels (int): The number of channles in input feature. + loss_cfg (dict): Config for building config. Default: dict(name='CrossEntropyLoss'). + drop_ratio(float): drop ratio. Default: 0.5. + std(float): Std(Scale) value in normal initilizar. Default: 0.001. + kwargs (dict, optional): Any keyword argument to initialize. + """ + def __init__(self, + num_classes, + in_channels, + drop_ratio=0.5, + std=0.001, + data_format="NCHW", + **kwargs): + super().__init__(num_classes, + in_channels, + drop_ratio=drop_ratio, + std=std, + data_format=data_format, + **kwargs) + + self.fc = Linear(self.in_channels, + self.num_classes, + weight_attr=ParamAttr(learning_rate=5.0, + regularizer=L2Decay(1e-4)), + bias_attr=ParamAttr(learning_rate=10.0, + regularizer=L2Decay(0.0))) + + assert (data_format in [ + 'NCHW', 'NHWC' + ]), f"data_format must be 'NCHW' or 'NHWC', but got {data_format}" + + self.data_format = data_format + + self.stdv = std + + def init_weights(self): + """Initiate the FC layer parameters""" + weight_init_(self.fc, 'Normal', 'fc_0.w_0', 'fc_0.b_0', std=self.stdv) + + def forward(self, x, num_seg): + """Define how the tsm-head is going to run. + + Args: + x (paddle.Tensor): The input data. + num_segs (int): Number of segments. + Returns: + score: (paddle.Tensor) The classification scores for input samples. + """ + # x.shape = [N * num_segs, in_channels, 7, 7] + + x = self.avgpool2d(x) # [N * num_segs, in_channels, 1, 1] + + if self.dropout is not None: + x = self.dropout(x) # [N * num_seg, in_channels, 1, 1] + + if self.data_format == 'NCHW': + x = paddle.reshape(x, x.shape[:2]) + else: + x = paddle.reshape(x, x.shape[::3]) + score = self.fc(x) # [N * num_seg, num_class] + score = paddle.reshape( + score, [-1, num_seg, score.shape[1]]) # [N, num_seg, num_class] + score = paddle.mean(score, axis=1) # [N, num_class] + score = paddle.reshape(score, + shape=[-1, self.num_classes]) # [N, num_class] + # score = F.softmax(score) #NOTE remove + return score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/heads/tsn_head.py b/Bank_second_part/detect_process/paddlevideo/modeling/heads/tsn_head.py new file mode 100644 index 0000000..f2f906b --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/heads/tsn_head.py @@ -0,0 +1,93 @@ +# 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 paddle +from paddle.nn import AdaptiveAvgPool2D, Linear, Dropout + +from .base import BaseHead +from ..registry import HEADS +from ..weight_init import weight_init_ + + +@HEADS.register() +class TSNHead(BaseHead): + """TSN Head. + + Args: + num_classes (int): The number of classes to be classified. + in_channels (int): The number of channles in input feature. + loss_cfg (dict): Config for building config. Default: dict(name='CrossEntropyLoss'). + drop_ratio(float): drop ratio. Default: 0.4. + std(float): Std(Scale) value in normal initilizar. Default: 0.01. + kwargs (dict, optional): Any keyword argument to initialize. + + """ + def __init__(self, + num_classes, + in_channels, + loss_cfg=dict(name='CrossEntropyLoss'), + drop_ratio=0.4, + std=0.01, + data_format="NCHW", + **kwargs): + + super().__init__(num_classes, in_channels, loss_cfg, **kwargs) + self.drop_ratio = drop_ratio + self.std = std + + #NOTE: global pool performance + self.avgpool2d = AdaptiveAvgPool2D((1, 1), data_format=data_format) + + if self.drop_ratio != 0: + self.dropout = Dropout(p=self.drop_ratio) + else: + self.dropout = None + + self.fc = Linear(self.in_channels, self.num_classes) + + def init_weights(self): + """Initiate the FC layer parameters""" + + weight_init_(self.fc, + 'Normal', + 'fc_0.w_0', + 'fc_0.b_0', + mean=0., + std=self.std) + + def forward(self, x, num_seg): + """Define how the head is going to run. + Args: + x (paddle.Tensor): The input data. + num_segs (int): Number of segments. + Returns: + score: (paddle.Tensor) The classification scores for input samples. + """ + + #XXX: check dropout location! + # [N * num_segs, in_channels, 7, 7] + + x = self.avgpool2d(x) + # [N * num_segs, in_channels, 1, 1] + x = paddle.reshape(x, [-1, num_seg, x.shape[1]]) + # [N, num_seg, in_channels] + x = paddle.mean(x, axis=1) + # [N, in_channels] + if self.dropout is not None: + x = self.dropout(x) + # [N, in_channels] + score = self.fc(x) + # [N, num_class] + #x = F.softmax(x) #NOTE remove + return score diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/losses/__init__.py new file mode 100644 index 0000000..d784c4c --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/losses/__init__.py @@ -0,0 +1,29 @@ +# 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. + +from .base import BaseWeightedLoss +from .bmn_loss import BMNLoss +from .cross_entropy_loss import CrossEntropyLoss +from .depth_loss import ADDSLoss +from .transnetv2_loss import TransNetV2Loss +from .actbert_loss import ActBertLoss +from .asrf_loss import ASRFLoss +from .distillation_loss import DistillationCELoss, DistillationDMLLoss +from .yowo_loss import RegionLoss + +__all__ = [ + 'CrossEntropyLoss', 'BMNLoss', 'TransNetV2Loss', 'ActBertLoss', 'ADDSLoss', + 'BaseWeightedLoss', 'ASRFLoss', 'DistillationCELoss', 'DistillationDMLLoss', + 'RegionLoss' +] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..72125a0dff70018ad50f6efd19f17f1666d09b0a GIT binary patch literal 703 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

_#Yd;HSlqyweDz$`pI!_152CdbZa5UHUNdk> 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 Sr@9V^c=aLe0Hdg}LH`22yeRSj literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/depth_loss.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/depth_loss.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1f884a12b8f537c34e8fbaf8e0e7781094148780 GIT binary patch literal 7026 zcmb7JO^h5z74HA;`Q6!{c>NbNK_Ov)IPoSR5{w;U$8nIoiDFAggF~l1)jOWe{JFZ< z@osv=!3l|k%z+a>m))beaN>fHIB-GY!VRfTh`_<*1im07SibkFXLk0_5wq&oRj;aE zRad?Dz4vMdl}gdT?~m>e#g(TG;}fb(|6EjF#*_R6L>R*C8cqE+dsfpj4PgnpYxkU{ zgR&#suG{mP9?G8ZKQNm9Yla9!;R8byVrwH||(Yp+B} z{GGVdzM012@*qiC)NlOrP@p|Hk0*HtLsDbY%^{BCB zj;sTvV7!)ifD|6T)5=op)L7M$u$o7#=b+YI>k&4c%{_bM94c}5+ICAkU~LnLZbmD# zGpB^_e$g0N8CH$Do7e5k+O)Qe%qF^M;IzDr-uXdqxR%CAJ-r#%lipyE-t5OoQt#q) z>MH|TkLse63?tb|*Xx~L)Q*dF{H~#QYtThI^Xi?XzLvy-N5rBXKNGzd$!UQ+YWcx7 ze$v4KU%PKA|J^tqicYWLC~p`E(T$ZI-AI(vi=)1><2%EKryQDI*_~cnmD(~AA=Se> z)0K5qc1PVbh>e(i_a}xAId=s-^$$UdI7gPA|71t z4Mg1S^xM~I7cfA?!}MlIl~coYHPepMP;V9Uj*z|{2f656G%s0}X_?-CFWLHCb82SI zl8>Reg=g2#&T9{!L?JesrZAe;N5%>rx%ENNwCQMJy3R+2V>DeHn5%*dos|_f9kQwM zkIE#Co`-WFsgc5T?(%^H0&v*(&E1Xe?h4+8Fl==r z>`BNwCl}CBo&fnWo`+kFBl2P->)dgjpvFH71>Nm#^sDjCTFY~0Og z7%N}Ky5P#F-;O1Ht1N*itJhQJHDwP6?==eYabkI$K5XlB{$5hW8&TT2877^LxLMF` zVRtDnE^$%dbXlpC4Z~1oM;`-eF`tFZ+L>3Vaft}kK6CHgtFQlmyMLBMKXUiq zpdNLQjVcR2eE-P>@czGm!lU;emdhuQfzFeq@)<}PD8CAlZ?t@o7%vg|29Yx$O*iQr zve9p$d9u+*X`?H8$)CB^v<=HN18+6e4&CbHi)bAKyD*zJgFE6hfV)F+0Kna4a3}16 zue*vhY@E3qt;e#S4&Y(gIkRu3Che7P#OZr++^D*?BUFpWH6kLZKar>F`CqMnm*N&fS|M(Bzzx3PDm2-`%hJ$k? zffQ0%{k|%E>vsFi!JxZzK^1yy;hk`Z3K!RPv6yraA54{Veu?>c#eFjpkN|sK=_>2| zX*^4ZqRrcwJ0W*l1@MmlYL*8ehC1QE4mJRCjuQa-Jt~>82`9-ekxJwov2AdU#KXY= zkcj7?1Q$wX060P@IFAq)=3u}bBAjI|8wt1`xNZg)yTE-jXMy_q0^=48s%6Hiw+OeK z`CRrFjRgbFm8EJ^Tg>~wrJ^VL>pq1v*enPOZnkg&GKG1_5#r%3OyM;4qo4D<4PIi%`uA>ng}O z>&l}I5BvFBOu-}vG33iu@g!6$0$qzZr6bl6^N3luo-~hJ8)ZJR-2NNBBo`~6B|=U@ z`C%vqEqFkNKoTcU6Pcfo9XKYr2@J<9TeXTL?%`NLfHua8gMvV^Cc+EhivVwr zalr!yM`bcHw*Ct!?6!U=hY=zt0Ch5L{oY+1bLgi5zYA%R-=(}> zCd<|SxS|b^K2aNBExO$fWsHb=6{g!6^wq*7ZOCI~N-LD#AA|`&Sx2A+3aJs$udJ}k zQYEg-xHagXmV~U+oFz5G%^2P3az4^thxZIdxoXQ3nWMec*ci7Ekmvn9 zVQ1a~GIcUW#G~xh8t%qhlZ~ z_>M6GI%1#NS6A>V6xzhj#&d90{cnqhe;ur-8KS4-O?FrMy<)TDf0E9jVGx zE7kH=Nb-&uWT+qNndU|n@Z7AD_pfFFaGnspnw7VJ?WS?-o2dnK4}=e83b3Y`eNs+B ziY>de5=hc>Rr@}zWT&3Z?34TsOP*oLGf+%N{wSMSB_Jt?;yr6r>s#5(sKzZn&w{Cz zS+oSB*{lW$URGQ6w@guDbp>bD&T850iUm1kNSVv#R(;{qcfV`NUuScp`99LO)gYV8 zd(3BkHoxi8<-^F&ikq&ehyqN)#T66YqlK)PEr^*#3i2LH3)y2?>8>?8f>Fk5F*^cd z!TwPQ$m87%{s^b(!&}uhOBqtUGsdkTbJH?*4*P!Be4Nb+?Xzd#^8l4|8?WW&#WB^i z+OqxZxd6en2;4zEs`rp6v&nIc#WqFWO?gQx!i|EgP{rp95qKb%3#zapDa-1Jgbi@{ znj|!7|KsK-AOGrKe?3d_O?0P|a4I2Rrlw23{LRn)`KOJu8$Kc3v+s|TLxn~~dC_nf z_k~lu}aBmrtMz@{3NNFC7>cm50yhMX9p8alf&sy{pbn0m*~4 z6lrRrf=&|l>26MWG;5rwVme5puC{TPKUH=iy*WROtksGw0 zV7wQMCC!t#X6dK6QrZs!and|~c&m(A8W7+{ryq-EDIJ7^VG5U!Ag88#BfcMM7W(*L zE~?VhRn1;3s*a&VfACKsJV`+un_M=)2f#z`s#!CuR@Gd<;~;kMw#&9-AwOfj=Fk{t z+aqcQ+m7Q|1Y1E@0mf`B?gKczs$G{Wvsj&n zhf!?~s0I{4>!bt1bmkzM7IC8~5mwFPA7c|6QRrvz>`!+TuA_}XNAjYqkN$Y+iL@ql9b zZHXD68FL|_M#x4jC=<$AgmTNcJ&M*9s0e;M5#xFEPZENFm>*4p}#j01dIm2%t*cQ;s!in=GEhAL`x4ryuSyv$2Nm_Y%W zr1(nqh=fGm0a2ca)2MY*MyNDqbvTkxE19YM0g;c0&MPpFKx8wT*dv0Ow=v;ZO>^*VB{2z+COl|-G literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/distillation_loss.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/distillation_loss.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b766587560a4a7b00f0d6cc2de49cdc471c604fd GIT binary patch literal 2437 zcmaJ@&2Jnv6t_JeJ3HBwl1BYXO9zmE73!)~fNrmyM@PHdJ%Z+2h@rBY7a3kT=KjmgLK<9UkIbwsa^!+uZnzUoS7;TR!CV^z`kd zP~WM++Ip$vVqO$I(w=U#?k0M19z?M&m#ix!?>c1VQ`U8*i&H!^cXv>fgEURbL7v^Y zM|0^c-wAX)|D4^e@qipFm1hi9Ig)rqE|AA;kr@>y~^&RJ?Ng zV!$frcm50C^(t?9qU%8SZY5TnU4OT+8;rI6DedN1)|iroRZunOk(DYq&#G{qonyOR z>Fm3ecQD?+?IzzKTK9APIMFidkFp-Q*a@R?yQSBP8%Hw|7QI}n=)J8(%2ah8sI16! z`$qI&T}8b#DT-R*-yLX8nyjj{IC;^U&PSPyNvl%yk-Z&f+c*(+X>%E|U>tB&*j zXG={9*95~uf&viaq$)G~zM1WjAu&uRxEQ|#!NWj)3v( z+_+?$Y1m1eOqf+1kqohhwok_6>T{+E+Ao&Xjg{L;wi)*asVZvr+Vzz!o%a;_4}jl0&Vy4sz_)htF7_Q&oD}#ND@*sOw2vdAj~HT;py7^%&iuRSB|*I#r8e6{KW)Y=cXGQV%$*P@P6x zpTWo<12Bpf+47#fBpt>Hf?s7Q5LjtBw09JB|VF&E8xi9 zg8s=+RXF7Yt<%0Hd3(0b>iqaI%d*bo1x!-?E;LLyC1{eMd8BIst=3Q%^|p5Ci@S=y t8=6ux`J%KfK=!PuC>;Ub1RvMc?o)ayEb4<(b3lCywaa(rxPRd+{|8a8QCa{1 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/transnetv2_loss.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/transnetv2_loss.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64637728ad41dbfac2929afd6df32cf075807704 GIT binary patch literal 1489 zcmZWp&2Aev5GJ|1+|^nVoIs789s*qoR2L&~4@H9@4bnfL2-FlVT414qSc{ar^=elk zDH{q_KvBEMq38p&C+V0+=v(yE1Ft;@DzsX1LKI}93}OPCxjr3CSKxW#0mHEU_uiLYo7;sIEj)7BSDvq75V~k z%EL>|d3Vfpe6#?GEhCcu5=;*VfD_o1a&r&766WRDg3;w)RYG|!* zlfM?!0W1VcFh>dDIPrMnH5y@?$7Lh&8BVk&ojOf`A9Y( zinQH(gH406VV=Sv_6Gg)wRkjmmKLXMl;uLz%ZG=9sVs*AOziGpnsT0tvy6*!;4YaJ zWX;nBq2mwYRO4E#1K;!T!)1ZDj=a0e~IidNwsT0~XgJY-d{ z3|Ht=^nG(c7L7$*#cuzkimLcSuzNYEB4}#ZmlluGqSu6@yiD~6hsH0;LO{oYyc}m5 zru10krXdBN4Q=bkVC|?Exqcd&Dm|YHgFiRjARmiyK;f&yns%el0_3*#TdpHA98?M5S{bA2lpmsMTN$Mw~oSfnZY OFr)Te+=P#M_wc{Eu!L9u literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/yowo_loss.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/losses/__pycache__/yowo_loss.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d69a0a54ac9da3969a1b72e165dcdbe71fef244d GIT binary patch literal 6236 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 b{k={BNnRQ3x{WQW(u=Eg6>7CUIH~?0`lvGX literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/actbert_loss.py b/Bank_second_part/detect_process/paddlevideo/modeling/losses/actbert_loss.py new file mode 100644 index 0000000..10ffea6 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/losses/actbert_loss.py @@ -0,0 +1,75 @@ +# Copyright (c) 2021 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 numpy as np +import paddle +import paddle.nn as nn +import paddle.nn.functional as F + +from ..registry import LOSSES +from .base import BaseWeightedLoss + + +@LOSSES.register() +class ActBertLoss(BaseWeightedLoss): + """Loss for ActBert model + """ + def __init__(self, vocab_size=30522, a_target_size=700): + super().__init__() + self.vocab_size = vocab_size + self.a_target_size = a_target_size + self.loss_fct = nn.CrossEntropyLoss(ignore_index=-1) + self.vis_criterion = nn.KLDivLoss(reduction="none") + + def forward(self, prediction_scores_t, prediction_scores_v, prediction_scores_a, seq_relationship_score, \ + text_labels, image_label, image_target, action_label, next_sentence_label): + """ + Args: + text_label: text label(with mask). Shape: [batch_size, seqence_length] + image_label: image label(with mask). Shape: [batch_size, region_length] + image_target: label of image feature distribution, + Shape: [batch_size, region_length-1, num_image_class](minus 1 for xxx). + action label: action label(with mask), Shape: [batch_size, action_length] + next_sentence_label: is next sentence or not. Shape: [batch_size] + """ + prediction_scores_v = prediction_scores_v[:, + 1:] #8,37,1601 --> 8,36,1601 + + img_loss = self.vis_criterion( + F.log_softmax(prediction_scores_v, axis=2), + image_target #8,36,1601 + ) + masked_img_loss = paddle.sum( + img_loss * (image_label == 1).unsqueeze(2).astype('float32')) / max( + paddle.sum((image_label == 1).astype('float32')), 1e-6) + + masked_text_loss = self.loss_fct( + prediction_scores_t.reshape([-1, self.vocab_size]), #8,36,30522 + text_labels.reshape([-1]), #8,36 # label -1 will be ignored + ) + + masked_action_loss = self.loss_fct( + prediction_scores_a.reshape([-1, self.a_target_size]), #8,5,700 + action_label.reshape([-1]), #8,5 + ) + + next_sentence_loss = self.loss_fct( + seq_relationship_score.reshape([-1, 2]), + next_sentence_label.reshape([-1]) #8,2 + ) + + total_loss = masked_text_loss.unsqueeze(0) + masked_img_loss.unsqueeze( + 0) + masked_action_loss.unsqueeze(0) + next_sentence_loss.unsqueeze( + 0) + return total_loss diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/asrf_loss.py b/Bank_second_part/detect_process/paddlevideo/modeling/losses/asrf_loss.py new file mode 100644 index 0000000..ce5d6b1 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/losses/asrf_loss.py @@ -0,0 +1,401 @@ +# 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. + +# https://github.com/yiskw713/asrf/libs/loss_fn/__init__.py + +import numpy as np +import pandas as pd +import paddle +import paddle.nn as nn +import paddle.nn.functional as F +import sys +import os + +from ..registry import LOSSES + + +class TMSE(nn.Layer): + """ + Temporal MSE Loss Function + Proposed in Y. A. Farha et al. MS-TCN: Multi-Stage Temporal Convolutional Network for ActionSegmentation in CVPR2019 + arXiv: https://arxiv.org/pdf/1903.01945.pdf + """ + + def __init__(self, threshold=4, ignore_index=255): + super().__init__() + self.threshold = threshold + self.ignore_index = ignore_index + self.mse = nn.MSELoss(reduction="none") + + def forward(self, preds, gts): + + total_loss = 0.0 + batch_size = preds.shape[0] + for pred, gt in zip(preds, gts): + pred = paddle.gather(pred, + paddle.nonzero(gt != self.ignore_index)[:, 0]) + + loss = self.mse(F.log_softmax(pred[:, 1:], axis=1), + F.log_softmax(pred[:, :-1], axis=1)) + + loss = paddle.clip(loss, min=0, max=self.threshold**2) + total_loss += paddle.mean(loss) + + return total_loss / batch_size + + +class GaussianSimilarityTMSE(nn.Layer): + """ + Temporal MSE Loss Function with Gaussian Similarity Weighting + """ + + def __init__(self, threshold=4, sigma=1.0, ignore_index=255): + super().__init__() + self.threshold = threshold + self.ignore_index = ignore_index + self.mse = nn.MSELoss(reduction="none") + self.sigma = sigma + + def forward(self, preds, gts, sim_index): + """ + Args: + preds: the output of model before softmax. (N, C, T) + gts: Ground Truth. (N, T) + sim_index: similarity index. (N, C, T) + Return: + the value of Temporal MSE weighted by Gaussian Similarity. + """ + total_loss = 0.0 + batch_size = preds.shape[0] + for pred, gt, sim in zip(preds, gts, sim_index): + pred = paddle.gather(pred, + paddle.nonzero(gt != self.ignore_index)[:, 0], + axis=1) + sim = paddle.gather(sim, + paddle.nonzero(gt != self.ignore_index)[:, 0], + axis=1) + + # calculate gaussian similarity + diff = sim[:, 1:] - sim[:, :-1] + similarity = paddle.exp( + (-1 * paddle.norm(diff, axis=0)) / (2 * self.sigma**2)) + + # calculate temporal mse + loss = self.mse(F.log_softmax(pred[:, 1:], axis=1), + F.log_softmax(pred[:, :-1], axis=1)) + loss = paddle.clip(loss, min=0, max=self.threshold**2) + + # gaussian similarity weighting + loss = similarity * loss + + total_loss += paddle.mean(loss) + + return total_loss / batch_size + + +class FocalLoss(nn.Layer): + + def __init__(self, + weight=None, + size_average=True, + batch_average=True, + ignore_index=255, + gamma=2.0, + alpha=0.25): + super().__init__() + + self.gamma = gamma + self.alpha = alpha + self.batch_average = batch_average + self.criterion = nn.CrossEntropyLoss(weight=weight, + ignore_index=ignore_index, + size_average=size_average) + + def forward(self, logit, target): + n, _, _ = logit.size() + + logpt = -self.criterion(logit, target.long()) + pt = paddle.exp(logpt) + + if self.alpha is not None: + logpt *= self.alpha + + loss = -((1 - pt)**self.gamma) * logpt + + if self.batch_average: + loss /= n + + return loss + + +class ActionSegmentationLoss(nn.Layer): + """ + Loss Function for Action Segmentation + You can choose the below loss functions and combine them. + - Cross Entropy Loss (CE) + - Focal Loss + - Temporal MSE (TMSE) + - Gaussian Similarity TMSE (GSTMSE) + """ + + def __init__(self, + num_classes, + file_path, + label_path, + ce=True, + focal=True, + tmse=False, + gstmse=False, + weight=None, + threshold=4., + ignore_index=255, + ce_weight=1.0, + focal_weight=1.0, + tmse_weight=0.15, + gstmse_weight=0.15): + super().__init__() + self.criterions = [] + self.weights = [] + + self.num_classes = num_classes + self.file_path = file_path + self.label_path = label_path + if weight: + class_weight = self.get_class_weight() + else: + class_weight = None + + if ce: + self.criterions.append( + nn.CrossEntropyLoss(weight=class_weight, + ignore_index=ignore_index)) + self.weights.append(ce_weight) + + if focal: + self.criterions.append(FocalLoss(ignore_index=ignore_index)) + self.weights.append(focal_weight) + + if tmse: + self.criterions.append( + TMSE(threshold=threshold, ignore_index=ignore_index)) + self.weights.append(tmse_weight) + + if gstmse: + self.criterions.append( + GaussianSimilarityTMSE(threshold=threshold, + ignore_index=ignore_index)) + self.weights.append(gstmse_weight) + + if len(self.criterions) == 0: + print("You have to choose at least one loss function.") + sys.exit(1) + + def get_class_weight(self): + """ + Class weight for CrossEntropy + Class weight is calculated in the way described in: + D. Eigen and R. Fergus, “Predicting depth, surface normals and semantic labels with a common multi-scale convolutional architecture,” in ICCV, + openaccess: https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/Eigen_Predicting_Depth_Surface_ICCV_2015_paper.pdf + """ + # load file list + file_ptr = open(self.file_path, 'r') + info = file_ptr.read().split('\n')[:-1] + file_ptr.close() + + nums = [0 for i in range(self.num_classes)] + for i in range(len(info)): + video_name = info[i] + file_name = video_name.split('.')[0] + ".npy" + label_file_path = os.path.join(self.label_path, file_name) + label = np.load(label_file_path).astype(np.int64) + num, cnt = np.unique(label, return_counts=True) + for n, c in zip(num, cnt): + nums[n] += c + + class_num = paddle.to_tensor(nums, dtype="float32") + total = class_num.sum().item() + frequency = class_num / total + median = paddle.median(frequency) + class_weight = median / frequency + return class_weight + + def forward(self, preds, gts, sim_index): + """ + Args: + preds: paddle.float (N, C, T). + gts: paddle.int64 (N, T). + sim_index: paddle.float (N, C', T). + """ + loss = 0.0 + for criterion, weight in zip(self.criterions, self.weights): + if isinstance(criterion, GaussianSimilarityTMSE): + loss += weight * criterion(preds, gts, sim_index) + elif isinstance(criterion, nn.CrossEntropyLoss): + preds_t = paddle.transpose(preds, perm=[0, 2, 1]) + loss += weight * criterion(preds_t, gts) + else: + loss += weight * criterion(preds, gts) + + return loss + + +class BoundaryRegressionLoss(nn.Layer): + """ + Boundary Regression Loss + bce: Binary Cross Entropy Loss for Boundary Prediction + mse: Mean Squared Error + """ + + def __init__(self, + file_path, + label_path, + bce=True, + focal=False, + mse=False, + weight=None, + pos_weight=None): + super().__init__() + + self.criterions = [] + self.file_path = file_path + self.label_path = label_path + + pos_weight = self.get_pos_weight() + + if bce: + self.criterions.append( + nn.BCEWithLogitsLoss(weight=weight, pos_weight=pos_weight)) + + if focal: + self.criterions.append(FocalLoss()) + + if mse: + self.criterions.append(nn.MSELoss()) + + if len(self.criterions) == 0: + print("You have to choose at least one loss function.") + sys.exit(1) + + def get_pos_weight(self, norm=None): + """ + pos_weight for binary cross entropy with logits loss + pos_weight is defined as reciprocal of ratio of positive samples in the dataset + """ + # load file list + file_ptr = open(self.file_path, 'r') + info = file_ptr.read().split('\n')[:-1] + file_ptr.close() + + n_classes = 2 # boundary or not + nums = [0 for i in range(n_classes)] + for i in range(len(info)): + video_name = info[i] + file_name = video_name.split('.')[0] + ".npy" + label_file_path = os.path.join(self.label_path, file_name) + label = np.load(label_file_path).astype(np.int64) + num, cnt = np.unique(label, return_counts=True) + for n, c in zip(num, cnt): + nums[n] += c + + pos_ratio = nums[1] / sum(nums) + pos_weight = 1 / pos_ratio + + if norm is not None: + pos_weight /= norm + + return paddle.to_tensor(pos_weight, dtype="float32") + + def forward(self, preds, gts): + """ + Args: + preds: paddle.float (N, 1, T). + gts: paddle.float (N, 1, T). + """ + loss = 0.0 + batch_size = float(preds.shape[0]) + + for criterion in self.criterions: + for pred, gt in zip(preds, gts): + loss += criterion(pred, gt) + + return loss / batch_size + + +@LOSSES.register() +class ASRFLoss(nn.Layer): + + def __init__(self, + lambda_bound_loss, + num_classes, + file_path, + label_path, + boundary_path, + ce=True, + asl_focal=True, + tmse=False, + gstmse=False, + asl_weight=None, + threshold=4., + ignore_index=255, + ce_weight=1.0, + focal_weight=1.0, + tmse_weight=0.15, + gstmse_weight=0.15, + bce=True, + brl_focal=False, + mse=False, + brl_weight=None): + super().__init__() + self.criterion_cls = ActionSegmentationLoss(ce=ce, + focal=asl_focal, + tmse=tmse, + gstmse=gstmse, + weight=asl_weight, + threshold=threshold, + ignore_index=ignore_index, + ce_weight=ce_weight, + focal_weight=focal_weight, + tmse_weight=tmse_weight, + gstmse_weight=gstmse_weight, + file_path=file_path, + label_path=label_path, + num_classes=num_classes) + self.criterion_boundary = BoundaryRegressionLoss( + bce=bce, + focal=brl_focal, + mse=mse, + weight=brl_weight, + file_path=file_path, + label_path=boundary_path) + self.lambda_bound_loss = lambda_bound_loss + + def forward(self, x, output_cls, label, outputs_boundary, boundary): + loss = 0.0 + if isinstance(output_cls, list): + n = len(output_cls) + for out in output_cls: + loss += self.criterion_cls(out, label, x) / n + else: + loss += self.criterion_cls(output_cls, label, x) + + if isinstance(outputs_boundary, list): + n = len(outputs_boundary) + for out in outputs_boundary: + loss += self.lambda_bound_loss * self.criterion_boundary( + out, boundary) / n + else: + loss += self.lambda_bound_loss * self.criterion_boundary( + outputs_boundary, boundary) + + return loss diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/base.py b/Bank_second_part/detect_process/paddlevideo/modeling/losses/base.py new file mode 100644 index 0000000..7284252 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/losses/base.py @@ -0,0 +1,49 @@ +# 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. + +from abc import abstractmethod +import paddle +import paddle.nn as nn + +#XXX use _forward?? or forward?? +class BaseWeightedLoss(nn.Layer): + """Base class for loss. + + All subclass should overwrite the ``_forward()`` method which returns the + normal loss without loss weights. + + Args: + loss_weight (float): Factor scalar multiplied on the loss. + Default: 1.0. + """ + + def __init__(self, loss_weight=1.0): + super().__init__() + self.loss_weight = loss_weight + + @abstractmethod + def _forward(self, *args, **kwargs): + pass + + def forward(self, *args, **kwargs): + """Defines the computation performed at every call. + Args: + *args: The positional arguments for the corresponding + loss. + **kwargs: The keyword arguments for the corresponding + loss. + Returns: + paddle.Tensor: The calculated loss. + """ + return self._forward(*args, **kwargs) * self.loss_weight diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/bmn_loss.py b/Bank_second_part/detect_process/paddlevideo/modeling/losses/bmn_loss.py new file mode 100644 index 0000000..e434850 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/losses/bmn_loss.py @@ -0,0 +1,155 @@ +# 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 numpy as np +import paddle +import paddle.nn.functional as F + +from ..registry import LOSSES +from .base import BaseWeightedLoss + + +@LOSSES.register() +class BMNLoss(BaseWeightedLoss): + """Loss for BMN model + Args: + tscale (int): sequence length, default 100. + dscale (int): max duration length, default 100. + """ + def __init__(self, dscale, tscale): + super().__init__() + self.dscale = dscale + self.tscale = tscale + + def _get_mask(self, dscale, tscale): + bm_mask = [] + for idx in range(dscale): + mask_vector = [1 for i in range(tscale - idx) + ] + [0 for i in range(idx)] + bm_mask.append(mask_vector) + bm_mask = np.array(bm_mask, dtype='float32') + bm_mask = paddle.to_tensor(bm_mask) + bm_mask.stop_gradient = True + return bm_mask + + def tem_loss_func(self, pred_start, pred_end, gt_start, gt_end): + def bi_loss(pred_score, gt_label, datatype): + pred_score = paddle.reshape(x=pred_score, shape=[-1]) + gt_label = paddle.reshape(x=gt_label, shape=[-1]) + gt_label.stop_gradient = True + pmask = paddle.cast(x=(gt_label > 0.5), dtype=datatype) + num_entries = paddle.cast(paddle.shape(pmask), dtype=datatype) + num_positive = paddle.cast(paddle.sum(pmask), dtype=datatype) + ratio = num_entries / num_positive + coef_0 = 0.5 * ratio / (ratio - 1) + coef_1 = 0.5 * ratio + epsilon = 0.000001 + loss_pos = paddle.multiply(paddle.log(pred_score + epsilon), pmask) + loss_pos = coef_1 * paddle.mean(loss_pos) + loss_neg = paddle.multiply(paddle.log(1.0 - pred_score + epsilon), + (1.0 - pmask)) + loss_neg = coef_0 * paddle.mean(loss_neg) + loss = -1 * (loss_pos + loss_neg) + return loss + + loss_start = bi_loss(pred_start, gt_start, pred_start.dtype) + loss_end = bi_loss(pred_end, gt_end, pred_start.dtype) + loss = loss_start + loss_end + return loss + + def pem_reg_loss_func(self, pred_score, gt_iou_map, mask): + gt_iou_map = paddle.multiply(gt_iou_map, mask) + + u_hmask = paddle.cast(x=gt_iou_map > 0.7, dtype=pred_score.dtype) + u_mmask = paddle.logical_and(gt_iou_map <= 0.7, gt_iou_map > 0.3) + u_mmask = paddle.cast(x=u_mmask, dtype=pred_score.dtype) + u_lmask = paddle.logical_and(gt_iou_map <= 0.3, gt_iou_map >= 0.) + u_lmask = paddle.cast(x=u_lmask, dtype=pred_score.dtype) + u_lmask = paddle.multiply(u_lmask, mask) + + num_h = paddle.cast(paddle.sum(u_hmask), dtype=pred_score.dtype) + num_m = paddle.cast(paddle.sum(u_mmask), dtype=pred_score.dtype) + num_l = paddle.cast(paddle.sum(u_lmask), dtype=pred_score.dtype) + + r_m = num_h / num_m + u_smmask = paddle.uniform(shape=[ + gt_iou_map.shape[1], gt_iou_map.shape[2] + ], + min=0.0, + max=1.0).astype(pred_score.dtype) + u_smmask = paddle.multiply(u_mmask, u_smmask) + u_smmask = paddle.cast(x=(u_smmask > (1. - r_m)), + dtype=pred_score.dtype) + + r_l = num_h / num_l + u_slmask = paddle.uniform(shape=[ + gt_iou_map.shape[1], gt_iou_map.shape[2] + ], + min=0.0, + max=1.0).astype(pred_score.dtype) + u_slmask = paddle.multiply(u_lmask, u_slmask) + u_slmask = paddle.cast(x=(u_slmask > (1. - r_l)), + dtype=pred_score.dtype) + + weights = u_hmask + u_smmask + u_slmask + weights.stop_gradient = True + loss = F.square_error_cost(pred_score, gt_iou_map) + loss = paddle.multiply(loss, weights) + loss = 0.5 * paddle.sum(loss) / paddle.sum(weights) + + return loss + + def pem_cls_loss_func(self, pred_score, gt_iou_map, mask): + gt_iou_map = paddle.multiply(gt_iou_map, mask) + gt_iou_map.stop_gradient = True + pmask = paddle.cast(x=(gt_iou_map > 0.9), dtype=pred_score.dtype) + nmask = paddle.cast(x=(gt_iou_map <= 0.9), dtype=pred_score.dtype) + nmask = paddle.multiply(nmask, mask) + + num_positive = paddle.sum(pmask) + num_entries = num_positive + paddle.sum(nmask) + ratio = num_entries / num_positive + coef_0 = 0.5 * ratio / (ratio - 1) + coef_1 = 0.5 * ratio + epsilon = 0.000001 + loss_pos = paddle.multiply(paddle.log(pred_score + epsilon), pmask) + loss_pos = coef_1 * paddle.sum(loss_pos) + loss_neg = paddle.multiply(paddle.log(1.0 - pred_score + epsilon), + nmask) + loss_neg = coef_0 * paddle.sum(loss_neg) + loss = -1 * (loss_pos + loss_neg) / num_entries + return loss + + def forward(self, pred_bm, pred_start, pred_end, gt_iou_map, gt_start, + gt_end): + pred_bm_reg = paddle.squeeze(paddle.slice(pred_bm, + axes=[1], + starts=[0], + ends=[1]), + axis=[1]) + pred_bm_cls = paddle.squeeze(paddle.slice(pred_bm, + axes=[1], + starts=[1], + ends=[2]), + axis=[1]) + + bm_mask = self._get_mask(self.dscale, self.tscale) + + pem_reg_loss = self.pem_reg_loss_func(pred_bm_reg, gt_iou_map, bm_mask) + pem_cls_loss = self.pem_cls_loss_func(pred_bm_cls, gt_iou_map, bm_mask) + + tem_loss = self.tem_loss_func(pred_start, pred_end, gt_start, gt_end) + + loss = tem_loss + 10 * pem_reg_loss + pem_cls_loss + return loss diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/cross_entropy_loss.py b/Bank_second_part/detect_process/paddlevideo/modeling/losses/cross_entropy_loss.py new file mode 100644 index 0000000..953f77c --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/losses/cross_entropy_loss.py @@ -0,0 +1,36 @@ +# 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 paddle +import paddle.nn.functional as F + +from ..registry import LOSSES +from .base import BaseWeightedLoss + + +@LOSSES.register() +class CrossEntropyLoss(BaseWeightedLoss): + """Cross Entropy Loss.""" + def _forward(self, score, labels, **kwargs): + """Forward function. + Args: + score (paddle.Tensor): The class score. + labels (paddle.Tensor): The ground truth labels. + kwargs: Any keyword argument to be used to calculate + CrossEntropy loss. + Returns: + loss (paddle.Tensor): The returned CrossEntropy loss. + """ + loss = F.cross_entropy(score, labels, **kwargs) + return loss diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/depth_loss.py b/Bank_second_part/detect_process/paddlevideo/modeling/losses/depth_loss.py new file mode 100644 index 0000000..ba9a2cb --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/losses/depth_loss.py @@ -0,0 +1,290 @@ +# 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 paddle +import paddle.nn as nn + +from ..registry import LOSSES +from .base import BaseWeightedLoss + + +def get_smooth_loss(disp, img): + """Computes the smoothness loss for a disparity image + The color image is used for edge-aware smoothness + """ + grad_disp_x = paddle.abs(disp[:, :, :, :-1] - disp[:, :, :, 1:]) + grad_disp_y = paddle.abs(disp[:, :, :-1, :] - disp[:, :, 1:, :]) + + grad_img_x = paddle.mean(paddle.abs(img[:, :, :, :-1] - img[:, :, :, 1:]), + 1, + keepdim=True) + grad_img_y = paddle.mean(paddle.abs(img[:, :, :-1, :] - img[:, :, 1:, :]), + 1, + keepdim=True) + + grad_disp_x *= paddle.exp(-grad_img_x) + grad_disp_y *= paddle.exp(-grad_img_y) + + return grad_disp_x.mean() + grad_disp_y.mean() + + +class DiffLoss(nn.Layer): + def __init__(self): + super(DiffLoss, self).__init__() + + def forward(self, input1, input2): + batch_size = input1.shape[0] + input1 = input1.reshape([batch_size, -1]) + input2 = input2.reshape([batch_size, -1]) + + input1_l2 = input1 + input2_l2 = input2 + + diff_loss = 0 + dim = input1.shape[1] + for i in range(input1.shape[0]): + diff_loss = diff_loss + paddle.mean( + ((input1_l2[i:i + 1, :].mm(input2_l2[i:i + 1, :].T)).pow(2)) / + dim) + + diff_loss = diff_loss / input1.shape[0] + + return diff_loss + + +class MSE(nn.Layer): + def __init__(self): + super(MSE, self).__init__() + + def forward(self, pred, real): + diffs = paddle.add(real, -pred) + n = paddle.numel(diffs) + mse = paddle.sum(diffs.pow(2)) / n + + return mse + + +class SIMSE(nn.Layer): + def __init__(self): + super(SIMSE, self).__init__() + + def forward(self, pred, real): + diffs = paddle.add(real, -pred) + n = paddle.numel(diffs) + simse = paddle.sum(diffs).pow(2) / (n**2) + + return simse + + +class SSIM(nn.Layer): + """Layer to compute the SSIM loss between a pair of images + """ + def __init__(self): + super(SSIM, self).__init__() + self.mu_x_pool = nn.AvgPool2D(3, 1, exclusive=False) + self.mu_y_pool = nn.AvgPool2D(3, 1, exclusive=False) + self.sig_x_pool = nn.AvgPool2D(3, 1, exclusive=False) + self.sig_y_pool = nn.AvgPool2D(3, 1, exclusive=False) + self.sig_xy_pool = nn.AvgPool2D(3, 1, exclusive=False) + + self.refl = nn.Pad2D(1, mode='reflect') + + self.C1 = 0.01**2 + self.C2 = 0.03**2 + + def forward(self, x, y): + x = self.refl(x) + y = self.refl(y) + + mu_x = self.mu_x_pool(x) + mu_y = self.mu_y_pool(y) + + sigma_x = self.sig_x_pool(x**2) - mu_x**2 + sigma_y = self.sig_y_pool(y**2) - mu_y**2 + sigma_xy = self.sig_xy_pool(x * y) - mu_x * mu_y + + SSIM_n = (2 * mu_x * mu_y + self.C1) * (2 * sigma_xy + self.C2) + SSIM_d = (mu_x**2 + mu_y**2 + self.C1) * (sigma_x + sigma_y + self.C2) + + return paddle.clip((1 - SSIM_n / SSIM_d) / 2, 0, 1) + + +@LOSSES.register() +class ADDSLoss(BaseWeightedLoss): + def __init__(self, avg_reprojection, disparity_smoothness, no_ssim): + super(ADDSLoss, self).__init__() + self.avg_reprojection = avg_reprojection + self.disparity_smoothness = disparity_smoothness + self.no_ssim = no_ssim + + self.loss_diff = DiffLoss() + self.loss_recon1 = MSE() + self.loss_recon2 = SIMSE() + self.loss_similarity = MSE() + + def compute_reprojection_loss(self, pred, target): + """Computes reprojection loss between a batch of predicted and target images + """ + abs_diff = paddle.abs(target - pred) + l1_loss = abs_diff.mean(1, True) + + if not self.no_ssim: + self.ssim = SSIM() + + if self.no_ssim: + reprojection_loss = l1_loss + else: + ssim_loss = self.ssim(pred, target).mean(1, True) + reprojection_loss = 0.85 * ssim_loss + 0.15 * l1_loss + + return reprojection_loss + + def compute_losses(self, inputs, outputs, is_night): + """Compute the reprojection and smoothness losses for a minibatch + """ + losses = {} + total_loss = 0 + + for scale in outputs['scales']: + loss = 0 + reprojection_losses = [] + + source_scale = 0 + + disp = outputs[("disp", scale)] + if is_night: + color = inputs[("color_n", 0, scale)] + target = inputs[("color_n", 0, source_scale)] + else: + color = inputs[("color", 0, scale)] + target = inputs[("color", 0, source_scale)] + + for frame_id in outputs['frame_ids'][1:]: + pred = outputs[("color", frame_id, scale)] + reprojection_losses.append( + self.compute_reprojection_loss(pred, target)) + + reprojection_losses = paddle.concat(reprojection_losses, 1) + + identity_reprojection_losses = [] + for frame_id in outputs['frame_ids'][1:]: + if is_night: + pred = inputs[("color_n", frame_id, source_scale)] + else: + pred = inputs[("color", frame_id, source_scale)] + identity_reprojection_losses.append( + self.compute_reprojection_loss(pred, target)) + + identity_reprojection_losses = paddle.concat( + identity_reprojection_losses, 1) + + if self.avg_reprojection: + identity_reprojection_loss = identity_reprojection_losses.mean( + 1, keepdim=True) + else: + # save both images, and do min all at once below + identity_reprojection_loss = identity_reprojection_losses + + if self.avg_reprojection: + reprojection_loss = reprojection_losses.mean(1, keepdim=True) + else: + reprojection_loss = reprojection_losses + + # add random numbers to break ties + identity_reprojection_loss = identity_reprojection_loss + paddle.randn( + identity_reprojection_loss.shape) * 0.00001 + + combined = paddle.concat( + (identity_reprojection_loss, reprojection_loss), axis=1) + if combined.shape[1] == 1: + to_optimise = combined + else: + to_optimise = paddle.min(combined, axis=1) + + loss = loss + to_optimise.mean() + + mean_disp = disp.mean(2, True).mean(3, True) + norm_disp = disp / (mean_disp + 1e-7) + smooth_loss = get_smooth_loss(norm_disp, color) + + loss = loss + self.disparity_smoothness * smooth_loss / (2**scale) + total_loss = total_loss + loss + losses["loss/{}".format(scale)] = loss + + total_loss /= len(outputs['scales']) + losses["loss"] = total_loss + return losses + + def forward(self, inputs, outputs): + + losses_day = self.compute_losses(inputs, outputs, 'day') + losses_night = self.compute_losses(inputs, outputs['outputs_night'], + 'night') + + loss = 0 + losses = [] + # diff + target_diff1 = 0.5 * self.loss_diff( + outputs['result'][0], outputs['result'][2]) # 10 when batchsize=1 + target_diff2 = 0.5 * self.loss_diff(outputs['result_night'][0], + outputs['result_night'][2]) + losses.append(target_diff1) + losses.append(target_diff2) + loss = loss + target_diff1 + loss = loss + target_diff2 + + target_diff3 = 1 * self.loss_diff( + outputs['result'][1], outputs['result'][3]) # 10 when batchsize=1 + target_diff4 = 1 * self.loss_diff(outputs['result_night'][1], + outputs['result_night'][3]) + losses.append(target_diff3) + losses.append(target_diff4) + loss = loss + target_diff3 + loss = loss + target_diff4 + + # recon + target_mse = 1 * self.loss_recon1(outputs['result'][5], + inputs["color_aug", 0, 0]) + loss = loss + target_mse + + target_simse = 1 * self.loss_recon2(outputs['result'][5], + inputs["color_aug", 0, 0]) + loss = loss + target_simse + + losses.append(target_mse) + losses.append(target_simse) + target_mse_night = 1 * self.loss_recon1(outputs['result_night'][5], + inputs["color_n_aug", 0, 0]) + loss = loss + target_mse_night + + target_simse_night = 1 * self.loss_recon2(outputs['result_night'][5], + inputs["color_n_aug", 0, 0]) + loss = loss + target_simse_night + + losses.append(target_mse_night) + losses.append(target_simse_night) + + # depth loss + pseudo_label = outputs[("disp", 0)].detach() + depth_loss = 1 * self.loss_similarity( + outputs['outputs_night'][("disp", 0)], pseudo_label) + loss = loss + depth_loss + + losses.append(depth_loss) + + outputs['loss'] = loss + losses_day['loss'] + losses_night['loss'] + outputs['losses_day'] = losses_day['loss'] + outputs['losses_night'] = losses_night['loss'] + + return outputs diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/distillation_loss.py b/Bank_second_part/detect_process/paddlevideo/modeling/losses/distillation_loss.py new file mode 100644 index 0000000..d27f941 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/losses/distillation_loss.py @@ -0,0 +1,79 @@ +# 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 paddle +import paddle.nn.functional as F +import paddle.nn as nn + +from ..registry import LOSSES +from .base import BaseWeightedLoss + + +@LOSSES.register() +class DistillationCELoss(BaseWeightedLoss): + """Distillation Entropy Loss.""" + def _forward(self, score, labels, **kwargs): + """Forward function. + Args: + score (paddle.Tensor): The class score. + labels (paddle.Tensor): The ground truth labels. + kwargs: Any keyword argument to be used to calculate + CrossEntropy loss. + Returns: + loss (paddle.Tensor): The returned CrossEntropy loss. + """ + if len(labels) == 1: + label = labels[0] + loss = F.cross_entropy(score, label, **kwargs) + # Deal with VideoMix + elif len(labels) == 3: + label_a, label_b, lam = labels + loss_a = F.cross_entropy(score, label_a, **kwargs) + loss_b = F.cross_entropy(score, label_b, **kwargs) + loss = lam * loss_a + (1 - lam) * loss_b + loss = paddle.mean(loss) #lam shape is bs + return loss + + +@LOSSES.register() +class DistillationDMLLoss(BaseWeightedLoss): + """ + DistillationDMLLoss + """ + def __init__(self, act="softmax", eps=1e-12, **kargs): + super().__init__(**kargs) + if act is not None: + assert act in ["softmax", "sigmoid"] + if act == "softmax": + self.act = nn.Softmax(axis=-1) + elif act == "sigmoid": + self.act = nn.Sigmoid() + else: + self.act = None + self.eps = eps + + def _kldiv(self, x, target): + class_num = x.shape[-1] + cost = target * paddle.log( + (target + self.eps) / (x + self.eps)) * class_num + return cost + + def _forward(self, x, target): + if self.act is not None: + x = self.act(x) + target = self.act(target) + loss = self._kldiv(x, target) + self._kldiv(target, x) + loss = loss / 2 + loss = paddle.mean(loss) + return loss diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/transnetv2_loss.py b/Bank_second_part/detect_process/paddlevideo/modeling/losses/transnetv2_loss.py new file mode 100644 index 0000000..624c468 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/losses/transnetv2_loss.py @@ -0,0 +1,56 @@ +# 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 paddle +import paddle.nn.functional as F +from ..registry import LOSSES +from .base import BaseWeightedLoss + + +@LOSSES.register() +class TransNetV2Loss(BaseWeightedLoss): + """Loss for TransNetV2 model + """ + def __init__(self, transition_weight=5.0, many_hot_loss_weight=0.1): + self.transition_weight = transition_weight + self.many_hot_loss_weight = many_hot_loss_weight + super().__init__() + + def _forward(self, one_hot_pred, one_hot_gt, + many_hot_pred=None, many_hot_gt=None, reg_losses=None): + assert transition_weight != 1 + + one_hot_pred = one_hot_pred[:, :, 0] + + one_hot_gt = one_hot_gt.astype('float32') + one_hot_loss = F.binary_cross_entropy_with_logits(logit=one_hot_pred, label=one_hot_gt, reduction='none') + + one_hot_loss *= 1 + one_hot_gt * (transition_weight - 1) + + one_hot_loss = paddle.mean(one_hot_loss) + + many_hot_loss = 0. + if many_hot_loss_weight != 0. and many_hot_pred is not None: + many_hot_loss = many_hot_loss_weight * paddle.mean( + F.binary_cross_entropy_with_logits(logit=many_hot_pred[:, :, 0], + label=many_hot_gt.astype('float32'), reduction='none')) + + total_loss = one_hot_loss + many_hot_loss + + if reg_losses is not None: + for name, value in reg_losses.items(): + if value is not None: + total_loss += value + + return total_loss \ No newline at end of file diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/losses/yowo_loss.py b/Bank_second_part/detect_process/paddlevideo/modeling/losses/yowo_loss.py new file mode 100644 index 0000000..5ca3290 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/losses/yowo_loss.py @@ -0,0 +1,251 @@ +# 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 numpy +import paddle +import paddle.nn.functional as F +import paddle.nn as nn +from paddle.static import Variable + +from ..registry import LOSSES +from .base import BaseWeightedLoss +from ..framework.localizers.yowo_utils import build_targets + + +class FocalLoss(nn.Layer): + """ + This criterion is a implemenation of Focal Loss, which is proposed in + Focal Loss for Dense Object Detection. + + Loss(x, class) = - \alpha (1-softmax(x)[class])^gamma \log(softmax(x)[class]) + + The losses are averaged across observations for each minibatch. + + Args: + alpha(1D Tensor, Variable) : the scalar factor for this criterion + gamma(float, double) : gamma > 0; reduces the relative loss for well-classified examples (p > .5), + putting more focus on hard, misclassified examples + size_average(bool): size_average(bool): By default, the losses are averaged over observations for each minibatch. + However, if the field size_average is set to False, the losses are + instead summed for each minibatch. + + """ + + def __init__(self, class_num, alpha=None, gamma=2, size_average=True): + super(FocalLoss, self).__init__() + + if alpha is None: + self.alpha = paddle.ones( + [class_num, 1]) + self.alpha.stop_gradient = False + else: + if isinstance(alpha, Variable): + self.alpha = alpha + else: + self.alpha = (alpha) + self.alpha.stop_gradient = False + self.gamma = gamma + self.class_num = class_num + self.size_average = size_average + + def forward(self, inputs, targets): + N = inputs.shape[0] + C = inputs.shape[1] + P = F.softmax(inputs, axis=1) + + tmp = numpy.zeros((N, C)) + class_mask = paddle.to_tensor(tmp, place=inputs.place) + class_mask.stop_gradient = False + ids = paddle.reshape(targets, [-1, 1]) + class_mask = F.one_hot(ids.squeeze(-1), class_mask.shape[1]) + + if "Place" not in str(inputs.place) and "Place" not in str(self.alpha.place): + self.alpha = self.alpha.cuda() + + alpha = self.alpha[paddle.reshape(ids.detach(), [-1])] + + probs = paddle.reshape((P * class_mask).sum(1), [-1, 1]) + + log_p = probs.log() + + batch_loss = -alpha * (paddle.pow((1 - probs), self.gamma)) * log_p + + if self.size_average: + loss = batch_loss.mean() + else: + loss = batch_loss.sum() + return loss + + +@LOSSES.register() +class RegionLoss(BaseWeightedLoss): + # for our model anchors has 10 values and number of anchors is 5 + # parameters: 24, 10 float values, 24, 5 + def __init__(self, num_classes, anchors, num_anchors, object_scale, noobject_scale, class_scale, coord_scale): + super().__init__() + self.num_classes = num_classes + self.anchors = [float(x) for x in anchors] + self.num_anchors = num_anchors + self.anchor_step = len(self.anchors) // self.num_anchors # each anchor has 2 parameters + self.object_scale = object_scale + self.noobject_scale = noobject_scale + self.class_scale = class_scale + self.coord_scale = coord_scale + self.focalloss = FocalLoss(class_num=self.num_classes, gamma=2, size_average=False) + self.thresh = 0.6 + + def convert2cpu(self, gpu_matrix): + # return paddle.to_tensor((gpu_matrix.shape), dtype="float32").copy_(gpu_matrix) + return gpu_matrix.cpu() + + def forward(self, output, target): + # output : B*A*(4+1+num_classes)*H*W 8*5*29*24*24 + # B: number of batches + # A: number of anchors + # 4: 4 parameters for each bounding box + # 1: confidence score + # num_classes + # H: height of the image (in grids) + # W: width of the image (in grids) + # for each grid cell, there are A*(4+1+num_classes) parameters + nB = output.detach().shape[0] # batch + nA = self.num_anchors # anchor_num + nC = self.num_classes + nH = output.detach().shape[2] + nW = output.detach().shape[3] + + # resize the output (all parameters for each anchor can be reached) + output = paddle.reshape(output, [nB, nA, (5 + nC), nH, nW]) + # anchor's parameter tx + + x = F.sigmoid( + paddle.reshape(paddle.index_select(output, paddle.to_tensor([0], dtype='int64').cuda(), axis=2), + [nB, nA, nH, nW])) + x.stop_gradient = False + # anchor's parameter ty + y = F.sigmoid( + paddle.reshape(paddle.index_select(output, paddle.to_tensor([1], dtype='int64').cuda(), axis=2), + [nB, nA, nH, nW])) + y.stop_gradient = False + # anchor's parameter tw + w = paddle.reshape(paddle.index_select(output, paddle.to_tensor([2], dtype='int64').cuda(), axis=2), + [nB, nA, nH, nW]) + w.stop_gradient = False + # anchor's parameter th + h = paddle.reshape(paddle.index_select(output, paddle.to_tensor([3], dtype='int64').cuda(), axis=2), + [nB, nA, nH, nW]) + h.stop_gradient = False + # confidence score for each anchor + conf = F.sigmoid( + paddle.reshape(paddle.index_select(output, paddle.to_tensor([4], dtype='int64').cuda(), axis=2), + [nB, nA, nH, nW])) + conf.stop_gradient = False + # anchor's parameter class label + cls = paddle.index_select(output, paddle.linspace(5, 5 + nC - 1, nC, 'int64').cuda(), axis=2) + cls.stop_gradient = False + # resize the data structure so that for every anchor there is a class label in the last dimension + cls = paddle.reshape(paddle.transpose(paddle.reshape(cls, [nB * nA, nC, nH * nW]), [0, 2, 1]), + [nB * nA * nH * nW, nC]) + + # for the prediction of localization of each bounding box, there exist 4 parameters (tx, ty, tw, th) + # pred_boxes = torch.cuda.FloatTensor(4, nB*nA*nH*nW) + pred_boxes = paddle.zeros([4, nB * nA * nH * nW], dtype='float32').cuda() + # tx and ty + grid_x = paddle.reshape(paddle.tile(paddle.tile(paddle.linspace(0, nW - 1, nW), [nH, 1]), [nB * nA, 1, 1]), + [nB * nA * nH * nW]).cuda() + grid_y = paddle.reshape(paddle.tile(paddle.tile(paddle.linspace(0, nH - 1, nH), [nW, 1]).t(), [nB * nA, 1, 1]), + [nB * nA * nH * nW]).cuda() + # for each anchor there are anchor_step variables (with the structure num_anchor*anchor_step) + # for each row(anchor), the first variable is anchor's width, second is anchor's height + # pw and ph + anchor_w = paddle.index_select(paddle.reshape(paddle.to_tensor(self.anchors), [nA, self.anchor_step]), + paddle.to_tensor([0], dtype='int64'), axis=1).cuda() + anchor_h = paddle.index_select(paddle.reshape(paddle.to_tensor(self.anchors), [nA, self.anchor_step]), + paddle.to_tensor([1], dtype='int64'), axis=1).cuda() + # for each pixel (grid) repeat the above process (obtain width and height of each grid) + anchor_w = paddle.reshape(paddle.tile(paddle.tile(anchor_w, [nB, 1]), [1, 1, nH * nW]), [nB * nA * nH * nW]) + anchor_h = paddle.reshape(paddle.tile(paddle.tile(anchor_h, [nB, 1]), [1, 1, nH * nW]), [nB * nA * nH * nW]) + # prediction of bounding box localization + # x.data and y.data: top left corner of the anchor + # grid_x, grid_y: tx and ty predictions made by yowo + + x_data = paddle.reshape(x.detach(), [-1]) + y_data = paddle.reshape(y.detach(), [-1]) + w_data = paddle.reshape(w.detach(), [-1]) + h_data = paddle.reshape(h.detach(), [-1]) + + pred_boxes[0] = paddle.cast(x_data, dtype='float32') + paddle.cast(grid_x, dtype='float32') # bx + pred_boxes[1] = paddle.cast(y_data, dtype='float32') + paddle.cast(grid_y, dtype='float32') # by + pred_boxes[2] = paddle.exp(paddle.cast(w_data, dtype='float32')) * paddle.cast(anchor_w, dtype='float32') # bw + pred_boxes[3] = paddle.exp(paddle.cast(h_data, dtype='float32')) * paddle.cast(anchor_h, dtype='float32') # bh + # the size -1 is inferred from other dimensions + # pred_boxes (nB*nA*nH*nW, 4) + + pred_boxes = self.convert2cpu( + paddle.cast(paddle.reshape(paddle.transpose(pred_boxes, (1, 0)), [-1, 4]), dtype='float32')) + + nGT, nCorrect, coord_mask, conf_mask, cls_mask, tx, ty, tw, th, tconf, tcls = build_targets(pred_boxes, + target.detach(), + self.anchors, nA, + nC, \ + nH, nW, + self.noobject_scale, + self.object_scale, + self.thresh) + cls_mask = (cls_mask == 1) + # keep those with high box confidence scores (greater than 0.25) as our final predictions + nProposals = int((conf > 0.25).sum().detach().item()) + + tx = (tx).cuda() + tx.stop_gradient = False + ty = ty.cuda() + ty.stop_gradient = False + tw = tw.cuda() + tw.stop_gradient = False + th = th.cuda() + th.stop_gradient = False + tconf = tconf.cuda() + tconf.stop_gradient = False + + tcls = paddle.reshape(tcls, [-1]).astype('int64')[paddle.reshape(cls_mask, [-1])].cuda() + tcls.stop_gradient = False + + coord_mask = coord_mask.cuda() + coord_mask.stop_gradient = False + conf_mask = conf_mask.cuda().sqrt() + coord_mask.stop_gradient = False + cls_mask = paddle.tile(paddle.reshape(cls_mask, [-1, 1]), [1, nC]).cuda() + cls_mask.stop_gradient = False + + cls = paddle.reshape(cls[cls_mask], [-1, nC]) + + # losses between predictions and targets (ground truth) + # In total 6 aspects are considered as losses: + # 4 for bounding box location, 2 for prediction confidence and classification seperately + L1_loss = nn.SmoothL1Loss(reduction='sum') + loss_x = self.coord_scale * L1_loss(paddle.cast(x, dtype="float32") * coord_mask, tx * coord_mask) / 2.0 + loss_y = self.coord_scale * L1_loss(paddle.cast(y, dtype="float32") * coord_mask, ty * coord_mask) / 2.0 + loss_w = self.coord_scale * L1_loss(paddle.cast(w * coord_mask, dtype="float32"), tw * coord_mask) / 2.0 + loss_h = self.coord_scale * L1_loss(paddle.cast(h * coord_mask, dtype="float32"), th * coord_mask) / 2.0 + loss_conf = nn.MSELoss(reduction='sum')(paddle.cast(conf, dtype="float32") * conf_mask, tconf * conf_mask) / 2.0 + + # try focal loss with gamma = 2 + loss_cls = self.class_scale * self.focalloss(cls, tcls) + + # sum of loss + loss = loss_x + loss_y + loss_w + loss_h + loss_conf + loss_cls + + return loss, nCorrect + + diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/registry.py b/Bank_second_part/detect_process/paddlevideo/modeling/registry.py new file mode 100644 index 0000000..b8140e1 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/registry.py @@ -0,0 +1,31 @@ +# 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. + +from ..utils import Registry + +BACKBONES = Registry('backbone') +HEADS = Registry('head') +RECOGNIZERS = Registry('recognizer') +SEGMENTERS = Registry('Segmenters') +LOCALIZERS = Registry('localizer') +PARTITIONERS = Registry('partitioner') +LOSSES = Registry('loss') +ROI_EXTRACTORS = Registry('roi_extractor') +DETECTORS = Registry('detectors') +BBOX_ASSIGNERS = Registry('bbox_assigner') +BBOX_SAMPLERS = Registry('bbox_sampler') +BBOX_CODERS = Registry('bbox_coder') +ESTIMATORS = Registry('estimator') +MULTIMODAL = Registry('multimodal') +SEGMENT = Registry('segment') diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/samplers/__init__.py b/Bank_second_part/detect_process/paddlevideo/modeling/samplers/__init__.py new file mode 100644 index 0000000..0cf7f15 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/samplers/__init__.py @@ -0,0 +1,17 @@ +# 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. + +from .random_sampler import RandomSampler + +__all__ = ['RandomSampler'] diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/samplers/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/samplers/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0155487c8557edbe17e09db66b75bbf30eacfb50 GIT binary patch literal 243 zcmYjLy$ZrG5WZAJ5!=ys=py1MBH}C#b}NA+c(DYNrX(u(3_gi(9sxX?;vYeSRR}*0L_kb~VL4+!QNi+vIvJ$h7Yk;}>UbwgvL+Lz z($cwRcAIwc#I-W|KfUfF3at_E;JTr&rT0e8`C61mJSZ*wH=WLSSS4L|R@H lNz08Tsa09<-)hehRjE#hlj>Rz7QsJjxoqC^&6QCyj6UwgKuQ1r literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/samplers/__pycache__/random_sampler.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/modeling/samplers/__pycache__/random_sampler.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5598aaa2c2f34915c8c1d8d3f2f83305bfb0de99 GIT binary patch literal 3581 zcma)9U2h||6&-RuG#X2?c310on{=zTXu020^gdHk+bN-M~(ZLNG8Gi?mku zXhtDNyK80iQt!UBNPmL`^kx4|pXaqt`v>w+1aQwKC4Y5ObPQ7DC3#8Sd+xb(-fTt= zzJL0E6JKmN&cCR0`SZ}ZhoXOtN;rb0PT&5rJ{MfLsXO-i9&ZP!&jC8Bp z9n_$6^--HH`zsXv6{?bzPVAH%H7oe3Te>A%P|qv*p)c4S7~{xQuPw*884EI3IG7U{ zX|P;TD?PgcBcU1b59>50_$JMcinY=^Z7iG<2Ay2(l+Iy9ed_6tf9w2(PS7m91v_mC zS9oTx_3U=hCe2voA2}+9j^*gwGrM@C$IdPN!yCexGWBS=|BdC@ZVG1?4#g=;V5L;c)Q-^P-E@5uM|?kCw%d@xF-w#}cvwKq}uKx%EId)73MMndL$<6KBW<(@&J zRC-S(naIcSvcEMsuEH319TjnW8#@@x2RvXc)^gh{;4R)@9oFVI*#@I_n@7CEB0hWN zD&n_RS_b6B)kiKoNBED?0XpD$V4_{HQy}}$CCQL4*qoIJRg&1&bGF^{R10eq(M1&u z@@$Y4s)0_At4)%*N*2a2wz^A`@1S}cMboMX=k~nd%wx0L*UoE=zYV{@09i7Yaa=`l z42w-uYB%Ee^J$VUM{02_@oCr{JEtFV+pSvA!olQ3ntCA`)x(4MamU@mmun;pDDuAg2~}^Rs)D1(i5lulwliiU^WHVXU3!8~9raG(BhfI!l>scr4U&1uPQkwm#vG&3 zJ=Yj6HP*n0L0KyUGe0Oo>`+IEI^g3u_155%@PLbY$w#d8|H1yw=5?%U6wT9CSwCH0 zI17fTsiWOqIP=J8h&G-18d_l5a_!pc#`)^T`RYb-v#gg5WE^CgGB^q5&9Vs)MYA_7 ze7f-Ds2DwxU0|vUGEGd!1`qO?A?a;Jb~hYe`J=3O`z<6{Ulhj^IeQnFungE8Pj%7V zm)#-MW!=XQQN08--I4BorlwL6VoiMYZYiQB)uhUBfp;)XQ;VbMPf0qJA1Re9^<7M; zYD=A!i<4YHuUcDjUW^-6^&*c8ndw|rJeyR(G#hZyqPEwvXnvKB zK`f)bMe~Tg?FH3ONl5Y3r?ir1Quo`GXylU#(i74Owl@6VUnjAq*MXH@n@3xk6tQmR zfWVg-;aa#Ba1n_#_=ar}8_EgrE=uzB0v1doSq#60>t!zfB{*5Q#$ zeUHyNSEJ0T9?)xO^^r@?>HHIP5E2Nmk{|gxG*1R1b$03!I0fX-DAZg~z4ub7574;_ zKKDuwpyRWj*%NeaKJV&$EW1eUW0@7Yd!X`hw|EHrBxx$uG0?XShB45v86r_hHk8(V zA=&~QJyvTtXU{jjgJ0}ggNw?e@qV3Vnsk5Nx=k8EvK&0jM+2##$FO;uZ}1J)fEj16 z?wA?7#*=F6%KVpF&UorK#&U;9c!yjt!M}tB3Kvf)&pgLmJn=f{`3UPva#)$EyJV@- z0eRp_xZtpwH+#b#B0aY6O=<0R9=O(zdh5Y+R)wJFVhYrmV0~V*;Z)1=Y$g#wZ5&M9 zpvr_mO(Q5IM(#nhG@&B+SB=ZCwzxO%8k7GnlHe~e_X`wFNxSW~{gAa`wg#WwxoWse zvH8tr`xHtFXJxh{!`#p?6N!&L5hU)vI_jRg%Ko#XlMG!uZ9lyIg7sL>(STY55sz6UD0?iG+0pYqOIORRfS3pN4ikQiYUNP i;7W#91+976W>xsUeL{Ue??7|ouo)s+T0D5O!~O%eZfmOm literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/samplers/random_sampler.py b/Bank_second_part/detect_process/paddlevideo/modeling/samplers/random_sampler.py new file mode 100644 index 0000000..4808454 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/samplers/random_sampler.py @@ -0,0 +1,146 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 paddle +import numpy as np +from ..registry import BBOX_SAMPLERS + +class SamplingResult(): + """Bbox sampling result. """ + + def __init__(self, pos_inds, neg_inds, bboxes, gt_bboxes, assign_result, + gt_flags): + self.pos_inds = pos_inds + self.neg_inds = neg_inds + self.pos_bboxes = paddle.index_select(bboxes,pos_inds) + + # neg_inds may be empty + if neg_inds.shape[0]!=0: + self.neg_bboxes = paddle.index_select(bboxes,neg_inds) + else: + self.neg_bboxes=None + + self.pos_is_gt = paddle.index_select(gt_flags,pos_inds) + self.num_gts = gt_bboxes.shape[0] + self.pos_assigned_gt_inds = paddle.index_select(assign_result.gt_inds,pos_inds) - 1 + + if float(gt_bboxes.numel()) == 0: + assert self.pos_assigned_gt_inds.numel() == 0 + self.pos_gt_bboxes = paddle.empty_like(gt_bboxes).view(-1, 4) + else: + if len(gt_bboxes.shape) < 2: + gt_bboxes = gt_bboxes.view(-1, 4) + + self.pos_gt_bboxes = paddle.index_select(gt_bboxes, self.pos_assigned_gt_inds) + + if assign_result.labels is not None: + self.pos_gt_labels = paddle.index_select(assign_result.labels, pos_inds) + else: + self.pos_gt_labels = None + + @property + def bboxes(self): + if self.neg_bboxes is not None: + ret = paddle.concat([self.pos_bboxes, self.neg_bboxes]) + else: + # neg bbox may be empty + ret = self.pos_bboxes + return ret + + + +@BBOX_SAMPLERS.register() +class RandomSampler(): + def __init__(self, + num, + pos_fraction, + neg_pos_ub=-1, + add_gt_as_proposals=True, + **kwargs): + self.num = num + self.pos_fraction = pos_fraction + self.neg_pos_ub = neg_pos_ub + self.add_gt_as_proposals = add_gt_as_proposals + + def sample(self, + assign_result, + bboxes, + gt_bboxes, + gt_labels=None, + **kwargs): + """Sample positive and negative bboxes. """ + + if len(bboxes.shape) < 2: + bboxes = bboxes[None, :] + + bboxes = bboxes[:, :4] + + gt_flags = paddle.full([bboxes.shape[0], ], 0, dtype='int32') + if self.add_gt_as_proposals and len(gt_bboxes) > 0: + if gt_labels is None: + raise ValueError( + 'gt_labels must be given when add_gt_as_proposals is True') + bboxes = paddle.concat([gt_bboxes, bboxes]) + assign_result.add_gt_(gt_labels) + gt_ones = paddle.full([gt_bboxes.shape[0], ], 1, dtype='int32') + gt_flags = paddle.concat([gt_ones, gt_flags]) + + #1. 得到正样本的数量, inds + num_expected_pos = int(self.num * self.pos_fraction) + pos_inds = self._sample_pos( assign_result, num_expected_pos, bboxes=bboxes, **kwargs) + pos_inds = paddle.to_tensor(np.unique(pos_inds.numpy())) + + #2. 得到负样本的数量, inds + num_sampled_pos = pos_inds.numel() + num_expected_neg = self.num - num_sampled_pos + neg_inds = self._sample_neg( + assign_result, num_expected_neg, bboxes=bboxes, **kwargs) + neg_inds = paddle.to_tensor(np.unique(neg_inds.numpy())) + + #3. 得到sampling result + sampling_result = SamplingResult(pos_inds, neg_inds, bboxes, gt_bboxes, + assign_result, gt_flags) + return sampling_result + def random_choice(self, gallery, num): + """Random select some elements from the gallery. """ + assert len(gallery) >= num + + perm = paddle.arange(gallery.numel())[:num] + perm = paddle.randperm(gallery.numel())[:num] + rand_inds = paddle.index_select(gallery, perm) + return rand_inds + + def _sample_pos(self, assign_result, num_expected, **kwargs): + """Randomly sample some positive samples.""" + #1.首先看一下给的bboxes里面有哪些label是大于0的 得到了他们的index + pos_inds = paddle.nonzero(assign_result.gt_inds, as_tuple=False) + + #2. 只要这个pos_inds的数目不是0个 这些就都可以是positive sample + # 当pos_inds的数目小于num_expected(想要的sample的最大数目), 就直接用这个pos_inds + # 反之就从这么多index里随机采样num_expected个出来 + if float(pos_inds.numel()) != 0: + pos_inds = pos_inds.squeeze() + if float(pos_inds.numel()) <= num_expected: + return pos_inds + else: + return self.random_choice(pos_inds, num_expected) + + def _sample_neg(self, assign_result, num_expected, **kwargs): + """Randomly sample some negative samples.""" + neg_inds = paddle.nonzero(assign_result.gt_inds == 0, as_tuple=False) + if float(neg_inds.numel()) != 0: + neg_inds = neg_inds.squeeze() + if (float(neg_inds.numel())) <= float(num_expected): + return neg_inds + else: + return self.random_choice(neg_inds, num_expected) diff --git a/Bank_second_part/detect_process/paddlevideo/modeling/weight_init.py b/Bank_second_part/detect_process/paddlevideo/modeling/weight_init.py new file mode 100644 index 0000000..4722895 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/modeling/weight_init.py @@ -0,0 +1,157 @@ +# 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 math +import paddle +import paddle.nn.initializer as init +import numpy as np +from scipy import special + + +def weight_init_(layer, + func, + weight_name=None, + bias_name=None, + bias_value=0.0, + **kwargs): + """ + In-place params init function. + Usage: + .. code-block:: python + + import paddle + import numpy as np + + data = np.ones([3, 4], dtype='float32') + linear = paddle.nn.Linear(4, 4) + input = paddle.to_tensor(data) + print(linear.weight) + linear(input) + + weight_init_(linear, 'Normal', 'fc_w0', 'fc_b0', std=0.01, mean=0.1) + print(linear.weight) + """ + + if hasattr(layer, 'weight') and layer.weight is not None: + getattr(init, func)(**kwargs)(layer.weight) + if weight_name is not None: + # override weight name + layer.weight.name = weight_name + + if hasattr(layer, 'bias') and layer.bias is not None: + init.Constant(bias_value)(layer.bias) + if bias_name is not None: + # override bias name + layer.bias.name = bias_name + + +def _no_grad_trunc_normal_(tensor, mean, std, a, b): + def norm_cdf(x): + # Computes standard normal cumulative distribution function + return (1. + math.erf(x / math.sqrt(2.))) / 2. + + if (mean < a - 2 * std) or (mean > b + 2 * std): + print("mean is more than 2 std from [a, b] in nn.init.trunc_normal_. " + "The distribution of values may be incorrect.") + + with paddle.no_grad(): + # Values are generated by using a truncated uniform distribution and + # then using the inverse CDF for the normal distribution. + # Get upper and lower cdf values + l = norm_cdf((a - mean) / std) + u = norm_cdf((b - mean) / std) + + # Uniformly fill tensor with values from [l, u], then translate to [2l-1, 2u-1]. + tmp = np.random.uniform(2 * l - 1, 2 * u - 1, + size=list(tensor.shape)).astype(np.float32) + + # Use inverse cdf transform for normal distribution to get truncated + # standard normal + tmp = special.erfinv(tmp) + + # Transform to proper mean, std + tmp *= (std * math.sqrt(2.0)) + tmp += mean + + # Clamp to ensure it's in the proper range + tmp = np.clip(tmp, a, b) + tensor.set_value(paddle.to_tensor(tmp)) + + return tensor + + +def _calculate_fan_in_and_fan_out(tensor): + dimensions = tensor.dim() + if dimensions < 2: + raise ValueError( + "Fan in and fan out can not be computed for tensor with fewer than 2 dimensions" + ) + + num_input_fmaps = tensor.shape[1] + num_output_fmaps = tensor.shape[0] + receptive_field_size = 1 + if tensor.dim() > 2: + receptive_field_size = tensor[0][0].numel() + fan_in = num_input_fmaps * receptive_field_size + fan_out = num_output_fmaps * receptive_field_size + + return fan_in, fan_out + + +def trunc_normal_(tensor, mean=0., std=1., a=-2., b=2.): + return _no_grad_trunc_normal_(tensor, mean, std, a, b) + + +def kaiming_normal_(tensor, a=0., mode='fan_in', nonlinearity='leaky_relu'): + def _calculate_correct_fan(tensor, mode): + mode = mode.lower() + valid_modes = ['fan_in', 'fan_out'] + if mode not in valid_modes: + raise ValueError( + "Mode {} not supported, please use one of {}".format( + mode, valid_modes)) + + fan_in, fan_out = _calculate_fan_in_and_fan_out(tensor) + return fan_in if mode == 'fan_in' else fan_out + + def calculate_gain(nonlinearity, param=None): + linear_fns = [ + 'linear', 'conv1d', 'conv2d', 'conv3d', 'conv_transpose1d', + 'conv_transpose2d', 'conv_transpose3d' + ] + if nonlinearity in linear_fns or nonlinearity == 'sigmoid': + return 1 + elif nonlinearity == 'tanh': + return 5.0 / 3 + elif nonlinearity == 'relu': + return math.sqrt(2.0) + elif nonlinearity == 'leaky_relu': + if param is None: + negative_slope = 0.01 + elif not isinstance(param, bool) and isinstance( + param, int) or isinstance(param, float): + negative_slope = param + else: + raise ValueError( + "negative_slope {} not a valid number".format(param)) + return math.sqrt(2.0 / (1 + negative_slope**2)) + else: + raise ValueError("Unsupported nonlinearity {}".format(nonlinearity)) + + fan = _calculate_correct_fan(tensor, mode) + gain = calculate_gain(nonlinearity, a) + std = gain / math.sqrt(fan) + with paddle.no_grad(): + paddle.nn.initializer.Normal(0, std)(tensor) + return tensor diff --git a/Bank_second_part/detect_process/paddlevideo/solver/__init__.py b/Bank_second_part/detect_process/paddlevideo/solver/__init__.py new file mode 100644 index 0000000..01cf9cd --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/solver/__init__.py @@ -0,0 +1,16 @@ +# 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. + +from .optimizer import build_optimizer +from .lr import build_lr diff --git a/Bank_second_part/detect_process/paddlevideo/solver/custom_lr.py b/Bank_second_part/detect_process/paddlevideo/solver/custom_lr.py new file mode 100644 index 0000000..bbf8d74 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/solver/custom_lr.py @@ -0,0 +1,338 @@ +# 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 math +from paddle.optimizer.lr import * +import numpy as np +""" +PaddleVideo Learning Rate Schedule: +You can use paddle.optimizer.lr +or define your custom_lr in this file. +""" + + +class CustomWarmupCosineDecay(LRScheduler): + r""" + We combine warmup and stepwise-cosine which is used in slowfast model. + + Args: + warmup_start_lr (float): start learning rate used in warmup stage. + warmup_epochs (int): the number epochs of warmup. + cosine_base_lr (float|int, optional): base learning rate in cosine schedule. + max_epoch (int): total training epochs. + num_iters(int): number iterations of each epoch. + last_epoch (int, optional): The index of last epoch. Can be set to restart training. Default: -1, means initial learning rate. + verbose (bool, optional): If ``True``, prints a message to stdout for each update. Default: ``False`` . + Returns: + ``CosineAnnealingDecay`` instance to schedule learning rate. + """ + + def __init__(self, + warmup_start_lr, + warmup_epochs, + cosine_base_lr, + max_epoch, + num_iters, + last_epoch=-1, + verbose=False): + self.warmup_start_lr = warmup_start_lr + self.warmup_epochs = warmup_epochs + self.cosine_base_lr = cosine_base_lr + self.max_epoch = max_epoch + self.num_iters = num_iters + #call step() in base class, last_lr/last_epoch/base_lr will be update + super(CustomWarmupCosineDecay, self).__init__(last_epoch=last_epoch, + verbose=verbose) + + def step(self, epoch=None): + """ + ``step`` should be called after ``optimizer.step`` . It will update the learning rate in optimizer according to current ``epoch`` . + The new learning rate will take effect on next ``optimizer.step`` . + Args: + epoch (int, None): specify current epoch. Default: None. Auto-increment from last_epoch=-1. + Returns: + None + """ + if epoch is None: + if self.last_epoch == -1: + self.last_epoch += 1 + else: + self.last_epoch += 1 / self.num_iters # update step with iters + else: + self.last_epoch = epoch + self.last_lr = self.get_lr() + + if self.verbose: + print('Epoch {}: {} set learning rate to {}.'.format( + self.last_epoch, self.__class__.__name__, self.last_lr)) + + def _lr_func_cosine(self, cur_epoch, cosine_base_lr, max_epoch): + return cosine_base_lr * (math.cos(math.pi * cur_epoch / max_epoch) + + 1.0) * 0.5 + + def get_lr(self): + """Define lr policy""" + lr = self._lr_func_cosine(self.last_epoch, self.cosine_base_lr, + self.max_epoch) + lr_end = self._lr_func_cosine(self.warmup_epochs, self.cosine_base_lr, + self.max_epoch) + + # Perform warm up. + if self.last_epoch < self.warmup_epochs: + lr_start = self.warmup_start_lr + alpha = (lr_end - lr_start) / self.warmup_epochs + lr = self.last_epoch * alpha + lr_start + return lr + + +class CustomWarmupPiecewiseDecay(LRScheduler): + r""" + This op combine warmup and stepwise-cosine which is used in slowfast model. + + Args: + warmup_start_lr (float): start learning rate used in warmup stage. + warmup_epochs (int): the number epochs of warmup. + step_base_lr (float|int, optional): base learning rate in step schedule. + max_epoch (int): total training epochs. + num_iters(int): number iterations of each epoch. + last_epoch (int, optional): The index of last epoch. Can be set to restart training. Default: -1, means initial learning rate. + verbose (bool, optional): If ``True``, prints a message to stdout for each update. Default: ``False`` . + Returns: + ``CustomWarmupPiecewiseDecay`` instance to schedule learning rate. + """ + + def __init__(self, + warmup_start_lr, + warmup_epochs, + step_base_lr, + lrs, + gamma, + steps, + max_epoch, + num_iters, + last_epoch=0, + verbose=False): + self.warmup_start_lr = warmup_start_lr + self.warmup_epochs = warmup_epochs + self.step_base_lr = step_base_lr + self.lrs = lrs + self.gamma = gamma + self.steps = steps + self.max_epoch = max_epoch + self.num_iters = num_iters + self.last_epoch = last_epoch + self.last_lr = self.warmup_start_lr # used in first iter + self.verbose = verbose + self._var_name = None + + def step(self, epoch=None, rebuild=False): + """ + ``step`` should be called after ``optimizer.step`` . It will update the learning rate in optimizer according to current ``epoch`` . + The new learning rate will take effect on next ``optimizer.step`` . + Args: + epoch (int, None): specify current epoch. Default: None. Auto-increment from last_epoch=-1. + Returns: + None + """ + if epoch is None: + if not rebuild: + self.last_epoch += 1 / self.num_iters # update step with iters + else: + self.last_epoch = epoch + self.last_lr = self.get_lr() + + if self.verbose: + print( + 'step Epoch {}: {} set learning rate to {}.self.num_iters={}, 1/self.num_iters={}' + .format(self.last_epoch, self.__class__.__name__, self.last_lr, + self.num_iters, 1 / self.num_iters)) + + def _lr_func_steps_with_relative_lrs(self, cur_epoch, lrs, base_lr, steps, + max_epoch): + # get step index + steps = steps + [max_epoch] + for ind, step in enumerate(steps): + if cur_epoch < step: + break + if self.verbose: + print( + '_lr_func_steps_with_relative_lrs, cur_epoch {}: {}, steps {}, ind {}, step{}, max_epoch{}' + .format(cur_epoch, self.__class__.__name__, steps, ind, step, + max_epoch)) + + return lrs[ind - 1] * base_lr + + def get_lr(self): + """Define lr policy""" + lr = self._lr_func_steps_with_relative_lrs( + self.last_epoch, + self.lrs, + self.step_base_lr, + self.steps, + self.max_epoch, + ) + lr_end = self._lr_func_steps_with_relative_lrs( + self.warmup_epochs, + self.lrs, + self.step_base_lr, + self.steps, + self.max_epoch, + ) + + # Perform warm up. + if self.last_epoch < self.warmup_epochs: + lr_start = self.warmup_start_lr + alpha = (lr_end - lr_start) / self.warmup_epochs + lr = self.last_epoch * alpha + lr_start + if self.verbose: + print( + 'get_lr, Epoch {}: {}, lr {}, lr_end {}, self.lrs{}, self.step_base_lr{}, self.steps{}, self.max_epoch{}' + .format(self.last_epoch, self.__class__.__name__, lr, lr_end, + self.lrs, self.step_base_lr, self.steps, + self.max_epoch)) + + return lr + + +class CustomPiecewiseDecay(PiecewiseDecay): + + def __init__(self, **kargs): + kargs.pop('num_iters') + super().__init__(**kargs) + + +class CustomWarmupCosineStepDecay(LRScheduler): + + def __init__(self, + warmup_iters, + warmup_ratio=0.1, + min_lr=0, + base_lr=3e-5, + max_epoch=30, + last_epoch=-1, + num_iters=None, + verbose=False): + + self.warmup_ratio = warmup_ratio + self.min_lr = min_lr + self.warmup_epochs = warmup_iters + self.warmup_iters = warmup_iters * num_iters + self.cnt_iters = 0 + self.cnt_epoch = 0 + self.num_iters = num_iters + self.tot_iters = max_epoch * num_iters + self.max_epoch = max_epoch + self.cosine_base_lr = base_lr # initial lr for all param groups + self.regular_lr = self.get_regular_lr() + super().__init__(last_epoch=last_epoch, verbose=verbose) + + def annealing_cos(self, start, end, factor, weight=1): + cos_out = math.cos(math.pi * factor) + 1 + return end + 0.5 * weight * (start - end) * cos_out + + def get_regular_lr(self): + progress = self.cnt_epoch + max_progress = self.max_epoch + target_lr = self.min_lr + return self.annealing_cos(self.cosine_base_lr, target_lr, progress / + max_progress) # self.cosine_base_lr + + def get_warmup_lr(self, cur_iters): + k = (1 - cur_iters / self.warmup_iters) * (1 - self.warmup_ratio) + warmup_lr = self.regular_lr * (1 - k) # 3e-5 * (1-k) + return warmup_lr + + def step(self, epoch=None): + self.regular_lr = self.get_regular_lr() + self.last_lr = self.get_lr() + self.cnt_epoch = (self.cnt_iters + + 1) // self.num_iters # update step with iters + self.cnt_iters += 1 + + if self.verbose: + print('Epoch {}: {} set learning rate to {}.'.format( + self.last_epoch, self.__class__.__name__, self.last_lr)) + + def get_lr(self): + """Define lr policy""" + cur_iter = self.cnt_iters + if cur_iter >= self.warmup_iters: + return self.regular_lr + else: + warmup_lr = self.get_warmup_lr(cur_iter) + return warmup_lr + + +class CustomWarmupAdjustDecay(LRScheduler): + r""" + We combine warmup and stepwise-cosine which is used in slowfast model. + + Args: + step_base_lr (float): start learning rate used in warmup stage. + warmup_epochs (int): the number epochs of warmup. + lr_decay_rate (float|int, optional): base learning rate decay rate. + step (int): step in change learning rate. + last_epoch (int, optional): The index of last epoch. Can be set to restart training. Default: -1, means initial learning rate. + verbose (bool, optional): If ``True``, prints a message to stdout for each update. Default: ``False`` . + Returns: + ``CosineAnnealingDecay`` instance to schedule learning rate. + """ + + def __init__(self, + step_base_lr, + warmup_epochs, + lr_decay_rate, + boundaries, + num_iters=None, + last_epoch=-1, + verbose=False): + self.step_base_lr = step_base_lr + self.warmup_epochs = warmup_epochs + self.lr_decay_rate = lr_decay_rate + self.boundaries = boundaries + self.num_iters = num_iters + #call step() in base class, last_lr/last_epoch/base_lr will be update + super(CustomWarmupAdjustDecay, self).__init__(last_epoch=last_epoch, + verbose=verbose) + + def step(self, epoch=None): + """ + ``step`` should be called after ``optimizer.step`` . It will update the learning rate in optimizer according to current ``epoch`` . + The new learning rate will take effect on next ``optimizer.step`` . + Args: + epoch (int, None): specify current epoch. Default: None. Auto-increment from last_epoch=-1. + Returns: + None + """ + if epoch is None: + if self.last_epoch == -1: + self.last_epoch += 1 + else: + self.last_epoch += 1 / self.num_iters # update step with iters + else: + self.last_epoch = epoch + + self.last_lr = self.get_lr() + + if self.verbose: + print('Epoch {}: {} set learning rate to {}.'.format( + self.last_epoch, self.__class__.__name__, self.last_lr)) + + def get_lr(self): + if self.last_epoch < self.warmup_epochs: + lr = self.step_base_lr * (self.last_epoch + 1) / self.warmup_epochs + else: + lr = self.step_base_lr * (self.lr_decay_rate**np.sum( + self.last_epoch >= np.array(self.boundaries))) + return lr diff --git a/Bank_second_part/detect_process/paddlevideo/solver/lr.py b/Bank_second_part/detect_process/paddlevideo/solver/lr.py new file mode 100644 index 0000000..3a56fad --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/solver/lr.py @@ -0,0 +1,52 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + +from typing import Dict + +from paddle.optimizer.lr import LRScheduler + +from . import custom_lr + + +def build_lr(cfg: Dict, num_iters: int) -> LRScheduler: + """Build a learning rate scheduler accroding to ```OPTIMIZER``` configuration, and it always pass into the optimizer. + In configuration: + learning_rate: + name: 'PiecewiseDecay' + boundaries: [20, 60] + values: [0.00025, 0.000025, 0.0000025] + + Args: + cfg (Dict): learning rate configuration. + num_iters (int): The number of iterations that may be used when calculating the learning rate + + Returns: + LRScheduler: learning rate scheduler. + """ + + cfg_copy = cfg.copy() + + #when learning_rate is LRScheduler + if cfg_copy.get('learning_rate') and isinstance(cfg_copy['learning_rate'], + dict): + cfg_copy['learning_rate'] = build_lr( + cfg_copy['learning_rate'], + num_iters) #not support only inner iter_step + + lr_name = cfg_copy.pop('name') + if cfg_copy.get('iter_step'): + cfg_copy['num_iters'] = num_iters + cfg_copy.pop('iter_step') + + return getattr(custom_lr, lr_name)(**cfg_copy) diff --git a/Bank_second_part/detect_process/paddlevideo/solver/optimizer.py b/Bank_second_part/detect_process/paddlevideo/solver/optimizer.py new file mode 100644 index 0000000..46ff916 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/solver/optimizer.py @@ -0,0 +1,132 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 inspect +from typing import Dict + +import paddle +from paddle.optimizer.lr import LRScheduler +from paddle.regularizer import L1Decay, L2Decay +from paddlevideo.utils import get_logger + + +def build_optimizer(cfg: Dict, + lr_scheduler: LRScheduler, + model: paddle.nn.Layer, + use_amp: bool = False, + amp_level: str = None) -> paddle.optimizer.Optimizer: + """Build an optimizer and learning rate scheduler to optimize parameters accroding to ```OPTIMIZER``` field in configuration. + + In configuration: + OPTIMIZER: + name: Momentum + momentum: 0.9 + weight_decay: 0.001 + or + + OPTIMIZER: + name: Momentum + momentum: 0.9 + weight_decay: + name: "L1" + value: 0.001 + + Momentum optimizer will be applied to optimize network and L1Decay regularizer will be applied to avoid overfit. + + OPTIMIZER: + name: Adam + weight_decay: + name: "L2" + value: 0.001 + + Adam optimizer will be applied to optimize network and L2Decay regularizer will applied to avoid overfit. + + Refer to ```https://www.paddlepaddle.org.cn/documentation/docs/en/develop/api/paddle/regularizer/L2Decay_en.html``` for more details. + + Args: + cfg (Dict): optimizer configuration. + lr_scheduler (LRScheduler): learning rate scheduler. + model (paddle.nn.Layer, optional): model which contains parameters to be optimized. Defaults to None. + use_amp (bool, optional): Whether use amp. Defaults to False. + amp_level (str, optional): amp level when amp is enabled. Defaults to None. + + + Returns: + paddle.optimizer.Optimizer: an optimizer for the input model. + """ + logger = get_logger("paddlevideo") + cfg_copy = cfg.copy() + # NOTE: check none and illegal cfg!!! + opt_name = cfg_copy.pop('name') + # deal with weight decay + if cfg_copy.get('weight_decay'): + if isinstance(cfg_copy.get('weight_decay'), + float): # just an float factor + cfg_copy['weight_decay'] = cfg_copy.get('weight_decay') + elif 'L1' in cfg_copy.get('weight_decay').get( + 'name').upper(): # specify L2 wd and it's float factor + cfg_copy['weight_decay'] = L1Decay( + cfg_copy.get('weight_decay').get('value')) + elif 'L2' in cfg_copy.get('weight_decay').get( + 'name').upper(): # specify L1 wd and it's float factor + cfg_copy['weight_decay'] = L2Decay( + cfg_copy.get('weight_decay').get('value')) + else: + raise ValueError + + # deal with grad clip + if cfg_copy.get('grad_clip'): + if isinstance(cfg_copy.get('grad_clip'), float): + cfg_copy['grad_clip'] = cfg_copy.get('grad_clip').get('value') + elif 'global' in cfg_copy.get('grad_clip').get('name').lower(): + cfg_copy['grad_clip'] = paddle.nn.ClipGradByGlobalNorm( + cfg_copy.get('grad_clip').get('value')) + else: + raise ValueError + + # Set for optimizers that cannot be applied to l2decay, i.e. AdamW + if cfg_copy.get('no_weight_decay_name'): + no_weight_decay_name = cfg_copy.pop('no_weight_decay_name') + no_weight_decay_name_list = no_weight_decay_name.split(' ') + + # NOTE: use param.name not name + no_weight_decay_param_list = [ + param.name for name, param in model.named_parameters() + if any(key_word in name for key_word in no_weight_decay_name_list) + ] # get the full param name of no weight decay + + _apply_decay_param_fun = lambda name: name not in no_weight_decay_param_list + cfg_copy['apply_decay_param_fun'] = _apply_decay_param_fun + logger.info( + f"No weight Decay list :({len(no_weight_decay_param_list)})", + no_weight_decay_param_list) + + cfg_copy.pop('learning_rate') + + # set multi_precision + optimizer_setting = { + 'learning_rate': lr_scheduler, + 'parameters': model.parameters(), + **cfg_copy + } + optimizer_init_args = inspect.getargspec( + getattr(paddle.optimizer, opt_name).__init__).args + if use_amp and amp_level == "O2" and "multi_precision" in optimizer_init_args: + # support "multi_precision" arg in optimizer's __init__ function. + optimizer_setting.update({"multi_precision": True}) + logger.info( + "Set multi_precision=True for optimizer when use_amp=True and amp_level='O2'" + ) + + return getattr(paddle.optimizer, opt_name)(**optimizer_setting) diff --git a/Bank_second_part/detect_process/paddlevideo/tasks/__init__.py b/Bank_second_part/detect_process/paddlevideo/tasks/__init__.py new file mode 100644 index 0000000..4d43f09 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/tasks/__init__.py @@ -0,0 +1,20 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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. + +from .train import train_model +from .test import test_model +from .train_dali import train_dali +from .train_multigrid import train_model_multigrid + +__all__ = ['train_model', 'test_model', 'train_dali', 'train_model_multigrid'] diff --git a/Bank_second_part/detect_process/paddlevideo/tasks/test.py b/Bank_second_part/detect_process/paddlevideo/tasks/test.py new file mode 100644 index 0000000..31c8653 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/tasks/test.py @@ -0,0 +1,90 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 paddle +from paddlevideo.utils import get_logger, load + +from ..loader.builder import build_dataloader, build_dataset +from ..metrics import build_metric +from ..modeling.builder import build_model + +logger = get_logger("paddlevideo") + + +@paddle.no_grad() +def test_model(cfg, weights, parallel=True): + """Test model entry + + Args: + cfg (dict): configuration. + weights (str): weights path to load. + parallel (bool): Whether to do multi-cards testing. Default: True. + + """ + + if cfg.get('use_npu', False): + places = paddle.set_device('npu') + elif cfg.get('use_xpu', False): + places = paddle.set_device('xpu') + else: + places = paddle.set_device('gpu') + + # 1. Construct model. + if cfg.MODEL.get('backbone') and cfg.MODEL.backbone.get('pretrained'): + cfg.MODEL.backbone.pretrained = '' # disable pretrain model init + model = build_model(cfg.MODEL) + + if parallel: + model = paddle.DataParallel(model) + + # 2. Construct dataset and dataloader. + cfg.DATASET.test.test_mode = True + dataset = build_dataset((cfg.DATASET.test, cfg.PIPELINE.test)) + batch_size = cfg.DATASET.get("test_batch_size", 8) + + # default num worker: 0, which means no subprocess will be created + num_workers = cfg.DATASET.get('num_workers', 0) + num_workers = cfg.DATASET.get('test_num_workers', num_workers) + dataloader_setting = dict(batch_size=batch_size, + num_workers=num_workers, + places=places, + drop_last=False, + shuffle=False) + + data_loader = build_dataloader( + dataset, **dataloader_setting) if cfg.model_name not in ['CFBI' + ] else dataset + + model.eval() + + state_dicts = load(weights) + model.set_state_dict(state_dicts) + + # add params to metrics + cfg.METRIC.data_size = len(dataset) + cfg.METRIC.batch_size = batch_size + Metric = build_metric(cfg.METRIC) + + if cfg.MODEL.framework == "FastRCNN": + Metric.set_dataset_info(dataset.info, len(dataset)) + + for batch_id, data in enumerate(data_loader): + if cfg.model_name in [ + 'CFBI' + ]: # for VOS task, dataset for video and dataloader for frames in each video + Metric.update(batch_id, data, model) + else: + outputs = model(data, mode='test') + Metric.update(batch_id, data, outputs) + Metric.accumulate() diff --git a/Bank_second_part/detect_process/paddlevideo/tasks/train.py b/Bank_second_part/detect_process/paddlevideo/tasks/train.py new file mode 100644 index 0000000..451ec5d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/tasks/train.py @@ -0,0 +1,426 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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.path as osp +import time + +import paddle +import paddle.amp as amp +import paddle.distributed as dist +import paddle.distributed.fleet as fleet +from paddlevideo.utils import (add_profiler_step, build_record, get_logger, + load, log_batch, log_epoch, mkdir, save) + +from ..loader.builder import build_dataloader, build_dataset +from ..metrics.ava_utils import collect_results_cpu +from ..modeling.builder import build_model +from ..solver import build_lr, build_optimizer +from ..utils import do_preciseBN + + +def train_model(cfg, + weights=None, + parallel=True, + validate=True, + use_amp=False, + amp_level=None, + max_iters=None, + use_fleet=False, + profiler_options=None): + """Train model entry + + Args: + cfg (dict): configuration. + weights (str, optional): weights path for finetuning. Defaults to None. + parallel (bool, optional): whether multi-cards training. Defaults to True. + validate (bool, optional): whether to do evaluation. Defaults to True. + use_amp (bool, optional): whether to use automatic mixed precision during training. Defaults to False. + amp_level (str, optional): amp optmization level, must be 'O1' or 'O2' when use_amp is True. Defaults to None. + max_iters (int, optional): max running iters in an epoch. Defaults to None. + use_fleet (bool, optional): whether to use fleet. Defaults to False. + profiler_options (str, optional): configuration for the profiler function. Defaults to None. + + """ + if use_fleet: + fleet.init(is_collective=True) + + logger = get_logger("paddlevideo") + batch_size = cfg.DATASET.get('batch_size', 8) + valid_batch_size = cfg.DATASET.get('valid_batch_size', batch_size) + + # gradient accumulation settings + use_gradient_accumulation = cfg.get('GRADIENT_ACCUMULATION', None) + if use_gradient_accumulation and dist.get_world_size() >= 1: + global_batch_size = cfg.GRADIENT_ACCUMULATION.get( + 'global_batch_size', None) + num_gpus = dist.get_world_size() + + assert isinstance( + global_batch_size, int + ), f"global_batch_size must be int, but got {type(global_batch_size)}" + assert batch_size <= global_batch_size, \ + f"global_batch_size({global_batch_size}) must not be less than batch_size({batch_size})" + + cur_global_batch_size = batch_size * num_gpus # The number of batches calculated by all GPUs at one time + assert global_batch_size % cur_global_batch_size == 0, \ + f"The global batchsize({global_batch_size}) must be divisible by cur_global_batch_size({cur_global_batch_size})" + cfg.GRADIENT_ACCUMULATION[ + "num_iters"] = global_batch_size // cur_global_batch_size + # The number of iterations required to reach the global batchsize + logger.info( + f"Using gradient accumulation training strategy, " + f"global_batch_size={global_batch_size}, " + f"num_gpus={num_gpus}, " + f"num_accumulative_iters={cfg.GRADIENT_ACCUMULATION.num_iters}") + + if cfg.get('use_npu', False): + places = paddle.set_device('npu') + elif cfg.get('use_xpu', False): + places = paddle.set_device('xpu') + else: + places = paddle.set_device('gpu') + + # default num worker: 0, which means no subprocess will be created + num_workers = cfg.DATASET.get('num_workers', 0) + valid_num_workers = cfg.DATASET.get('valid_num_workers', num_workers) + model_name = cfg.model_name + output_dir = cfg.get("output_dir", f"./output/{model_name}") + mkdir(output_dir) + + # 1. Construct model + model = build_model(cfg.MODEL) + + if cfg.get('to_static', False): + specs = None + model = paddle.jit.to_static(model, input_spec=specs) + logger.info( + "Successfully to apply @to_static with specs: {}".format(specs)) + + # 2. Construct dataset and dataloader for training and evaluation + train_dataset = build_dataset((cfg.DATASET.train, cfg.PIPELINE.train)) + train_dataloader_setting = dict( + batch_size=batch_size, + num_workers=num_workers, + collate_fn_cfg=cfg.get('MIX', None), + places=places) + train_loader = build_dataloader(train_dataset, **train_dataloader_setting) + + if validate: + valid_dataset = build_dataset((cfg.DATASET.valid, cfg.PIPELINE.valid)) + validate_dataloader_setting = dict( + batch_size=valid_batch_size, + num_workers=valid_num_workers, + places=places, + drop_last=False, + shuffle=cfg.DATASET.get( + 'shuffle_valid', + False) # NOTE: attention_LSTM needs to shuffle valid data. + ) + valid_loader = build_dataloader(valid_dataset, + **validate_dataloader_setting) + + # 3. Construct learning rate scheduler(lr) and optimizer + lr = build_lr(cfg.OPTIMIZER.learning_rate, len(train_loader)) + optimizer = build_optimizer( + cfg.OPTIMIZER, lr, model=model, use_amp=use_amp, amp_level=amp_level) + + # 4. Construct scalar and convert parameters for amp(optional) + if use_amp: + scaler = amp.GradScaler( + init_loss_scaling=2.0**16, + incr_every_n_steps=2000, + decr_every_n_nan_or_inf=1) + # convert model parameters to fp16 when amp_level is O2(pure fp16) + model, optimizer = amp.decorate( + models=model, + optimizers=optimizer, + level=amp_level, + master_weight=True, + save_dtype=None) + # NOTE: save_dtype is set to float32 now. + logger.info(f"Training in amp mode, amp_level={amp_level}.") + else: + assert amp_level is None, f"amp_level must be None when training in fp32 mode, but got {amp_level}." + logger.info("Training in fp32 mode.") + + # 5. Resume(optional) + resume_epoch = cfg.get("resume_epoch", 0) + if resume_epoch: + filename = osp.join(output_dir, + model_name + f"_epoch_{resume_epoch:05d}") + resume_model_dict = load(filename + '.pdparams') + resume_opt_dict = load(filename + '.pdopt') + model.set_state_dict(resume_model_dict) + optimizer.set_state_dict(resume_opt_dict) + logger.info("Resume from checkpoint: {}".format(filename)) + + # 6. Finetune(optional) + if weights: + assert resume_epoch == 0, f"Conflict occurs when finetuning, please switch resume function off by setting resume_epoch to 0 or not indicating it." + model_dict = load(weights) + model.set_state_dict(model_dict) + logger.info("Finetune from checkpoint: {}".format(weights)) + + # 7. Parallelize(optional) + if parallel: + model = paddle.DataParallel(model) + + if use_fleet: + model = fleet.distributed_model(model) + optimizer = fleet.distributed_optimizer(optimizer) + + # 8. Train Model + best = 0.0 + for epoch in range(0, cfg.epochs): + if epoch < resume_epoch: + logger.info( + f"| epoch: [{epoch + 1}] <= resume_epoch: [{resume_epoch}], continue..." + ) + continue + model.train() + + record_list = build_record(cfg.MODEL) + tic = time.time() + for i, data in enumerate(train_loader): + """Next two line of code only used in test_tipc, + ignore it most of the time""" + if max_iters is not None and i >= max_iters: + break + + record_list['reader_time'].update(time.time() - tic) + + # Collect performance information when profiler_options is activate + add_profiler_step(profiler_options) + + # 8.1 forward + # AMP # + if use_amp: + with amp.auto_cast( + custom_black_list={"reduce_mean", "conv3d"}, + level=amp_level): + outputs = model(data, mode='train') + avg_loss = outputs['loss'] + if use_gradient_accumulation: + # clear grad at when epoch begins + if i == 0: + optimizer.clear_grad() + # Loss normalization + avg_loss /= cfg.GRADIENT_ACCUMULATION.num_iters + # Loss scaling + scaled = scaler.scale(avg_loss) + # 8.2 backward + scaled.backward() + # 8.3 minimize + if (i + 1) % cfg.GRADIENT_ACCUMULATION.num_iters == 0: + scaler.minimize(optimizer, scaled) + optimizer.clear_grad() + else: # general case + # Loss scaling + scaled = scaler.scale(avg_loss) + # 8.2 backward + scaled.backward() + # 8.3 minimize + scaler.minimize(optimizer, scaled) + optimizer.clear_grad() + else: + outputs = model(data, mode='train') + avg_loss = outputs['loss'] + if use_gradient_accumulation: + # clear grad at when epoch begins + if i == 0: + optimizer.clear_grad() + # Loss normalization + avg_loss /= cfg.GRADIENT_ACCUMULATION.num_iters + # 8.2 backward + avg_loss.backward() + # 8.3 minimize + if (i + 1) % cfg.GRADIENT_ACCUMULATION.num_iters == 0: + optimizer.step() + optimizer.clear_grad() + else: # general case + # 8.2 backward + avg_loss.backward() + # 8.3 minimize + optimizer.step() + optimizer.clear_grad() + + # log record + record_list['lr'].update(optimizer.get_lr(), batch_size) + for name, value in outputs.items(): + if name in record_list: + record_list[name].update(value, batch_size) + + record_list['batch_time'].update(time.time() - tic) + tic = time.time() + + if i % cfg.get("log_interval", 10) == 0: + ips = "ips: {:.5f} instance/sec,".format( + batch_size / record_list["batch_time"].val) + cur_progress = ((i + 1) + epoch * len(train_loader)) / ( + len(train_loader) * cfg.epochs) + eta = int(record_list["batch_time"].sum * + (1 - cur_progress) / cur_progress + 0.5) + log_batch(record_list, i, epoch + 1, cfg.epochs, "train", ips, + eta) + + # learning rate iter step + if cfg.OPTIMIZER.learning_rate.get("iter_step"): + lr.step() + + # learning rate epoch step + if not cfg.OPTIMIZER.learning_rate.get("iter_step"): + lr.step() + + ips = "avg_ips: {:.5f} instance/sec.".format( + batch_size * record_list["batch_time"].count / + record_list["batch_time"].sum) + log_epoch(record_list, epoch + 1, "train", ips) + + def evaluate(best): + model.eval() + results = [] + record_list = build_record(cfg.MODEL) + record_list.pop('lr') + tic = time.time() + if parallel: + rank = dist.get_rank() + # single_gpu_test and multi_gpu_test + for i, data in enumerate(valid_loader): + """Next two line of code only used in test_tipc, + ignore it most of the time""" + if max_iters is not None and i >= max_iters: + break + + if use_amp: + with amp.auto_cast( + custom_black_list={"reduce_mean", "conv3d"}, + level=amp_level): + outputs = model(data, mode='valid') + else: + outputs = model(data, mode='valid') + + if cfg.MODEL.framework == "FastRCNN": + results.extend(outputs) + + # log_record + if cfg.MODEL.framework != "FastRCNN": + for name, value in outputs.items(): + if name in record_list: + record_list[name].update(value, batch_size) + + record_list['batch_time'].update(time.time() - tic) + tic = time.time() + + if i % cfg.get("log_interval", 10) == 0: + ips = "ips: {:.5f} instance/sec.".format( + valid_batch_size / record_list["batch_time"].val) + log_batch(record_list, i, epoch + 1, cfg.epochs, "val", ips) + + if cfg.MODEL.framework == "FastRCNN": + if parallel: + results = collect_results_cpu(results, len(valid_dataset)) + if not parallel or (parallel and rank == 0): + eval_res = valid_dataset.evaluate(results) + for name, value in eval_res.items(): + record_list[name].update(value, valid_batch_size) + + ips = "avg_ips: {:.5f} instance/sec.".format( + valid_batch_size * record_list["batch_time"].count / + record_list["batch_time"].sum) + log_epoch(record_list, epoch + 1, "val", ips) + + best_flag = False + if cfg.MODEL.framework == "FastRCNN" and (not parallel or + (parallel and rank == 0)): + if record_list["mAP@0.5IOU"].val > best: + best = record_list["mAP@0.5IOU"].val + best_flag = True + return best, best_flag + + if cfg.MODEL.framework == "YOWOLocalizer" and (not parallel or + (parallel and rank == 0)): + if record_list["fscore"].avg > best: + best = record_list["fscore"].avg + best_flag = True + return best, best_flag + + # forbest2, cfg.MODEL.framework != "FastRCNN": + for top_flag in ['hit_at_one', 'top1', 'rmse', "F1@0.50"]: + if record_list.get(top_flag): + if top_flag != 'rmse' and record_list[top_flag].avg > best: + best = record_list[top_flag].avg + best_flag = True + elif top_flag == 'rmse' and ( + best == 0.0 or record_list[top_flag].avg < best): + best = record_list[top_flag].avg + best_flag = True + + return best, best_flag + + # use precise bn to improve acc + if cfg.get("PRECISEBN") and ( + epoch % cfg.PRECISEBN.preciseBN_interval == 0 + or epoch == cfg.epochs - 1): + do_preciseBN(model, train_loader, parallel, + min(cfg.PRECISEBN.num_iters_preciseBN, + len(train_loader)), use_amp, amp_level) + + # 9. Validation + if validate and (epoch % cfg.get("val_interval", 1) == 0 + or epoch == cfg.epochs - 1): + with paddle.no_grad(): + best, save_best_flag = evaluate(best) + # save best + if save_best_flag: + save(optimizer.state_dict(), + osp.join(output_dir, model_name + "_best.pdopt")) + save_student_model_flag = True if "Distillation" in cfg.MODEL.framework else False + save( + model.state_dict(), + osp.join(output_dir, model_name + "_best.pdparams"), + save_student_model=save_student_model_flag) + if model_name == "AttentionLstm": + logger.info( + f"Already save the best model (hit_at_one){best}") + elif cfg.MODEL.framework == "FastRCNN": + logger.info( + f"Already save the best model (mAP@0.5IOU){int(best * 10000) / 10000}" + ) + elif cfg.MODEL.framework == "DepthEstimator": + logger.info( + f"Already save the best model (rmse){int(best * 10000) / 10000}" + ) + elif cfg.MODEL.framework in ['MSTCN', 'ASRF']: + logger.info( + f"Already save the best model (F1@0.50){int(best * 10000) / 10000}" + ) + elif cfg.MODEL.framework in ['YOWOLocalizer']: + logger.info( + f"Already save the best model (fsocre){int(best * 10000) / 10000}" + ) + else: + logger.info( + f"Already save the best model (top1 acc){int(best * 10000) / 10000}" + ) + + # 10. Save model and optimizer + if epoch % cfg.get("save_interval", 1) == 0 or epoch == cfg.epochs - 1: + save(optimizer.state_dict(), + osp.join(output_dir, + model_name + f"_epoch_{epoch + 1:05d}.pdopt")) + save(model.state_dict(), + osp.join(output_dir, + model_name + f"_epoch_{epoch + 1:05d}.pdparams")) + + logger.info(f'training {model_name} finished') diff --git a/Bank_second_part/detect_process/paddlevideo/tasks/train_dali.py b/Bank_second_part/detect_process/paddlevideo/tasks/train_dali.py new file mode 100644 index 0000000..8dd0a20 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/tasks/train_dali.py @@ -0,0 +1,143 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 time +import os.path as osp + +import paddle +from ..modeling.builder import build_model +from ..solver import build_lr, build_optimizer +from ..utils import do_preciseBN +from paddlevideo.utils import get_logger, coloring +from paddlevideo.utils import (AverageMeter, build_record, log_batch, log_epoch, + save, load, mkdir) +from paddlevideo.loader import TSN_Dali_loader, get_input_data +""" +We only supported DALI training for TSN model now. +""" + + +def train_dali(cfg, weights=None, parallel=True): + """Train model entry + + Args: + cfg (dict): configuration. + weights (str): weights path for finetuning. + parallel (bool): Whether multi-cards training. Default: True. + + """ + + logger = get_logger("paddlevideo") + batch_size = cfg.DALI_LOADER.get('batch_size', 8) + places = paddle.set_device('gpu') + model_name = cfg.model_name + output_dir = cfg.get("output_dir", f"./output/{model_name}") + mkdir(output_dir) + + # 1. Construct model + model = build_model(cfg.MODEL) + if parallel: + model = paddle.DataParallel(model) + + # 2. Construct dali dataloader + train_loader = TSN_Dali_loader(cfg.DALI_LOADER).build_dali_reader() + + # 3. Construct solver. + lr = build_lr(cfg.OPTIMIZER.learning_rate, None) + optimizer = build_optimizer(cfg.OPTIMIZER, lr, model=model) + + # Resume + resume_epoch = cfg.get("resume_epoch", 0) + if resume_epoch: + filename = osp.join(output_dir, + model_name + f"_epoch_{resume_epoch:05d}") + resume_model_dict = load(filename + '.pdparams') + resume_opt_dict = load(filename + '.pdopt') + model.set_state_dict(resume_model_dict) + optimizer.set_state_dict(resume_opt_dict) + + # Finetune: + if weights: + assert resume_epoch == 0, f"Conflict occurs when finetuning, please switch resume function off by setting resume_epoch to 0 or not indicating it." + model_dict = load(weights) + model.set_state_dict(model_dict) + + # 4. Train Model + for epoch in range(0, cfg.epochs): + if epoch < resume_epoch: + logger.info( + f"| epoch: [{epoch+1}] <= resume_epoch: [{ resume_epoch}], continue... " + ) + continue + model.train() + record_list = build_record(cfg.MODEL) + tic = time.time() + for i, data in enumerate(train_loader): + data = get_input_data(data) + record_list['reader_time'].update(time.time() - tic) + # 4.1 forward + outputs = model(data, mode='train') + # 4.2 backward + avg_loss = outputs['loss'] + avg_loss.backward() + # 4.3 minimize + optimizer.step() + optimizer.clear_grad() + + # log record + record_list['lr'].update(optimizer._global_learning_rate(), + batch_size) + for name, value in outputs.items(): + record_list[name].update(value, batch_size) + + record_list['batch_time'].update(time.time() - tic) + tic = time.time() + + if i % cfg.get("log_interval", 10) == 0: + ips = "ips: {:.5f} instance/sec.".format( + batch_size / record_list["batch_time"].val) + log_batch(record_list, i, epoch + 1, cfg.epochs, "train", ips) + + # learning rate iter step + if cfg.OPTIMIZER.learning_rate.get("iter_step"): + lr.step() + + # learning rate epoch step + if not cfg.OPTIMIZER.learning_rate.get("iter_step"): + lr.step() + + ips = "ips: {:.5f} instance/sec.".format( + batch_size * record_list["batch_time"].count / + record_list["batch_time"].sum) + log_epoch(record_list, epoch + 1, "train", ips) + + # use precise bn to improve acc + if cfg.get("PRECISEBN") and (epoch % cfg.PRECISEBN.preciseBN_interval + == 0 or epoch == cfg.epochs - 1): + do_preciseBN( + model, train_loader, parallel, + min(cfg.PRECISEBN.num_iters_preciseBN, len(train_loader))) + + # 5. Save model and optimizer + if epoch % cfg.get("save_interval", 1) == 0 or epoch == cfg.epochs - 1: + save( + optimizer.state_dict(), + osp.join(output_dir, + model_name + f"_epoch_{epoch+1:05d}.pdopt")) + save( + model.state_dict(), + osp.join(output_dir, + model_name + f"_epoch_{epoch+1:05d}.pdparams")) + + logger.info(f'training {model_name} finished') diff --git a/Bank_second_part/detect_process/paddlevideo/tasks/train_multigrid.py b/Bank_second_part/detect_process/paddlevideo/tasks/train_multigrid.py new file mode 100644 index 0000000..19e756f --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/tasks/train_multigrid.py @@ -0,0 +1,335 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 time +import os.path as osp + +import paddle +import paddle.distributed as dist + +from ..loader.builder import build_dataloader, build_dataset +from ..modeling.builder import build_model +from ..solver import build_lr, build_optimizer +from ..utils import do_preciseBN +from paddlevideo.utils import get_logger, coloring +from paddlevideo.utils import (AverageMeter, build_record, log_batch, log_epoch, + save, load, mkdir) +from paddlevideo.utils.multigrid import MultigridSchedule, aggregate_sub_bn_stats, subn_load, subn_save, is_eval_epoch + + +def construct_loader(cfg, places, validate, precise_bn, num_iters_precise_bn, + world_size): + batch_size = cfg.DATASET.get('batch_size', 2) + train_dataset = build_dataset((cfg.DATASET.train, cfg.PIPELINE.train)) + precise_bn_dataloader_setting = dict( + batch_size=batch_size, + num_workers=cfg.DATASET.get('num_workers', 0), + places=places, + ) + if precise_bn: + cfg.DATASET.train.num_samples_precise_bn = num_iters_precise_bn * batch_size * world_size + precise_bn_dataset = build_dataset((cfg.DATASET.train, + cfg.PIPELINE.train)) + precise_bn_loader = build_dataloader(precise_bn_dataset, + **precise_bn_dataloader_setting) + cfg.DATASET.train.num_samples_precise_bn = None + else: + precise_bn_loader = None + + if cfg.MULTIGRID.SHORT_CYCLE: + # get batch size list in short cycle schedule + bs_factor = [ + int( + round((float(cfg.PIPELINE.train.transform[1]['MultiCrop'][ + 'target_size']) / (s * cfg.MULTIGRID.default_crop_size)) + **2)) for s in cfg.MULTIGRID.short_cycle_factors + ] + batch_sizes = [ + batch_size * bs_factor[0], + batch_size * bs_factor[1], + batch_size, + ] + train_dataloader_setting = dict( + batch_size=batch_sizes, + multigrid=True, + num_workers=cfg.DATASET.get('num_workers', 0), + places=places, + ) + else: + train_dataloader_setting = precise_bn_dataloader_setting + + train_loader = build_dataloader(train_dataset, **train_dataloader_setting) + if validate: + valid_dataset = build_dataset((cfg.DATASET.valid, cfg.PIPELINE.valid)) + validate_dataloader_setting = dict( + batch_size=batch_size, + num_workers=cfg.DATASET.get('num_workers', 0), + places=places, + drop_last=False, + shuffle=False) + valid_loader = build_dataloader(valid_dataset, + **validate_dataloader_setting) + else: + valid_loader = None + + return train_loader, valid_loader, precise_bn_loader + + +def build_trainer(cfg, places, parallel, validate, precise_bn, + num_iters_precise_bn, world_size): + """ + Build training model and its associated tools, including optimizer, + dataloaders and meters. + Args: + cfg (CfgNode): configs. + Returns: + model: training model. + optimizer: optimizer. + train_loader: training data loader. + val_loader: validatoin data loader. + precise_bn_loader: training data loader for computing + precise BN. + """ + model = build_model(cfg.MODEL) + if parallel: + model = paddle.DataParallel(model) + + train_loader, valid_loader, precise_bn_loader = \ + construct_loader(cfg, + places, + validate, + precise_bn, + num_iters_precise_bn, + world_size, + ) + + lr = build_lr(cfg.OPTIMIZER.learning_rate, len(train_loader)) + optimizer = build_optimizer(cfg.OPTIMIZER, lr, model=model) + + return ( + model, + lr, + optimizer, + train_loader, + valid_loader, + precise_bn_loader, + ) + + +def train_model_multigrid(cfg, world_size=1, validate=True): + """Train model entry + + Args: + cfg (dict): configuration. + parallel (bool): Whether multi-card training. Default: True + validate (bool): Whether to do evaluation. Default: False. + + """ + # Init multigrid. + multigrid = None + if cfg.MULTIGRID.LONG_CYCLE or cfg.MULTIGRID.SHORT_CYCLE: + multigrid = MultigridSchedule() + cfg = multigrid.init_multigrid(cfg) + if cfg.MULTIGRID.LONG_CYCLE: + cfg, _ = multigrid.update_long_cycle(cfg, cur_epoch=0) + multi_save_epoch = [i[-1] - 1 for i in multigrid.schedule] + + parallel = world_size != 1 + logger = get_logger("paddlevideo") + batch_size = cfg.DATASET.get('batch_size', 2) + + if cfg.get('use_npu', False): + places = paddle.set_device('npu') + elif cfg.get('use_xpu', False): + places = paddle.set_device('xpu') + else: + places = paddle.set_device('gpu') + + model_name = cfg.model_name + output_dir = cfg.get("output_dir", f"./output/{model_name}") + mkdir(output_dir) + local_rank = dist.ParallelEnv().local_rank + precise_bn = cfg.get("PRECISEBN") + num_iters_precise_bn = cfg.PRECISEBN.num_iters_preciseBN + + # 1. Construct model + model = build_model(cfg.MODEL) + if parallel: + model = paddle.DataParallel(model) + + # 2. Construct dataloader + train_loader, valid_loader, precise_bn_loader = \ + construct_loader(cfg, + places, + validate, + precise_bn, + num_iters_precise_bn, + world_size, + ) + + # 3. Construct optimizer + lr = build_lr(cfg.OPTIMIZER.learning_rate, len(train_loader)) + optimizer = build_optimizer( + cfg.OPTIMIZER, lr, parameter_list=model.parameters()) + + # Resume + resume_epoch = cfg.get("resume_epoch", 0) + if resume_epoch: + filename = osp.join( + output_dir, + model_name + str(local_rank) + '_' + f"{resume_epoch:05d}") + subn_load(model, filename, optimizer) + + # 4. Train Model + best = 0. + total_epochs = int(cfg.epochs * cfg.MULTIGRID.epoch_factor) + for epoch in range(total_epochs): + if epoch < resume_epoch: + logger.info( + f"| epoch: [{epoch+1}] <= resume_epoch: [{ resume_epoch}], continue... " + ) + continue + + if cfg.MULTIGRID.LONG_CYCLE: + cfg, changed = multigrid.update_long_cycle(cfg, epoch) + if changed: + logger.info("====== Rebuild model/optimizer/loader =====") + ( + model, + lr, + optimizer, + train_loader, + valid_loader, + precise_bn_loader, + ) = build_trainer(cfg, places, parallel, validate, precise_bn, + num_iters_precise_bn, world_size) + + #load checkpoint after re-build model + if epoch != 0: + #epoch no need to -1, haved add 1 when save + filename = osp.join( + output_dir, + model_name + str(local_rank) + '_' + f"{(epoch):05d}") + subn_load(model, filename, optimizer) + #update lr last epoch, not to use saved params + lr.last_epoch = epoch + lr.step(rebuild=True) + + model.train() + record_list = build_record(cfg.MODEL) + tic = time.time() + for i, data in enumerate(train_loader): + record_list['reader_time'].update(time.time() - tic) + # 4.1 forward + outputs = model(data, mode='train') + # 4.2 backward + avg_loss = outputs['loss'] + avg_loss.backward() + # 4.3 minimize + optimizer.step() + optimizer.clear_grad() + + # log record + record_list['lr'].update( + float(optimizer._global_learning_rate()), batch_size) + for name, value in outputs.items(): + record_list[name].update(float(value), batch_size) + record_list['batch_time'].update(time.time() - tic) + tic = time.time() + + if i % cfg.get("log_interval", 10) == 0: + ips = "ips: {:.5f} instance/sec.".format( + batch_size / record_list["batch_time"].val) + log_batch(record_list, i, epoch + 1, total_epochs, "train", ips) + + # learning rate iter step + if cfg.OPTIMIZER.learning_rate.get("iter_step"): + lr.step() + + # learning rate epoch step + if not cfg.OPTIMIZER.learning_rate.get("iter_step"): + lr.step() + + ips = "ips: {:.5f} instance/sec.".format( + batch_size * record_list["batch_time"].count / + record_list["batch_time"].sum) + log_epoch(record_list, epoch + 1, "train", ips) + + def evaluate(best): + model.eval() + record_list = build_record(cfg.MODEL) + record_list.pop('lr') + tic = time.time() + for i, data in enumerate(valid_loader): + outputs = model(data, mode='valid') + + # log_record + for name, value in outputs.items(): + record_list[name].update(float(value), batch_size) + + record_list['batch_time'].update(time.time() - tic) + tic = time.time() + + if i % cfg.get("log_interval", 10) == 0: + ips = "ips: {:.5f} instance/sec.".format( + batch_size / record_list["batch_time"].val) + log_batch(record_list, i, epoch + 1, total_epochs, "val", + ips) + + ips = "ips: {:.5f} instance/sec.".format( + batch_size * record_list["batch_time"].count / + record_list["batch_time"].sum) + log_epoch(record_list, epoch + 1, "val", ips) + + best_flag = False + if record_list.get('top1') and record_list['top1'].avg > best: + best = record_list['top1'].avg + best_flag = True + return best, best_flag + + # use precise bn to improve acc + if is_eval_epoch(cfg, epoch, total_epochs, multigrid.schedule): + logger.info(f"do precise BN in {epoch+1} ...") + do_preciseBN(model, precise_bn_loader, parallel, + min(num_iters_precise_bn, len(precise_bn_loader))) + + # aggregate sub_BN stats + logger.info("Aggregate sub_BatchNorm stats...") + aggregate_sub_bn_stats(model) + + # 5. Validation + if is_eval_epoch(cfg, epoch, total_epochs, multigrid.schedule): + logger.info(f"eval in {epoch+1} ...") + with paddle.no_grad(): + best, save_best_flag = evaluate(best) + # save best + if save_best_flag: + save(optimizer.state_dict(), + osp.join(output_dir, model_name + "_best.pdopt")) + save(model.state_dict(), + osp.join(output_dir, model_name + "_best.pdparams")) + logger.info( + f"Already save the best model (top1 acc){int(best * 10000) / 10000}" + ) + + # 6. Save model and optimizer + if is_eval_epoch( + cfg, epoch, + total_epochs, multigrid.schedule) or epoch % cfg.get( + "save_interval", 10) == 0 or epoch in multi_save_epoch: + logger.info("[Save parameters] ======") + subn_save(output_dir, model_name + str(local_rank) + '_', epoch + 1, + model, optimizer) + + logger.info(f'training {model_name} finished') diff --git a/Bank_second_part/detect_process/paddlevideo/utils/__init__.py b/Bank_second_part/detect_process/paddlevideo/utils/__init__.py new file mode 100644 index 0000000..d18561d --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/__init__.py @@ -0,0 +1,24 @@ +# 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. + +from .registry import Registry +from .build_utils import build +from .config import * +from .logger import setup_logger, coloring, get_logger +from .record import AverageMeter, build_record, log_batch, log_epoch +from .dist_utils import get_dist_info, main_only +from .save_load import save, load, load_ckpt, mkdir +from .precise_bn import do_preciseBN +from .profiler import add_profiler_step +__all__ = ['Registry', 'build'] diff --git a/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..64ae2234c5e2a00c55bf725e7f0cafd54652c36e GIT binary patch literal 734 zcmYjO%Z}496ph;?P12{`77!6yH@*J~F} z2&sf169pB8E0i=RL>VCj7g2CXR{%v6MT+*;PU5@GdS!c03OEgS z9TLAGk!biM)YNYI7c?;5C0v-5M>FGjZ{OHfhleQw`w@TU-y?*6hGgF;Brjl@E;t@> z%*ibtBTnC;e(a+%TZ%mN?5qPp3~LC>jKNvtki|Dd-*d#FYh>=9p-}<)qhIkC4F8WZgb_NeWx-j-mWtPf zU^A_jELY`B&KZ}vJxLkZOFcJ(CJI?To3mcn><`#*ua&*F%q&zL_$(_#W^ACcnJk%I z2zDh_EnOhdVlIu-Uo<$os#;-pXrN*}fCKP9=C{Juy4=&M zE-qVc5CZ*mZUtvh6uZ&RKRo)lX40@yS@u^b6n0X+p?>01X(XVtG8aAygZn5~)ymUK zRi4g;^~oEtdZo3}zB5yLnOO}-i~1c;;jnzNWAhY*j}xd(8-fIsOv8BNgAnC~(FAaf z`!y7U$!S(zO=q$YrVXDwom5)o!kDHysWQ$BaV@z}liJF{OfJHGPMi1yB*smC9G=qy ta1Yajq&OuB?u74mm*^uXpZ9Sq7&qyih&Bq3*C)@~C-OW@W`fM_(I1GR(X{{o literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/config.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/config.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7d3a10eef4c2ce641b42a31d9456dfe636bcf61a GIT binary patch literal 4706 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/dist_utils.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/dist_utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c43503fe2c4cec8e914194c1b8b9d3eb4f26f5c4 GIT binary patch literal 749 zcmY*Xv2N5r5S>}CeZB)9QD`6y4UL;qM2Vs(3jH;7Crg&`+L3iW+uHSUN_1Bx5|NPj z1|reqZ>YDRq2d>4U}l}5W2||zZ{(TTd3GB`6CnHUe^x&{fS*kEO%ORFH^&4D6xOg9 zA}-KzvGNuYK?&vEz`|Ej`4j_%?;#F;Q5DQ{#z*6h?C;3U3xXcL;vMWb3W~VJEtG<) zaUOeCs><|sdQtT0rq#7dO?6e+kh#v9Wi0GuFE2TF4|+s>f1ej`lXK!}S=EIZj>m73 zPPchsjLRlnrc_;gtW?n^>%OW@!t+vhoOPEr;z2G|HD&vp?;H?>$d4Y=F-L+&7qkUjy5{$xFnWUQhUsO`nIi&^*L)|p{G=?pE0oRI%04`#{XLJhkj6w zhDd!#JRa!-3N{!%f;}AKjOEtVhjm{l`(%%3R@Z6n%7i4r){vCy6Ufoli8Tky#R06A4;kB-SM zk={M>6IIr>z2`8>tg$7|DxjYss+5zLbcQI1%Na65)=3Uu=rmj2t<{y)HL&_nc%UqF zb?H`?WI{VT{Dst3CUu#oyRpbpZFjlSwp1dtbh*c+jJjNxI>`Pz5hp+8~uo}gzv_TXBz_*Cvqdnx?L{n{TJFZ+TyhP2_6qUI!!~WY*g~dT|?omh?2*WEfvU6LJZQ8aVRCZ3sbmZg~vv({p zn>%|B&`M)UN$SI{1G{tkyDsjsQtq_N`;<$lr%0>U)~J-04PL=CLtJ?;$#!Mr<}UL= z&-Xy}RdsuURbSIlIWHSqMr&Rgd4Nym9@+qVwY+RrgiQ>n_%$bc$JpeU%C1?}##C(Q zWK;o*$G1=HP343g8(X7_vE+z6udw5LCv(s}16;s!%J7}eD`Sdj{@S8&{oB*P2dNIe z`ni9^8y`F|F)*I^=!u%yo5fh6caSWnqu(H)egI=Rja3{a@sI~1-nbv97_feOxHmMsKPfO!<8QI7|i z0F=docT^@`pcWbJax_>EmN$cDmh$t#vp7kDG*bsOqo6Q^>Tv)wPniT>wH3_O)pIq6 z%IE5!YVLdxNjd0oh6bMUqaM7gWfe{?p2ZT3f*fiC%OHSG8Q~|zQ7)i^VB^W5xH-=L z2{C>m1BZJV8yp;U6XF`n{a~8dtZ_9E>5)Kz+Ah>deZ|xch6;DMFx>BS3>%69yT&?v zatZ*Xf$10{E4TKnF%W*I&Cu2!ixgLJk83;4p6LoM)u5knpxKglw7uC=t%~4L(ngvo z`2wKYLZCf_i@?4lu@HUg(cwps34?yS@UMO?$vROYuh&t9;TES+x^%m7^UfBS0OvGajDNWjq<& zg{~}Rq8BN}g|2k66cXPop>3|1yU`v*Vg-x999evb=dM6=>_=VjSKuva-^8blR`uk% z@$D{@QvynD2`w4?Wsq8W0(2eP^P#D}W%Dq-F}nr!L+$h4@blg{ z4$kfy&q3-0b*K+N&priQH6t-?*X#+i>jPEX0CoSXlY_@&4ygF9<^&!KD<{g@C8C;J z>qOZ(yq=7{hIME)LrYu*Uhx%x&=DWw`cnj7BDet{v=2GN*SL#M<&nDaAwl-5BLRwe z_ONgqI$?=L)IiPufY5G=Qz(k{BBqg0Eezs4i_Z|u0BB7W9l6dRTSfeIpg1$RCGhW* wc}NevGX{=$WPCH_>|HB*(se8pi4U?@^S~{Lyk(Uz+J`^)AAiE}e7p9|e`b1+mjD0& literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/precise_bn.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/precise_bn.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..79ae684d410a50ed35a1ccbe5aa18eba57bd95e9 GIT binary patch literal 2950 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/registry.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/registry.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..56450c323f2338ef8b0a2ddfad0dac13f622c177 GIT binary patch literal 2465 zcmb_ePj4GV6yMoh+Z*GgDNQdNVCW?=G*$%?2P=v4hpK`~u4ux=iZosCjGaxK9W%2V zWV5-@2$1*^?Fr?haO3PN--1hdZ^pZJnu0hm@{H&2oA-Y2_ui~rUamV({;2%Qe}~?m zI9Mz`40fUFHE5nV+~MR3s&HOL>a5RdO!9$u#sAB?DQ0P|O-Xdq02t~tWCb4bTS}ht$E;f5Z8J)G;bTm#+WMbD)!~MO3r~A)3j}PfK zE%e`5?}gD>PbOl$X)eHxyXDT7wMeLq`D!!_wFUvYBhq$x2G5OP!Av|;cHw{1=s(IP^ z#*rp~X!b_HnX+IX>j6}~3QbOOhdHqWE#U;{=1#sUuh>%qeG_z}%m#3=*#;H~OE%d@ zM(L7}<@rw2omPwi(|`dV8ITdCd@Y9ksgJU*9aRM_{@NAoWBnNDXS{B!i1GZYJlgZtJd#z&q79JR=b3B|= z=M~AxYY5j2@VF*mgu*RT4={#4ik^CBVr(?GO%3N7j72g@!#L55eGW4kkzOT}`wKeE zcSI<(DA=z+HF|sk9rVkob3ydV*N|vXBN)4{-IwG?lDoK;lPyR@=&{aZd#{L2;}K5R zf4E$y--nupLnT5!F5_5m8YgzSK=0$GXAP|Or8*B&g=)hb8mdsKsRzEhZ7r9~iV*4x z*rglLG+duliTlQXv*InUQb|(gy_{&#Bc&KA>|^HDomxK@JnRcqK86IE+YsG$hEWx2%AU%RS*HWU@o|G zi-d^5J;dNcXaEBT?5v@iFNv`e+>dtV;Bd7BTdrMXywzCUfr+NuUG8T|#H3>8UgNrJ zV%>;ArVLAcRQ^jC>HwMmywxB+nS4}owD4(b3o?5+)H^L>E+&hnZ>6oEG-QTCl`S*g z$DX+%C?ssdlwn0sS#|wt;8h7k!#pC3eK)|k9SLPbUb-^^+)G{VzVb{=_(e?#rUyOQmJKx^mZ`9rEdkJIrt5tjb3Uj1;hoP+Bo$6Nu%_w z$zYvMb4lIBtLlu|2cI#_Uf*Tm&@yUTV+`obm_m{$jBGb1t2S;P0BYQIa&_+3J#!Isr&2c?-5x_0Mpqb^UR literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/save_load.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/utils/__pycache__/save_load.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..62b126991082ab6428ae9479c1833dca8776cc2e GIT binary patch literal 7342 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/build_utils.py b/Bank_second_part/detect_process/paddlevideo/utils/build_utils.py new file mode 100644 index 0000000..73c0ca4 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/build_utils.py @@ -0,0 +1,35 @@ +# 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. + + +def build(cfg, registry, key='name'): + """Build a module from config dict. + Args: + cfg (dict): Config dict. It should at least contain the key. + registry (XXX): The registry to search the type from. + key (str): the key. + Returns: + obj: The constructed object. + """ + + assert isinstance(cfg, dict) and key in cfg + + cfg_copy = cfg.copy() + obj_type = cfg_copy.pop(key) + + obj_cls = registry.get(obj_type) + if obj_cls is None: + raise KeyError('{} is not in the {} registry'.format( + obj_type, registry.name)) + return obj_cls(**cfg_copy) diff --git a/Bank_second_part/detect_process/paddlevideo/utils/config.py b/Bank_second_part/detect_process/paddlevideo/utils/config.py new file mode 100644 index 0000000..f4d7941 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/config.py @@ -0,0 +1,174 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 yaml +from paddlevideo.utils.logger import coloring, get_logger, setup_logger + +__all__ = ['get_config'] + +logger = setup_logger("./", name="paddlevideo", level="INFO") + + +class AttrDict(dict): + def __getattr__(self, key): + return self[key] + + def __setattr__(self, key, value): + if key in self.__dict__: + self.__dict__[key] = value + else: + self[key] = value + + +def create_attr_dict(yaml_config): + from ast import literal_eval + for key, value in yaml_config.items(): + if type(value) is dict: + yaml_config[key] = value = AttrDict(value) + if isinstance(value, str): + try: + value = literal_eval(value) + except BaseException: + pass + if isinstance(value, AttrDict): + create_attr_dict(yaml_config[key]) + else: + yaml_config[key] = value + + +def parse_config(cfg_file): + """Load a config file into AttrDict""" + with open(cfg_file, 'r') as fopen: + yaml_config = AttrDict(yaml.load(fopen, Loader=yaml.SafeLoader)) + create_attr_dict(yaml_config) + return yaml_config + + +def print_dict(d, delimiter=0): + """ + Recursively visualize a dict and + indenting acrrording by the relationship of keys. + """ + placeholder = "-" * 60 + for k, v in sorted(d.items()): + if isinstance(v, dict): + logger.info("{}{} : ".format(delimiter * " ", coloring(k, + "HEADER"))) + print_dict(v, delimiter + 4) + elif isinstance(v, list) and len(v) >= 1 and isinstance(v[0], dict): + logger.info("{}{} : ".format(delimiter * " ", + coloring(str(k), "HEADER"))) + for value in v: + print_dict(value, delimiter + 4) + else: + logger.info("{}{} : {}".format(delimiter * " ", + coloring(k, "HEADER"), + coloring(v, "OKGREEN"))) + + if k.isupper(): + logger.info(placeholder) + + +def print_config(config): + """ + visualize configs + Arguments: + config: configs + """ + print_dict(config) + + +def check_config(config): + """ + Check config + """ + pass + + +def override(dl, ks, v): + """ + Recursively replace dict of list + Args: + dl(dict or list): dict or list to be replaced + ks(list): list of keys + v(str): value to be replaced + """ + def str2num(v): + try: + return eval(v) + except Exception: + return v + + assert isinstance(dl, (list, dict)), ("{} should be a list or a dict") + assert len(ks) > 0, ('lenght of keys should larger than 0') + if isinstance(dl, list): + k = str2num(ks[0]) + if len(ks) == 1: + assert k < len(dl), ('index({}) out of range({})'.format(k, dl)) + dl[k] = str2num(v) + else: + override(dl[k], ks[1:], v) + else: + if len(ks) == 1: + #assert ks[0] in dl, ('{} is not exist in {}'.format(ks[0], dl)) + if not ks[0] in dl: + logger.warning('A new filed ({}) detected!'.format(ks[0], dl)) + dl[ks[0]] = str2num(v) + else: + assert ks[0] in dl, ( + '({}) doesn\'t exist in {}, a new dict field is invalid'.format( + ks[0], dl)) + override(dl[ks[0]], ks[1:], v) + + +def override_config(config, options=None): + """ + Recursively override the config + Args: + config(dict): dict to be replaced + options(list): list of pairs(key0.key1.idx.key2=value) + such as: [ + epochs=20', + 'PIPELINE.train.transform.1.ResizeImage.resize_short=300' + ] + Returns: + config(dict): replaced config + """ + if options is not None: + for opt in options: + assert isinstance(opt, + str), ("option({}) should be a str".format(opt)) + assert "=" in opt, ( + "option({}) should contain a =" + "to distinguish between key and value".format(opt)) + pair = opt.split('=') + assert len(pair) == 2, ("there can be only a = in the option") + key, value = pair + keys = key.split('.') + override(config, keys, value) + + return config + + +def get_config(fname, overrides=None, show=True): + """ + Read config from file + """ + assert os.path.exists(fname), ('config file({}) is not exist'.format(fname)) + config = parse_config(fname) + override_config(config, overrides) + if show: + print_config(config) + check_config(config) + return config diff --git a/Bank_second_part/detect_process/paddlevideo/utils/dist_utils.py b/Bank_second_part/detect_process/paddlevideo/utils/dist_utils.py new file mode 100644 index 0000000..7659e88 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/dist_utils.py @@ -0,0 +1,30 @@ +# 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 functools + +import paddle +import paddle.distributed as dist + +def get_dist_info(): + world_size = dist.get_world_size() + rank = dist.get_rank() + return rank, world_size + +def main_only(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + rank, _ = get_dist_info() + if rank == 0: + return func(*args, **kwargs) + return wrapper diff --git a/Bank_second_part/detect_process/paddlevideo/utils/logger.py b/Bank_second_part/detect_process/paddlevideo/utils/logger.py new file mode 100644 index 0000000..e9791b8 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/logger.py @@ -0,0 +1,113 @@ +# Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 logging +import os +import sys +import datetime + +from paddle.distributed import ParallelEnv + + + +Color = { + 'RED': '\033[31m', + 'HEADER': '\033[35m', # deep purple + 'PURPLE': '\033[95m', # purple + 'OKBLUE': '\033[94m', + 'OKGREEN': '\033[92m', + 'WARNING': '\033[93m', + 'FAIL': '\033[91m', + 'ENDC': '\033[0m' +} + + +def coloring(message, color="OKGREEN"): + assert color in Color.keys() + if os.environ.get('COLORING', True): + return Color[color] + str(message) + Color["ENDC"] + else: + return message + + +logger_initialized = [] + + +def setup_logger(output=None, name="paddlevideo", level="INFO"): + """ + Initialize the paddlevideo logger and set its verbosity level to "INFO". + Args: + output (str): a file name or a directory to save log. If None, will not save log file. + If ends with ".txt" or ".log", assumed to be a file name. + Otherwise, logs will be saved to `output/log.txt`. + name (str): the root module name of this logger + Returns: + logging.Logger: a logger + """ + def time_zone(sec, fmt): + real_time = datetime.datetime.now() + return real_time.timetuple() + logging.Formatter.converter = time_zone + + logger = logging.getLogger(name) + if level == "INFO": + logger.setLevel(logging.INFO) + elif level=="DEBUG": + logger.setLevel(logging.DEBUG) + logger.propagate = False + + if level == "DEBUG": + plain_formatter = logging.Formatter( + "[%(asctime)s] %(name)s %(levelname)s: %(message)s", + datefmt="%m/%d %H:%M:%S") + else: + plain_formatter = logging.Formatter( + "[%(asctime)s] %(message)s", + datefmt="%m/%d %H:%M:%S") + # stdout logging: master only + local_rank = ParallelEnv().local_rank + if local_rank == 0: + ch = logging.StreamHandler(stream=sys.stdout) + ch.setLevel(logging.DEBUG) + formatter = plain_formatter + ch.setFormatter(formatter) + logger.addHandler(ch) + + # file logging: all workers + if output is not None: + if output.endswith(".txt") or output.endswith(".log"): + filename = output + else: + filename = os.path.join(output, ".log.txt") + if local_rank > 0: + filename = filename + ".rank{}".format(local_rank) + + # PathManager.mkdirs(os.path.dirname(filename)) + os.makedirs(os.path.dirname(filename), exist_ok=True) + + # fh = logging.StreamHandler(_cached_log_stream(filename) + fh = logging.FileHandler(filename, mode='a') + fh.setLevel(logging.DEBUG) + fh.setFormatter(plain_formatter) + logger.addHandler(fh) + logger_initialized.append(name) + return logger + + +def get_logger(name, output=None): + logger = logging.getLogger(name) + if name in logger_initialized: + return logger + + return setup_logger(name=name, output=name) diff --git a/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__init__.py b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__init__.py new file mode 100644 index 0000000..10295b5 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__init__.py @@ -0,0 +1,10 @@ +from .multigrid import MultigridSchedule +from .batchnorm_helper import get_norm, aggregate_sub_bn_stats +from .short_sampler import DistributedShortSampler +from .save_load_helper import subn_save, subn_load +from .interval_helper import is_eval_epoch + +__all__ = [ + 'MultigridSchedule', 'get_norm', 'aggregate_sub_bn_stats', + 'DistributedShortSampler', 'subn_save', 'subn_load', 'is_eval_epoch' +] diff --git a/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dc3ea5920a16275e2e9a91d225d9fc7b00b01906 GIT binary patch literal 540 zcmYk3&1&2*5P&7`kG)x&Y%a+&_)#A?bH=FG0enzNdzRq=-@296#FO@QQ&#k7lkETi literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/batchnorm_helper.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/batchnorm_helper.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..05cf1e81aeeae987bd0d7a63a5136e0520654a4e GIT binary patch literal 4486 zcmaJ_&u<&Y72eq&~Ma*nR)ZQ@4ZpJ zy4tjm{^k9d|NRG+^&hG%CKr`o;#2pLaf`Fm8nQjcsBEY9p3NQZKC|{5?(rIa-H$9@ z=l(N``@$Z0gW8F+SLgO)tKE1G309jG^-&~s5~aJbO)axTWm@bZK6MA#1dBbfrLV04 z8$bZ+HtHMN(e8wC=PR^nkGrR}iFL+K*q>P2JN`#AK>C&Jse7hGwYb|0wjOqSyEzx_ zd%+MtY0w!bDNnLq5a(Gp>8b623mqk?3L+_jBnxz3pl>)7nN~sGt)!8}vXABk-6Rz| zrt?#w$1+=3H_LWDiH?N4XU1o_97bt!9O)#_f|NSSc}1fW>9|k*#i|;2!m0{gHM8+B zRHHP}>iF$l3<>nnNCbbJ28jx?TnB1A8s$<8-mVw5QN(#F3Omb+l?No0X54)wNw>w? z<8f!9vAD9E>yL+{RL~Ix|Fx94ENWfarf%CstCNMar;rvbR;gBPLFE5F75DZZ zMA?&&w4lo3yLa|SGLMB)rggvE(?P;TzCYGb@cwX|>ZB(VzF(a*?2B{+g^Z30zbCX= z*drj&GQRIKpS756`^pP$B07R5+WmiFIn7S&ytgY));>CbqUuY`HnH zPn|Q1S-_9|o;77()FupQvQOB&2B12}|D0WDJeDds5a|)FIpaZ;rU5B&moPNOiGzq* zdp#+7krud%&MkB*9cfkG?J^Kcu7?G=992lS=Lie{pc47<%@Asgr{E>&j<%^`}-g$6=qR<^gD!ZU{{ zJhK!07@2fi1{v}amB1&~CO&hEuHRx!++&li*)B7EG5VGg-6SRTb7aEWW84D4us!EX ztBV`s&NF|{JX} zdAHQhXRvkB1CJyRaD&D=$@)iQjaxRl2%=c#3Reygh^G-5jv}6jf{%Xp`A+b07N~qE z%z`nNL7yfYZBsTEzcw_3(Pa%D(uQaRcpZKTf53J#oY*67Pjt#(*S zo9kffXScCL7s>_Uw6P5?Mgm!;)1#f>(O448ii0Q}8|vF8#Z<6TMi%jDxo}tJL!;u^ zLCvA^OyC&hRW11p!b=U`3Ss8AxNmL2)~yr!)Gn=jVuj8G2)YjM5yH;7ZAu&N^?>1~S>=*h`q7_h3b>dI&PgF=E4Og|V6dt^&kR=EDp%D;< zk{pn{PT390-lUo9vBVBVNX9c18j}crvQB*~3kw(i!`x7-E^6gT;M;XR3VSl*32dWS zO+_R#*hWZZSh!|CKFP5=S>YQcf^g}SN~B%08ypxa`8v37a^ab?q~lABAlb=S^$sR=ucS?49>vwzDi@;$8#1 z&t5a<4QuL6+=+)ptu%NJa?}0kVYbk;1PP&HDos% zZy_wWK`8vzcH9@XW4~};`rh%6FQV={B)t+0lHnQ@{ssk*9dIarh=7nN7}RHSB0=xW z*|(=`O6|3Qb6TIUGlt-hYA$Lv)i`@>zP24bSj5!hqb%;rJOj-H@UzB}>1>tfH7y5` zB*#w{ywl0faREf803!l~jzGvQjDy@JcxFLNeI~rxA-B2Je!n8g-%~#|ZX>*thZL@K z$60Ki6o(0>nYpvo;EI(Nk-@KNnsdr_C2!`P%|Ban8Mc*v%rAz9#uU94Nx0&mYA5-5OACN8VHTh4kH1N69V_v z5Q`cpm4>vpf%<%6Shih&qP&WE5}(>Y=KI8hHRgg9*Srnp{`dIi1-w1w1=x^Gx*lpe_+p{;Q6xRhHcwd*Abu&44p>R@rfbiw)sJG`LsqCP|E3C1aU z3e?y-RDJ{RxF#G+)81s8s2^`$Q2lILyHUU$XYjOPSTw`1e0HJS3d1kPQ9A3Xhat~n z_(Jl422AB$e@MGqow>?br0LvU8hW}#gUvgI-ad3N)k5Z5E^9UX+y3SC%O)ad`$fYT yS)QlLJf%yO(L2;UV@mJunYX@~v7m)>BJ}Tus78+bJNW zC%Ew>ybb4EIrRZJz-1XHqO7zd&15{D`M&YkNjseup!}$Ptj@%qsa*;yO29`M>TAI?s7LHYQVj6tK_p|LEBEmef2qn8R4;IfrYKOfZ+)xXr~0XXpl|&F?K5Bdm)^6AX;!ZJTr6V z%$YOaIcK(CEE*Dif6e^TdFvHP`Wt=B|5SXujmLi#g(KA^M|N0OuCptWqd4lvlB2rH zeWk8C8AtnAs%M<6qvNePY*(t~MlZZG^cq3C@A+o4&&}Sj8?;-z?U(_#+g{sitv?21 zX{SNu{Ey+|Z9M*26s}a4F*$SOy5cZL!33&N7+P-f(ZnN#V{xhU8{bZ17dyY9AICkKgjb_WV8;w49AaD2Hx?tBJ0jEEz zlcp3r{$&}Ol0(UoK9M?dhoMv~6=kNQb+R2@eCLvH!(pq?Bp!8@`YTqR%1(j*D3l%) zKam~^PEMvJJ7S@s)R8Vr_vK~kUFw{$%JI8Xc67l3G}Lpe(z4_jr;=VoIWPTOYRXO? z>e8oN5+0R=M+Li^`xzukzh^uv#IwcHc`L+&X!Im}7Cw=7sjhSu`2#Uqfo4m%l}YZT zXE~@QRE(i@bQY?!R>7xM9Q{+Mns)E~*;ee^zU!EMZ*Kd1Hwdsde!Ml*e}lLDbLnWJ z&@P^B^u1=g<=4)cNzDun?0`N3n4_OsrP%(NvHAnI(QdXIM;H>*gL?y)4{UDt+`#2? z^WSiTA@@FCgy6tUOw1waX2S10h6zbgPMGo~-XBEyz~(JCu>AJO<#_d%OOt9s`MLnn+~J=c!J*}=@Et8@+%H;7A$j!6h@|ae7Z0Q*g7xDOCMtwJ5uL?Mru&?KirTT`Okwd;FZSGVe$H=<(KwK;*4#c}?lOv~=|Y@S2E zM{=ZKt76R+K;T6bU&Z5-GBt^@GZSs{*&?1nFCn5amIDX{F#!=|`tdFa&X7iFdjSmK z{q4Q2D>t?-M+JA#ZyZ=nyAkxc5QWo5KPAZP^MaHhNbO{#Pa!SJUf$T-*xlTVjD0%* zGhs~27!oZ25pCe6HEW3U>s!}1x3_jSqm01nsN}efzT;ZH-5YdW9vR-SXEn+6{pjSB zLE!cVeQtLJ^C*Xro)6&fMU`of2JBh1){X6JJ6EhrKe)8L87-4_cl%Iz<6fhSNfI39 z6Hzl%c471Xj^keSRTOx7p5QjiTHOgM2E zhl>Avs3t9NEr$yK;2k z#J$)lStq=LLo$eZP!2WGo4zWbl4P0Af*8LTs;6+ksBTq*lMZ^y65iPdOY!*5iH9=L zre975GkuI6dfKBB_W&&?Xpk4{IE7^a7 zvQt36=)y`})4k*Jd!{g~H4`S-I5gW$lkCzIc4_(t_P|BiA9exS2e#L8*Uhb_*$z@x zjkkI%(myacW1uoe{yVMI-xYjJiFiT zcQM-!4_r7xZU+5CpU2e=4;@hSCiW%OvjA>RVHc+Z6y*eXc>tSw(I4)|SVo_t#qHS! z#xb3LZdA$bdlofY0i5_b^P}--L6CrI{-E0qd_j9Lw|8S>YiE6ij34?G1|lr9xpPbO zc|AwSy1w)NRqLG_8&@}X&Aa9d+pOJHoMBFZ$oeLJWZux5&%VtCG6 zy>@wXJJR><#^HY7b47Ei5&@?5B55gANmLZ*KXr}#1@Nw~%;PpWhiP+^8F2Dr8hHRa zsAYML1R`9Ha;e$XH6hV{6u;3umav}NN8}MZyfjkb0>vxwF3u_Dd*JDBqhJM1HYN*< zA>06U|l0s}fdX8tMySAzb*jG%kci%vlQaq|va_RK)CmxcyuBLGpErSUK&_a;$UA zR1K@);%O;Fc1hgFCu0sIPnaQ^;B+$Pl#ZqyS|M4GUKOzFBI!a%wS-kJW3?+pyY<|7 zHC&}sFI)oeQ{hT@3R13w%aC%F^p6ty7CX2?9O8L?E#J-ttKqWnoXhZDMZ0~(dmT@S zp2|$tlB5?v3imZla{Eowo`c&N%758@>6u<875glu25=p_aax8<9;*OpZYd^VNbIfA zid-J+Zu8W4kRzfWl6vm?gT6*SQ<)#Ny#5;9P>6bIi&MfyGHKBaNh zbMl!OWEJ>sD z|ION`tZJubsR*ZpkAH)TnG>G*U*V3)3D+0qJY($1e6fZ6J2dtz6)&NP77;IU_R1iI_Kt)Shd5*m#OJkpa10lyl*gU6G$E{;ej}KJ6Jg1Mi*+|0xzb-<8Sf)I^kZIn*v8-2cTSplsF-;idnn6;H z0_4`-f376vnhCr;tMuhbsQcEDk~n$P|}k_Ni_xuyW>% zqJsxRprRskR1u66@Vtyil}EMz*j#sN*+{o652?6iMTTYd`gHM$dcm@85AAN!lC>@uB7bW~#RFDGZj_K^I(h;RY?Nf@ZOOQ>`Un{)9iGBb+L4=wwKSrxW=MD8s~C3QP694_ao4J2e9%Qgy(dHg1U&X$#UkDBP`}J zXn(=u(-%{j2rNyMoLY_qg9K+P9-*0aR6^27Y0N^T_k{R|5-+2Mgq{K3b^&l9bcYZF z6zD{;A5ES7mG&LiGwoD0!len5j`OoMlZy*S;oj+xCF$zS3&zSk>epuu_5XP<`c&jG z3o6p1{)LI=G4~%sjX8Dv8?n20T))BF`@(f2teGtqN`bOwdN_I${GrI@O!AjdTh|Vt zTuMI^SX?_2B>-jjk)0w^im$rXOn-n8cGq;;J=gQ`uZ>&r5`|leBLzASHANUvlo8t` zQ0Qq}T0^%8PkhD-bg#rF1;&YvWNC+*GZ0{Kk5dQ{Y5o0<+X%!N6y_#+&T&nTZ=|1( WG2j9$D7IBq(pg!NeyqP+$p0Jpd7fSX literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/save_load_helper.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/save_load_helper.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..68e467efb368aa07b5ca9908840096daa9bde20f GIT binary patch literal 6813 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/short_sampler.cpython-310.pyc b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/__pycache__/short_sampler.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..de4dd56fd533c6aade0558eb9b27a77c861cb72c GIT binary patch literal 5085 zcmb7I&5zs06(4?xqPW_Pvr%owNn1MU#|qe}L0cf`!f_MVagm_d6m`*}Tc=zuXC!f# zBIV&|?OjlSopsR`y%a_N0Q;C*|CFA2?J2jObEx}!LrUVtn*gQ2(af89Z{B8&eslDj3evNX1zSh|A;SI7fdM zgYKCHUQOCRIHV5wYfDVelT_d2Un$Bua#zM`OWf zi5PgA%=>bbuLzR*pq{O1$T^n8+2D2s>F=9+Ng!=~q;_Sb$Xy1>?FeV~ZOBRXE z<&#N2!zoCAdZNZz>SqUsB2xZ?aSYWjaRt8^dp`&gkp{s&B$JiwODo9y5e~W1`o-Ak zY;u5|VF%hq@@ys}C}F|d0U35cs?4_%m^B2}ph~+0A=E4tl^R!wpc_arO=4Kl7JO&h z&!*%$VFD7<44c4;>doWS=PQ@-l?>w)=d&V4+o86EP2v9@V=YCVC_z+;@dpGk@Z2LkpgV4$fC6^{EHQG*%_podZ?iMw%*Zc&glu$X zd}oqOF+kiV7J^;K$a7qk`JL$}k$qI|JnIS*K zDoc51rhFd|=g7`Kz-m`h!5+a{+A7*->~M|x1#%*ABH-8>=l6g(N3A>nPDkU|Sl6v_ zy3{WmwCkMO4dtnqo?gBuq&ZcKc@O;h^e_Q(A~K0GWfgOK%mp zK4X$@5MO*OcJAGRmjuH&5qZ^p`-k^xZ_?0vRqQ^FxybI#RGj4ZCh+ZeBx8P0XN#cD zV1wyN*|`DR6%VKK<`0NJ+$R&Mk+U-g!Oi#+SmB4vvA%m4KQ5tJN zr31{;Cbr9VEp@qBr`JZpkn30{$pcFVu_QgpOHV5}ph4MLYNKq4X%>x3dlD+Nk%*IW zjU=uP6=*6`VWQJr-!1K2BtyAD#4i!?Zc{m>O~hr7X0KACnIJ>c)+W~o!(E*C_b|$D zpmEwg(=_boj@dQ3#-d06UCT9l8seIs+3Y)}WBA6VaoW6dU1(V6{HjCS;eC_#-h#h8 zW{Ulp9l|l;Tjo=%FrFDt?PqLmA^@43=34MMgrKYJkLIiF9n4f?nmID_H$P&Z8t6On z9c3Q2pStLGK*K4_XNCcM8)I&~!%P-*{=|j|ciej7&MmC-xN&65JB3B`8+6w|_hX`~ zx_ZVQv3ZNza|bx<+NJpQ$8+Q6d?+S zIH>R!Yl#Zcz5fT`UdsPgVR0KA{k_7Xz_fV#t=-Qlyqwb}X_8Fr71HKE(X4a{$|mTV z1?k4>vCC|36(qBD8RZD%yGrs^kZWviD;smI!ss!D5DM2ZRN9xwrlxK z0OVyfWeYZq7=tp4$(IS>h=)p~yzi9lIv1ChDj!+-X}L+Ygud8w1UQ}I;mb(84QDRD zp#ha!HgJvjGedrh_S3GTz2;hgOY4GCaB$Kf^E<4}2WULQ#?OV{Y?_|o;dKr7zgMlE zX&Vl_$b9bV)_#tkeR}(ALb4LF8Ir$x^D1J#tTm&0xwrQfMELklHE5cw9GvRj9% zfKbczN|_72w^4~8QAkPNkA%n{R*Kyw^kq!Kf*_!JIlqO*eB>D$h6lZQ(57SbFzQ-f z&owqpXc!tL?UKIngFd^KgYhMd%txCv_xx)kliuu{FHy!{UXX|b_@jwfg02 z0N^q~2DrBo9*-KPR_SeJmF>FB`V?z(y5jYqu%6K~Prv=u#-$6hh~!;7)TdWp4vBho zIjn9q;Xe>}mKV~y0+l<}3_5Go#nQn4?O3FXBB9QT@BUiO#Qt_wi&p8K>Y`cRs2Nd; z=R$DYzK2wVz%XlyC?js2_`E7(wh2k*{vQk*vwWj5s-)!t6!kNz!W)&nkEc>ERcokPKA;=ILf1=7eB{xdTiZ(I#a~MH z9mo-AT7SW@=5)xOcY6J+jAOaFZ}0Bjxr2y|+XB8+h#)AvAedzIH3I!^5Zs@INj(EA z_s89K-=pn@Gc}Xg zP7>SFLQ}S2NYfMTGx8b%I?FE`lJ2@Cc!8RML%w{`=B0b165}SN)0}QnUDh>RM3t`T Hm_6%%Y<+Ue literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/multigrid/batchnorm_helper.py b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/batchnorm_helper.py new file mode 100644 index 0000000..e39b067 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/batchnorm_helper.py @@ -0,0 +1,142 @@ +from functools import partial +import paddle + + +def get_norm(bn_norm_type, bn_num_splits): + """ + Args: + cfg (CfgNode): model building configs, details are in the comments of + the config file. + Returns: + nn.Layer: the normalization layer. + """ + if bn_norm_type == "batchnorm": + return paddle.nn.BatchNorm3D + elif bn_norm_type == "sub_batchnorm": + return partial(SubBatchNorm3D, num_splits=bn_num_splits) + else: + raise NotImplementedError( + "Norm type {} is not supported".format(bn_norm_type)) + + +def aggregate_sub_bn_stats(model): + """ + Recursively find all SubBN modules and aggregate sub-BN stats. + Args: + model (nn.Layer): model to be aggregate sub-BN stats + Returns: + count (int): number of SubBN module found. + """ + count = 0 + for child in model.children(): + if isinstance(child, SubBatchNorm3D): + child.aggregate_stats() + count += 1 + else: + count += aggregate_sub_bn_stats(child) + return count + + +class SubBatchNorm3D(paddle.nn.Layer): + """ + Implement based on paddle2.0. + The standard BN layer computes stats across all examples in a GPU. In some + cases it is desirable to compute stats across only a subset of examples + SubBatchNorm3D splits the batch dimension into N splits, and run BN on + each of them separately (so that the stats are computed on each subset of + examples (1/N of batch) independently. During evaluation, it aggregates + the stats from all splits into one BN. + """ + def __init__(self, num_splits, **args): + """ + Args: + num_splits (int): number of splits. + args (list): list of args + """ + super(SubBatchNorm3D, self).__init__() + self.num_splits = num_splits + self.num_features = args["num_features"] + self.weight_attr = args["weight_attr"] + self.bias_attr = args["bias_attr"] + + # Keep only one set of weight and bias (outside). + if self.weight_attr == False: + self.weight = self.create_parameter( + attr=None, + shape=[self.num_features], + default_initializer=paddle.nn.initializer.Constant(1.0)) + self.weight.stop_gradient = True + else: + self.weight = self.create_parameter( + attr=self.weight_attr, + shape=[self.num_features], + default_initializer=paddle.nn.initializer.Constant(1.0)) + self.weight.stop_gradient = self.weight_attr is not None \ + and self.weight_attr.learning_rate == 0. + + if self.bias_attr == False: + self.bias = self.create_parameter(attr=None, + shape=[self.num_features], + is_bias=True) + self.bias.stop_gradient = True + else: + self.bias = self.create_parameter(attr=self.bias_attr, + shape=[self.num_features], + is_bias=True) + self.bias.stop_gradient = self.bias_attr is not None \ + and self.bias_attr.learning_rate == 0. + + # set weights and bias fixed (inner). + args["weight_attr"] = False + args["bias_attr"] = False + self.bn = paddle.nn.BatchNorm3D(**args) + # update number of features used in split_bn + args["num_features"] = self.num_features * self.num_splits + self.split_bn = paddle.nn.BatchNorm3D(**args) + + def _get_aggregated_mean_std(self, means, stds, n): + """ + Calculate the aggregated mean and stds. + Use the method of update mean and std when merge multi-part data. + Args: + means (tensor): mean values. + stds (tensor): standard deviations. + n (int): number of sets of means and stds. + """ + mean = paddle.sum(paddle.reshape(means, (n, -1)), axis=0) / n + std = (paddle.sum(paddle.reshape(stds, (n, -1)), axis=0) / n + + paddle.sum(paddle.reshape( + paddle.pow((paddle.reshape(means, (n, -1)) - mean), 2), + (n, -1)), + axis=0) / n) + return mean, std + + def aggregate_stats(self): + """ + Synchronize running_mean, and running_var to self.bn. + Call this before eval, then call model.eval(); + When eval, forward function will call self.bn instead of self.split_bn, + During this time the running_mean, and running_var of self.bn has been obtained from + self.split_bn. + """ + if self.split_bn.training: + bn_mean_tensor, bn_variance_tensor = self._get_aggregated_mean_std( + self.split_bn._mean, + self.split_bn._variance, + self.num_splits, + ) + self.bn._mean.set_value(bn_mean_tensor) + self.bn._variance.set_value(bn_variance_tensor) + + def forward(self, x): + if self.training: + n, c, t, h, w = x.shape + x = paddle.reshape( + x, (n // self.num_splits, c * self.num_splits, t, h, w)) + x = self.split_bn(x) + x = paddle.reshape(x, (n, c, t, h, w)) + else: + x = self.bn(x) + x = paddle.multiply(x, paddle.reshape(self.weight, (-1, 1, 1, 1))) + x = paddle.add(x, paddle.reshape(self.bias, (-1, 1, 1, 1))) + return x diff --git a/Bank_second_part/detect_process/paddlevideo/utils/multigrid/interval_helper.py b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/interval_helper.py new file mode 100644 index 0000000..2df4bc7 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/interval_helper.py @@ -0,0 +1,19 @@ +def is_eval_epoch(cfg, cur_epoch, total_epochs, multigrid_schedule): + """ + Determine if the model should be evaluated at the current epoch. + Args: + cfg (CfgNode): configs. Details can be found in + slowfast/config/defaults.py + cur_epoch (int): current epoch. + multigrid_schedule (List): schedule for multigrid training. + """ + if cur_epoch + 1 == total_epochs: + return True + if multigrid_schedule is not None: + prev_epoch = 0 + for s in multigrid_schedule: + if cur_epoch < s[-1]: + period = max( + (s[-1] - prev_epoch) // cfg.MULTIGRID.EVAL_FREQ + 1, 1) + return (s[-1] - 1 - cur_epoch) % period == 0 + prev_epoch = s[-1] diff --git a/Bank_second_part/detect_process/paddlevideo/utils/multigrid/multigrid.py b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/multigrid.py new file mode 100644 index 0000000..a296a06 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/multigrid.py @@ -0,0 +1,233 @@ +"""Functions for multigrid training.""" + +import numpy as np + + +class MultigridSchedule(object): + """ + This class defines multigrid training schedule and update cfg accordingly. + """ + def init_multigrid(self, cfg): + """ + Update cfg based on multigrid settings. + Args: + cfg (configs): configs that contains training and multigrid specific + hyperparameters. + Returns: + cfg (configs): the updated cfg. + """ + self.schedule = None + # We may modify cfg.DATASET.batch_size, cfg.PIPELINE.train.decode_sampler.num_frames, and + # cfg.PIPELINE.train.transform[1]['MultiCrop']['target_size'] during training, so we store their original + # value in cfg and use them as global variables. + cfg.MULTIGRID.default_batch_size = cfg.DATASET.batch_size # total bs,64 + cfg.MULTIGRID.default_temporal_size = cfg.PIPELINE.train.decode_sampler.num_frames # 32 + cfg.MULTIGRID.default_crop_size = cfg.PIPELINE.train.transform[1][ + 'MultiCrop']['target_size'] # 224 + + if cfg.MULTIGRID.LONG_CYCLE: + self.schedule = self.get_long_cycle_schedule(cfg) + cfg.OPTIMIZER.learning_rate.steps = [0] + [ + s[-1] for s in self.schedule + ] + # Fine-tuning phase. + cfg.OPTIMIZER.learning_rate.steps[-1] = ( + cfg.OPTIMIZER.learning_rate.steps[-2] + + cfg.OPTIMIZER.learning_rate.steps[-1]) // 2 + cfg.OPTIMIZER.learning_rate.lrs = [ + cfg.OPTIMIZER.learning_rate.gamma**s[0] * s[1][0] + for s in self.schedule + ] + # Fine-tuning phase. + cfg.OPTIMIZER.learning_rate.lrs = cfg.OPTIMIZER.learning_rate.lrs[:-1] + [ + cfg.OPTIMIZER.learning_rate.lrs[-2], + cfg.OPTIMIZER.learning_rate.lrs[-1], + ] + + cfg.OPTIMIZER.learning_rate.max_epoch = self.schedule[-1][-1] + + elif cfg.MULTIGRID.SHORT_CYCLE: + cfg.OPTIMIZER.learning_rate.steps = [ + int(s * cfg.MULTIGRID.epoch_factor) + for s in cfg.OPTIMIZER.learning_rate.steps + ] + cfg.OPTIMIZER.learning_rate.max_epoch = int( + cfg.OPTIMIZER.learning_rate.max_epoch * + cfg.OPTIMIZER.learning_rate.max_epoch) + return cfg + + def update_long_cycle(self, cfg, cur_epoch): + """ + Before every epoch, check if long cycle shape should change. If it + should, update cfg accordingly. + Args: + cfg (configs): configs that contains training and multigrid specific + hyperparameters. + cur_epoch (int): current epoch index. + Returns: + cfg (configs): the updated cfg. + changed (bool): whether to change long cycle shape at this epoch + """ + base_b, base_t, base_s = get_current_long_cycle_shape( + self.schedule, cur_epoch) + if base_s != cfg.PIPELINE.train.transform[1]['MultiCrop'][ + 'target_size'] or base_t != cfg.PIPELINE.train.decode_sampler.num_frames: + #NOTE Modify + # no need to modify, used by pool_size in head, None when multigrid + # cfg.MODEL.head.num_frames = base_t + # cfg.MODEL.head.crop_size = base_s + cfg.PIPELINE.train.decode_sampler.num_frames = base_t + cfg.PIPELINE.train.transform[1]['MultiCrop']['target_size'] = base_s + cfg.DATASET.batch_size = base_b * cfg.MULTIGRID.default_batch_size #change bs + + bs_factor = (float(cfg.DATASET.batch_size) / + cfg.MULTIGRID.bn_base_size) + + if bs_factor == 1: #single bs == bn_base_size (== 8) + cfg.MODEL.backbone.bn_norm_type = "batchnorm" + else: + cfg.MODEL.backbone.bn_norm_type = "sub_batchnorm" + cfg.MODEL.backbone.bn_num_splits = int(bs_factor) + + cfg.MULTIGRID.long_cycle_sampling_rate = cfg.PIPELINE.train.decode_sampler.sampling_rate * ( + cfg.MULTIGRID.default_temporal_size // base_t) + print("Long cycle updates:") + print("\tbn_norm_type: {}".format(cfg.MODEL.backbone.bn_norm_type)) + if cfg.MODEL.backbone.bn_norm_type == "sub_batchnorm": + print("\tbn_num_splits: {}".format( + cfg.MODEL.backbone.bn_num_splits)) + print("\tTRAIN.batch_size[single card]: {}".format( + cfg.DATASET.batch_size)) + print("\tDATA.NUM_FRAMES x LONG_CYCLE_SAMPLING_RATE: {}x{}".format( + cfg.PIPELINE.train.decode_sampler.num_frames, + cfg.MULTIGRID.long_cycle_sampling_rate)) + print("\tDATA.train_crop_size: {}".format( + cfg.PIPELINE.train.transform[1]['MultiCrop']['target_size'])) + return cfg, True + else: + return cfg, False + + def get_long_cycle_schedule(self, cfg): + """ + Based on multigrid hyperparameters, define the schedule of a long cycle. + Args: + cfg (configs): configs that contains training and multigrid specific + hyperparameters. + Returns: + schedule (list): Specifies a list long cycle base shapes and their + corresponding training epochs. + """ + + steps = cfg.OPTIMIZER.learning_rate.steps + + default_size = float( + cfg.PIPELINE.train.decode_sampler.num_frames * + cfg.PIPELINE.train.transform[1]['MultiCrop']['target_size']** + 2) # 32 * 224 * 224 C*H*W + default_iters = steps[-1] # 196 + + # Get shapes and average batch size for each long cycle shape. + avg_bs = [] + all_shapes = [] + # for t_factor, s_factor in cfg.MULTIGRID.long_cycle_factors: + for item in cfg.MULTIGRID.long_cycle_factors: + t_factor, s_factor = item["value"] + base_t = int( + round(cfg.PIPELINE.train.decode_sampler.num_frames * t_factor)) + base_s = int( + round( + cfg.PIPELINE.train.transform[1]['MultiCrop']['target_size'] + * s_factor)) + if cfg.MULTIGRID.SHORT_CYCLE: + shapes = [ + [ + base_t, + cfg.MULTIGRID.default_crop_size * + cfg.MULTIGRID.short_cycle_factors[0], + ], + [ + base_t, + cfg.MULTIGRID.default_crop_size * + cfg.MULTIGRID.short_cycle_factors[1], + ], + [base_t, base_s], + ] #first two is short_cycle, last is the base long_cycle + else: + shapes = [[base_t, base_s]] + + # (T, S) -> (B, T, S) + shapes = [[ + int(round(default_size / (s[0] * s[1] * s[1]))), s[0], s[1] + ] for s in shapes] + avg_bs.append(np.mean([s[0] for s in shapes])) + all_shapes.append(shapes) + + # Get schedule regardless of cfg.MULTIGRID.epoch_factor. + total_iters = 0 + schedule = [] + for step_index in range(len(steps) - 1): + step_epochs = steps[step_index + 1] - steps[step_index] + + for long_cycle_index, shapes in enumerate(all_shapes): + #ensure each of 4 sequences run the same num of iters + cur_epochs = (step_epochs * avg_bs[long_cycle_index] / + sum(avg_bs)) + + # get cur_iters from cur_epochs + cur_iters = cur_epochs / avg_bs[long_cycle_index] + total_iters += cur_iters + schedule.append((step_index, shapes[-1], cur_epochs)) + + iter_saving = default_iters / total_iters # ratio between default iters and real iters + + final_step_epochs = cfg.OPTIMIZER.learning_rate.max_epoch - steps[-1] + + # We define the fine-tuning phase to have the same amount of iteration + # saving as the rest of the training. + #final_step_epochs / iter_saving make fine-tune having the same iters as training + ft_epochs = final_step_epochs / iter_saving * avg_bs[-1] + + # schedule.append((step_index + 1, all_shapes[-1][2], ft_epochs)) + schedule.append((step_index + 1, all_shapes[-1][-1], ft_epochs)) + + # Obtrain final schedule given desired cfg.MULTIGRID.epoch_factor. + x = (cfg.OPTIMIZER.learning_rate.max_epoch * + cfg.MULTIGRID.epoch_factor / sum(s[-1] for s in schedule)) + + final_schedule = [] + total_epochs = 0 + for s in schedule: + epochs = s[2] * x + total_epochs += epochs + final_schedule.append((s[0], s[1], int(round(total_epochs)))) + print_schedule(final_schedule) + return final_schedule + + +def print_schedule(schedule): + """ + Log schedule. + """ + print( + "Long_cycle_index\tBase_shape(bs_factor,temporal_size,crop_size)\tEpochs" + ) + for s in schedule: + print("{}\t\t\t{}\t\t\t\t\t{}".format(s[0], s[1], s[2])) + + +def get_current_long_cycle_shape(schedule, epoch): + """ + Given a schedule and epoch index, return the long cycle base shape. + Args: + schedule (configs): configs that contains training and multigrid specific + hyperparameters. + cur_epoch (int): current epoch index. + Returns: + shapes (list): A list describing the base shape in a long cycle: + [batch size relative to default, + number of frames, spatial dimension]. + """ + for s in schedule: + if epoch < s[-1]: + return s[1] + return schedule[-1][1] diff --git a/Bank_second_part/detect_process/paddlevideo/utils/multigrid/save_load_helper.py b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/save_load_helper.py new file mode 100644 index 0000000..94a52d5 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/save_load_helper.py @@ -0,0 +1,237 @@ +import os +import numpy as np +import paddle +import copy + + +def sub_to_normal_bn(sd): + """ + When save, Convert the Sub-BN paprameters to normal BN parameters in a state dict. + There are two copies of BN layers in a Sub-BN implementation: `bn.bn` and + `bn.split_bn`. `bn.split_bn` is used during training and + "compute_precise_bn". Before saving or evaluation, its stats are copied to + `bn.bn`. We rename `bn.bn` to `bn` and store it to be consistent with normal + BN layers. + Args: + sd (OrderedDict): a dict of parameters which might contain Sub-BN + parameters. + Returns: + new_sd (OrderedDict): a dict with Sub-BN parameters reshaped to + normal parameters. + """ + modifications = [ + ("bn.bn._mean", "bn._mean"), + ("bn.bn._variance", "bn._variance"), + ] + to_remove = ["bn.bn.", ".split_bn."] + key_list = list(sd.keys()) #odict_keys to list + for key in key_list: + for before, after in modifications: + if key.endswith(before): + new_key = key.split(before)[0] + after + sd[new_key] = sd.pop(key) + + for rm in to_remove: + if rm in key and key in sd: + del sd[key] + + +def normal_to_sub_bn(checkpoint_sd, model_sd): + """ + When load, Convert BN parameters to Sub-BN parameters if model contains Sub-BNs. + Args: + checkpoint_sd (OrderedDict): source dict of parameters. + model_sd (OrderedDict): target dict of parameters. + Returns: + new_sd (OrderedDict): converted dict of parameters. + """ + for key in model_sd: + if key not in checkpoint_sd: + # not to replace bn.weight and bn.bias + if "bn.split_bn." in key and "bn.weight" not in key and "bn.bias" not in key: + load_key = key.replace("bn.split_bn.", "bn.") + bn_key = key.replace("bn.split_bn.", "bn.bn.") + checkpoint_sd[key] = checkpoint_sd.pop(load_key) + checkpoint_sd[bn_key] = checkpoint_sd[key] + + # match the shape of bn.split_bn._xx + # model_sd: split_bn.rm.shape = num_feature*num_split + # checkpoint_sd: split_bn.rm.shape = bn.rm.shape = num_feature + for key in model_sd: + if key in checkpoint_sd: + model_blob_shape = model_sd[key].shape #bn.split_bn + c2_blob_shape = checkpoint_sd[key].shape #bn.bn + + if (len(model_blob_shape) == 1 and len(c2_blob_shape) == 1 + and model_blob_shape[0] > c2_blob_shape[0] + and model_blob_shape[0] % c2_blob_shape[0] == 0): + before_shape = checkpoint_sd[key].shape + checkpoint_sd[key] = np.concatenate( + [checkpoint_sd[key]] * + (model_blob_shape[0] // c2_blob_shape[0])) + if 'split_bn' not in key: #split_bn is excepted + print("{} {} -> {}".format(key, before_shape, + checkpoint_sd[key].shape)) + return checkpoint_sd + + +def mapping_opt_dict(opt_dict, model_key_list): + """ + Paddle Name schedule: conv_1.w -> conv_2.w + Sometimes: sub_bn -> bn + when re-build model, we desire the parameter name to be coincident, + but the parameters name index will be added, as conv_1 to conv_2, not conv_1. + It will raise error if we set old saved parameters to new created optimizer. + as conv_2 cannot find in state_dict(only conv_1). + Args: + opt_dict: optimizer state dict, including the name and value of parameters gradient. + model_key_list: the parameters name list of re-build model. + Return: optimizer state dict with modified keys + """ + def get_name_info(PNAME, PN_key_list, key_list): + min_index = float('inf') + max_index = 0 + for name in PN_key_list[1:]: + for key in key_list: + if name in key: + index = int(key.split('.')[0].split(name)[-1]) + if index < min_index: + min_index = index + if index > max_index: + max_index = index + num_name = max_index - min_index + 1 + PNAME[name].append((min_index, max_index, num_name)) + min_index = float('inf') + max_index = 0 + + PNAME = { + "LR_Scheduler": [], + "conv3d_": [], + "linear_": [], + "sub_batch_norm3d_": [], + "batch_norm3d_": [], + } + + pd_key_list = list(opt_dict.keys()) + print("The number of parameters in saved optimizer state dict = {}".format( + len(pd_key_list))) + print("The number of parameters in re-build model list = {}".format( + len(model_key_list))) + # 1 may be LR_Scheduler + PN_key_list = list(PNAME.keys()) + + # get the number of each PNAME + get_name_info(PNAME, PN_key_list, pd_key_list) + get_name_info(PNAME, PN_key_list, model_key_list) + print("[Parameters info] prefix: min_index, max_index, number_params: \n", + PNAME) + + # whether to change name of bn layer + change_name = False + if PNAME["sub_batch_norm3d_"][0][-1] == -float('inf'): + PN_key_list.remove("sub_batch_norm3d_") + if PNAME["sub_batch_norm3d_"][1][-1] != -float('inf'): + print( + "Optimizer state dict saved bn, but Re-build model use sub_bn, changed name!" + ) + change_name = True + else: + print("Optimizer state dict saved bn, and Re-build model use bn") + else: + PN_key_list.remove("batch_norm3d_") + if PNAME["sub_batch_norm3d_"][1][-1] == -float('inf'): + print( + "Optimizer state dict saved sub_bn, but Re-build model use bn, changed name!" + ) + change_name = True + else: + print( + "Optimizer state dict saved sub_bn, Re-build model use sub_bn") + + #update key name + # sub_bn -> bn name mapping, pre-define dict + change_dict = { + "sub_batch_norm3d_": "batch_norm3d_", + "batch_norm3d_": "sub_batch_norm3d_" + } + for key in pd_key_list: + for name in PN_key_list[1:]: + if key.startswith(name): + start = change_dict[name] if ( + change_name and "batch_norm" in name) else name + str_index = key.split('.')[0].split(name)[-1] + index = int(str_index) + new_index = str(index + + (PNAME[start][1][0] - PNAME[name][0][0])) + end = key.split('.')[-1] + update_key = start + new_index + '.' + end + opt_dict[update_key] = opt_dict.pop(key) + + return opt_dict + + +def subn_save(save_dir, name_prefix, epoch, video_model, optimizer): + if not os.path.isdir(save_dir): + os.makedirs(save_dir) + model_path = os.path.join(save_dir, name_prefix + "{:05d}".format(epoch)) + model_dict = video_model.state_dict() + sub_to_normal_bn(model_dict) + opti_dict = optimizer.state_dict() + paddle.save(model_dict, model_path + '.pdparams') + paddle.save(opti_dict, model_path + '.pdopt') + print('[Saved Epoch {} parameters and optimizer state ]'.format(epoch)) + + +def subn_load(model, ck_path, optimizer=None): + """ + Load the checkpoint from the given file. + Args: + model (model): model to load the weights from the checkpoint. + optimizer (optim, optional): optimizer to load the historical state. + ck_path (str): checkpoint path + Returns: + (int): the number of training epoch of the checkpoint. + """ + + assert os.path.exists(ck_path + ".pdparams"), \ + "Given dir {}.pdparams not exist.".format(ck_path) + print("load checkpint from {}.pdparams".format(ck_path)) + + model_dict = model.state_dict() + checkpoint_dict = paddle.load(ck_path + ".pdparams") + # checkpoint_dict = copy.deepcopy(checkpoint_dict_orig) #not modify when multi card + pre_train_dict = normal_to_sub_bn(checkpoint_dict, model_dict) + + # Match pre-trained weights that have same shape as current model. + pre_train_dict_match = { + k: v + for k, v in pre_train_dict.items() + if k in model_dict and tuple(v.shape) == tuple(model_dict[k].shape) + } + + # Weights that do not have match from the pre-trained model. + not_load_layers = [ + k for k in model_dict.keys() if k not in pre_train_dict_match.keys() + ] + # Log weights that are not loaded with the pre-trained weights. + if not_load_layers: + for k in not_load_layers: + if 'bn.weight' not in k and 'bn.bias' not in k: + print("Network weights {} not loaded.".format(k)) + + # Load pre-trained weights. + model.set_state_dict(pre_train_dict_match) + + if optimizer: + assert os.path.exists(ck_path + ".pdopt"), \ + "Given dir {}.pdopt not exist.".format(ck_path) + print("load checkpint from {}.pdopt".format(ck_path)) + opt_dict = paddle.load(ck_path + ".pdopt") + # get parameters that required gradient from re-build model + model_key_list = [] + for param in model.parameters(): + if param.stop_gradient == False: + model_key_list.append(param.name) + + new_opt_dict = mapping_opt_dict(opt_dict, model_key_list) + optimizer.set_state_dict(new_opt_dict) diff --git a/Bank_second_part/detect_process/paddlevideo/utils/multigrid/short_sampler.py b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/short_sampler.py new file mode 100644 index 0000000..0004dac --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/multigrid/short_sampler.py @@ -0,0 +1,147 @@ +from __future__ import print_function +from __future__ import division + +import numpy as np +import math + +from paddle.io import BatchSampler + +__all__ = ["DistributedShortSampler"] + + +class DistributedShortSampler(BatchSampler): + """Sampler that restricts data loading to a subset of the dataset. + In such case, each process can pass a DistributedBatchSampler instance + as a DataLoader sampler, and load a subset of the original dataset that + is exclusive to it. + .. note:: + Batch size is dynamic changed following short cycle schedule. + + Args: + dataset(paddle.io.Dataset): this could be a `paddle.io.Dataset` implement + or other python object which implemented + `__len__` for BatchSampler to get sample + number of data source. + batch_sizes(list): batch size list of one cycle. + num_replicas(int, optional): porcess number in distributed training. + If :attr:`num_replicas` is None, :attr:`num_replicas` will be + retrieved from :code:`paddle.fluid.dygraph.parallel.ParallenEnv`. + Default None. + rank(int, optional): the rank of the current process among :attr:`num_replicas` + processes. If :attr:`rank` is None, :attr:`rank` is retrieved from + :code:`paddle.fluid.dygraph.parallel.ParallenEnv`. Default None. + shuffle(bool): whther to shuffle indices order before genrating + batch indices. Default False. + drop_last(bool): whether drop the last incomplete batch dataset size + is not divisible by the batch size. Default False + """ + def __init__(self, + dataset, + batch_sizes, + num_replicas=None, + rank=None, + shuffle=False, + drop_last=False): + self.dataset = dataset + + assert any(isinstance(batch_size, int) and batch_size > 0 for batch_size in batch_sizes), \ + "batch_size should be a positive integer" + self.batch_sizes = batch_sizes + self.len_batch_sizes = len(self.batch_sizes) + assert isinstance(shuffle, bool), \ + "shuffle should be a boolean value" + self.shuffle = shuffle + assert isinstance(drop_last, bool), \ + "drop_last should be a boolean number" + + from paddle.distributed import ParallelEnv + + if num_replicas is not None: + assert isinstance(num_replicas, int) and num_replicas > 0, \ + "num_replicas should be a positive integer" + self.nranks = num_replicas + else: + self.nranks = ParallelEnv().nranks + + if rank is not None: + assert isinstance(rank, int) and rank >= 0, \ + "rank should be a non-negative integer" + self.local_rank = rank + else: + self.local_rank = ParallelEnv().local_rank + + self.drop_last = drop_last + self.epoch = 0 + self.num_samples = int(math.ceil(len(self.dataset) * 1.0 / self.nranks)) + self.total_size = self.num_samples * self.nranks + + def __iter__(self): + num_samples = len(self.dataset) + indices = np.arange(num_samples).tolist() + indices += indices[:(self.total_size - + len(indices))] #completion last iter + assert len(indices) == self.total_size + if self.shuffle: + np.random.RandomState(self.epoch).shuffle(indices) + self.epoch += 1 + + # subsample + def _get_indices_by_batch_size(indices): + total_batch_size = sum(self.batch_sizes) + subsampled_indices = [] + last_batch_size = self.total_size % ( + total_batch_size * self.nranks) #number samples of last batch + assert last_batch_size % self.nranks == 0 + last_local_batch_size = last_batch_size // self.nranks + + for i in range(self.local_rank * total_batch_size, + len(indices) - last_batch_size, + total_batch_size * self.nranks): + subsampled_indices.extend(indices[i:i + total_batch_size]) + + indices = indices[len(indices) - last_batch_size:] + subsampled_indices.extend( + indices[self.local_rank * + last_local_batch_size:(self.local_rank + 1) * + last_local_batch_size]) + return subsampled_indices + + if self.nranks > 1: + indices = _get_indices_by_batch_size(indices) + + assert len(indices) == self.num_samples #index length in each card + _sample_iter = iter(indices) + + batch_indices = [] + counter = 0 + batch_size = self.batch_sizes[0] + for idx in _sample_iter: + batch_indices.append( + (idx, counter % + self.len_batch_sizes)) #to be used in dataloader get_item + if len(batch_indices) == batch_size: + yield batch_indices + counter += 1 + batch_size = self.batch_sizes[counter % self.len_batch_sizes] + batch_indices = [] + if not self.drop_last and len(batch_indices) > 0: + yield batch_indices + + def __len__(self): + avg_batch_size = sum(self.batch_sizes) / float(self.len_batch_sizes) + if self.drop_last: + return int(np.floor(self.num_samples / avg_batch_size)) + else: + return int(np.ceil(self.num_samples / avg_batch_size)) + + def set_epoch(self, epoch): + """ + Sets the epoch number. When :attr:`shuffle=True`, this number is used + as seeds of random numbers. By default, users may not set this, all + replicas (workers) use a different random ordering for each epoch. + If set same number at each epoch, this sampler will yield the same + ordering at all epoches. + Arguments: + epoch (int): Epoch number. + """ + self.epoch = epoch diff --git a/Bank_second_part/detect_process/paddlevideo/utils/precise_bn.py b/Bank_second_part/detect_process/paddlevideo/utils/precise_bn.py new file mode 100644 index 0000000..c9fdd40 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/precise_bn.py @@ -0,0 +1,94 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 paddle +import itertools + +from paddlevideo.utils import get_logger + +logger = get_logger("paddlevideo") +""" +Implement precise bn, which is useful for improving accuracy. +""" + + +@paddle.no_grad() # speed up and save CUDA memory +def do_preciseBN(model, + data_loader, + parallel, + num_iters=200, + use_amp=False, + amp_level=None): + """ + Recompute and update the batch norm stats to make them more precise. During + training both BN stats and the weight are changing after every iteration, so + the running average can not precisely reflect the actual stats of the + current model. + In this function, the BN stats are recomputed with fixed weights, to make + the running average more precise. Specifically, it computes the true average + of per-batch mean/variance instead of the running average. + This is useful to improve validation accuracy. + Args: + model: the model whose bn stats will be recomputed + data_loader: an iterator. Produce data as input to the model + num_iters: number of iterations to compute the stats. + Return: + the model with precise mean and variance in bn layers. + """ + bn_layers_list = [ + m for m in model.sublayers() + if any((isinstance(m, bn_type) + for bn_type in (paddle.nn.BatchNorm1D, paddle.nn.BatchNorm2D, + paddle.nn.BatchNorm3D))) and m.training + ] + if len(bn_layers_list) == 0: + return + + # moving_mean=moving_mean*momentum+batch_mean*(1.−momentum) + # we set momentum=0. to get the true mean and variance during forward + momentum_actual = [bn._momentum for bn in bn_layers_list] + for bn in bn_layers_list: + bn._momentum = 0. + + running_mean = [paddle.zeros_like(bn._mean) + for bn in bn_layers_list] # pre-ignore + running_var = [paddle.zeros_like(bn._variance) for bn in bn_layers_list] + + ind = -1 + for ind, data in enumerate(itertools.islice(data_loader, num_iters)): + logger.info("Computing precise BN {} / {}...".format( + ind + 1, num_iters)) + + if use_amp: + with paddle.amp.auto_cast( + custom_black_list={"reduce_mean", + "conv3d"}, level=amp_level): + model(data, mode='train') + else: + model(data, mode='train') + + for i, bn in enumerate(bn_layers_list): + # Accumulates the bn stats. + running_mean[i] += (bn._mean - running_mean[i]) / (ind + 1) + running_var[i] += (bn._variance - running_var[i]) / (ind + 1) + + assert ind == num_iters - 1, ( + "update_bn_stats is meant to run for {} iterations, but the dataloader stops at {} iterations." + .format(num_iters, ind)) + + # Sets the precise bn stats. + for i, bn in enumerate(bn_layers_list): + bn._mean.set_value(running_mean[i]) + bn._variance.set_value(running_var[i]) + bn._momentum = momentum_actual[i] diff --git a/Bank_second_part/detect_process/paddlevideo/utils/profiler.py b/Bank_second_part/detect_process/paddlevideo/utils/profiler.py new file mode 100644 index 0000000..629ef4e --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/profiler.py @@ -0,0 +1,128 @@ +# copyright (c) 2021 PaddlePaddle Authors. All Rights Reserve. +# +# 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 sys +import paddle.profiler as profiler + +# A global variable to record the number of calling times for profiler +# functions. It is used to specify the tracing range of training steps. +_profiler_step_id = 0 + +# A global variable to avoid parsing from string every time. +_profiler_options = None +_prof = None + +class ProfilerOptions(object): + ''' + Use a string to initialize a ProfilerOptions. + The string should be in the format: "key1=value1;key2=value;key3=value3". + For example: + "profile_path=model.profile" + "batch_range=[50, 60]; profile_path=model.profile" + "batch_range=[50, 60]; tracer_option=OpDetail; profile_path=model.profile" + + ProfilerOptions supports following key-value pair: + batch_range - a integer list, e.g. [100, 110]. + state - a string, the optional values are 'CPU', 'GPU' or 'All'. + sorted_key - a string, the optional values are 'calls', 'total', + 'max', 'min' or 'ave. + tracer_option - a string, the optional values are 'Default', 'OpDetail', + 'AllOpDetail'. + profile_path - a string, the path to save the serialized profile data, + which can be used to generate a timeline. + exit_on_finished - a boolean. + ''' + + def __init__(self, options_str): + assert isinstance(options_str, str) + + self._options = { + 'batch_range': [10, 20], + 'state': 'All', + 'sorted_key': 'total', + 'tracer_option': 'Default', + 'profile_path': '/tmp/profile', + 'exit_on_finished': True, + 'timer_only': True + } + self._parse_from_string(options_str) + + def _parse_from_string(self, options_str): + for kv in options_str.replace(' ', '').split(';'): + key, value = kv.split('=') + if key == 'batch_range': + value_list = value.replace('[', '').replace(']', '').split(',') + value_list = list(map(int, value_list)) + if len(value_list) >= 2 and value_list[0] >= 0 and value_list[ + 1] > value_list[0]: + self._options[key] = value_list + elif key == 'exit_on_finished': + self._options[key] = value.lower() in ("yes", "true", "t", "1") + elif key in [ + 'state', 'sorted_key', 'tracer_option', 'profile_path' + ]: + self._options[key] = value + elif key == 'timer_only': + self._options[key] = value + + def __getitem__(self, name): + if self._options.get(name, None) is None: + raise ValueError( + "ProfilerOptions does not have an option named %s." % name) + return self._options[name] + + +def add_profiler_step(options_str=None): + ''' + Enable the operator-level timing using PaddlePaddle's profiler. + The profiler uses a independent variable to count the profiler steps. + One call of this function is treated as a profiler step. + Args: + profiler_options - a string to initialize the ProfilerOptions. + Default is None, and the profiler is disabled. + ''' + if options_str is None: + return + + global _prof + global _profiler_step_id + global _profiler_options + + if _profiler_options is None: + _profiler_options = ProfilerOptions(options_str) + # profile : https://www.paddlepaddle.org.cn/documentation/docs/zh/guides/performance_improving/profiling_model.html#chakanxingnengshujudetongjibiaodan + # timer_only = True only the model's throughput and time overhead are displayed + # timer_only = False calling summary can print a statistical form that presents performance data from different perspectives. + # timer_only = False the output Timeline information can be found in the profiler_log directory + if _prof is None: + _timer_only = str(_profiler_options['timer_only']) == str(True) + _prof = profiler.Profiler( + scheduler = (_profiler_options['batch_range'][0], _profiler_options['batch_range'][1]), + on_trace_ready = profiler.export_chrome_tracing('./profiler_log'), + timer_only = _timer_only) + _prof.start() + else: + _prof.step() + + if _profiler_step_id == _profiler_options['batch_range'][1]: + _prof.stop() + _prof.summary( + op_detail=True, + thread_sep=False, + time_unit='ms') + _prof = None + if _profiler_options['exit_on_finished']: + sys.exit(0) + + _profiler_step_id += 1 diff --git a/Bank_second_part/detect_process/paddlevideo/utils/record.py b/Bank_second_part/detect_process/paddlevideo/utils/record.py new file mode 100644 index 0000000..4aad434 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/record.py @@ -0,0 +1,163 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 datetime +from collections import OrderedDict + +import paddle + +from .logger import coloring, get_logger + +logger = get_logger("paddlevideo") + +__all__ = ['AverageMeter', 'build_record', 'log_batch', 'log_epoch'] + + +def build_record(cfg): + record_list = [ + ("loss", AverageMeter('loss', '7.5f')), + ("lr", AverageMeter('lr', 'f', need_avg=False)), + ] + if 'Recognizer1D' in cfg.framework: #TODO: required specify str in framework + record_list.append(("hit_at_one", AverageMeter("hit_at_one", '.5f'))) + record_list.append(("perr", AverageMeter("perr", '.5f'))) + record_list.append(("gap", AverageMeter("gap", '.5f'))) + elif 'Recognizer' in cfg.framework: + record_list.append(("top1", AverageMeter("top1", '.5f'))) + record_list.append(("top5", AverageMeter("top5", '.5f'))) + elif 'FastRCNN' in cfg.framework: + record_list.append( + ("recall@thr=0.5", AverageMeter("recall@thr=0.5", '.5f'))) + record_list.append(("prec@thr=0.5", AverageMeter("prec@thr=0.5", + '.5f'))) + record_list.append(("recall@top3", AverageMeter("recall@top3", '.5f'))) + record_list.append(("prec@top3", AverageMeter("prec@top3", '.5f'))) + record_list.append(("recall@top5", AverageMeter("recall@top5", '.5f'))) + record_list.append(("prec@top5", AverageMeter("prec@top5", '.5f'))) + record_list.append(("mAP@0.5IOU", AverageMeter("mAP@0.5IOU", '.5f'))) + elif 'DepthEstimator' in cfg.framework: + record_list.append(("abs_rel", AverageMeter("abs_rel", '.5f'))) + record_list.append(("sq_rel", AverageMeter("sq_rel", '.5f'))) + record_list.append(("rmse", AverageMeter("rmse", '.5f'))) + record_list.append(("rmse_log", AverageMeter("rmse_log", '.5f'))) + record_list.append(("a1", AverageMeter("a1", '.5f'))) + record_list.append(("a2", AverageMeter("a2", '.5f'))) + record_list.append(("a3", AverageMeter("a3", '.5f'))) + record_list.append(("losses_day", AverageMeter("losses_day", '.5f'))) + record_list.append(("losses_night", AverageMeter("losses_night", + '.5f'))) + elif 'MSTCN' in cfg.framework or 'ASRF' in cfg.framework: + record_list.append(("F1@0.50", AverageMeter("F1@0.50", '.5f'))) + + elif 'YOWOLocalizer' in cfg.framework: + record_list.append(("nCorrect", AverageMeter('nCorrect', '.1f'))) + record_list.append(("fscore", AverageMeter("fscore", '.5f'))) + + record_list.append(("batch_time", AverageMeter('batch_cost', '.5f'))) + record_list.append(("reader_time", AverageMeter('reader_cost', '.5f'))) + record_list = OrderedDict(record_list) + return record_list + + +class AverageMeter(object): + """ + Computes and stores the average and current value + """ + def __init__(self, name='', fmt='f', need_avg=True): + self.name = name + self.fmt = fmt + self.need_avg = need_avg + self.reset() + + def reset(self): + """ reset """ + self.val = 0 + self.avg = 0 + self.sum = 0 + self.count = 0 + + def update(self, val, n=1): + """ update """ + if isinstance(val, paddle.Tensor): + val = float(val) + self.val = val + self.sum += val * n + self.count += n + self.avg = self.sum / self.count + + @property + def total(self): + return '{self.name}_sum: {self.sum:{self.fmt}}'.format(self=self) + + @property + def total_minute(self): + return '{self.name}_sum: {s:{self.fmt}} min'.format(s=self.sum / 60, + self=self) + + @property + def mean(self): + return '{self.name}_avg: {self.avg:{self.fmt}}'.format( + self=self) if self.need_avg else '' + + @property + def value(self): + return '{self.name}: {self.val:{self.fmt}}'.format(self=self) + + +def log_batch(metric_list, + batch_id, + epoch_id, + total_epoch, + mode, + ips, + eta_sec: int = None): + batch_cost = str(metric_list['batch_time'].value) + ' sec,' + reader_cost = str(metric_list['reader_time'].value) + ' sec,' + + metric_values = [] + for m in metric_list: + if not (m == 'batch_time' or m == 'reader_time'): + metric_values.append(metric_list[m].value) + metric_str = ' '.join([str(v) for v in metric_values]) + epoch_str = "epoch:[{:>3d}/{:<3d}]".format(epoch_id, total_epoch) + step_str = "{:s} step:{:<4d}".format(mode, batch_id) + if eta_sec is not None: + eta_str = "eta: {:s}".format( + str(datetime.timedelta(seconds=int(eta_sec)))) + else: + eta_str = '' + logger.info("{:s} {:s} {:s} {:s} {:s} {} {:s}".format( + coloring(epoch_str, "HEADER") if batch_id == 0 else epoch_str, + coloring(step_str, "PURPLE"), coloring(metric_str, 'OKGREEN'), + coloring(batch_cost, "OKGREEN"), coloring(reader_cost, 'OKGREEN'), ips, + eta_str)) + + +def log_epoch(metric_list, epoch, mode, ips): + batch_cost = 'avg_' + str(metric_list['batch_time'].value) + ' sec,' + reader_cost = 'avg_' + str(metric_list['reader_time'].value) + ' sec,' + batch_sum = str(metric_list['batch_time'].total) + ' sec,' + + metric_values = [] + for m in metric_list: + if not (m == 'batch_time' or m == 'reader_time'): + metric_values.append(metric_list[m].mean) + metric_str = ' '.join([str(v) for v in metric_values]) + + end_epoch_str = "END epoch:{:<3d}".format(epoch) + + logger.info("{:s} {:s} {:s} {:s} {:s} {:s} {}".format( + coloring(end_epoch_str, "RED"), coloring(mode, "PURPLE"), + coloring(metric_str, "OKGREEN"), coloring(batch_cost, "OKGREEN"), + coloring(reader_cost, "OKGREEN"), coloring(batch_sum, "OKGREEN"), ips)) diff --git a/Bank_second_part/detect_process/paddlevideo/utils/registry.py b/Bank_second_part/detect_process/paddlevideo/utils/registry.py new file mode 100644 index 0000000..81b76bd --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/registry.py @@ -0,0 +1,96 @@ +# 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. + + +class Registry(object): + """ + The registry that provides name -> object mapping, to support third-party users' custom modules. + + To register an object: + + .. code-block:: python + + BACKBONES = Registry('backbone') + @BACKBONES.register() + class ResNet: + pass + Or: + .. code-block:: python + + BACKBONES = Registry('backbone') + class ResNet: + pass + BACKBONES.register(ResNet) + + Usage: To build a module. + + .. code-block:: python + backbone_name = "ResNet" + b = BACKBONES.get(backbone_name)() + + """ + def __init__(self, name): + """ + Args: + name (str): the name of this registry + """ + self._name = name + self._obj_map = {} + + def __contains__(self, key): + return self._obj_map.get(key) is not None + + def _do_register(self, name, obj): + assert ( + name not in self._obj_map + ), "An object named '{}' was already registered in '{}' registry!".format( + name, self._name) + self._obj_map[name] = obj + + def register(self, obj=None, name=None): + """ + Register the given object under the the name `obj.__name__`. + Can be used as either a decorator or not. See docstring of this class for usage. + """ + if obj is None: + # used as a decorator + def deco(func_or_class, name=name): + if name is None: + name = func_or_class.__name__ + self._do_register(name, func_or_class) + return func_or_class + + return deco + + # used as a function call + if name is None: + name = obj.__name__ + self._do_register(name, obj) + + def get(self, name): + """Get the registry record. + + Args: + name (str): The class name. + + Returns: + ret: The class. + """ + ret = self._obj_map.get(name) + if ret is None: + raise KeyError( + "No object named '{}' found in '{}' registry!".format( + name, self._name)) + + return ret diff --git a/Bank_second_part/detect_process/paddlevideo/utils/save_load.py b/Bank_second_part/detect_process/paddlevideo/utils/save_load.py new file mode 100644 index 0000000..10bb5f0 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/utils/save_load.py @@ -0,0 +1,289 @@ +# 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 time + +import paddle +import paddle.nn.functional as F +from paddlevideo.utils import get_logger, main_only +from tqdm import tqdm +import numpy as np +from scipy import ndimage + + +def pretrain_swin_param_trans(model, state_dicts): + # delete classifier's params + if 'head.fc' + '.weight' in state_dicts: + del state_dicts['head.fc' + '.weight'] + if 'head.fc' + '.bias' in state_dicts: + del state_dicts['head.fc' + '.bias'] + + state_dicts = { + k.replace('backbone.', ''): v + for k, v in state_dicts.items() + } + + if len(state_dicts) == len(model.state_dict()): + print("Load 3D weights") + return state_dicts + + print("Load 2D weights") + relative_position_index_keys = [ + k for k in state_dicts.keys() if "relative_position_index" in k + ] + for k in relative_position_index_keys: + del state_dicts[k] + + # delete attn_mask since we always re-init it + attn_mask_keys = [k for k in state_dicts.keys() if "attn_mask" in k] + for k in attn_mask_keys: + del state_dicts[k] + + state_dicts['patch_embed.proj.weight'] = state_dicts[ + 'patch_embed.proj.weight'].unsqueeze(2).tile( + [1, 1, model.patch_size[0], 1, 1]) / model.patch_size[0] + + # bicubic interpolate relative_position_bias_table if not match + relative_position_bias_table_keys = [ + k for k in state_dicts.keys() if "relative_position_bias_table" in k + ] + total_len = len(relative_position_bias_table_keys) + with tqdm(total=total_len, + position=1, + bar_format='{desc}', + desc="Loading weights") as desc: + for key in tqdm(relative_position_bias_table_keys, + total=total_len, + position=0): + relative_position_bias_table_pretrained = state_dicts[key] + relative_position_bias_table_current = model.state_dict()[key] + L1, nH1 = relative_position_bias_table_pretrained.shape + L2, nH2 = relative_position_bias_table_current.shape + L2 = (2 * model.window_size[1] - 1) * (2 * model.window_size[2] - 1) + wd = model.window_size[0] + if nH1 != nH2: + desc.set_description(f"Error in loading {key}, skip") + else: + if L1 != L2: + S1 = int(L1**0.5) + relative_position_bias_table_pretrained_resized = paddle.nn.functional.interpolate( + relative_position_bias_table_pretrained.transpose( + [1, 0]).reshape([1, nH1, S1, S1]), + size=(2 * model.window_size[1] - 1, + 2 * model.window_size[2] - 1), + mode='bicubic') + relative_position_bias_table_pretrained = relative_position_bias_table_pretrained_resized.reshape( + [nH2, L2]).transpose([1, 0]) + desc.set_description(f"Loading {key}") + state_dicts[key] = relative_position_bias_table_pretrained.tile( + [2 * wd - 1, 1]) + time.sleep(0.01) + ret_str = "loading {:<20d} weights completed.".format( + len(model.state_dict())) + desc.set_description(ret_str) + return state_dicts + + +def pretrain_vit_param_trans(model, state_dicts, num_patches, num_seg, + attention_type): + """ + Convert ViT's pre-trained model parameters to a parameter dictionary that matches the existing model + """ + if 'head' + '.weight' in state_dicts: + del state_dicts['head' + '.weight'] + if 'head' + '.bias' in state_dicts: + del state_dicts['head' + '.bias'] + + total_len = len(model.state_dict()) + if num_patches + 1 != state_dicts['pos_embed'].shape[1]: # when + pos_embed = state_dicts['pos_embed'] + cls_pos_embed = paddle.to_tensor( + pos_embed[0, 0, :]).unsqueeze(0).unsqueeze(1) + other_pos_embed = paddle.to_tensor(pos_embed[0, 1:, :]) + gs_new = int(np.sqrt(num_patches)) + gs_old = int(np.sqrt(other_pos_embed.shape[0])) + zoom = (gs_new / gs_old, gs_new / gs_old, 1) + other_pos_embed = paddle.reshape(other_pos_embed, [gs_old, gs_old, -1]) + other_pos_embed = ndimage.zoom(other_pos_embed, zoom, order=1) + other_pos_embed = paddle.to_tensor(other_pos_embed) + new_pos_embed = paddle.reshape(other_pos_embed, [1, num_patches, -1]) + new_pos_embed = paddle.concat((cls_pos_embed, new_pos_embed), axis=1) + state_dicts['pos_embed'] = new_pos_embed + time.sleep(0.01) + + if 'time_embed' in state_dicts and num_seg != state_dicts[ + 'time_embed'].shape[1]: + time_embed = state_dicts['time_embed'].transpose((0, 2, 1)).unsqueeze(0) + new_time_embed = F.interpolate(time_embed, + size=(time_embed.shape[-2], num_seg), + mode='nearest') + state_dicts['time_embed'] = new_time_embed.squeeze(0).transpose( + (0, 2, 1)) + time.sleep(0.01) + with tqdm(total=total_len, + position=1, + bar_format='{desc}', + desc="Loading weights") as desc: + if attention_type == 'divided_space_time': + new_state_dicts = state_dicts.copy() + for key in tqdm(state_dicts): + if 'blocks' in key and 'attn' in key: + desc.set_description("Loading %s" % key) + new_key = key.replace('attn', 'temporal_attn') + if not new_key in state_dicts: + new_state_dicts[new_key] = state_dicts[key] + else: + new_state_dicts[new_key] = state_dicts[new_key] + if 'blocks' in key and 'norm1' in key: + desc.set_description("Loading %s" % key) + new_key = key.replace('norm1', 'temporal_norm1') + if not new_key in state_dicts: + new_state_dicts[new_key] = state_dicts[key] + else: + new_state_dicts[new_key] = state_dicts[new_key] + time.sleep(0.01) + elif attention_type == 'space_only': # tokenshift raw vit + new_state_dicts = state_dicts.copy() + + ret_str = "loading {:<20d} weights completed.".format( + len(model.state_dict())) + desc.set_description(ret_str) + return new_state_dicts + + +def pretrain_resnet18_param_trans(model, loaded_dict): + encoder_dict = model.encoder.state_dict() + pose_encoder_dict = model.pose_encoder.state_dict() + + names = ['encoder.', 'encoder_day.', 'encoder_night.'] + for name in names: + total_len = len(loaded_dict.items()) + with tqdm(total=total_len, + position=1, + bar_format='{desc}', + desc="Loading weights") as desc: + for key, value in tqdm(loaded_dict.items(), + total=total_len, + position=0): + key = str(name + key) + if key in encoder_dict: + encoder_dict[key] = value + desc.set_description('Loading %s' % key) + time.sleep(0.01) + + num_input_images = 2 + loaded_dict['conv1.weight'] = paddle.concat( + [loaded_dict['conv1.weight']] * num_input_images, 1) / num_input_images + total_len = len(loaded_dict.items()) + with tqdm(total=total_len, + position=1, + bar_format='{desc}', + desc="Loading weights") as desc: + for name, value in tqdm(loaded_dict.items(), + total=total_len, + position=0): + name = str('encoder.' + name) + if name in pose_encoder_dict: + pose_encoder_dict[name] = value + desc.set_description('Loading %s' % key) + time.sleep(0.01) + ret_str = "loading {:<20d} weights completed.".format( + len(model.state_dict())) + desc.set_description(ret_str) + return encoder_dict, pose_encoder_dict + + +#XXX(shipping): maybe need load N times because of different cards have different params. +@main_only +def load_ckpt(model, weight_path, **kargs): + """ + 1. Load pre-trained model parameters + 2. Extract and convert from the pre-trained model to the parameters + required by the existing model + 3. Load the converted parameters of the existing model + """ + #model.set_state_dict(state_dict) + + if not osp.isfile(weight_path): + raise IOError(f'{weight_path} is not a checkpoint file') + #state_dicts = load(weight_path) + + logger = get_logger("paddlevideo") + state_dicts = paddle.load(weight_path) + if 'ResnetEncoder' in str(model): + encoder_dict, pose_encoder_dict = pretrain_resnet18_param_trans( + model, state_dicts) + model.encoder.load_dict(encoder_dict) + model.pose_encoder.load_dict(pose_encoder_dict) + tmp = model.state_dict() + elif "VisionTransformer" in str(model): # For TimeSformer case + tmp = pretrain_vit_param_trans(model, state_dicts, kargs['num_patches'], + kargs['num_seg'], + kargs['attention_type']) + elif 'SwinTransformer3D' in str(model): + tmp = pretrain_swin_param_trans(model, state_dicts) + else: + tmp = {} + total_len = len(model.state_dict()) + with tqdm(total=total_len, + position=1, + bar_format='{desc}', + desc="Loading weights") as desc: + for item in tqdm(model.state_dict(), total=total_len, position=0): + name = item + desc.set_description('Loading %s' % name) + if name not in state_dicts: # Convert from non-parallel model + if str('backbone.' + name) in state_dicts: + tmp[name] = state_dicts['backbone.' + name] + else: # Convert from parallel model + tmp[name] = state_dicts[name] + time.sleep(0.01) + ret_str = "loading {:<20d} weights completed.".format( + len(model.state_dict())) + desc.set_description(ret_str) + model.set_state_dict(tmp) + + +def mkdir(dir): + if not os.path.exists(dir): + # avoid error when train with multiple gpus + try: + os.makedirs(dir) + except: + pass + + +def _extract_student_weights(all_params, student_prefix="Student."): + s_params = { + key[len(student_prefix):]: all_params[key] + for key in all_params if student_prefix in key + } + return s_params + + +@main_only +def save(obj, path, save_student_model=False): + if save_student_model: + s_params = _extract_student_weights(obj) + student_path = path.replace(".pdparams", "_student.pdparams") + if len(s_params) > 0: + paddle.save(s_params, student_path) + paddle.save(obj, path) + + +def load(file_name): + if not osp.isfile(file_name): + raise IOError(f'{file_name} not exist') + return paddle.load(file_name) diff --git a/Bank_second_part/detect_process/paddlevideo/version.py b/Bank_second_part/detect_process/paddlevideo/version.py new file mode 100644 index 0000000..b5b7f48 --- /dev/null +++ b/Bank_second_part/detect_process/paddlevideo/version.py @@ -0,0 +1,16 @@ +# 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. + +__all__ = ["paddlevideo_version"] +paddlevideo_version = "0.0.1" diff --git a/Bank_second_part/detect_process/personDet.py b/Bank_second_part/detect_process/personDet.py new file mode 100644 index 0000000..0cef736 --- /dev/null +++ b/Bank_second_part/detect_process/personDet.py @@ -0,0 +1,42 @@ + +def analysis_yolov8(frame, model_coco,confidence_set): + + # 第一步:用COCO数据集推理 + results_coco = model_coco(frame) + + re_list = [] + + if results_coco: + + for r in results_coco: + + boxes = r.boxes + + idx = 0 + + for box in boxes: + + idx += 1 + b = box.xyxy[0] # get box coordinates in (top, left, bottom, right) format + c = box.cls + + # 保存标签和坐标值作为返回结果 + blist = b.tolist() + labels_name = model_coco.names[int(c)] + + confidence = float(box.conf) + + confidence = round(confidence, 2) + + # 过滤置信度以下目标 + if confidence < confidence_set: + + continue + + if labels_name == 'person': + # 一个结果字典 + re_dict = {labels_name:blist} + + re_list.append(re_dict) + + return re_list diff --git a/Bank_second_part/detect_process/tools.py b/Bank_second_part/detect_process/tools.py deleted file mode 100644 index 8d9af60..0000000 --- a/Bank_second_part/detect_process/tools.py +++ /dev/null @@ -1,212 +0,0 @@ -import cv2 -import os - -class Process_tools(): - - # 图像文件夹 - def get_video_list(path): - video_ext = [".mp4", ".avi",".MP4"] - video_names = [] - for maindir, subdir, file_name_list in os.walk(path): - for filename in file_name_list: - apath = os.path.join(maindir, filename) - ext = os.path.splitext(apath)[1] - if ext in video_ext: - video_names.append(apath) - return video_names - - - # 截取裁剪需要的视频帧 - def save_seg_video(video_name,frameToStart,frametoStop,videoWriter,bbox): - - cap = cv2.VideoCapture(video_name) - count = 0 - while True: - - success, frame = cap.read() - - if success: - - count += 1 - if count <= frametoStop and count > frameToStart: # 选取起始帧 - print('correct= ', count) - - #裁剪视频画面 - frame_target = frame[int(bbox[1]):int(bbox[3]), int(bbox[0]):int(bbox[2])] # (split_height, split_width) - - videoWriter.write(frame_target) - - if not success or count >= frametoStop: - break - - print('end') - - - # 获得字典中所有values值(这个值是列表) - def get_dict_values(lst): - """ - 获取列表中所有字典的 values 值(如果值是列表) - - 参数: - lst: 包含字典的列表 - - 返回值: - values: 包含所有字典的 values 值的列表(如果值是列表) - """ - return [value for dictionary in lst for value in dictionary.values() if isinstance(value, list)] - - - - # 解析检测后的结果,为检测后的结果排序 - def analysis_sort_list(result_dict): - - # print('result_dict:',result_dict) - - # 获得检测列表 - re_list = result_dict['start_bbox'] - # print('re_list:',re_list) - - # 获得列表中所有字典的values值 - re_bbox_list = Process_tools.get_dict_values(re_list) - - # 为检测出来的标注框排序 - sorted_lst = sorted(re_bbox_list, key=lambda x: x[0]) - - return sorted_lst - - - #对比重叠率高的两个部分,并结合标注框,保存最大的标注框 - def contrast_bbox(e_bbox,r_bbox): - - e_bbox_min = e_bbox[:2] - r_bbox_min = r_bbox[:2] - - bbox_min = [min(x, y) for x, y in zip(e_bbox_min, r_bbox_min)] - - e_bbox_max = e_bbox[-2:] - r_bbox_max = r_bbox[-2:] - - bbox_max = [max(x, y) for x, y in zip(e_bbox_max, r_bbox_max)] - - bbox = bbox_min + bbox_max - - return bbox - - - - # 解析result_list列表 - def analysis_re01_list(example_dict,result_dict): - - # 第一次检测到目标的帧率和信息 - example_dict_fps = list(example_dict.keys())[0] - example_sorted_lst = Process_tools.analysis_sort_list(example_dict) - - # 当前帧检测结果中所有的检测结果数值 - re_dict_fps = list(result_dict.keys())[0] - re_dict_sorted_lst = Process_tools.analysis_sort_list(result_dict) - - # 保存前后帧率连续的范围、筛选出相同的部分 - cut_list = [] - example_temp = [] - re_temp = [] - - for i,ex_bbox in enumerate(example_sorted_lst): - - for j,re_bbox in enumerate(re_dict_sorted_lst): - - iou = Process_tools.calculate_iou(box1=ex_bbox, box2=re_bbox) - - # print(iou) - - if iou > 0: - - bbox = Process_tools.contrast_bbox(e_bbox=ex_bbox,r_bbox=re_bbox) - - cut_list.append({i:bbox}) - example_temp.append(ex_bbox) - re_temp.append(re_bbox) - - break - - else: - continue - - example_sorted_lst = [item for item in example_sorted_lst if item not in example_temp] - re_dict_sorted_lst = [item for item in re_dict_sorted_lst if item not in re_temp] - - return cut_list,example_sorted_lst,re_dict_sorted_lst - - - # 计算前后帧率重叠范围 - def calculate_iou(box1, box2): - """ - 计算两个边界框之间的IoU值 - - 参数: - box1: 边界框1的坐标(x1, y1, x2, y2) - box2: 边界框2的坐标(x1, y1, x2, y2) - - 返回值: - iou: 两个边界框之间的IoU值 - """ - x1 = max(box1[0], box2[0]) - y1 = max(box1[1], box2[1]) - x2 = min(box1[2], box2[2]) - y2 = min(box1[3], box2[3]) - - # 计算交集区域面积 - intersection_area = max(0, x2 - x1 + 1) * max(0, y2 - y1 + 1) - - # 计算边界框1和边界框2的面积 - box1_area = (box1[2] - box1[0] + 1) * (box1[3] - box1[1] + 1) - box2_area = (box2[2] - box2[0] + 1) * (box2[3] - box2[1] + 1) - - # 计算并集区域面积 - union_area = box1_area + box2_area - intersection_area - - # 计算IoU值 - iou = intersection_area / union_area - - return iou - - def para_correction(images_size,bbox,dertpara): - - ''' - 修正检测后标注框过小的情况,如果有修正参数则使用修正参数,如果没有就按照坐标值扩大两倍 - - ''' - - if dertpara: - pass - else: - w = (bbox[2] - bbox[0]) /2 - h = (bbox[3] - bbox[1]) /2 - - bbox_extand_list_x = [bbox[0] - w,bbox[2] + w] - bbox_extand_list_y = [bbox[1] - h,bbox[3] + h] - - bbox_list_x = Process_tools.contrast(size=images_size[0],bbox_extand_list=bbox_extand_list_x) - bbox_list_y = Process_tools.contrast(size=images_size[1],bbox_extand_list=bbox_extand_list_y) - - bbox_list = bbox_list_x + bbox_list_y - - return bbox_list - - - def contrast(size,bbox_extand_list): - - ''' - 对比数值是否在这个范围内 - ''' - - bbox_list = [] - - for x in bbox_extand_list: - - if x in range(size): - bbox_list.append(x) - if x > size: - bbox_list.append(size) - if x < 0: - bbox_list.append(0) - return bbox_list \ No newline at end of file diff --git a/Bank_second_part/detect_process/tools/__init__.py b/Bank_second_part/detect_process/tools/__init__.py new file mode 100644 index 0000000..e8d173d --- /dev/null +++ b/Bank_second_part/detect_process/tools/__init__.py @@ -0,0 +1,19 @@ +# 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. + +__all__ = ['utils', 'PaddleVideo', 'ava_predict'] + +from . import utils +from .wheel import PaddleVideo +from . import ava_predict diff --git a/Bank_second_part/detect_process/tools/__pycache__/__init__.cpython-310.pyc b/Bank_second_part/detect_process/tools/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3988193eadf1fabc28be7beb219b7bc2f65b49ee GIT binary patch literal 286 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/tools/__pycache__/utils.cpython-310.pyc b/Bank_second_part/detect_process/tools/__pycache__/utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b17058fbf52c63a1ce187104b68748d1124fb4d8 GIT binary patch literal 42787 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 literal 0 HcmV?d00001 diff --git a/Bank_second_part/detect_process/tools/ava_predict.py b/Bank_second_part/detect_process/tools/ava_predict.py new file mode 100644 index 0000000..5d333a2 --- /dev/null +++ b/Bank_second_part/detect_process/tools/ava_predict.py @@ -0,0 +1,509 @@ +# copyright (c) 2020 PaddlePaddle Authors. All Rights Reserve. +# +# 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 paddle +import os, sys +import copy as cp +import cv2 +import math +try: + import ppdet +except ImportError as e: + print( + f"Warning! {e}, [paddledet] package and it's dependencies is required for AVA." + ) + +__dir__ = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.abspath(os.path.join(__dir__, '../'))) + +from paddlevideo.modeling.builder import build_model +from paddlevideo.utils import get_config +from paddlevideo.loader.builder import build_dataloader, build_dataset, build_pipeline +from paddlevideo.metrics.ava_utils import read_labelmap + +import time +from os import path as osp +import numpy as np +from paddlevideo.utils import get_config +import pickle + +from paddlevideo.utils import (get_logger, load, mkdir, save) +import shutil + +FONTFACE = cv2.FONT_HERSHEY_DUPLEX +FONTSCALE = 0.5 +FONTCOLOR = (255, 255, 255) # BGR, white +MSGCOLOR = (128, 128, 128) # BGR, gray +THICKNESS = 1 +LINETYPE = 1 + + +def hex2color(h): + """Convert the 6-digit hex string to tuple of 3 int value (RGB)""" + return (int(h[:2], 16), int(h[2:4], 16), int(h[4:], 16)) + + +plate_blue = '03045e-023e8a-0077b6-0096c7-00b4d8-48cae4' +plate_blue = plate_blue.split('-') +plate_blue = [hex2color(h) for h in plate_blue] +plate_green = '004b23-006400-007200-008000-38b000-70e000' +plate_green = plate_green.split('-') +plate_green = [hex2color(h) for h in plate_green] + + +def abbrev(name): + """Get the abbreviation of label name: + 'take (an object) from (a person)' -> 'take ... from ...' + """ + while name.find('(') != -1: + st, ed = name.find('('), name.find(')') + name = name[:st] + '...' + name[ed + 1:] + return name + + +# annotations is pred results +def visualize(frames, annotations, plate=plate_blue, max_num=5): + """Visualize frames with predicted annotations. + Args: + frames (list[np.ndarray]): Frames for visualization, note that + len(frames) % len(annotations) should be 0. + annotations (list[list[tuple]]): The predicted results. + plate (str): The plate used for visualization. Default: plate_blue. + max_num (int): Max number of labels to visualize for a person box. + Default: 5,目前不能大于5. + Returns: + list[np.ndarray]: Visualized frames. + """ + + assert max_num + 1 <= len(plate) + plate = [x[::-1] for x in plate] + frames_ = cp.deepcopy(frames) + nf, na = len(frames), len(annotations) + assert nf % na == 0 + nfpa = len(frames) // len(annotations) + anno = None + h, w, _ = frames[0].shape + # proposals被归一化需要还原真实坐标值 + scale_ratio = np.array([w, h, w, h]) + + for i in range(na): + anno = annotations[i] + if anno is None: + continue + for j in range(nfpa): + ind = i * nfpa + j + frame = frames_[ind] + for ann in anno: + box = ann[0] + label = ann[1] + if not len(label): + continue + score = ann[2] + box = (box * scale_ratio).astype(np.int64) + st, ed = tuple(box[:2]), tuple(box[2:]) + cv2.rectangle(frame, st, ed, plate[0], 2) + for k, lb in enumerate(label): + if k >= max_num: + break + text = abbrev(lb) + text = ': '.join([text, str(score[k])]) + location = (0 + st[0], 18 + k * 18 + st[1]) + textsize = cv2.getTextSize(text, FONTFACE, FONTSCALE, + THICKNESS)[0] + textwidth = textsize[0] + diag0 = (location[0] + textwidth, location[1] - 14) + diag1 = (location[0], location[1] + 2) + cv2.rectangle(frame, diag0, diag1, plate[k + 1], -1) + cv2.putText(frame, text, location, FONTFACE, FONTSCALE, + FONTCOLOR, THICKNESS, LINETYPE) + + return frames_ + + +def frame_extraction(video_path, target_dir): + """Extract frames given video_path. + Args: + video_path (str): The video_path. + """ + + if not os.path.exists(target_dir): + os.makedirs(target_dir, exist_ok=True) + + # Should be able to handle videos up to several hours + frame_tmpl = osp.join(target_dir, '{:05d}.jpg') + vid = cv2.VideoCapture(video_path) + + FPS = int(vid.get(5)) + + frames = [] + frame_paths = [] + + flag, frame = vid.read() + index = 1 + while flag: + frames.append(frame) + frame_path = frame_tmpl.format(index) + frame_paths.append(frame_path) + cv2.imwrite(frame_path, frame) + index += 1 + flag, frame = vid.read() + return frame_paths, frames, FPS + + +def parse_args(): + def str2bool(v): + return v.lower() in ("true", "t", "1") + + # general params + parser = argparse.ArgumentParser("PaddleVideo Inference model script") + parser.add_argument('-c', + '--config', + type=str, + default='configs/example.yaml', + help='config file path') + + parser.add_argument('--video_path', help='video file/url') + + parser.add_argument('-o', + '--override', + action='append', + default=[], + help='config options to be overridden') + parser.add_argument('-w', + '--weights', + type=str, + help='weights for finetuning or testing') + + #detection_model_name + parser.add_argument('--detection_model_name', + help='the name of detection model ') + # detection_model_weights + parser.add_argument('--detection_model_weights', + help='the weights path of detection model ') + + # params for predict + parser.add_argument('--out-filename', + default='ava_det_demo.mp4', + help='output filename') + parser.add_argument('--predict-stepsize', + default=8, + type=int, + help='give out a prediction per n frames') + parser.add_argument( + '--output-stepsize', + default=4, + type=int, + help=('show one frame per n frames in the demo, we should have: ' + 'predict_stepsize % output_stepsize == 0')) + parser.add_argument('--output-fps', + default=6, + type=int, + help='the fps of demo video output') + + return parser.parse_args() + + +# 一帧的结果。根据概率大小进行排序 +def pack_result(human_detection, result): + """Short summary. + Args: + human_detection (np.ndarray): Human detection result. + result (type): The predicted label of each human proposal. + Returns: + tuple: Tuple of human proposal, label name and label score. + """ + results = [] + if result is None: + return None + + for prop, res in zip(human_detection, result): + res.sort(key=lambda x: -x[1]) + + results.append((prop, [x[0] for x in res], [x[1] for x in res])) + + return results + + +# 构造数据处理需要的results +def get_timestep_result(frame_dir, timestamp, clip_len, frame_interval, FPS): + result = {} + + result["frame_dir"] = frame_dir + + frame_num = len(os.listdir(frame_dir)) + + dir_name = frame_dir.split("/")[-1] + result["video_id"] = dir_name + + result['timestamp'] = timestamp + + timestamp_str = '{:04d}'.format(timestamp) + img_key = dir_name + "," + timestamp_str + result['img_key'] = img_key + + result['shot_info'] = (1, frame_num) + result['fps'] = FPS + + result['suffix'] = '{:05}.jpg' + + result['timestamp_start'] = 1 + result['timestamp_end'] = int(frame_num / result['fps']) + + return result + + +def detection_inference(frame_paths, output_dir, model_name, weights_path): + """Detect human boxes given frame paths. + Args: + frame_paths (list[str]): The paths of frames to do detection inference. + Returns: + list[np.ndarray]: The human detection results. + """ + + detection_cfg = ppdet.model_zoo.get_config_file(model_name) + detection_cfg = ppdet.core.workspace.load_config(detection_cfg) + detection_trainer = ppdet.engine.Trainer(detection_cfg, mode='test') + detection_trainer.load_weights(weights_path) + + print('Performing Human Detection for each frame') + + detection_trainer.predict(frame_paths, output_dir=output_dir, save_txt=True) + + print("finish object detection") + + results = [] + + for frame_path in frame_paths: + (file_dir, file_name) = os.path.split(frame_path) + (file_path, ext) = os.path.splitext(frame_path) + + txt_file_name = file_name.replace(ext, ".txt") + txt_path = os.path.join(output_dir, txt_file_name) + results.append(txt_path) + + return results + + +def get_detection_result(txt_file_path, img_h, img_w, person_det_score_thr): + """ + 根据检测结果文件得到图像中人的检测框(proposals)和置信度(scores) + txt_file_path:检测结果存放路径 + img_h:图像高度 + img_w:图像宽度 + """ + + proposals = [] + scores = [] + + with open(txt_file_path, 'r') as detection_file: + lines = detection_file.readlines() + for line in lines: # person 0.9842637181282043 0.0 469.1407470703125 944.7770385742188 831.806396484375 + items = line.split(" ") + if items[0] != 'person': #只要人 + continue + + score = items[1] + + if (float)(score) < person_det_score_thr: + continue + + x1 = (float(items[2])) / img_w + y1 = ((float)(items[3])) / img_h + box_w = ((float)(items[4])) + box_h = ((float)(items[5])) + + x2 = (float(items[2]) + box_w) / img_w + y2 = (float(items[3]) + box_h) / img_h + + scores.append(score) + + proposals.append([x1, y1, x2, y2]) + + return np.array(proposals), np.array(scores) + + +@paddle.no_grad() +def main(args): + config = get_config(args.config, show=False) #parse config file + + # extract frames from video + video_path = args.video_path + frame_dir = 'tmp_frames' + frame_paths, frames, FPS = frame_extraction(video_path, frame_dir) + + num_frame = len(frame_paths) #视频秒数*FPS + assert num_frame != 0 + print("Frame Number:", num_frame) + + # 帧图像高度和宽度 + h, w, _ = frames[0].shape + + # Get clip_len, frame_interval and calculate center index of each clip + data_process_pipeline = build_pipeline(config.PIPELINE.test) #测试时输出处理流水配置 + + clip_len = config.PIPELINE.test.sample['clip_len'] + assert clip_len % 2 == 0, 'We would like to have an even clip_len' + frame_interval = config.PIPELINE.test.sample['frame_interval'] + + # 此处关键帧每秒取一个 + clip_len = config.PIPELINE.test.sample['clip_len'] + assert clip_len % 2 == 0, 'We would like to have an even clip_len' + frame_interval = config.PIPELINE.test.sample['frame_interval'] + window_size = clip_len * frame_interval + timestamps = np.arange(window_size // 2, (num_frame + 1 - window_size // 2), + args.predict_stepsize) + print("timetamps number:", len(timestamps)) + + # get selected frame list according to timestamps + selected_frame_list = [] + for timestamp in timestamps: + selected_frame_list.append(frame_paths[timestamp - 1]) + + # Load label_map + label_map_path = config.DATASET.test['label_file'] + categories, class_whitelist = read_labelmap(open(label_map_path)) + label_map = {} + for item in categories: + id = item['id'] + name = item['name'] + label_map[id] = name + + # Construct model. + if config.MODEL.backbone.get('pretrained'): + config.MODEL.backbone.pretrained = '' # disable pretrain model init + model = build_model(config.MODEL) + + model.eval() + state_dicts = load(args.weights) + model.set_state_dict(state_dicts) + + detection_result_dir = 'tmp_detection' + detection_model_name = args.detection_model_name + detection_model_weights = args.detection_model_weights + detection_txt_list = detection_inference(selected_frame_list, + detection_result_dir, + detection_model_name, + detection_model_weights) + assert len(detection_txt_list) == len(timestamps) + + print('Performing SpatioTemporal Action Detection for each clip') + human_detections = [] + predictions = [] + + index = 0 + for timestamp, detection_txt_path in zip(timestamps, detection_txt_list): + proposals, scores = get_detection_result( + detection_txt_path, h, w, + (float)(config.DATASET.test['person_det_score_thr'])) + if proposals.shape[0] == 0: + predictions.append(None) + human_detections.append(None) + continue + + human_detections.append(proposals) + + result = get_timestep_result(frame_dir, + timestamp, + clip_len, + frame_interval, + FPS=FPS) + result["proposals"] = proposals + result["scores"] = scores + + new_result = data_process_pipeline(result) + proposals = new_result['proposals'] + + img_slow = new_result['imgs'][0] + img_slow = img_slow[np.newaxis, :] + img_fast = new_result['imgs'][1] + img_fast = img_fast[np.newaxis, :] + + proposals = proposals[np.newaxis, :] + + scores = scores[np.newaxis, :] + + img_shape = np.asarray(new_result['img_shape']) + img_shape = img_shape[np.newaxis, :] + + data = [ + paddle.to_tensor(img_slow, dtype='float32'), + paddle.to_tensor(img_fast, dtype='float32'), + paddle.to_tensor(proposals, dtype='float32'), scores, + paddle.to_tensor(img_shape, dtype='int32') + ] + + with paddle.no_grad(): + result = model(data, mode='infer') + + result = result[0] + prediction = [] + + person_num = proposals.shape[1] + # N proposals + for i in range(person_num): + prediction.append([]) + + # Perform action score thr + for i in range(len(result)): + if i + 1 not in class_whitelist: + continue + for j in range(person_num): + if result[i][j, 4] > config.MODEL.head['action_thr']: + prediction[j].append((label_map[i + 1], result[i][j, + 4])) + predictions.append(prediction) + + index = index + 1 + if index % 10 == 0: + print(index, "/", len(timestamps)) + + results = [] + for human_detection, prediction in zip(human_detections, predictions): + results.append(pack_result(human_detection, prediction)) + + def dense_timestamps(timestamps, n): + """Make it nx frames.""" + old_frame_interval = (timestamps[1] - timestamps[0]) + start = timestamps[0] - old_frame_interval / n * (n - 1) / 2 + new_frame_inds = np.arange( + len(timestamps) * n) * old_frame_interval / n + start + return new_frame_inds.astype(np.int) + + dense_n = int(args.predict_stepsize / args.output_stepsize) #30 + frames = [ + cv2.imread(frame_paths[i - 1]) + for i in dense_timestamps(timestamps, dense_n) + ] + + vis_frames = visualize(frames, results) + + try: + import moviepy.editor as mpy + except ImportError: + raise ImportError('Please install moviepy to enable output file') + + vid = mpy.ImageSequenceClip([x[:, :, ::-1] for x in vis_frames], + fps=args.output_fps) + vid.write_videofile(args.out_filename) + print("finish write !") + + # delete tmp files and dirs + shutil.rmtree(frame_dir) + shutil.rmtree(detection_result_dir) + + +if __name__ == '__main__': + args = parse_args() #解析参数 + main(args) diff --git a/Bank_second_part/detect_process/tools/export_model.py b/Bank_second_part/detect_process/tools/export_model.py new file mode 100644 index 0000000..401091a --- /dev/null +++ b/Bank_second_part/detect_process/tools/export_model.py @@ -0,0 +1,267 @@ +# 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 +import os.path as osp +import sys + +import paddle +from paddle.jit import to_static +from paddle.static import InputSpec + +__dir__ = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.abspath(os.path.join(__dir__, '../'))) + +from paddlevideo.modeling.builder import build_model +from paddlevideo.utils import get_config + + +def parse_args(): + parser = argparse.ArgumentParser("PaddleVideo export model script") + parser.add_argument('-c', + '--config', + type=str, + default='configs/example.yaml', + help='config file path') + parser.add_argument('--override', + action='append', + default=[], + help='config options to be overridden') + parser.add_argument("-p", + "--pretrained_params", + default='./best.pdparams', + type=str, + help='params path') + parser.add_argument("-o", + "--output_path", + type=str, + default="./inference", + help='output path') + + parser.add_argument('--save_name', + type=str, + default=None, + help='specify the exported inference \ + files(pdiparams and pdmodel) name,\ + only used in TIPC') + + return parser.parse_args() + + +def trim_config(cfg): + """ + Reuse the trainging config will bring useless attributes, such as: backbone.pretrained model. + and some build phase attributes should be overrided, such as: backbone.num_seg. + Trim it here. + """ + model_name = cfg.model_name + if cfg.MODEL.get('backbone') and cfg.MODEL.backbone.get('pretrained'): + cfg.MODEL.backbone.pretrained = "" # not ued when inference + + # for distillation + if cfg.MODEL.get('models'): + if cfg.MODEL.models[0]['Teacher']['backbone'].get('pretrained'): + cfg.MODEL.models[0]['Teacher']['backbone']['pretrained'] = "" + if cfg.MODEL.models[1]['Student']['backbone'].get('pretrained'): + cfg.MODEL.models[1]['Student']['backbone']['pretrained'] = "" + + return cfg, model_name + + +def get_input_spec(cfg, model_name): + if model_name in ['ppTSM', 'TSM', 'MoViNet', 'ppTSMv2']: + input_spec = [[ + InputSpec( + shape=[None, cfg.num_seg, 3, cfg.target_size, cfg.target_size], + dtype='float32'), + ]] + elif model_name in ['TokenShiftVisionTransformer']: + input_spec = [[ + InputSpec(shape=[ + None, 3, cfg.num_seg * 3, cfg.target_size, cfg.target_size + ], + dtype='float32'), + ]] + elif model_name in ['TSN', 'ppTSN']: + input_spec = [[ + InputSpec(shape=[ + None, cfg.num_seg * 10, 3, cfg.target_size, cfg.target_size + ], + dtype='float32'), + ]] + elif model_name in ['BMN']: + input_spec = [[ + InputSpec(shape=[None, cfg.feat_dim, cfg.tscale], + dtype='float32', + name='feat_input'), + ]] + elif model_name in ['TimeSformer', 'ppTimeSformer']: + input_spec = [[ + InputSpec(shape=[ + None, 3, cfg.num_seg * 3, cfg.target_size, cfg.target_size + ], + dtype='float32'), + ]] + elif model_name in ['VideoSwin']: + input_spec = [[ + InputSpec(shape=[ + None, 3, cfg.num_seg * cfg.seg_len * 1, cfg.target_size, + cfg.target_size + ], + dtype='float32'), + ]] + elif model_name in ['VideoSwin_TableTennis']: + input_spec = [[ + InputSpec(shape=[ + None, 3, cfg.num_seg * cfg.seg_len * 3, cfg.target_size, + cfg.target_size + ], + dtype='float32'), + ]] + elif model_name in ['AttentionLSTM']: + input_spec = [[ + InputSpec(shape=[None, cfg.embedding_size, cfg.feature_dims[0]], + dtype='float32'), # for rgb_data + InputSpec(shape=[ + None, + ], dtype='int64'), # for rgb_len + InputSpec(shape=[None, cfg.embedding_size, cfg.feature_dims[0]], + dtype='float32'), # for rgb_mask + InputSpec(shape=[None, cfg.embedding_size, cfg.feature_dims[1]], + dtype='float32'), # for audio_data + InputSpec(shape=[ + None, + ], dtype='int64'), # for audio_len + InputSpec(shape=[None, cfg.embedding_size, cfg.feature_dims[1]], + dtype='float32'), # for audio_mask + ]] + elif model_name in ['SlowFast']: + input_spec = [[ + InputSpec(shape=[ + None, 3, cfg.num_frames // cfg.alpha, cfg.target_size, + cfg.target_size + ], + dtype='float32', + name='slow_input'), + InputSpec(shape=[ + None, 3, cfg.num_frames, cfg.target_size, cfg.target_size + ], + dtype='float32', + name='fast_input'), + ]] + elif model_name in ['STGCN', 'AGCN', 'CTRGCN']: + input_spec = [[ + InputSpec(shape=[ + None, cfg.num_channels, cfg.window_size, cfg.vertex_nums, + cfg.person_nums + ], + dtype='float32'), + ]] + # 由于在模型运行过程中涉及到第一维乘human个数(N*M), 所以这里用1作为shape + elif model_name in ['AGCN2s']: + input_spec = [[ + InputSpec(shape=[ + 1, cfg.num_channels, cfg.window_size, cfg.vertex_nums, + cfg.person_nums + ], + dtype='float32'), + ]] + elif model_name in ['TransNetV2']: + input_spec = [[ + InputSpec(shape=[ + None, + cfg.num_frames, + cfg.height, + cfg.width, + cfg.num_channels, + ], + dtype='float32'), + ]] + elif model_name in ['MSTCN', 'ASRF']: + input_spec = [[ + InputSpec(shape=[None, cfg.num_channels, None], dtype='float32'), + ]] + elif model_name in ['ADDS']: + input_spec = [[ + InputSpec(shape=[None, cfg.num_channels, cfg.height, cfg.width], + dtype='float32'), + ]] + elif model_name in ['AVA_SlowFast_FastRcnn']: + input_spec = [[ + InputSpec(shape=[ + None, 3, cfg.num_frames // cfg.alpha, cfg.target_size, + cfg.target_size + ], + dtype='float32', + name='slow_input'), + InputSpec(shape=[ + None, 3, cfg.num_frames, cfg.target_size, cfg.target_size + ], + dtype='float32', + name='fast_input'), + InputSpec(shape=[None, None, 4], dtype='float32', name='proposals'), + InputSpec(shape=[None, 2], dtype='float32', name='img_shape') + ]] + elif model_name in ['PoseC3D']: + input_spec = [[ + InputSpec(shape=[None, 1, 17, 48, 56, 56], dtype='float32'), + ]] + elif model_name in ['YOWO']: + input_spec = [[ + InputSpec(shape=[ + 1, 3, cfg.num_seg, cfg.target_size, cfg.target_size + ], + dtype='float32'), + ]] + return input_spec + + +def main(): + args = parse_args() + cfg, model_name = trim_config( + get_config(args.config, overrides=args.override, show=False)) + + print(f"Building model({model_name})...") + model = build_model(cfg.MODEL) + assert osp.isfile( + args.pretrained_params + ), f"pretrained params ({args.pretrained_params} is not a file path.)" + + if not os.path.isdir(args.output_path): + os.makedirs(args.output_path) + + print(f"Loading params from ({args.pretrained_params})...") + params = paddle.load(args.pretrained_params) + model.set_dict(params) + + model.eval() + + # for rep nets + for layer in model.sublayers(): + if hasattr(layer, "rep") and not getattr(layer, "is_repped"): + layer.rep() + + input_spec = get_input_spec(cfg.INFERENCE, model_name) + model = to_static(model, input_spec=input_spec) + paddle.jit.save( + model, + osp.join(args.output_path, + model_name if args.save_name is None else args.save_name)) + print( + f"model ({model_name}) has been already saved in ({args.output_path}).") + + +if __name__ == "__main__": + main() diff --git a/Bank_second_part/detect_process/tools/predict.py b/Bank_second_part/detect_process/tools/predict.py new file mode 100644 index 0000000..bc9bd8c --- /dev/null +++ b/Bank_second_part/detect_process/tools/predict.py @@ -0,0 +1,327 @@ +# 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 +from os import path as osp +import paddle +from paddle import inference +from paddle.inference import Config, create_predictor + +from utils import build_inference_helper +from paddlevideo.utils import get_config + + +def parse_args(): + def str2bool(v): + return v.lower() in ("true", "t", "1") + + # general params + parser = argparse.ArgumentParser("PaddleVideo Inference model script") + parser.add_argument( + '-c', + '--config', + type=str, + default='configs/example.yaml', + help='config file path') + parser.add_argument( + '-o', + '--override', + action='append', + default=[], + help='config options to be overridden') + parser.add_argument("-i", "--input_file", type=str, help="input file path") + parser.add_argument( + "--time_test_file", + type=str2bool, + default=False, + help="whether input time test file") + parser.add_argument("--model_file", type=str) + parser.add_argument("--params_file", type=str) + + # params for paddle predict + parser.add_argument("-b", "--batch_size", type=int, default=1) + parser.add_argument("--use_gpu", type=str2bool, default=True) + parser.add_argument("--use_xpu", type=str2bool, default=False) + parser.add_argument("--use_npu", type=str2bool, default=False) + parser.add_argument("--precision", type=str, default="fp32") + parser.add_argument("--ir_optim", type=str2bool, default=True) + parser.add_argument("--use_tensorrt", type=str2bool, default=False) + parser.add_argument("--gpu_mem", type=int, default=8000) + parser.add_argument("--enable_benchmark", type=str2bool, default=False) + parser.add_argument("--enable_mkldnn", type=str2bool, default=False) + parser.add_argument("--cpu_threads", type=int, default=None) + parser.add_argument("--disable_glog", type=str2bool, default=False) + # parser.add_argument("--hubserving", type=str2bool, default=False) #TODO + + return parser.parse_args() + + +def create_paddle_predictor(args, cfg): + config = Config(args.model_file, args.params_file) + if args.use_gpu: + config.enable_use_gpu(args.gpu_mem, 0) + elif args.use_npu: + config.enable_npu() + elif args.use_xpu: + config.enable_xpu() + else: + config.disable_gpu() + if args.cpu_threads: + config.set_cpu_math_library_num_threads(args.cpu_threads) + if args.enable_mkldnn: + # cache 10 different shapes for mkldnn to avoid memory leak + config.set_mkldnn_cache_capacity(10) + config.enable_mkldnn() + if args.precision == "fp16": + config.enable_mkldnn_bfloat16() + + # config.disable_glog_info() + config.switch_ir_optim(args.ir_optim) # default true + if args.use_tensorrt: + # choose precision + if args.precision == "fp16": + precision = inference.PrecisionType.Half + elif args.precision == "int8": + precision = inference.PrecisionType.Int8 + else: + precision = inference.PrecisionType.Float32 + + # calculate real max batch size during inference when tenrotRT enabled + max_batch_size = args.batch_size + if 'num_seg' in cfg.INFERENCE: + # num_seg: number of segments when extracting frames. + # seg_len: number of frames extracted within a segment, default to 1. + # num_views: the number of video frame groups obtained by cropping and flipping, + # uniformcrop=3, tencrop=10, centercrop=1. + num_seg = cfg.INFERENCE.num_seg + seg_len = cfg.INFERENCE.get('seg_len', 1) + num_views = 1 + if 'tsm' in cfg.model_name.lower(): + num_views = 1 # CenterCrop + elif 'tsn' in cfg.model_name.lower(): + num_views = 10 # TenCrop + elif 'timesformer' in cfg.model_name.lower(): + num_views = 3 # UniformCrop + elif 'videoswin' in cfg.model_name.lower(): + num_views = 3 # UniformCrop + elif 'tokenshift' in cfg.model_name.lower(): + num_views = 3 # UniformCrop + max_batch_size = args.batch_size * num_views * num_seg * seg_len + config.enable_tensorrt_engine( + precision_mode=precision, max_batch_size=max_batch_size) + + config.enable_memory_optim() + # use zero copy + config.switch_use_feed_fetch_ops(False) + + # disable glog + if args.disable_glog: + config.disable_glog_info() + + # for ST-GCN tensorRT case usage + # config.delete_pass("shuffle_channel_detect_pass") + + predictor = create_predictor(config) + + return config, predictor + + +def parse_file_paths(input_path: str) -> list: + if osp.isfile(input_path): + files = [ + input_path, + ] + else: + files = os.listdir(input_path) + files = [ + file for file in files + if (file.endswith(".avi") or file.endswith(".mp4")) + ] + files = [osp.join(input_path, file) for file in files] + return files + + +def main(): + """predict using paddle inference model + """ + args = parse_args() + cfg = get_config(args.config, overrides=args.override, show=False) + + model_name = cfg.model_name + print(f"Inference model({model_name})...") + InferenceHelper = build_inference_helper(cfg.INFERENCE) + + inference_config, predictor = create_paddle_predictor(args, cfg) + + # get input_tensor and output_tensor + input_names = predictor.get_input_names() + output_names = predictor.get_output_names() + input_tensor_list = [] + output_tensor_list = [] + for item in input_names: + input_tensor_list.append(predictor.get_input_handle(item)) + for item in output_names: + output_tensor_list.append(predictor.get_output_handle(item)) + + # get the absolute file path(s) to be processed + if model_name in ["MSTCN", "ASRF"]: + files = InferenceHelper.get_process_file(args.input_file) + else: + files = parse_file_paths(args.input_file) + + if model_name == 'TransNetV2': + for file in files: + inputs = InferenceHelper.preprocess(file) + outputs = [] + for input in inputs: + # Run inference + for i in range(len(input_tensor_list)): + input_tensor_list[i].copy_from_cpu(input) + predictor.run() + output = [] + for j in range(len(output_tensor_list)): + output.append(output_tensor_list[j].copy_to_cpu()) + outputs.append(output) + + # Post process output + InferenceHelper.postprocess(outputs) + + elif model_name == 'AVA_SlowFast_FastRcnn': + for file in files: # for videos + inputs = InferenceHelper.preprocess(file) + outputs = [] + for input in inputs: + # Run inference + input_len = len(input_tensor_list) + + for i in range(input_len): + if type(input[i]) == paddle.Tensor: + input_tmp = input[i].numpy() + else: + input_tmp = input[i] + input_tensor_list[i].copy_from_cpu(input_tmp) + predictor.run() + output = [] + for j in range(len(output_tensor_list)): + output.append(output_tensor_list[j].copy_to_cpu()) + outputs.append(output) + + # Post process output + InferenceHelper.postprocess(outputs) + elif model_name == 'YOWO': + for file in files: # for videos + (_, filename) = os.path.split(file) + (filename, _) = os.path.splitext(filename) + save_dir = osp.join('inference', 'YOWO_infer') + if not osp.exists('inference'): + os.mkdir('inference') + if not osp.exists(save_dir): + os.mkdir(save_dir) + save_path = osp.join(save_dir, filename) + if not osp.exists(save_path): + os.mkdir(save_path) + inputs, frames = InferenceHelper.preprocess(file) + for idx, input in enumerate(inputs): + # Run inference + outputs = [] + input_len = len(input_tensor_list) + for i in range(input_len): + input_tensor_list[i].copy_from_cpu(input[i]) + predictor.run() + for j in range(len(output_tensor_list)): + outputs.append(output_tensor_list[j].copy_to_cpu()) + # Post process output + InferenceHelper.postprocess(outputs, frames[idx], osp.join(save_path, str(idx).zfill(3))) + else: + if args.enable_benchmark: + num_warmup = 3 + + # instantiate auto log + try: + import auto_log + except ImportError as e: + print(f"{e}, [git+https://github.com/LDOUBLEV/AutoLog] " + f"package and it's dependencies is required for " + f"python-inference when enable_benchmark=True.") + pid = os.getpid() + autolog = auto_log.AutoLogger( + model_name=cfg.model_name, + model_precision=args.precision, + batch_size=args.batch_size, + data_shape="dynamic", + save_path="./output/auto_log.lpg", + inference_config=inference_config, + pids=pid, + process_name=None, + gpu_ids=0 if args.use_gpu else None, + time_keys=[ + 'preprocess_time', 'inference_time', 'postprocess_time' + ], + warmup=num_warmup) + if not args.time_test_file: + test_video_num = 15 + files = [args.input_file for _ in range(test_video_num)] + else: + f_input = open(args.input_file, 'r') + files = [i.strip() for i in f_input.readlines()] + test_video_num = len(files) + f_input.close() + + # Inferencing process + batch_num = args.batch_size + for st_idx in range(0, len(files), batch_num): + ed_idx = min(st_idx + batch_num, len(files)) + + # auto log start + if args.enable_benchmark: + autolog.times.start() + + # Pre process batched input + batched_inputs = InferenceHelper.preprocess_batch( + files[st_idx:ed_idx]) + + # get pre process time cost + if args.enable_benchmark: + autolog.times.stamp() + + # run inference + for i in range(len(input_tensor_list)): + input_tensor_list[i].copy_from_cpu(batched_inputs[i]) + predictor.run() + + batched_outputs = [] + for j in range(len(output_tensor_list)): + batched_outputs.append(output_tensor_list[j].copy_to_cpu()) + + # get inference process time cost + if args.enable_benchmark: + autolog.times.stamp() + + InferenceHelper.postprocess(batched_outputs, + not args.enable_benchmark) + + # get post process time cost + if args.enable_benchmark: + autolog.times.end(stamp=True) + + # time.sleep(0.01) # sleep for T4 GPU + + # report benchmark log if enabled + if args.enable_benchmark: + autolog.report() + + +if __name__ == "__main__": + main() diff --git a/Bank_second_part/detect_process/tools/summary.py b/Bank_second_part/detect_process/tools/summary.py new file mode 100644 index 0000000..28bd6f7 --- /dev/null +++ b/Bank_second_part/detect_process/tools/summary.py @@ -0,0 +1,82 @@ +# 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 +import sys +import os.path as osp + +import paddle +import paddle.nn.functional as F +from paddle.jit import to_static +import paddleslim + +__dir__ = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.abspath(os.path.join(__dir__, '../'))) + +from paddlevideo.modeling.builder import build_model +from paddlevideo.utils import get_config + + +def parse_args(): + + parser = argparse.ArgumentParser("PaddleVideo Summary") + parser.add_argument('-c', + '--config', + type=str, + default='configs/example.yaml', + help='config file path') + + parser.add_argument("--img_size", type=int, default=224) + parser.add_argument("--num_seg", type=int, default=8) + parser.add_argument("--FLOPs", + action="store_true", + help="whether to print FLOPs") + + return parser.parse_args() + + +def _trim(cfg, args): + """ + Reuse the trainging config will bring useless attribute, such as: backbone.pretrained model. Trim it here. + """ + model_name = cfg.model_name + cfg = cfg.MODEL + cfg.backbone.pretrained = "" + + if 'num_seg' in cfg.backbone: + cfg.backbone.num_seg = args.num_seg + return cfg, model_name + + +def main(): + args = parse_args() + cfg, model_name = _trim(get_config(args.config, show=False), args) + print(f"Building model({model_name})...") + model = build_model(cfg) + + img_size = args.img_size + num_seg = args.num_seg + #NOTE: only support tsm now, will refine soon + params_info = paddle.summary(model, (1, 1, num_seg, 3, img_size, img_size)) + print(params_info) + + if args.FLOPs: + flops_info = paddleslim.analysis.flops( + model, [1, 1, num_seg, 3, img_size, img_size]) + print(flops_info) + + +if __name__ == "__main__": + main() diff --git a/Bank_second_part/detect_process/tools/utils.py b/Bank_second_part/detect_process/tools/utils.py new file mode 100644 index 0000000..bbdd2d1 --- /dev/null +++ b/Bank_second_part/detect_process/tools/utils.py @@ -0,0 +1,1670 @@ +# 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 json +import os +import shutil +import sys +from typing import List +import pickle + +import cv2 +try: + import imageio +except ImportError as e: + print( + f"Warning! {e}, [imageio] package and it's dependencies is required for VideoSwin." + ) +try: + import matplotlib as mpl + import matplotlib.cm as cm +except ImportError as e: + print( + f"Warning! {e}, [matplotlib] package and it's dependencies is required for ADDS." + ) +import numpy as np +import paddle +import paddle.nn.functional as F +import pandas +from PIL import Image + +__dir__ = os.path.dirname(os.path.abspath(__file__)) +sys.path.append(os.path.abspath(os.path.join(__dir__, '../'))) +from abc import abstractmethod + +from paddlevideo.loader.builder import build_pipeline +from paddlevideo.loader.pipelines import ( + AutoPadding, CenterCrop, DecodeSampler, FeatureDecoder, FrameDecoder, + GroupResize, Image2Array, ImageDecoder, JitterScale, MultiCrop, + Normalization, PackOutput, Sampler, SamplerPkl, Scale, SkeletonNorm, + TenCrop, ToArray, UniformCrop, VideoDecoder, SegmentationSampler, + SketeonCropSample, MultiCenterCrop, SketeonCropSample, UniformSampleFrames, + PoseDecode, PoseCompact, Resize, CenterCrop_V2, GeneratePoseTarget, + FormatShape, Collect) +from paddlevideo.metrics.ava_utils import read_labelmap +from paddlevideo.metrics.bmn_metric import boundary_choose, soft_nms +from paddlevideo.utils import Registry, build, get_config +from paddlevideo.modeling.framework.segmenters.utils import ASRFPostProcessing + +from tools.ava_predict import (detection_inference, frame_extraction, + get_detection_result, get_timestep_result, + pack_result, visualize) +from paddlevideo.modeling.framework.localizers.yowo_utils import nms, get_region_boxes + +INFERENCE = Registry('inference') + + +def build_inference_helper(cfg): + return build(cfg, INFERENCE) + + +class Base_Inference_helper(): + def __init__(self, + num_seg=8, + seg_len=1, + short_size=256, + target_size=224, + top_k=1): + """Base_Inference_helper + + Args: + num_seg (int, optional): number of segmentations of an sliced input video. Defaults to 8. + seg_len (int, optional): length of each segmentation. Defaults to 1. + short_size (int, optional): short size of input video. Defaults to 256. + target_size (int, optional): size of cropped video. Defaults to 224. + top_k (int, optional): select topk result in outputs. Defaults to 1. + """ + self.num_seg = num_seg + self.seg_len = seg_len + self.short_size = short_size + self.target_size = target_size + self.top_k = top_k + + @abstractmethod + def preprocess(self, input_file: str): + """preprocess abstractmethod + + Args: + input_file (str): input file path. + """ + pass + + def preprocess_batch(self, file_list: List[str]) -> List[np.ndarray]: + """preprocess for file list + + Args: + file_list (List[str]): file pathes in an list, [path1, path2, ...]. + + Returns: + List[np.ndarray]: batched inputs data, [data_batch[0], data_batch[1], ...]. + """ + batched_inputs = [] + for file in file_list: + inputs = self.preprocess(file) + batched_inputs.append(inputs) + batched_inputs = [ + np.concatenate([item[i] for item in batched_inputs]) + for i in range(len(batched_inputs[0])) + ] + self.input_file = file_list + return batched_inputs + + def postprocess(self, + output: np.ndarray, + print_output: bool = True, + return_result: bool = False): + """postprocess + + Args: + output (np.ndarray): batched output scores, shape of (batch_size, class_num). + print_output (bool, optional): whether to print result. Defaults to True. + """ + if not isinstance(self.input_file, list): + self.input_file = [ + self.input_file, + ] + output = output[0] # [B, num_cls] + N = len(self.input_file) + if output.shape[0] != N: + output = output.reshape([N] + [output.shape[0] // N] + + list(output.shape[1:])) # [N, T, C] + output = output.mean(axis=1) # [N, C] + output = F.softmax(paddle.to_tensor(output), axis=-1).numpy() + results_list = [] + for i in range(N): + classes = np.argpartition(output[i], -self.top_k)[-self.top_k:] + classes = classes[np.argsort(-output[i, classes])] + scores = output[i, classes] + topk_class = classes[:self.top_k] + topk_scores = scores[:self.top_k] + result = { + "video_id": self.input_file[i], + "topk_class": topk_class, + "topk_scores": topk_scores + } + results_list.append(result) + if print_output: + print("Current video file: {0}".format(self.input_file[i])) + print("\ttop-{0} class: {1}".format(self.top_k, topk_class)) + print("\ttop-{0} score: {1}".format(self.top_k, topk_scores)) + if return_result: + return results_list + + +@INFERENCE.register() +class ppTSM_Inference_helper(Base_Inference_helper): + def __init__(self, + num_seg=8, + seg_len=1, + short_size=256, + target_size=224, + top_k=1): + self.num_seg = num_seg + self.seg_len = seg_len + self.short_size = short_size + self.target_size = target_size + self.top_k = top_k + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + results = {'filename': input_file} + img_mean = [0.485, 0.456, 0.406] + img_std = [0.229, 0.224, 0.225] + ops = [ + VideoDecoder(backend="decord"), + Sampler(self.num_seg, self.seg_len, valid_mode=True), + Scale(self.short_size), + CenterCrop(self.target_size), + Image2Array(), + Normalization(img_mean, img_std) + ] + for op in ops: + results = op(results) + + res = np.expand_dims(results['imgs'], axis=0).copy() + return [res] + + +@INFERENCE.register() +class ppTSN_Inference_helper(Base_Inference_helper): + def __init__(self, + num_seg=25, + seg_len=1, + short_size=256, + target_size=224, + top_k=1): + self.num_seg = num_seg + self.seg_len = seg_len + self.short_size = short_size + self.target_size = target_size + self.top_k = top_k + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + results = {'filename': input_file} + img_mean = [0.485, 0.456, 0.406] + img_std = [0.229, 0.224, 0.225] + ops = [ + VideoDecoder(backend="decord"), + Sampler(self.num_seg, + self.seg_len, + valid_mode=True, + select_left=True), + Scale(self.short_size, + fixed_ratio=True, + do_round=True, + backend='cv2'), + TenCrop(self.target_size), + Image2Array(), + Normalization(img_mean, img_std) + ] + for op in ops: + results = op(results) + + res = np.expand_dims(results['imgs'], axis=0).copy() + return [res] + + +@INFERENCE.register() +class BMN_Inference_helper(Base_Inference_helper): + def __init__(self, feat_dim, dscale, tscale, result_path): + self.feat_dim = feat_dim + self.dscale = dscale + self.tscale = tscale + self.result_path = result_path + if not os.path.isdir(self.result_path): + os.makedirs(self.result_path) + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + file_info = json.load(open(input_file)) + self.feat_path = file_info['feat_path'] + self.video_duration = file_info['duration_second'] + feat = np.load(self.feat_path).astype('float32').T + res = np.expand_dims(feat, axis=0).copy() + + return [res] + + def postprocess(self, outputs, print_output=True): + """ + output: list + """ + pred_bm, pred_start, pred_end = outputs + self._gen_props(pred_bm, pred_start[0], pred_end[0], print_output) + + def _gen_props(self, pred_bm, pred_start, pred_end, print_output): + snippet_xmins = [1.0 / self.tscale * i for i in range(self.tscale)] + snippet_xmaxs = [ + 1.0 / self.tscale * i for i in range(1, self.tscale + 1) + ] + + pred_bm = pred_bm[0, 0, :, :] * pred_bm[0, 1, :, :] + start_mask = boundary_choose(pred_start) + start_mask[0] = 1. + end_mask = boundary_choose(pred_end) + end_mask[-1] = 1. + score_vector_list = [] + for idx in range(self.dscale): + for jdx in range(self.tscale): + start_index = jdx + end_index = start_index + idx + if end_index < self.tscale and start_mask[ + start_index] == 1 and end_mask[end_index] == 1: + xmin = snippet_xmins[start_index] + xmax = snippet_xmaxs[end_index] + xmin_score = pred_start[start_index] + xmax_score = pred_end[end_index] + bm_score = pred_bm[idx, jdx] + conf_score = xmin_score * xmax_score * bm_score + score_vector_list.append([xmin, xmax, conf_score]) + + cols = ["xmin", "xmax", "score"] + score_vector_list = np.stack(score_vector_list) + df = pandas.DataFrame(score_vector_list, columns=cols) + + result_dict = {} + proposal_list = [] + df = soft_nms(df, alpha=0.4, t1=0.55, t2=0.9) + for idx in range(min(100, len(df))): + tmp_prop={"score":df.score.values[idx], \ + "segment":[max(0,df.xmin.values[idx])*self.video_duration, \ + min(1,df.xmax.values[idx])*self.video_duration]} + proposal_list.append(tmp_prop) + + result_dict[self.feat_path] = proposal_list + + # print top-5 predictions + if print_output: + print("Current video file: {0} :".format(self.feat_path)) + for pred in proposal_list[:5]: + print(pred) + + # save result + outfile = open( + os.path.join(self.result_path, "bmn_results_inference.json"), "w") + + json.dump(result_dict, outfile) + + +@INFERENCE.register() +class TokenShift_Inference_helper(Base_Inference_helper): + def __init__(self, + num_seg=8, + seg_len=1, + short_size=256, + target_size=256, + top_k=1, + mean=[0.5, 0.5, 0.5], + std=[0.5, 0.5, 0.5]): + self.num_seg = num_seg + self.seg_len = seg_len + self.short_size = short_size + self.target_size = target_size + self.top_k = top_k + self.mean = mean + self.std = std + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + results = {'filename': input_file} + ops = [ + VideoDecoder(backend='pyav', mode='test', num_seg=self.num_seg), + Sampler(self.num_seg, self.seg_len, valid_mode=True), + Normalization(self.mean, self.std, tensor_shape=[1, 1, 1, 3]), + Image2Array(data_format='cthw'), + JitterScale(self.short_size, self.short_size), + MultiCenterCrop(self.target_size) + ] + for op in ops: + results = op(results) + + # [N,C,Tx3,H,W] + res = np.expand_dims(results['imgs'], axis=0).copy() + return [res] + + +@INFERENCE.register() +class TimeSformer_Inference_helper(Base_Inference_helper): + def __init__(self, + num_seg=8, + seg_len=1, + short_size=224, + target_size=224, + top_k=1, + mean=[0.45, 0.45, 0.45], + std=[0.225, 0.225, 0.225]): + self.num_seg = num_seg + self.seg_len = seg_len + self.short_size = short_size + self.target_size = target_size + self.top_k = top_k + self.mean = mean + self.std = std + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + results = {'filename': input_file} + ops = [ + VideoDecoder(backend='pyav', mode='test', num_seg=self.num_seg), + Sampler(self.num_seg, + self.seg_len, + valid_mode=True, + linspace_sample=True), + Normalization(self.mean, self.std, tensor_shape=[1, 1, 1, 3]), + Image2Array(data_format='cthw'), + JitterScale(self.short_size, self.short_size), + UniformCrop(self.target_size) + ] + for op in ops: + results = op(results) + + # [N,C,Tx3,H,W] + res = np.expand_dims(results['imgs'], axis=0).copy() + return [res] + + +@INFERENCE.register() +class VideoSwin_Inference_helper(Base_Inference_helper): + def __init__(self, + num_seg=4, + seg_len=32, + frame_interval=2, + short_size=224, + target_size=224, + top_k=1, + mean=[123.675, 116.28, 103.53], + std=[58.395, 57.12, 57.375]): + + self.num_seg = num_seg + self.seg_len = seg_len + self.frame_interval = frame_interval + self.short_size = short_size + self.target_size = target_size + self.top_k = top_k + self.mean = mean + self.std = std + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + self.input_file = input_file + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + results = {'filename': input_file} + ops = [ + VideoDecoder(backend='decord', mode='valid'), + Sampler(num_seg=self.num_seg, + frame_interval=self.frame_interval, + seg_len=self.seg_len, + valid_mode=True, + use_pil=False), + Scale(short_size=self.short_size, + fixed_ratio=False, + keep_ratio=True, + backend='cv2', + do_round=True), + CenterCrop(target_size=224, backend='cv2'), + Normalization(mean=self.mean, + std=self.std, + tensor_shape=[3, 1, 1, 1], + inplace=True), + Image2Array(data_format='cthw') + ] + for op in ops: + results = op(results) + + res = np.expand_dims(results['imgs'], axis=0).copy() + return [res] + + def postprocess(self, output, print_output=True): + """ + output: list + """ + if not isinstance(self.input_file, list): + self.input_file = [ + self.input_file, + ] + output = output[0] # [B, num_cls] + N = len(self.input_file) + if output.shape[0] != N: + output = output.reshape([N] + [output.shape[0] // N] + + list(output.shape[1:])) # [N, T, C] + output = output.mean(axis=1) # [N, C] + for i in range(N): + classes = np.argpartition(output[i], -self.top_k)[-self.top_k:] + classes = classes[np.argsort(-output[i, classes])] + scores = output[i, classes] + if print_output: + print("Current video file: {0}".format(self.input_file[i])) + for j in range(self.top_k): + print("\ttop-{0} class: {1}".format(j + 1, classes[j])) + print("\ttop-{0} score: {1}".format(j + 1, scores[j])) + + +@INFERENCE.register() +class VideoSwin_TableTennis_Inference_helper(Base_Inference_helper): + def __init__(self, + num_seg=1, + seg_len=32, + short_size=256, + target_size=224, + top_k=1): + self.num_seg = num_seg + self.seg_len = seg_len + self.short_size = short_size + self.target_size = target_size + self.top_k = top_k + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + results = {'frame_dir': input_file, 'suffix': 'img_{:05}.jpg'} + img_mean = [123.675, 116.28, 103.53] + img_std = [58.395, 57.12, 57.375] + ops = [ + FrameDecoder(), + SamplerPkl(num_seg=self.num_seg, + seg_len=self.seg_len, + backend='cv2', + valid_mode=True), + Scale(short_size=self.short_size, + fixed_ratio=False, + keep_ratio=True, + backend='cv2', + do_round=True), + UniformCrop(target_size=self.target_size, backend='cv2'), + Normalization(mean=img_mean, + std=img_std, + tensor_shape=[3, 1, 1, 1], + inplace=True), + Image2Array(data_format='cthw') + ] + for op in ops: + results = op(results) + + res = np.expand_dims(results['imgs'], axis=0).copy() + return [res] + + def add_text_to_video( + self, + video_path, + output_dir="applications/TableTennis/ActionRecognition/results", + text=None): + os.makedirs(output_dir, exist_ok=True) + if video_path.endswith('.pkl'): + try: + import cPickle as pickle + from cStringIO import StringIO + except ImportError: + import pickle + from io import BytesIO + from PIL import Image + data_loaded = pickle.load(open(video_path, 'rb'), encoding='bytes') + _, _, frames = data_loaded + frames_len = len(frames) + + else: + videoCapture = cv2.VideoCapture() + videoCapture.open(video_path) + + fps = videoCapture.get(cv2.CAP_PROP_FPS) + frame_width = int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)) + frame_height = int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)) + + frames_len = videoCapture.get(cv2.CAP_PROP_FRAME_COUNT) + print("fps=", int(fps), "frames=", int(frames_len), "scale=", + f"{frame_height}x{frame_width}") + + frames_rgb_list = [] + for i in range(int(frames_len)): + if video_path.endswith('.pkl'): + frame = np.array( + Image.open(BytesIO(frames[i])).convert("RGB").resize( + (240, 135)))[:, :, ::-1].astype('uint8') + else: + _, frame = videoCapture.read() + frame = cv2.putText(frame, text, (30, 30), cv2.FONT_HERSHEY_COMPLEX, + 1.0, (0, 0, 255), 2) + frames_rgb_list.append(frame[:, :, ::-1]) # bgr to rgb + if not video_path.endswith('.pkl'): + videoCapture.release() + cv2.destroyAllWindows() + output_filename = os.path.basename(video_path) + output_filename = output_filename.split('.')[0] + '.gif' + imageio.mimsave(f'{output_dir}/{output_filename}', + frames_rgb_list, + 'GIF', + duration=0.00085) + + def postprocess(self, output, print_output=True, save_gif=True): + """ + output: list + """ + if not isinstance(self.input_file, list): + self.input_file = [ + self.input_file, + ] + output = output[0] # [B, num_cls] + N = len(self.input_file) + if output.shape[0] != N: + output = output.reshape([N] + [output.shape[0] // N] + + list(output.shape[1:])) # [N, T, C] + output = output.mean(axis=1) # [N, C] + for i in range(N): + classes = np.argpartition(output[i], -self.top_k)[-self.top_k:] + classes = classes[np.argsort(-output[i, classes])] + scores = output[i, classes] + if print_output: + print("Current video file: {0}".format(self.input_file[i])) + for j in range(self.top_k): + print("\ttop-{0} class: {1}".format(j + 1, classes[j])) + print("\ttop-{0} score: {1}".format(j + 1, scores[j])) + if save_gif: + self.add_text_to_video( + self.input_file[0], + text=f"{str(classes[0])} {float(scores[0]):.5f}") + + +@INFERENCE.register() +class SlowFast_Inference_helper(Base_Inference_helper): + def __init__(self, + num_frames=32, + sampling_rate=2, + target_size=256, + alpha=8, + top_k=1): + self.num_frames = num_frames + self.sampling_rate = sampling_rate + self.target_size = target_size + self.alpha = alpha + self.top_k = top_k + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + results = { + 'filename': input_file, + 'temporal_sample_index': 0, + 'spatial_sample_index': 0, + 'temporal_num_clips': 1, + 'spatial_num_clips': 1 + } + img_mean = [0.45, 0.45, 0.45] + img_std = [0.225, 0.225, 0.225] + ops = [ + DecodeSampler(self.num_frames, self.sampling_rate, test_mode=True), + JitterScale(self.target_size, self.target_size), + MultiCrop(self.target_size), + Image2Array(transpose=False), + Normalization(img_mean, img_std, tensor_shape=[1, 1, 1, 3]), + PackOutput(self.alpha), + ] + for op in ops: + results = op(results) + + res = [] + for item in results['imgs']: + res.append(np.expand_dims(item, axis=0).copy()) + return res + + def postprocess(self, output, print_output=True): + """ + output: list + """ + if not isinstance(self.input_file, list): + self.input_file = [ + self.input_file, + ] + output = output[0] # [B, num_cls] + + N = len(self.input_file) + if output.shape[0] != N: + output = output.reshape([N] + [output.shape[0] // N] + + list(output.shape[1:])) # [N, T, C] + output = output.mean(axis=1) # [N, C] + # output = F.softmax(paddle.to_tensor(output), axis=-1).numpy() # done in it's head + for i in range(N): + classes = np.argpartition(output[i], -self.top_k)[-self.top_k:] + classes = classes[np.argsort(-output[i, classes])] + scores = output[i, classes] + if print_output: + print("Current video file: {0}".format(self.input_file[i])) + for j in range(self.top_k): + print("\ttop-{0} class: {1}".format(j + 1, classes[j])) + print("\ttop-{0} score: {1}".format(j + 1, scores[j])) + + +@INFERENCE.register() +class STGCN_Inference_helper(Base_Inference_helper): + def __init__(self, + num_channels, + window_size, + vertex_nums, + person_nums, + top_k=1): + self.num_channels = num_channels + self.window_size = window_size + self.vertex_nums = vertex_nums + self.person_nums = person_nums + self.top_k = top_k + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + data = np.load(input_file) + results = {'data': data} + ops = [AutoPadding(window_size=self.window_size), SkeletonNorm()] + for op in ops: + results = op(results) + + res = np.expand_dims(results['data'], axis=0).copy() + return [res] + + +@INFERENCE.register() +class CTRGCN_Inference_helper(Base_Inference_helper): + def __init__(self, + num_channels=3, + vertex_nums=25, + person_nums=2, + window_size=64, + p_interval=[0.95], + top_k=1): + self.window_size = window_size + self.p_interval = p_interval + self.num_channels = num_channels + self.vertex_nums = vertex_nums + self.person_nums = person_nums + self.top_k = top_k + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + data = np.load(input_file) + results = {'data': data} + ops = [ + SketeonCropSample(window_size=self.window_size, + p_interval=self.p_interval) + ] + for op in ops: + results = op(results) + + res = np.expand_dims(results['data'], axis=0).copy() + return [res] + + +@INFERENCE.register() +class AGCN2s_Inference_helper(Base_Inference_helper): + def __init__(self, + window_size=300, + num_channels=3, + vertex_nums=25, + person_nums=2, + top_k=1): + self.window_size = window_size + self.num_channels = num_channels + self.vertex_nums = vertex_nums + self.person_nums = person_nums + self.top_k = top_k + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + data = np.load(input_file) + results = {'data': data} + + res = np.expand_dims(results['data'], axis=0).copy() + return [res] + + +@INFERENCE.register() +class MSTCN_Inference_helper(Base_Inference_helper): + def __init__(self, num_channels, actions_map_file_path, feature_path=None): + self.num_channels = num_channels + file_ptr = open(actions_map_file_path, 'r') + actions = file_ptr.read().split('\n')[:-1] + file_ptr.close() + self.actions_dict = dict() + for a in actions: + self.actions_dict[a.split()[1]] = int(a.split()[0]) + + self.feature_path = feature_path + self.file_name_list = [] + + def get_process_file(self, input_file_txt): + with open(input_file_txt, 'r') as file_ptr: + info = file_ptr.read().split('\n')[:-1] + + files = [] + for video_name in info: + if self.feature_path is not None: + file_name = video_name.split('.')[0] + ".npy" + input_file = os.path.join(self.feature_path, file_name) + else: + input_file = video_name + + assert os.path.isfile( + input_file) is not None, "{0} not exists".format(input_file) + files.append(input_file) + + self.file_name_list.append(input_file.split('/')[-1].split('.')[0]) + return files + + def preprocess(self, input_file): + """ + input_file: str, feature file list txt path + return: list + """ + output_list = [] + + data = np.load(input_file) + results = {'video_feat': data, 'video_gt': None} + ops = [] + for op in ops: + results = op(results) + + res = np.expand_dims(results['video_feat'], axis=0).copy() + output_list.append(res) + return output_list + + def postprocess(self, output, print_output=True): + reslut_path = os.path.join("./inference/infer_results/") + if not os.path.isdir(reslut_path): + os.makedirs(reslut_path) + output = [output] + for outputs in output: + output_np = outputs[0] + recognition = [] + for i in range(output_np.shape[0]): + recognition = np.concatenate((recognition, [ + list(self.actions_dict.keys())[list( + self.actions_dict.values()).index(output_np[i])] + ])) + recog_content = list(recognition) + recog_content = [line + "\n" for line in recog_content] + + filename = self.file_name_list.pop(0) + + write_path = os.path.join(reslut_path, filename + ".txt") + f = open(write_path, "w") + f.writelines(recog_content) + f.close() + print("result write in : " + write_path) + + +@INFERENCE.register() +class ASRF_Inference_helper(Base_Inference_helper): + def __init__(self, + num_channels, + actions_map_file_path, + postprocessing_method, + boundary_threshold, + feature_path=None): + self.num_channels = num_channels + file_ptr = open(actions_map_file_path, 'r') + actions = file_ptr.read().split('\n')[:-1] + file_ptr.close() + self.actions_dict = dict() + for a in actions: + self.actions_dict[a.split()[1]] = int(a.split()[0]) + + self.postprocessing_method = postprocessing_method + self.boundary_threshold = boundary_threshold + self.feature_path = feature_path + self.file_name_list = [] + + def get_process_file(self, input_file_txt): + with open(input_file_txt, 'r') as file_ptr: + info = file_ptr.read().split('\n')[:-1] + + files = [] + for video_name in info: + if self.feature_path is not None: + file_name = video_name.split('.')[0] + ".npy" + input_file = os.path.join(self.feature_path, file_name) + else: + input_file = video_name + + assert os.path.isfile( + input_file) is not None, "{0} not exists".format(input_file) + files.append(input_file) + + self.file_name_list.append(input_file.split('/')[-1].split('.')[0]) + return files + + def preprocess(self, input_file): + """ + input_file: str, feature file list txt path + return: list + """ + + output_list = [] + + data = np.load(input_file) + results = {'video_feat': data, 'video_gt': None} + ops = [] + for op in ops: + results = op(results) + + res = np.expand_dims(results['video_feat'], axis=0).copy() + output_list.append(res) + return output_list + + def postprocess(self, output, print_output=True): + reslut_path = os.path.join("./inference/infer_results/") + if not os.path.isdir(reslut_path): + os.makedirs(reslut_path) + output = [output] + for outputs in output: + outputs_cls_np = outputs[0] + outputs_boundary_np = outputs[1] + + output_np = ASRFPostProcessing( + outputs_cls_np, + outputs_boundary_np, + self.postprocessing_method, + boundary_threshold=self.boundary_threshold).numpy()[0, :] + + recognition = [] + for i in range(output_np.shape[0]): + recognition = np.concatenate((recognition, [ + list(self.actions_dict.keys())[list( + self.actions_dict.values()).index(output_np[i])] + ])) + recog_content = list(recognition) + recog_content = [line + "\n" for line in recog_content] + + filename = self.file_name_list.pop(0) + + write_path = os.path.join(reslut_path, filename + ".txt") + f = open(write_path, "w") + f.writelines(recog_content) + f.close() + print("result write in : " + write_path) + + +@INFERENCE.register() +class AttentionLSTM_Inference_helper(Base_Inference_helper): + def __init__( + self, + num_classes, #Optional, the number of classes to be classified. + feature_num, + feature_dims, + embedding_size, + lstm_size, + top_k=1): + self.num_classes = num_classes + self.feature_num = feature_num + self.feature_dims = feature_dims + self.embedding_size = embedding_size + self.lstm_size = lstm_size + self.top_k = top_k + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + results = {'filename': input_file} + ops = [FeatureDecoder(num_classes=self.num_classes, has_label=False)] + for op in ops: + results = op(results) + + res = [] + for modality in ['rgb', 'audio']: + res.append( + np.expand_dims(results[f'{modality}_data'], axis=0).copy()) + res.append( + np.expand_dims(results[f'{modality}_len'], axis=0).copy()) + res.append( + np.expand_dims(results[f'{modality}_mask'], axis=0).copy()) + return res + + +@INFERENCE.register() +class TransNetV2_Inference_helper(): + def __init__(self, + num_frames, + height, + width, + num_channels, + threshold=0.5, + output_path=None, + visualize=True): + self._input_size = (height, width, num_channels) + self.output_path = output_path + self.len_frames = 0 + self.threshold = threshold + self.visualize = visualize + + def input_iterator(self, frames): + # return windows of size 100 where the first/last 25 frames are from the previous/next batch + # the first and last window must be padded by copies of the first and last frame of the video + no_padded_frames_start = 25 + no_padded_frames_end = 25 + 50 - ( + len(frames) % 50 if len(frames) % 50 != 0 else 50) # 25 - 74 + + start_frame = np.expand_dims(frames[0], 0) + end_frame = np.expand_dims(frames[-1], 0) + padded_inputs = np.concatenate([start_frame] * no_padded_frames_start + + [frames] + + [end_frame] * no_padded_frames_end, 0) + + ptr = 0 + while ptr + 100 <= len(padded_inputs): + out = padded_inputs[ptr:ptr + 100] + out = out.astype(np.float32) + ptr += 50 + yield out[np.newaxis] + + def preprocess(self, input_file): + """ + input_file: str, file path + return: iterator + """ + try: + import ffmpeg + except ImportError as e: + print( + f"Warning! {e}, [ffmpeg-python] package and it's dependencies is required for TransNetV2." + ) + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + self.input_file = input_file + self.filename = os.path.splitext(os.path.split(self.input_file)[1])[0] + video_stream, err = ffmpeg.input( + self.input_file).output("pipe:", + format="rawvideo", + pix_fmt="rgb24", + s="48x27").run(capture_stdout=True, + capture_stderr=True) + self.frames = np.frombuffer(video_stream, + np.uint8).reshape([-1, 27, 48, 3]) + self.len_frames = len(self.frames) + + return self.input_iterator(self.frames) + + def predictions_to_scenes(self, predictions): + predictions = (predictions > self.threshold).astype(np.uint8) + scenes = [] + t, t_prev, start = -1, 0, 0 + for i, t in enumerate(predictions): + if t_prev == 1 and t == 0: + start = i + if t_prev == 0 and t == 1 and i != 0: + scenes.append([start, i]) + t_prev = t + if t == 0: + scenes.append([start, i]) + + # just fix if all predictions are 1 + if len(scenes) == 0: + return np.array([[0, len(predictions) - 1]], dtype=np.int32) + + return np.array(scenes, dtype=np.int32) + + def visualize_predictions(self, frames, predictions): + from PIL import Image, ImageDraw + + if isinstance(predictions, np.ndarray): + predictions = [predictions] + + ih, iw, ic = frames.shape[1:] + width = 25 + + # pad frames so that length of the video is divisible by width + # pad frames also by len(predictions) pixels in width in order to show predictions + pad_with = width - len(frames) % width if len( + frames) % width != 0 else 0 + frames = np.pad(frames, [(0, pad_with), (0, 1), (0, len(predictions)), + (0, 0)]) + + predictions = [np.pad(x, (0, pad_with)) for x in predictions] + height = len(frames) // width + + img = frames.reshape([height, width, ih + 1, iw + len(predictions), ic]) + img = np.concatenate(np.split( + np.concatenate(np.split(img, height), axis=2)[0], width), + axis=2)[0, :-1] + + img = Image.fromarray(img) + draw = ImageDraw.Draw(img) + + # iterate over all frames + for i, pred in enumerate(zip(*predictions)): + x, y = i % width, i // width + x, y = x * (iw + len(predictions)) + iw, y * (ih + 1) + ih - 1 + + # we can visualize multiple predictions per single frame + for j, p in enumerate(pred): + color = [0, 0, 0] + color[(j + 1) % 3] = 255 + + value = round(p * (ih - 1)) + if value != 0: + draw.line((x + j, y, x + j, y - value), + fill=tuple(color), + width=1) + return img + + def postprocess(self, outputs, print_output=True): + """ + output: list + """ + predictions = [] + for output in outputs: + single_frame_logits, all_frames_logits = output + single_frame_pred = F.sigmoid(paddle.to_tensor(single_frame_logits)) + all_frames_pred = F.sigmoid(paddle.to_tensor(all_frames_logits)) + predictions.append((single_frame_pred.numpy()[0, 25:75, 0], + all_frames_pred.numpy()[0, 25:75, 0])) + single_frame_pred = np.concatenate( + [single_ for single_, all_ in predictions]) + all_frames_pred = np.concatenate( + [all_ for single_, all_ in predictions]) + single_frame_predictions, all_frame_predictions = single_frame_pred[: + self + . + len_frames], all_frames_pred[: + self + . + len_frames] + + scenes = self.predictions_to_scenes(single_frame_predictions) + + if print_output: + print("Current video file: {0}".format(self.input_file)) + print("\tShot Boundarys: {0}".format(scenes)) + + if self.output_path: + if not os.path.exists(self.output_path): + os.makedirs(self.output_path) + predictions = np.stack( + [single_frame_predictions, all_frame_predictions], 1) + predictions_file = os.path.join(self.output_path, + self.filename + "_predictions.txt") + np.savetxt(predictions_file, predictions, fmt="%.6f") + scenes_file = os.path.join(self.output_path, + self.filename + "_scenes.txt") + np.savetxt(scenes_file, scenes, fmt="%d") + + if self.visualize: + pil_image = self.visualize_predictions( + self.frames, + predictions=(single_frame_predictions, + all_frame_predictions)) + image_file = os.path.join(self.output_path, + self.filename + "_vis.png") + pil_image.save(image_file) + + +@INFERENCE.register() +class ADDS_Inference_helper(Base_Inference_helper): + def __init__(self, + frame_idxs=[0], + num_scales=4, + side_map={ + "2": 2, + "3": 3, + "l": 2, + "r": 3 + }, + height=256, + width=512, + full_res_shape=None, + num_channels=None, + img_ext=".png", + K=None): + + self.frame_idxs = frame_idxs + self.num_scales = num_scales + self.side_map = side_map + self.full_res_shape = full_res_shape + self.img_ext = img_ext + self.height = height + self.width = width + self.K = K + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + results = { + 'filename': input_file, + 'mode': 'infer', + 'day_or_night': 'day', + } + ops = [ + ImageDecoder( + backend='pil', + dataset='kitti', + frame_idxs=self.frame_idxs, + num_scales=self.num_scales, + side_map=self.side_map, + full_res_shape=self.full_res_shape, + img_ext=self.img_ext, + ), + GroupResize( + height=self.height, + width=self.width, + K=self.K, + scale=1, + mode='infer', + ), + ToArray(), + ] + for op in ops: + results = op(results) + res = results['imgs'][('color', 0, 0)] + res = np.expand_dims(res, axis=0).copy() + return [res] + + def postprocess(self, output, print_output, save_dir='data/'): + """ + output: list + """ + if not isinstance(self.input_file, list): + self.input_file = [ + self.input_file, + ] + print(len(output)) + N = len(self.input_file) + for i in range(N): + pred_depth = output[i] # [H, W] + if print_output: + print("Current input image: {0}".format(self.input_file[i])) + file_name = os.path.basename(self.input_file[i]).split('.')[0] + save_path = os.path.join(save_dir, + file_name + "_depth" + ".png") + pred_depth_color = self._convertPNG(pred_depth) + pred_depth_color.save(save_path) + print(f"pred depth image saved to: {save_path}") + + def _convertPNG(self, image_numpy): + disp_resized = cv2.resize(image_numpy, (1280, 640)) + disp_resized_np = disp_resized + vmax = np.percentile(disp_resized_np, 95) + normalizer = mpl.colors.Normalize(vmin=disp_resized_np.min(), vmax=vmax) + mapper = cm.ScalarMappable(norm=normalizer, cmap='magma') + colormapped_im = (mapper.to_rgba(disp_resized_np)[:, :, :3] * + 255).astype(np.uint8) + im = Image.fromarray(colormapped_im) + return im + + +@INFERENCE.register() +class AVA_SlowFast_FastRCNN_Inference_helper(Base_Inference_helper): + def __init__(self, + detection_model_name, + detection_model_weights, + config_file_path, + predict_stepsize=8, + output_stepsize=4, + output_fps=6, + out_filename='ava_det_demo.mp4', + num_frames=32, + alpha=4, + target_size=256): + self.detection_model_name = detection_model_name + self.detection_model_weights = detection_model_weights + + self.config = get_config(config_file_path, + show=False) #parse config file + self.predict_stepsize = predict_stepsize + self.output_stepsize = output_stepsize + self.output_fps = output_fps + self.out_filename = out_filename + self.num_frames = num_frames + self.alpha = alpha + self.target_size = target_size + + def preprocess(self, input_file): + """ + input_file: str, file path + """ + + frame_dir = 'tmp_frames' + self.frame_paths, frames, FPS = frame_extraction(input_file, frame_dir) + num_frame = len(self.frame_paths) #视频秒数*FPS + assert num_frame != 0 + + # 帧图像高度和宽度 + h, w, _ = frames[0].shape + + # Get clip_len, frame_interval and calculate center index of each clip + data_process_pipeline = build_pipeline( + self.config.PIPELINE.test) #测试时输出处理流水配置 + + clip_len = self.config.PIPELINE.test.sample['clip_len'] + assert clip_len % 2 == 0, 'We would like to have an even clip_len' + frame_interval = self.config.PIPELINE.test.sample['frame_interval'] + + # 此处关键帧每秒取一个 + clip_len = self.config.PIPELINE.test.sample['clip_len'] + assert clip_len % 2 == 0, 'We would like to have an even clip_len' + frame_interval = self.config.PIPELINE.test.sample['frame_interval'] + window_size = clip_len * frame_interval + timestamps = np.arange(window_size // 2, + (num_frame + 1 - window_size // 2), + self.predict_stepsize) + + selected_frame_list = [] + for timestamp in timestamps: + selected_frame_list.append(self.frame_paths[timestamp - 1]) + + # Load label_map + label_map_path = self.config.DATASET.test['label_file'] + self.categories, self.class_whitelist = read_labelmap( + open(label_map_path)) + label_map = {} + for item in self.categories: + id = item['id'] + name = item['name'] + label_map[id] = name + + self.label_map = label_map + + detection_result_dir = 'tmp_detection' + detection_model_name = self.detection_model_name + detection_model_weights = self.detection_model_weights + detection_txt_list = detection_inference(selected_frame_list, + detection_result_dir, + detection_model_name, + detection_model_weights) + assert len(detection_txt_list) == len(timestamps) + + human_detections = [] + data_list = [] + person_num_list = [] + + for timestamp, detection_txt_path in zip(timestamps, + detection_txt_list): + proposals, scores = get_detection_result( + detection_txt_path, h, w, + (float)(self.config.DATASET.test['person_det_score_thr'])) + + if proposals.shape[0] == 0: + #person_num_list.append(0) + human_detections.append(None) + continue + + human_detections.append(proposals) + + result = get_timestep_result(frame_dir, + timestamp, + clip_len, + frame_interval, + FPS=FPS) + result["proposals"] = proposals + result["scores"] = scores + + new_result = data_process_pipeline(result) + proposals = new_result['proposals'] + + img_slow = new_result['imgs'][0] + img_slow = img_slow[np.newaxis, :] + img_fast = new_result['imgs'][1] + img_fast = img_fast[np.newaxis, :] + + proposals = proposals[np.newaxis, :] + + scores = scores[np.newaxis, :] + + img_shape = np.asarray(new_result['img_shape']) + img_shape = img_shape[np.newaxis, :] + + data = [ + paddle.to_tensor(img_slow, dtype='float32'), + paddle.to_tensor(img_fast, dtype='float32'), + paddle.to_tensor(proposals, dtype='float32'), + paddle.to_tensor(img_shape, dtype='int32') + ] + + person_num = proposals.shape[1] + person_num_list.append(person_num) + + data_list.append(data) + + self.human_detections = human_detections + self.person_num_list = person_num_list + self.timestamps = timestamps + self.frame_dir = frame_dir + self.detection_result_dir = detection_result_dir + + return data_list + + def postprocess(self, outputs, print_output=True): + """ + output: list + """ + predictions = [] + + assert len(self.person_num_list) == len(outputs) + + #print("*** self.human_detections",len( self.human_detections)) + #print("*** outputs",len( outputs)) + + index = 0 + for t_index in range(len(self.timestamps)): + if self.human_detections[t_index] is None: + predictions.append(None) + continue + + human_detection = self.human_detections[t_index] + + output = outputs[index] + result = output #长度为类别个数,不包含背景 + + person_num = self.person_num_list[index] + + index = index + 1 + + prediction = [] + + if human_detection is None: + predictions.append(None) + continue + + # N proposals + for i in range(person_num): + prediction.append([]) + + # Perform action score thr + for i in range(len(result)): # for class + if i + 1 not in self.class_whitelist: + continue + for j in range(person_num): + if result[i][j, 4] > self.config.MODEL.head['action_thr']: + prediction[j].append( + (self.label_map[i + 1], result[i][j, 4] + )) # label_map is a dict, label index start from 1 + predictions.append(prediction) + + results = [] + for human_detection, prediction in zip(self.human_detections, + predictions): + results.append(pack_result(human_detection, prediction)) + + def dense_timestamps(timestamps, n): + """Make it nx frames.""" + old_frame_interval = (timestamps[1] - timestamps[0]) + start = timestamps[0] - old_frame_interval / n * (n - 1) / 2 + new_frame_inds = np.arange( + len(timestamps) * n) * old_frame_interval / n + start + return new_frame_inds.astype(np.int) + + dense_n = int(self.predict_stepsize / self.output_stepsize) #30 + frames = [ + cv2.imread(self.frame_paths[i - 1]) + for i in dense_timestamps(self.timestamps, dense_n) + ] + + vis_frames = visualize(frames, results) + + try: + import moviepy.editor as mpy + except ImportError: + raise ImportError('Please install moviepy to enable output file') + + vid = mpy.ImageSequenceClip([x[:, :, ::-1] for x in vis_frames], + fps=self.output_fps) + vid.write_videofile(self.out_filename) + print("finish write !") + + # delete tmp files and dirs + shutil.rmtree(self.frame_dir) + shutil.rmtree(self.detection_result_dir) + + +@INFERENCE.register() +class PoseC3D_Inference_helper(Base_Inference_helper): + def __init__(self, top_k=1): + self.top_k = top_k + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + with open(input_file, 'rb') as f: + data = pickle.load(f) + self.input_file = input_file + + left_kp = [1, 3, 5, 7, 9, 11, 13, 15] + right_kp = [2, 4, 6, 8, 10, 12, 14, 16] + ops = [ + UniformSampleFrames(clip_len=48, num_clips=10, test_mode=True), + PoseDecode(), + PoseCompact(hw_ratio=1., allow_imgpad=True), + Resize(scale=(-1, 56)), + CenterCrop_V2(crop_size=56), + GeneratePoseTarget(sigma=0.6, + use_score=True, + with_kp=True, + with_limb=False, + double=True, + left_kp=left_kp, + right_kp=right_kp), + FormatShape(input_format='NCTHW'), + Collect(keys=['imgs', 'label'], meta_keys=[]) + ] + + for op in ops: + results = op(data) + results = [results[0][np.newaxis, :, :, :, :, :]] + self.num_segs = results[0].shape[1] + return results + + def postprocess(self, outputs, print_output=True): + batch_size = outputs[0].shape[0] + cls_score = outputs[0].reshape( + [batch_size // self.num_segs, self.num_segs, outputs[0].shape[-1]]) + output = F.softmax(paddle.to_tensor(cls_score), + axis=2).mean(axis=1).numpy() + N = len(self.input_file) + for i in range(N): + classes = np.argpartition(output[i], -self.top_k)[-self.top_k:] + classes = classes[np.argsort(-output[i, classes])] + scores = output[i, classes] + if print_output: + print("Current video file: {0}".format(self.input_file[i])) + for j in range(self.top_k): + print("\ttop-{0} class: {1}".format(j + 1, classes[j])) + print("\ttop-{0} score: {1}".format(j + 1, scores[j])) + + +@INFERENCE.register() +class YOWO_Inference_helper(Base_Inference_helper): + + def __init__(self, + num_seg=16, + target_size=224, + nms_thresh=0.5, + conf_thresh_valid=0.5, + mean=[0.4345, 0.4051, 0.3775], + std=[0.2768, 0.2713, 0.2737]): + self.num_seg = num_seg + self.target_size = target_size + self.nms_thresh = nms_thresh + self.conf_thresh_valid = conf_thresh_valid + self.mean = mean + self.std = std + + def preprocess(self, input_file): + """ + input_file: str, file path + return: list + """ + assert os.path.isfile(input_file) is not None, "{0} not exists".format( + input_file) + cap = cv2.VideoCapture(input_file) + queue = [] + inputs = [] + frames = [] + while (cap.isOpened()): + ret, frame = cap.read() + if ret == False: + break + if len(queue) <= 0: # At initialization, populate queue with initial frame + for i in range(self.num_seg): + queue.append(frame) + + # Add the read frame to last and pop out the oldest one + queue.append(frame) + queue.pop(0) + + # Resize images + imgs = [cv2.resize(img, (self.target_size, self.target_size), interpolation=cv2.INTER_LINEAR) for img in + queue] + + # Convert image to CHW keeping BGR order. + imgs = [img.transpose([2, 0, 1]) for img in imgs] + + # Image [0, 255] -> [0, 1]. + imgs = [img / 255.0 for img in imgs] + + imgs = [ + np.ascontiguousarray( + img.reshape((3, imgs[0].shape[1], imgs[0].shape[2])) + ).astype(np.float32) + for img in imgs + ] + + # Concat list of images to single ndarray. + imgs = np.concatenate( + [np.expand_dims(img, axis=1) for img in imgs], axis=1 + ) + + imgs = np.ascontiguousarray(imgs) + imgs = np.expand_dims(imgs, axis=0) + imgs = np.expand_dims(imgs, axis=0) + inputs.append(imgs) + frames.append(queue[-1]) + + return inputs, frames + + def postprocess(self, outputs, frame, filename, save_img=True): + """ + outputs: list + frames: list + """ + labels = [ + "Basketball", "BasketballDunk", "Biking", "CliffDiving", "CricketBowling", + "Diving", "Fencing", "FloorGymnastics", "GolfSwing", "HorseRiding", + "IceDancing", "LongJump", "PoleVault", "RopeClimbing", "SalsaSpin", + "SkateBoarding", "Skiing", "Skijet", "SoccerJuggling", "Surfing", + "TennisSwing", "TrampolineJumping", "VolleyballSpiking", "WalkingWithDog"] + nms_thresh = 0.5 + font = cv2.FONT_HERSHEY_SIMPLEX + for out in outputs: + out = paddle.to_tensor(out) + preds = [] + all_boxes = get_region_boxes(out) + for i in range(out.shape[0]): + boxes = all_boxes[i] + boxes = nms(boxes, nms_thresh) + + for box in boxes: + x1 = round(float(box[0] - box[2] / 2.0) * 320.0) + y1 = round(float(box[1] - box[3] / 2.0) * 240.0) + x2 = round(float(box[0] + box[2] / 2.0) * 320.0) + y2 = round(float(box[1] + box[3] / 2.0) * 240.0) + + det_conf = float(box[4]) + for j in range((len(box) - 5) // 2): + cls_conf = float(box[5 + 2 * j].item()) + prob = det_conf * cls_conf + preds.append([[x1, y1, x2, y2], prob, labels[int(box[6])]]) + + for _, dets in enumerate(preds): + if dets[1] < 0.4: + break + text = dets[2] + ' ' + '{:.2f}'.format(dets[1]) + cv2.rectangle(frame, (dets[0][0], dets[0][1]), (dets[0][2], dets[0][3]), (0, 255, 0), 2) + cv2.putText(frame, text, (dets[0][0] + 3, dets[0][1] - 5 - 10 * _), font, 0.5, (0, 255, 0), 2) + cv2.imwrite('{}.jpg'.format(filename), frame) \ No newline at end of file diff --git a/Bank_second_part/detect_process/tools/wheel.py b/Bank_second_part/detect_process/tools/wheel.py new file mode 100644 index 0000000..77281be --- /dev/null +++ b/Bank_second_part/detect_process/tools/wheel.py @@ -0,0 +1,354 @@ +# 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. + +# 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 sys + +__dir__ = os.path.dirname(__file__) +sys.path.append(os.path.join(__dir__, '')) + +import numpy as np +import tarfile +import requests +from tqdm import tqdm +import shutil + +from paddle import inference +from paddle.inference import Config, create_predictor + +from tools.utils import ppTSM_Inference_helper + +__all__ = ['PaddleVideo'] + +# path of download model and data +BASE_DIR = os.path.expanduser("~/.paddlevideo_inference/") +BASE_INFERENCE_MODEL_DIR = os.path.join(BASE_DIR, 'inference_model') +BASE_VIDEOS_DIR = os.path.join(BASE_DIR, 'videos') + +# support Models +MODELS = { + 'ppTSM': + 'https://videotag.bj.bcebos.com/PaddleVideo/InferenceModel/ppTSM_infer.tar', + 'ppTSM_v2': + 'https://videotag.bj.bcebos.com/PaddleVideo/InferenceModel/ppTSM_v2_infer.tar' +} + +MODEL_NAMES = list(MODELS.keys()) + + +def parse_args(mMain=True, add_help=True): + """ + Args: + mMain: bool. True for command args, False for python interface + """ + import argparse + + def str2bool(v): + return v.lower() in ("true", "t", "1") + + if mMain == True: + + # general params + parser = argparse.ArgumentParser(add_help=add_help) + parser.add_argument("--model_name", type=str, default='') + parser.add_argument("-v", "--video_file", type=str, default='') + parser.add_argument("--use_gpu", type=str2bool, default=True) + + # params for decode and sample + parser.add_argument("--num_seg", type=int, default=16) + + # params for preprocess + parser.add_argument("--short_size", type=int, default=256) + parser.add_argument("--target_size", type=int, default=224) + + # params for predict + parser.add_argument("--model_file", type=str, default='') + parser.add_argument("--params_file", type=str) + parser.add_argument("-b", "--batch_size", type=int, default=1) + parser.add_argument("--use_fp16", type=str2bool, default=False) + parser.add_argument("--ir_optim", type=str2bool, default=True) + parser.add_argument("--use_tensorrt", type=str2bool, default=False) + parser.add_argument("--gpu_mem", type=int, default=8000) + parser.add_argument("--top_k", type=int, default=1) + parser.add_argument("--enable_mkldnn", type=bool, default=False) + parser.add_argument("--label_name_path", type=str, default='') + + return parser.parse_args() + + else: + return argparse.Namespace(model_name='', + video_file='', + use_gpu=True, + num_seg=16, + short_size=256, + target_size=224, + model_file='', + params_file='', + batch_size=1, + use_fp16=False, + ir_optim=True, + use_tensorrt=False, + gpu_mem=8000, + top_k=1, + enable_mkldnn=False, + label_name_path='') + + +def parse_file_paths(input_path: str) -> list: + if os.path.isfile(input_path): + files = [ + input_path, + ] + else: + files = os.listdir(input_path) + files = [ + file for file in files + if (file.endswith(".avi") or file.endswith(".mp4")) + ] + files = [os.path.join(input_path, file) for file in files] + return files + + +def download_with_progressbar(url, save_path): + response = requests.get(url, stream=True) + total_size_in_bytes = int(response.headers.get('content-length', 0)) + block_size = 1024 # 1 Kibibyte + progress_bar = tqdm(total=total_size_in_bytes, unit='iB', unit_scale=True) + with open(save_path, 'wb') as file: + for data in response.iter_content(block_size): + progress_bar.update(len(data)) + file.write(data) + progress_bar.close() + if total_size_in_bytes == 0 or progress_bar.n != total_size_in_bytes: + raise Exception("Something went wrong while downloading models") + + +def download_inference_model(model_storage_directory, url): + # using custom model + tar_file_name_list = [ + 'inference.pdiparams', 'inference.pdiparams.info', 'inference.pdmodel' + ] + if not os.path.exists( + os.path.join(model_storage_directory, + 'inference.pdiparams')) or not os.path.exists( + os.path.join(model_storage_directory, + 'inference.pdmodel')): + tmp_path = os.path.join(model_storage_directory, url.split('/')[-1]) + print('download {} to {}'.format(url, tmp_path)) + os.makedirs(model_storage_directory, exist_ok=True) + download_with_progressbar(url, tmp_path) #download + + #save to directory + with tarfile.open(tmp_path, 'r') as tarObj: + for member in tarObj.getmembers(): + filename = None + for tar_file_name in tar_file_name_list: + if tar_file_name in member.name: + filename = tar_file_name + if filename is None: + continue + file = tarObj.extractfile(member) + with open(os.path.join(model_storage_directory, filename), + 'wb') as f: + f.write(file.read()) + os.remove(tmp_path) + + +def create_paddle_predictor(args): + config = Config(args.model_file, args.params_file) + + if args.use_gpu: + config.enable_use_gpu(args.gpu_mem, 0) + else: + config.disable_gpu() + if args.enable_mkldnn: + # cache 10 different shapes for mkldnn to avoid memory leak + config.set_mkldnn_cache_capacity(10) + config.enable_mkldnn() + + config.disable_glog_info() + config.switch_ir_optim(args.ir_optim) # default true + if args.use_tensorrt: + config.enable_tensorrt_engine( + precision_mode=Config.Precision.Half + if args.use_fp16 else Config.Precision.Float32, + max_batch_size=args.batch_size) + + config.enable_memory_optim() + # use zero copy + config.switch_use_feed_fetch_ops(False) + predictor = create_predictor(config) + + return predictor + + +def load_label_name_dict(path): + result = {} + if not os.path.exists(path): + print( + 'Warning: If want to use your own label_dict, please input legal path!\nOtherwise label_names will be empty!' + ) + else: + for line in open(path, 'r'): + partition = line.split('\n')[0].partition(' ') + try: + result[int(partition[0])] = str(partition[-1]) + except: + result = {} + break + return result + + +class PaddleVideo(object): + def __init__(self, **kwargs): + print( + '\nInference models that Paddle provides are listed as follows:\n{}' + .format(MODEL_NAMES), '\n') + process_params = parse_args(mMain=False, add_help=False) + process_params.__dict__.update(**kwargs) + + if not os.path.exists(process_params.model_file): + if process_params.model_name is None: + raise Exception('Please input model name that you want to use!') + if process_params.model_name in MODEL_NAMES: + url = MODELS[process_params.model_name] + download_path = os.path.join(BASE_INFERENCE_MODEL_DIR, + process_params.model_name) + if not os.path.exists(download_path): + os.makedirs(download_path) + + #create pretrained model download_path + download_inference_model(model_storage_directory=download_path, + url=url) + + process_params.model_file = os.path.join( + download_path, 'inference.pdmodel') + process_params.params_file = os.path.join( + download_path, 'inference.pdiparams') + process_params.label_name_path = os.path.join( + __dir__, '../data/k400/Kinetics-400_label_list.txt') + else: + raise Exception( + 'If you want to use your own model, Please input model_file as model path!' + ) + else: + print('Using user-specified model and params!') + print("process params are as follows: \n{}".format(process_params)) + self.label_name_dict = load_label_name_dict( + process_params.label_name_path) + + self.args = process_params + self.predictor = create_paddle_predictor(process_params) + + def predict(self, video): + """ + predict label of video with paddlevideo + Args: + video:input video for clas, support single video , internet url, folder path containing series of videos + Returns: + list[dict:{videoname: "",class_ids: [], scores: [], label_names: []}],if label name path is None,label names will be empty + """ + video_list = [] + assert isinstance(video, (str)) + + # get input_tensor and output_tensor + input_names = self.predictor.get_input_names() + output_names = self.predictor.get_output_names() + input_tensor_list = [] + output_tensor_list = [] + for item in input_names: + input_tensor_list.append(self.predictor.get_input_handle(item)) + for item in output_names: + output_tensor_list.append(self.predictor.get_output_handle(item)) + + if isinstance(video, str): + # download internet video + if video.startswith('http'): + if not os.path.exists(BASE_VIDEOS_DIR): + os.makedirs(BASE_VIDEOS_DIR) + video_path = os.path.join(BASE_VIDEOS_DIR, 'tmp.mp4') + download_with_progressbar(video, video_path) + print("Current using video from Internet:{}, renamed as: {}". + format(video, video_path)) + video = video_path + files = parse_file_paths(video) + else: + print('Please input legal video!') + + # Inferencing process + InferenceHelper = ppTSM_Inference_helper( + num_seg=self.args.num_seg, + short_size=self.args.short_size, + target_size=self.args.target_size, + top_k=self.args.top_k) + batch_num = self.args.batch_size + for st_idx in range(0, len(files), batch_num): + ed_idx = min(st_idx + batch_num, len(files)) + + # Pre process batched input + batched_inputs = InferenceHelper.preprocess_batch( + files[st_idx:ed_idx]) + + # run inference + for i in range(len(input_tensor_list)): + input_tensor_list[i].copy_from_cpu(batched_inputs[i]) + self.predictor.run() + + batched_outputs = [] + for j in range(len(output_tensor_list)): + batched_outputs.append(output_tensor_list[j].copy_to_cpu()) + + results_list = InferenceHelper.postprocess(batched_outputs, + print_output=False, + return_result=True) + + for res in results_list: + classes = res["topk_class"] + label_names = [] + if len(self.label_name_dict) != 0: + label_names = [self.label_name_dict[c] for c in classes] + res["label_names"] = label_names + + print("Current video file: {0}".format(res["video_id"])) + print("\ttop-{0} classes: {1}".format(len(res["topk_class"]), + res["topk_class"])) + print("\ttop-{0} scores: {1}".format(len(res["topk_scores"]), + res["topk_scores"])) + print("\ttop-{0} label names: {1}".format( + len(res["label_names"]), res["label_names"])) + + +def main(): + # for cmd + args = parse_args(mMain=True) + clas_engine = PaddleVideo(**(args.__dict__)) + clas_engine.predict(args.video_file) + + +if __name__ == '__main__': + main() diff --git a/Bank_second_part/detect_process/tools_function.py b/Bank_second_part/detect_process/tools_function.py new file mode 100644 index 0000000..14eb9a3 --- /dev/null +++ b/Bank_second_part/detect_process/tools_function.py @@ -0,0 +1,353 @@ +import cv2 +import os + + + +# 图像文件夹 +def get_video_list(path): + video_ext = [".mp4", ".avi",".MP4"] + video_names = [] + for maindir, subdir, file_name_list in os.walk(path): + for filename in file_name_list: + apath = os.path.join(maindir, filename) + ext = os.path.splitext(apath)[1] + if ext in video_ext: + video_names.append(apath) + return video_names + + +# # 截取裁剪需要的视频帧 +# def save_seg_video(video_name, frameToStart, frametoStop, videoWriter, bbox): +# cap = video_name +# cap.set(cv2.CAP_PROP_POS_FRAMES, frameToStart) # 设置初始帧数 +# count = frameToStart + +# while True: +# success, frame = cap.read() + +# if not success or count > frametoStop: +# break + +# if count >= frameToStart: +# # 裁剪视频画面 +# frame_target = frame[int(bbox[1]):int(bbox[3]), int(bbox[0]):int(bbox[2])] +# videoWriter.write(frame_target) + +# count += 1 + +# cap.release() + + # 截取裁剪需要的视频帧 +def save_seg_video(video_name,frameToStart,frametoStop,videoWriter,bbox): + + cap = cv2.VideoCapture(video_name) + count = 0 + while True: + success,frame = cap.read() + if success: + count += 1 + if count <= frametoStop and count > frameToStart: # 选取起始帧 + # print('correct= ', count) + + #裁剪视频画面 + frame_target = frame[int(bbox[1]):int(bbox[3]), int(bbox[0]):int(bbox[2])] # (split_height, split_width) + frame_target = cv2.resize(frame_target,(200,200)) + + videoWriter.write(frame_target) + + if not success or count >= frametoStop: + break + + videoWriter.release() + cap.release() + + + + +# 获得字典中所有values值(这个值是列表) +def get_dict_values(lst): + """ + 获取列表中所有字典的 values 值(如果值是列表) + + 参数: + lst: 包含字典的列表 + + 返回值: + values: 包含所有字典的 values 值的列表(如果值是列表) + """ + return [value for dictionary in lst for value in dictionary.values() if isinstance(value, list)] + + + # 解析检测后的结果,为检测后的结果排序 +def analysis_sort_list(re_list): + + # print('result_dict:',result_dict) + + # 获得检测列表 + # re_list = result_dict['start_bbox'] + # print('re_list:',re_list) + + # 获得列表中所有字典的values值 + # re_bbox_list = Process_tools.get_dict_values(re_list) + + # 为检测出来的标注框排序 + sorted_lst = sorted(re_list, key=lambda x: x[0]) + + return sorted_lst + + + #对比重叠率高的两个部分,并结合标注框,保存最大的标注框 +def contrast_bbox(e_bbox,r_bbox): + + e_bbox_min = e_bbox[:2] + r_bbox_min = r_bbox[:2] + + bbox_min = [min(x, y) for x, y in zip(e_bbox_min, r_bbox_min)] + + e_bbox_max = e_bbox[-2:] + r_bbox_max = r_bbox[-2:] + + bbox_max = [max(x, y) for x, y in zip(e_bbox_max, r_bbox_max)] + + bbox = bbox_min + bbox_max + + return bbox + + + # 解析result_list列表 +def analysis_re01_list(example_list,result_list): + + ''' + example_dict:对比的参照 + result_dict: 需要与参照对比的结果 + + example_sorted_lst:返回值中,原先有现在没有部分 + re_dict_sorted_lst:返回值中,现在有原先没有部分 + + cut_list:原先有,现在也有的部分 + + ''' + # 第一次检测到目标的帧率和信息 + # example_dict_fps = list(example_dict.keys())[0] + # example_sorted_lst = Process_tools.analysis_sort_list(example_list) + + # 当前帧检测结果中所有的检测结果数值 + # re_dict_fps = list(result_dict.keys())[0] + # re_dict_sorted_lst = Process_tools.analysis_sort_list(result_list) + + # 保存前后帧率连续的范围、筛选出相同的部分 + cut_list = [] + example_temp = [] + re_temp = [] + + for i,ex_bbox_dict in enumerate(example_list): + + ex_bbox = ex_bbox_dict['result'] + + for j,re_bbox in enumerate(result_list): + + iou = calculate_iou(box1=ex_bbox, box2=re_bbox) + + # print(iou) + + if iou > 0.5: + + # bbox = Process_tools.contrast_bbox(e_bbox=ex_bbox,r_bbox=re_bbox) + + # cut_list.append({i:re_bbox}) + cut_list.append(re_bbox) + example_temp.append(ex_bbox) + re_temp.append(re_bbox) + + break + + # print('example_temp:',example_temp) + # print('re_temp:',re_temp) + example_sorted_lst = [item for item in example_list if item['result'] not in example_temp] + re_dict_sorted_lst = [item for item in result_list if item not in re_temp] + + return cut_list,example_sorted_lst,re_dict_sorted_lst + + +# 计算前后帧率重叠范围 +def calculate_iou(box1, box2): + """ + 计算两个边界框之间的IoU值 + + 参数: + box1: 边界框1的坐标(x1, y1, x2, y2) + box2: 边界框2的坐标(x1, y1, x2, y2) + + 返回值: + iou: 两个边界框之间的IoU值 + """ + x1 = max(box1[0], box2[0]) + y1 = max(box1[1], box2[1]) + x2 = min(box1[2], box2[2]) + y2 = min(box1[3], box2[3]) + + # 计算交集区域面积 + intersection_area = max(0, x2 - x1 + 1) * max(0, y2 - y1 + 1) + + # 计算边界框1和边界框2的面积 + box1_area = (box1[2] - box1[0] + 1) * (box1[3] - box1[1] + 1) + box2_area = (box2[2] - box2[0] + 1) * (box2[3] - box2[1] + 1) + + # 计算并集区域面积 + union_area = box1_area + box2_area - intersection_area + + # 计算IoU值 + iou = intersection_area / union_area + + return iou + +# 修正坐标参数 +def para_correction(images_size,bbox,dertpara): + + ''' + 修正检测后标注框过小的情况,如果有修正参数则使用修正参数,如果没有就按照坐标值扩大两倍 + + ''' + + # if dertpara: + # pass + # else: + w = (bbox[2] - bbox[0]) / int(dertpara) + h = (bbox[3] - bbox[1]) / int(dertpara) + + bbox_extand_list_x = [bbox[0] - w,bbox[2] + w] + bbox_extand_list_y = [bbox[1] - h,bbox[3] + h] + + bbox_list_x = contrast(size=images_size[0],bbox_extand_list=bbox_extand_list_x) + bbox_list_y = contrast(size=images_size[1],bbox_extand_list=bbox_extand_list_y) + + bbox_list = [bbox_list_x[0],bbox_list_y[0],bbox_list_x[1],bbox_list_y[1]] + + return bbox_list + + +def para_list_correction(images_size,bbox_list,dertpara): + + updata_result_list = [] + + for bbox in bbox_list: + + updata_bbox = para_correction(images_size,bbox,dertpara) + + updata_result_list.append(updata_bbox) + + return updata_result_list + +# 对比数值是否在这个范围内 +def contrast(size,bbox_extand_list): + + ''' + 对比数值是否在这个范围内 + ''' + + # print('bbox_extand_list:',bbox_extand_list) + # print('size:',size) + bbox_list = [] + + for x in bbox_extand_list: + + # print('size:',size) + + if 0 <= int(x) <= int(size): + # print('in:',x,size) + bbox_list.append(x) + if int(x) > int(size): + # print('>:',x,size) + bbox_list.append(size) + if int(x) < 0: + # print('<:',x,size) + bbox_list.append(0) + + # print('bbox_list:',bbox_list) + + return bbox_list + + +def change_list_dict(fps1,re_list): + + ''' + 给列表的结果设置对应帧率 + ''' + + bbox_list_all = [] + + for bbox_list in re_list: + + bbox_dict = {'fps':fps1,'result':bbox_list} + bbox_list_all.append(bbox_dict) + + return bbox_list_all + + +def statistics_fps(fps_now,re_list,parameter): + + ''' + 统计时长,返回时间满足截取要求的目标坐标 + ''' + + time_out_list = [] + + for bbox_dict in re_list: + + con_fps = int(fps_now) - int(bbox_dict["fps"]) + + if con_fps > parameter: + + time_out_list.append(bbox_dict) + + return time_out_list + + +def change_dict_list(dict_list): + ''' + 从字典列表得到bbox列表 + ''' + + bbox_list = [] + + for dicts1 in dict_list: + + bbox_list.append(dicts1['result']) + + return bbox_list + + +def select_list(result_list): + + ''' + 筛选列表中的空列表 + ''' + if result_list: + result_only = [] + + for result in result_list: + + if result == None : + pass + else: + + # result_bbox = select_bbox(result) + result_only.append(result) + + return result_only + +def select_bbox(bbox_list): + + # bbox_list_return = [] + + # print('bbox:',bbox_list) + left_top = [min(bbox_list, key=lambda p: p[0])[0], min(bbox_list, key=lambda p: p[1])[1]] + right_bottom = [max(bbox_list, key=lambda p: p[0])[0], max(bbox_list, key=lambda p: p[1])[1]] + + bbox_list_return = left_top + right_bottom + + + # print('bbox_list:',bbox_list_return) + + return bbox_list_return + \ No newline at end of file diff --git a/Bank_second_part/detect_process/video_process.py b/Bank_second_part/detect_process/video_process.py index c928a68..5c6ced6 100644 --- a/Bank_second_part/detect_process/video_process.py +++ b/Bank_second_part/detect_process/video_process.py @@ -1,4 +1,3 @@ -import numpy as np import cv2 import os import time @@ -11,8 +10,11 @@ import threading from config import Q_SZ from personDet import analysis_yolov8 -import tools +import tools_function from holisticDet import MediapipeProcess +import mediapipe_detection_image +from PP_TSMv2_infer import PP_TSMv2_predict +import shutil @@ -31,24 +33,25 @@ class DealVideo(): self.person_model = person_model self.mediapipe_model = mediapipe_model - self.pptsmv2_model = pptsmv2_model + self.predictor = pptsmv2_model[1] + self.infer = pptsmv2_model[0] + self.batch_size = 1 - # 图片检测后队列 + # 队列 self.videoQueue = queue.Queue(maxsize=Q_SZ) - self.frameQueue = queue.Queue(maxsize=0) + self.videoQueue2 = queue.Queue(maxsize=Q_SZ) self.cutbboxQueue = queue.Queue(maxsize=0) - self.videoframeQueue = queue.Queue(maxsize=0) - self.videohandsQueue = queue.Queue(maxsize=0) - self.videoheadQueue = queue.Queue(maxsize=0) - self.videopersonQueue = queue.Queue(maxsize=0) + self.videodetQueue = queue.Queue(maxsize=0) + self.videoQueue3 = queue.Queue(maxsize=0) #线程 self.get_video_listThread = threading.Thread(target=self.get_video_list) self.get_video_frameThread = threading.Thread(target=self.get_video_frame) - self.person_detThread = threading.Thread(target=self.person_det) self.write_videoThread = threading.Thread(target=self.write_video) - self.select_video_frameThread = threading.Thread(target=self.select_video_frame) self.head_hands_detThread = threading.Thread(target=self.head_hands_det) + self.video_select_dectThread = threading.Thread(target=self.video_select_dect) + self.select_video_pathThread = threading.Thread(target=self.select_video_path) + def get_video_list(self): @@ -70,173 +73,268 @@ class DealVideo(): else: self.videoQueue.put(self.video_file) - # def cut_video_seg(self): - - # pass - def get_video_frame(self): ''' 对视频进行分帧、每一帧都保存队列 ''' - while True: - if ~self.videoQueue.empty(): - - try: - video_path = self.videoQueue.get() - - # video_basename = os.path.basename(video_path).split('.')[0] + if self.videoQueue.empty(): - cap = cv2.VideoCapture(video_path) + time.sleep(1) + + else: + + t1 = time.time() + video_path = self.videoQueue.get() + + # video_basename = os.path.basename(video_path).split('.')[0] - frame_list = [] - count_fps = 0 + print('video_path:',video_path) - while cap.isOpened(): - success, frame = cap.read() - if not success: - print(video_path,"Ignoring empty camera frame.") - break - count_fps += 1 - # print('count_fps_read_video=',count_fps) + cap = cv2.VideoCapture(video_path) + video_fps = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) - frame_dict = {'fps':count_fps,'frame':frame} - frame_list.append(frame_dict) - + # frame_list = [] + count_fps = 0 + frame_result_contact = [] + count_fps_del = 0 - video_dict = {'video_path':video_path,'frame_list':frame_list} - - self.frameQueue.put(video_dict) - # time.sleep(30) + while cap.isOpened(): + success, frame = cap.read() + if not success: + print(video_path,"Ignoring empty camera frame.") + print('video_fps:',video_fps,'count_fps:',count_fps) + break + + # print('count_fps_read_video=',count_fps) + imgsize = frame.shape - except Exception as e: - print(e) + person_det = analysis_yolov8(frame=frame, + model_coco=self.person_model, + confidence_set=0.5) + person_list = tools_function.get_dict_values(person_det) - def person_det(self): + if frame_result_contact: + start_fps = frame_result_contact[0]['fps'] + + else: + start_fps = count_fps - ''' - 从队列中获取视频帧frame,进行第一步人员的检测 - ''' + if count_fps == (video_fps - 1): - while True: + video_end = True - if ~self.videoframeQueue.empty(): + else: - video_frame_dict = self.videoframeQueue.get() + video_end = False - frame_list = video_frame_dict['frame_list'] - video_path = video_frame_dict['video_path'] + if person_list: - frame_result_contact = [] + count_fps_del_re,updata_result_contact = self.analysis_by_bbox(imgsize=imgsize, + detect_result=person_list, + dertpara=10, + start_fps=start_fps, + now_fps=count_fps, + label_name='person', + video_path=video_path, + frame_result_contact=frame_result_contact, + parameter_fps=200, + count_fps_del=count_fps_del, + video_end=video_end + ) + count_fps_del = count_fps_del_re + frame_result_contact = updata_result_contact - for i in range(len(frame_list)): + count_fps += 1 - if frame_list[i]["fps"] == i + 1: - person_det = analysis_yolov8(frame=frame_list[i]['frame'], - model_coco=self.person_model, - confidence_set=0.5) - - # 当前帧检测的结果列表,只包含bboxlist - person_list = tools.get_dict_values(person_det) - label_name = list(person_det[0].keys())[0] + def head_hands_det(self): - update_frame_result_contact = self.get_cut_message(fps1=frame_list[i]["fps"], - label_name = label_name, - re_list=person_list, - video_path=video_path, - frame_result_contact=frame_result_contact) - - frame_result_contact = update_frame_result_contact - # print('frame_result_contact:',frame_result_contact) + print('head_hands_detaohgaogh') + while True: - def head_hands_det(self): + if self.videoQueue3.empty(): - while True: + time.sleep(1) + else: - if ~self.videopersonQueue.empty(): + t0 = time.time() + video_path = self.videoQueue3.get() - person_frame_dict = self.videopersonQueue.get() + print('video_path_head_hands_det:',video_path) - person_frame_list = person_frame_dict['frame_list'] - video_path = person_frame_dict['video_path'] + cap = cv2.VideoCapture(video_path) + video_fps = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) + + # frame_list = [] + count_fps = 0 head_result_contact = [] hands_result_contact = [] + count_fps_del_head = 0 + count_fps_del_hand = 0 - for i in range(len(person_frame_list)): + while cap.isOpened(): + success, frame = cap.read() + if not success: + print(video_path,"Ignoring empty camera frame.") + print('count_fps:',count_fps,'video_fps:',video_fps) + break - if person_frame_list[i]["fps"] == i + 1: + # print('count_fps_read_video=',count_fps) + imgsize = frame.shape - image = person_frame_list[i]["frame"] + # 模型推理 + hh_result = MediapipeProcess.mediapipe_det(image=frame, + holistic=self.mediapipe_model) + hh_result_dict = MediapipeProcess.get_analysis_result(image=frame,results=hh_result) - imgsize = image.shape + # # 获得当前坐标列表 + head_result = hh_result_dict['face_bbox'] + head_result_1 = tools_function.select_list(head_result) + hands_result = hh_result_dict['hand_bbox'] + hands_result_1 = tools_function.select_list(hands_result) - # print(type(image)) + + if count_fps == (video_fps - 1): + + print('count_fps:',count_fps,'video_fps:',video_fps) + + video_end = True + else: + + video_end = False + + # 统一修正坐标,分别对头和手进行分析 + if head_result_1: + + if head_result_contact: + start_fps = head_result_contact[0]['fps'] + else: + start_fps = count_fps + count_fps_del_re,updata_result_contact = self.analysis_by_bbox(imgsize=imgsize, + detect_result=head_result_1, + dertpara=1, + start_fps=start_fps, + now_fps=count_fps, + label_name='head', + video_path=video_path, + frame_result_contact=head_result_contact, + parameter_fps=50, + count_fps_del=count_fps_del_head, + video_end=video_end + ) + count_fps_del_head = count_fps_del_re + head_result_contact = updata_result_contact + + if hands_result_1: + + if hands_result_contact: + start_fps = hands_result_contact[0]['fps'] + else: + start_fps = count_fps + + count_fps_del_re,updata_result_contact = self.analysis_by_bbox(imgsize=imgsize, + detect_result=hands_result_1, + dertpara=2, + start_fps=start_fps, + now_fps=count_fps, + label_name='hands', + video_path=video_path, + frame_result_contact=hands_result_contact, + parameter_fps=50, + count_fps_del=count_fps_del_hand, + video_end=video_end + ) + count_fps_del_hand = count_fps_del_re + hands_result_contact = updata_result_contact + + count_fps += 1 + + + def video_select_dect(self): - # 模型推理 - hh_result = MediapipeProcess.mediapipe_det(image=image, - holistic=self.mediapipe_model) - hh_result_dict = MediapipeProcess.get_analysis_result(image=image,results=hh_result) + while True: + if self.videodetQueue.empty(): + time.sleep(5) + else: - - # 获得当前坐标列表 - head_result = hh_result_dict['face_bbox'] - head_result_1 = tools.select_list(head_result) - hands_result = hh_result_dict['hand_bbox'] - hands_result_1 = tools.select_list(hands_result) - - print('head_result_1:',head_result_1) - print('head_result_1:',hands_result_1) - - # 统一修正坐标,分别对头和手进行分析 - if head_result_1: - head_bbox_list = tools.para_list_correction(images_size=imgsize, - bbox_list=head_result_1, - dertpara=[]) - - - update_head_result_contact = self.get_cut_message(fps1=person_frame_list[i]["fps"], - label_name = 'head', - re_list=head_bbox_list, - video_path=video_path, - frame_result_contact=head_result_contact) - head_result_contact = update_head_result_contact - - - if hands_result_1: - - hands_bbox_list = tools.para_list_correction(images_size=imgsize, - bbox_list=hands_result_1, - dertpara=[]) - - update_hands_result_contact = self.get_cut_message(fps1=person_frame_list[i]["fps"], - label_name = 'hands', - re_list=hands_bbox_list, - video_path=video_path, - frame_result_contact=hands_result_contact) - - hands_result_contact = update_hands_result_contact + video_path = self.videodetQueue.get() - # print("head_result_contact:",head_result_contact) - # print("hands_result_contact:",hands_result_contact) + try: + result_list = PP_TSMv2_predict().predict(input_f=video_path, + batch_size=self.batch_size, + predictor=self.predictor, + InferenceHelper=self.infer) + + video_base_name = os.path.basename(video_path) + video_save_select_path = self.video_save_file + '/' + 'video_select_dect/'+ str(result_list['topk_class']) + os.makedirs(video_save_select_path, exist_ok=True) + video_save = os.path.join(video_save_select_path, video_base_name) - def get_cut_message(self,fps1,label_name,re_list,video_path,frame_result_contact): + os.rename(video_path, video_save) + + print("result_list_video_select_dect:",result_list) + + except Exception as e: + print(e) + + def analysis_by_bbox(self,imgsize,detect_result,dertpara,start_fps,now_fps,label_name,video_path,frame_result_contact,parameter_fps,count_fps_del,video_end): + ''' + imgsize:图片的尺寸, + detect_result:检测到的图像的结果,bboxlist + dertpara:标注框修正参数,取整数,2,3 + start_fps: 对比列表中的起始帧 + now_fpsl:当前帧率 + label_name:用于分析的检测类别 + video_path:视频路径 + frame_result_contact:对比列表 + parameter_fps:统计截止时间 + count_fps_del:统计前后帧未出现次数 + + ''' + + bbox_list = tools_function.para_list_correction(images_size=imgsize, + bbox_list=detect_result, + dertpara=dertpara) + + count_fps_del_re,update_frame_result_contact = self.get_cut_message(fps1=now_fps, + label_name = label_name, + re_list=bbox_list, + video_path=video_path, + frame_result_contact=frame_result_contact, + parameter_fps=parameter_fps, + count_fps_del=count_fps_del, + video_end=video_end) + + # count_fps_del_re,updata_result_contact = self.get_continue_keys(count_fps_del=count_fps_del, + # continue_para=continue_para, + # start_fps=start_fps, + # now_fps=now_fps, + # frame_result_contact=frame_result_contact, + # update_frame_result_contact=update_frame_result_contact)\ + + return count_fps_del_re,update_frame_result_contact + + + def get_cut_message(self,fps1,label_name,re_list,video_path,frame_result_contact,parameter_fps,count_fps_del,video_end): + + # continue_para = False if not frame_result_contact: - bbox_list_all = tools.change_list_dict(fps1=fps1,re_list=re_list) + bbox_list_all = tools_function.change_list_dict(fps1=fps1,re_list=re_list) frame_result_contact = bbox_list_all # print("frame_result_contact:",frame_result_contact) @@ -244,41 +342,45 @@ class DealVideo(): else: example_dict_list = frame_result_contact - print('example_dict_list:',example_dict_list) - print('re_list:',re_list) - cut_list,example_lst,re_dict_lst = tools.analysis_re01_list(example_list=example_dict_list, + cut_list,example_lst,re_dict_lst = tools_function.analysis_re01_list(example_list=example_dict_list, result_list=re_list) - - # print('cut_list:',cut_list) - # print('example_sorted_lst:',example_lst) - # print('re_dict_sorted_lst:',re_dict_lst) - - # 有目标减少情况 if example_lst: - + # 截图保存视频 + # continue_para = True cut_dict = {'video_path':video_path,'label_name':label_name,"stop_fps":fps1,'bbox_list':example_lst} + + start_fps = example_lst[0]['fps'] - # 添加到新的队列 - self.cutbboxQueue.put(cut_dict) + if count_fps_del <= 3: + + frame_result_contact = frame_result_contact + count_fps_del = count_fps_del + 1 + + else: - frame_result_contact = [item for item in frame_result_contact if item not in example_lst] + if (fps1 - start_fps) < 10: + + frame_result_contact = frame_result_contact + else: + + frame_result_contact = [item for item in frame_result_contact if item not in example_lst] + self.cutbboxQueue.put(cut_dict) - # 有新添加目标情况 + # 有新添加目标情况 if re_dict_lst: # 对比示例列表更新 - update_list = tools.change_list_dict(fps1=fps1,re_list=re_dict_lst) + update_list = tools_function.change_list_dict(fps1=fps1,re_list=re_dict_lst) frame_result_contact = frame_result_contact + update_list # 统计截止时间 - time_out_list = tools.statistics_fps(fps_now=fps1,re_list=frame_result_contact,parameter=20) + time_out_list = tools_function.statistics_fps(fps_now=fps1,re_list=frame_result_contact,parameter=parameter_fps) - if time_out_list: # 裁剪保存视频 @@ -291,143 +393,183 @@ class DealVideo(): # 对比示例列表更新 frame_result_contact = [item for item in frame_result_contact if item not in time_out_list] + + if video_end: + + cut_dict = {'video_path':video_path,'label_name':label_name,"stop_fps":fps1,'bbox_list':frame_result_contact} + + self.cutbboxQueue.put(cut_dict) + + frame_result_contact.clear() # print('frame_result_contact:',frame_result_contact) - - return frame_result_contact + + return count_fps_del,frame_result_contact + + + # def get_continue_keys(self,count_fps_del,continue_para,start_fps,now_fps,frame_result_contact,update_frame_result_contact): + + # # 判断是否有偶然没检测到的情况 + # if continue_para: + + # dert_fps = now_fps - start_fps + + # print('dert_fps:',dert_fps) + + # if dert_fps <= 20: + + # count_fps_del = count_fps_del + 1 + + # if count_fps_del <= 3: + + # frame_result_contact = frame_result_contact + + # else: + + # frame_result_contact = update_frame_result_contact + # count_fps_del = 0 + + # else: + # count_fps_del = 0 + + # else: + + # frame_result_contact = update_frame_result_contact + + # return count_fps_del,frame_result_contact + def write_video(self): + # print('write_videoafagragr') ''' 保存成视频 ''' - while True: - - if ~self.cutbboxQueue.empty(): - + if self.cutbboxQueue.empty(): + time.sleep(2) + else: video_frame_dict = self.cutbboxQueue.get() - - # print('video_frame_dict:',video_frame_dict) - # 视频路径 video_path = video_frame_dict['video_path'] video_basename = os.path.basename(video_path).split('.')[0] file_name = video_frame_dict['label_name'] - # video_name_save = os.path.join(self.video_save_file, video_basename) - # 原视频帧率和尺寸 cap = cv2.VideoCapture(video_path) fps = cap.get(cv2.CAP_PROP_FPS) + video_fps = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) - # 获得起始帧 + print(video_path,'fps:',fps,'video_fps:',video_fps) + # 获得起始 stop_fps = video_frame_dict['stop_fps'] - # 裁剪信息 result_list = video_frame_dict['bbox_list'] + if cap.isOpened(): - for i,bbox_dict in enumerate(result_list): - - start_fps = bbox_dict['fps'] - bbox_list = bbox_dict['result'] - - w = int(bbox_list[2]) - int(bbox_list[0]) - h = int(bbox_list[3]) - int(bbox_list[1]) + for i,bbox_dict in enumerate(result_list): + start_fps = bbox_dict['fps'] - size = (w,h) + if start_fps >= stop_fps: - # 根据标签保存不同视频分类 - video_name_save = video_basename + '_' + str(start_fps) + '_' + str(stop_fps) + '_' + str(i) + '.avi' - video_save_file = self.video_save_file + '/' + file_name - os.makedirs(video_save_file, exist_ok=True) - video_save_path = os.path.join(video_save_file, video_name_save) - - videoWriter =cv2.VideoWriter(video_save_path,cv2.VideoWriter_fourcc('X','V','I','D'),fps,size) + print('start_fps:',start_fps,'stop_fps:',stop_fps) + break - tools.save_seg_video(video_name=video_path, - frameToStart=start_fps, - frametoStop=stop_fps, - videoWriter=videoWriter, - bbox=bbox_list) - - videoWriter.release() + else: + bbox_list = bbox_dict['result'] + # w = int(bbox_list[2]) - int(bbox_list[0]) + # h = int(bbox_list[3]) - int(bbox_list[1]) + size = (200,200) + # 根据标签保存不同视频分类 + video_name_save = video_basename + '_' + str(start_fps) + '_' + str(stop_fps) + '_' + str(i) + '.avi' + video_save_file = self.video_save_file + '/' + file_name + os.makedirs(video_save_file, exist_ok=True) + video_save_path = os.path.join(video_save_file, video_name_save) + videoWriter =cv2.VideoWriter(video_save_path,cv2.VideoWriter_fourcc('X','V','I','D'),fps,size) + + tools_function.save_seg_video(video_name=video_path, + frameToStart=start_fps, + frametoStop=stop_fps, + videoWriter=videoWriter, + bbox=bbox_list) + videoWriter.release() + self.videoQueue2.put(video_save_path) + + cap.release() + + else: + print(video_path) + break - self.videoQueue.put(video_save_path) - cap.release() - def select_video_frame(self): + def select_video_path(self): while True: - if ~self.frameQueue.empty(): - - video_dict = self.frameQueue.get() - video_path = video_dict["video_path"] + if self.videoQueue2.empty(): + time.sleep(5) + else: + video_path = self.videoQueue2.get() directory = os.path.dirname(video_path) labels = directory.split('/')[-1] - print('labels:',labels) - - if labels == 'person': + print('video_pathagfg:',video_path) - self.videopersonQueue.put(video_dict) + # print(labels) - if labels == 'head': - - # print('youshou') + if labels == 'person': - self.videoheadQueue.put(video_dict) - - if labels == 'hands': + self.videoQueue3.put(video_path) - # print('youshou') + if labels == 'head' or labels == 'hands': - self.videohandsQueue.put(video_dict) + self.videodetQueue.put(video_path) else: - - self.videoframeQueue.put(video_dict) - + pass def run(self): self.get_video_listThread.start() self.get_video_frameThread.start() - self.person_detThread.start() self.write_videoThread.start() - self.select_video_frameThread.start() + # self.write_videoThread.join() self.head_hands_detThread.start() + self.video_select_dectThread.start() + self.select_video_pathThread.start() if __name__ == '__main__': - - - - video = "E:/Bank_files/Bank_02/dataset/video_test/test03_3.avi" + t1 = time.time() + video = "E:/Bank_files/Bank_02/dataset/video_test/1min/0711-7_4.avi" video_save = 'test_video' - person_model = YOLO("model_file/yolov8x_person.pt") + # 初始化目标检测 + person_model = YOLO("model_file/yolov8n.pt") + + # 初始化pptsmv2 + config = 'model_file/inference/pptsm_lcnet_k400_16frames_uniform.yaml' # 配置文件地址 + model_file = 'model_file/inference/ppTSMv2.pdmodel' # 推理模型存放地址 + params_file = 'model_file/inference/ppTSMv2.pdiparams' + # batch_size= 1 + infer,predictor = PP_TSMv2_predict().create_inference_model(config,model_file,params_file) + # PP_TSMv2_predict().predict(config,input_file,batch_size,predictor,infer) + # 初始化mediapipe mp_holistic = mp.solutions.holistic holistic = mp_holistic.Holistic( min_detection_confidence=0.5, min_tracking_confidence=0.5) # get_seg_video(video_file=video,video_save_path=video_save,dertTime=dertTime) - deal = DealVideo(video_file=video,video_save_file=video_save,person_model=person_model,mediapipe_model=holistic,pptsmv2_model='model_file/yolov8x_person.pt') - deal.run() - - + deal = DealVideo(video_file=video,video_save_file=video_save,person_model=person_model,mediapipe_model=holistic,pptsmv2_model=[infer,predictor]) + deal.run() + t2 = time.time() - - - - - + # print('总时间:',t2-t1)