├── .vscode
└── settings.json
├── README.md
├── README_en.md
├── __init__.py
├── __pycache__
├── __init__.cpython-38.pyc
├── cfg_utils.cpython-38.pyc
├── datacollector.cpython-38.pyc
├── download.cpython-38.pyc
└── pipe_utils.cpython-38.pyc
├── cfg_utils.py
├── config
├── examples
│ ├── infer_cfg_calling.yml
│ ├── infer_cfg_fall_down.yml
│ ├── infer_cfg_fight_recognition.yml
│ ├── infer_cfg_human_attr.yml
│ ├── infer_cfg_human_mot.yml
│ ├── infer_cfg_illegal_parking.yml
│ ├── infer_cfg_reid.yml
│ ├── infer_cfg_smoking.yml
│ ├── infer_cfg_vehicle_attr.yml
│ ├── infer_cfg_vehicle_plate.yml
│ └── infer_cfg_vehicle_violation.yml
├── infer_cfg_pphuman.yml
├── infer_cfg_ppvehicle.yml
├── lane_seg_config.yml
└── tracker_config.yml
├── datacollector.py
├── docs
├── images
│ └── ppvehicleplate.jpg
└── tutorials
│ ├── PPHuman_QUICK_STARTED.md
│ ├── PPHuman_QUICK_STARTED_en.md
│ ├── PPVehicle_QUICK_STARTED.md
│ ├── PPVehicle_QUICK_STARTED_en.md
│ ├── pphuman_action.md
│ ├── pphuman_action_en.md
│ ├── pphuman_attribute.md
│ ├── pphuman_attribute_en.md
│ ├── pphuman_mot.md
│ ├── pphuman_mot_en.md
│ ├── pphuman_mtmct.md
│ ├── pphuman_mtmct_en.md
│ ├── ppvehicle_attribute.md
│ ├── ppvehicle_attribute_en.md
│ ├── ppvehicle_illegal_parking.md
│ ├── ppvehicle_illegal_parking_en.md
│ ├── ppvehicle_mot.md
│ ├── ppvehicle_mot_en.md
│ ├── ppvehicle_plate.md
│ ├── ppvehicle_plate_en.md
│ ├── ppvehicle_press.md
│ ├── ppvehicle_press_en.md
│ ├── ppvehicle_retrograde.md
│ └── ppvehicle_retrograde_en.md
├── download.py
├── mtmct.gif
├── pipe_utils.py
├── pipeline.py
├── pipeline_muti.py
├── pphuman
├── __pycache__
│ ├── action_infer.cpython-38.pyc
│ ├── action_utils.cpython-38.pyc
│ ├── attr_infer.cpython-38.pyc
│ ├── mtmct.cpython-38.pyc
│ ├── reid.cpython-38.pyc
│ ├── video_action_infer.cpython-38.pyc
│ └── video_action_preprocess.cpython-38.pyc
├── action_infer.py
├── action_utils.py
├── attr_infer.py
├── mtmct.py
├── reid.py
├── video_action_infer.py
└── video_action_preprocess.py
├── ppvehicle
├── __pycache__
│ ├── lane_seg_infer.cpython-38.pyc
│ ├── vehicle_attr.cpython-38.pyc
│ ├── vehicle_plate.cpython-38.pyc
│ ├── vehicle_plateutils.cpython-38.pyc
│ ├── vehicle_pressing.cpython-38.pyc
│ ├── vehicle_retrograde.cpython-38.pyc
│ └── vehicleplate_postprocess.cpython-38.pyc
├── lane_seg_infer.py
├── rec_word_dict.txt
├── vehicle_attr.py
├── vehicle_plate.py
├── vehicle_plateutils.py
├── vehicle_pressing.py
├── vehicle_retrograde.py
└── vehicleplate_postprocess.py
├── tools
├── ccpd2ocr_all.py
├── clip_video.py
├── create_dataset_list.py
├── get_video_info.py
├── lane_to_mask.py
└── split_fight_train_test_dataset.py
└── 录屏 2023年07月26日 10时13 -big-original.gif
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "cSpell.words": [
3 | "mtmct"
4 | ],
5 | "[python]": {
6 | "editor.defaultFormatter": "ms-python.black-formatter"
7 | },
8 | "python.formatting.provider": "none"
9 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ## 写在前面
7 | - **主要在飞桨的跨镜头跟踪基础上进行改进,主要实现两路rtsp视频流的实时跨镜头跟踪,相较于原来只能跟踪视频数据的工程,主要改动在于```pipline.py```与```mtmct.py```**
8 |
9 | ### 简单介绍
10 | - **相较于视频的mtmct,本质上是对两个视频的人物ID进行重新分配,无需真正的考虑跨境头的问题,不会出现一个人从一个镜头走到另一个,即一个人同时只出现在一个镜头的情况。视频推流的实时跟踪主要的难点在于各个人物的特征数据少,若是同一人出现在两镜头区域还好说,如果是从一个镜头走到另一个镜头,对于实时跟踪就要求存储两镜头中所有出现过的人物,进行对比,这样就会有很大的计算量.不过好歹最终效果有点像样,不管了**
11 |
12 | ### 底层苦劳工的心血展示
13 | 
14 | 
15 |
16 | ### 关于模型
17 | - **模型都是用的最轻量级,原计划部署在npu,因为reid对数据精度要求颇高选择放弃**
18 | ## 🗳 模型库
19 |
20 | ### PP-Human
21 |
22 |
23 | 端到端模型效果(点击展开)
24 |
25 | | 任务 | 端到端速度(ms) | 模型方案 | 模型体积 |
26 | | :------------------: | :----------------: | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: | :---------------------------------------------------------------: |
27 | | 行人检测(高精度) | 25.1ms | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip) | 182M |
28 | | 行人检测(轻量级) | 16.2ms | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_s_36e_pipeline.zip) | 27M |
29 | | 行人检测(超轻量级) | 10ms(Jetson AGX) | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/pphuman/ppyoloe_plus_crn_t_auxhead_320_60e_pphuman.tar.gz) | 17M |
30 | | 行人跟踪(高精度) | 31.8ms | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip) | 182M |
31 | | 行人跟踪(轻量级) | 21.0ms | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_s_36e_pipeline.zip) | 27M |
32 | | 行人跟踪(超轻量级) | 13.2ms(Jetson AGX) | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/pphuman/ppyoloe_plus_crn_t_auxhead_320_60e_pphuman.tar.gz) | 17M |
33 | | 跨镜跟踪(REID) | 单人1.5ms | [REID](https://bj.bcebos.com/v1/paddledet/models/pipeline/reid_model.zip) | REID:92M |
34 | | 属性识别(高精度) | 单人8.5ms | [目标检测](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip)
[属性识别](https://bj.bcebos.com/v1/paddledet/models/pipeline/strongbaseline_r50_30e_pa100k.zip) | 目标检测:182M
属性识别:86M |
35 | | 属性识别(轻量级) | 单人7.1ms | [目标检测](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip)
[属性识别](https://bj.bcebos.com/v1/paddledet/models/pipeline/strongbaseline_r50_30e_pa100k.zip) | 目标检测:182M
属性识别:86M |
36 | | 摔倒识别 | 单人10ms | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip)
[关键点检测](https://bj.bcebos.com/v1/paddledet/models/pipeline/dark_hrnet_w32_256x192.zip)
[基于关键点行为识别](https://bj.bcebos.com/v1/paddledet/models/pipeline/STGCN.zip) | 多目标跟踪:182M
关键点检测:101M
基于关键点行为识别:21.8M |
37 | | 闯入识别 | 31.8ms | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip) | 182M |
38 | | 打架识别 | 19.7ms | [视频分类](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip) | 90M |
39 | | 抽烟识别 | 单人15.1ms | [目标检测](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip)
[基于人体id的目标检测](https://bj.bcebos.com/v1/paddledet/models/pipeline/ppyoloe_crn_s_80e_smoking_visdrone.zip) | 目标检测:182M
基于人体id的目标检测:27M |
40 | | 打电话识别 | 单人ms | [目标检测](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip)
[基于人体id的图像分类](https://bj.bcebos.com/v1/paddledet/models/pipeline/PPHGNet_tiny_calling_halfbody.zip) | 目标检测:182M
基于人体id的图像分类:45M |
41 |
42 |
43 | 点击模型方案中的模型即可下载指定模型,下载后解压存放至`./output_inference`目录中
44 |
45 |
46 |
47 |
48 |
49 | ## 📚 详细文档
50 |
51 | ### 🚶♀️ 行人分析工具PP-Human
52 |
53 | #### [快速开始](docs/tutorials/PPHuman_QUICK_STARTED.md)
54 |
55 | #### 行为识别
56 |
57 | - [快速开始](docs/tutorials/pphuman_action.md)
58 |
59 | - [二次开发教程](../../docs/advanced_tutorials/customization/action_recognotion/README.md)
60 |
61 | #### 行人属性/特征识别
62 |
63 | - [快速开始](docs/tutorials/pphuman_attribute.md)
64 |
65 | - [二次开发教程](../../docs/advanced_tutorials/customization/pphuman_attribute.md)
66 |
67 | #### 跨镜跟踪/ReID
68 |
69 | - [快速开始](docs/tutorials/pphuman_mtmct.md)
70 |
71 | - [二次开发教程](../../docs/advanced_tutorials/customization/pphuman_mtmct.md)
72 |
73 | #### 行人跟踪、人流计数与轨迹记录
74 |
75 | - [快速开始](docs/tutorials/pphuman_mot.md)
76 |
77 | - [二次开发教程](../../docs/advanced_tutorials/customization/pphuman_mot.md)
78 |
79 | ### 🚘 车辆分析工具PP-Vehicle
80 |
81 | #### [快速开始](docs/tutorials/PPVehicle_QUICK_STARTED.md)
82 |
83 | #### 车牌识别
84 |
85 | - [快速开始](docs/tutorials/ppvehicle_plate.md)
86 |
87 | - [二次开发教程](../../docs/advanced_tutorials/customization/ppvehicle_plate.md)
88 |
89 | #### 车辆属性分析
90 |
91 | - [快速开始](docs/tutorials/ppvehicle_attribute.md)
92 |
93 | - [二次开发教程](../../docs/advanced_tutorials/customization/ppvehicle_attribute.md)
94 |
95 | #### 违章检测
96 |
97 | - [快速开始](docs/tutorials/ppvehicle_illegal_parking.md)
98 |
99 | - [二次开发教程](../../docs/advanced_tutorials/customization/pphuman_mot.md)
100 |
101 | #### 车辆跟踪、车流计数与轨迹记录
102 |
103 | - [快速开始](docs/tutorials/ppvehicle_mot.md)
104 |
105 | - [二次开发教程](../../docs/advanced_tutorials/customization/pphuman_mot.md)
106 |
107 | #### 车辆违法压线
108 |
109 | - [快速开始](docs/tutorials/ppvehicle_press.md)
110 |
111 | - [二次开发教程](../../docs/advanced_tutorials/customization/ppvehicle_violation.md)
112 |
113 | #### 车辆逆行
114 |
115 | - [快速开始](docs/tutorials/ppvehicle_retrograde.md)
116 |
117 | - [二次开发教程](../../docs/advanced_tutorials/customization/ppvehicle_violation.md)
118 |
--------------------------------------------------------------------------------
/__init__.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
--------------------------------------------------------------------------------
/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/__pycache__/cfg_utils.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/__pycache__/cfg_utils.cpython-38.pyc
--------------------------------------------------------------------------------
/__pycache__/datacollector.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/__pycache__/datacollector.cpython-38.pyc
--------------------------------------------------------------------------------
/__pycache__/download.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/__pycache__/download.cpython-38.pyc
--------------------------------------------------------------------------------
/__pycache__/pipe_utils.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/__pycache__/pipe_utils.cpython-38.pyc
--------------------------------------------------------------------------------
/cfg_utils.py:
--------------------------------------------------------------------------------
1 | import ast
2 | import yaml
3 | import copy
4 | import argparse
5 | from argparse import ArgumentParser, RawDescriptionHelpFormatter
6 |
7 |
8 | class ArgsParser(ArgumentParser):
9 | def __init__(self):
10 | super(ArgsParser, self).__init__(
11 | formatter_class=RawDescriptionHelpFormatter)
12 | self.add_argument(
13 | "-o", "--opt", nargs='*', help="set configuration options")
14 |
15 | def parse_args(self, argv=None):
16 | args = super(ArgsParser, self).parse_args(argv)
17 | assert args.config is not None, \
18 | "Please specify --config=configure_file_path."
19 | args.opt = self._parse_opt(args.opt)
20 | return args
21 |
22 | def _parse_opt(self, opts):
23 | config = {}
24 | if not opts:
25 | return config
26 | for s in opts:
27 | s = s.strip()
28 | k, v = s.split('=', 1)
29 | if '.' not in k:
30 | config[k] = yaml.load(v, Loader=yaml.Loader)
31 | else:
32 | keys = k.split('.')
33 | if keys[0] not in config:
34 | config[keys[0]] = {}
35 | cur = config[keys[0]]
36 | for idx, key in enumerate(keys[1:]):
37 | if idx == len(keys) - 2:
38 | cur[key] = yaml.load(v, Loader=yaml.Loader)
39 | else:
40 | cur[key] = {}
41 | cur = cur[key]
42 | return config
43 |
44 |
45 | def argsparser():
46 | parser = ArgsParser()
47 |
48 | parser.add_argument(
49 | "--config",
50 | type=str,
51 | default=None,
52 | help=("Path of configure"),
53 | required=True)
54 | parser.add_argument(
55 | "--image_file", type=str, default=None, help="Path of image file.")
56 | parser.add_argument(
57 | "--image_dir",
58 | type=str,
59 | default=None,
60 | help="Dir of image file, `image_file` has a higher priority.")
61 | parser.add_argument(
62 | "--video_file",
63 | type=str,
64 | default=None,
65 | help="Path of video file, `video_file` or `camera_id` has a highest priority."
66 | )
67 | parser.add_argument(
68 | "--video_dir",
69 | type=str,
70 | default=None,
71 | help="Dir of video file, `video_file` has a higher priority.")
72 | parser.add_argument(
73 | "--rtsp",
74 | type=str,
75 | nargs='+',
76 | default=None,
77 | help="list of rtsp inputs, for one or multiple rtsp input.")
78 | parser.add_argument(
79 | "--camera_id",
80 | type=int,
81 | default=-1,
82 | help="device id of camera to predict.")
83 | parser.add_argument(
84 | "--output_dir",
85 | type=str,
86 | default="output",
87 | help="Directory of output visualization files.")
88 | parser.add_argument(
89 | "--pushurl",
90 | type=str,
91 | default="",
92 | help="url of output visualization stream.")
93 | parser.add_argument(
94 | "--run_mode",
95 | type=str,
96 | default='paddle',
97 | help="mode of running(paddle/trt_fp32/trt_fp16/trt_int8)")
98 | parser.add_argument(
99 | "--device",
100 | type=str,
101 | default='cpu',
102 | help="Choose the device you want to run, it can be: CPU/GPU/XPU, default is CPU."
103 | )
104 | parser.add_argument(
105 | "--enable_mkldnn",
106 | type=ast.literal_eval,
107 | default=False,
108 | help="Whether use mkldnn with CPU.")
109 | parser.add_argument(
110 | "--cpu_threads", type=int, default=1, help="Num of threads with CPU.")
111 | parser.add_argument(
112 | "--trt_min_shape", type=int, default=1, help="min_shape for TensorRT.")
113 | parser.add_argument(
114 | "--trt_max_shape",
115 | type=int,
116 | default=1280,
117 | help="max_shape for TensorRT.")
118 | parser.add_argument(
119 | "--trt_opt_shape",
120 | type=int,
121 | default=640,
122 | help="opt_shape for TensorRT.")
123 | parser.add_argument(
124 | "--trt_calib_mode",
125 | type=bool,
126 | default=False,
127 | help="If the model is produced by TRT offline quantitative "
128 | "calibration, trt_calib_mode need to set True.")
129 | parser.add_argument(
130 | "--do_entrance_counting",
131 | action='store_true',
132 | help="Whether counting the numbers of identifiers entering "
133 | "or getting out from the entrance. Note that only support single-class MOT."
134 | )
135 | parser.add_argument(
136 | "--do_break_in_counting",
137 | action='store_true',
138 | help="Whether counting the numbers of identifiers break in "
139 | "the area. Note that only support single-class MOT and "
140 | "the video should be taken by a static camera.")
141 | parser.add_argument(
142 | "--illegal_parking_time",
143 | type=int,
144 | default=-1,
145 | help="illegal parking time which units are seconds, default is -1 which means not recognition illegal parking"
146 | )
147 | parser.add_argument(
148 | "--region_type",
149 | type=str,
150 | default='horizontal',
151 | help="Area type for entrance counting or break in counting, 'horizontal' and "
152 | "'vertical' used when do entrance counting. 'custom' used when do break in counting. "
153 | "Note that only support single-class MOT, and the video should be taken by a static camera."
154 | )
155 | parser.add_argument(
156 | '--region_polygon',
157 | nargs='+',
158 | type=int,
159 | default=[],
160 | help="Clockwise point coords (x0,y0,x1,y1...) of polygon of area when "
161 | "do_break_in_counting. Note that only support single-class MOT and "
162 | "the video should be taken by a static camera.")
163 | parser.add_argument(
164 | "--secs_interval",
165 | type=int,
166 | default=2,
167 | help="The seconds interval to count after tracking")
168 | parser.add_argument(
169 | "--draw_center_traj",
170 | action='store_true',
171 | help="Whether drawing the trajectory of center")
172 |
173 | return parser
174 |
175 |
176 | def merge_cfg(args):
177 | # load config
178 | with open(args.config) as f:
179 | pred_config = yaml.safe_load(f)
180 |
181 | def merge(cfg, arg):
182 | # update cfg from arg directly
183 | merge_cfg = copy.deepcopy(cfg)
184 | for k, v in cfg.items():
185 | if k in arg:
186 | merge_cfg[k] = arg[k]
187 | else:
188 | if isinstance(v, dict):
189 | merge_cfg[k] = merge(v, arg)
190 |
191 | return merge_cfg
192 |
193 | def merge_opt(cfg, arg):
194 | merge_cfg = copy.deepcopy(cfg)
195 | # merge opt
196 | if 'opt' in arg.keys() and arg['opt']:
197 | for name, value in arg['opt'].items(
198 | ): # example: {'MOT': {'batch_size': 3}}
199 | if name not in merge_cfg.keys():
200 | print("No", name, "in config file!")
201 | continue
202 | for sub_k, sub_v in value.items():
203 | if sub_k not in merge_cfg[name].keys():
204 | print("No", sub_k, "in config file of", name, "!")
205 | continue
206 | merge_cfg[name][sub_k] = sub_v
207 |
208 | return merge_cfg
209 |
210 | args_dict = vars(args)
211 | pred_config = merge(pred_config, args_dict)
212 | pred_config = merge_opt(pred_config, args_dict)
213 |
214 | return pred_config
215 |
216 |
217 | def print_arguments(cfg):
218 | print('----------- Running Arguments -----------')
219 | buffer = yaml.dump(cfg)
220 | print(buffer)
221 | print('------------------------------------------')
222 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_calling.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | visual: True
3 | warmup_frame: 50
4 |
5 | MOT:
6 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip
7 | tracker_config: deploy/pipeline/config/tracker_config.yml
8 | batch_size: 1
9 | enable: True
10 |
11 | ID_BASED_CLSACTION:
12 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/PPHGNet_tiny_calling_halfbody.zip
13 | batch_size: 8
14 | threshold: 0.8
15 | display_frames: 80
16 | skip_frame_num: 2
17 | enable: True
18 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_fall_down.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | kpt_thresh: 0.2
3 | visual: True
4 | warmup_frame: 50
5 |
6 | MOT:
7 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip
8 | tracker_config: deploy/pipeline/config/tracker_config.yml
9 | batch_size: 1
10 | enable: True
11 |
12 | KPT:
13 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/dark_hrnet_w32_256x192.zip
14 | batch_size: 8
15 |
16 | SKELETON_ACTION:
17 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/STGCN.zip
18 | batch_size: 1
19 | max_frames: 50
20 | display_frames: 80
21 | coord_size: [384, 512]
22 | enable: True
23 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_fight_recognition.yml:
--------------------------------------------------------------------------------
1 | visual: True
2 | warmup_frame: 50
3 |
4 | VIDEO_ACTION:
5 | model_dir: https://videotag.bj.bcebos.com/PaddleVideo-release2.3/ppTSM_fight.zip
6 | batch_size: 1
7 | frame_len: 8
8 | sample_freq: 7
9 | short_size: 340
10 | target_size: 320
11 | enable: True
12 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_human_attr.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | attr_thresh: 0.5
3 | visual: True
4 | warmup_frame: 50
5 |
6 | DET:
7 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip
8 | batch_size: 1
9 |
10 | MOT:
11 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip
12 | tracker_config: deploy/pipeline/config/tracker_config.yml
13 | batch_size: 1
14 | enable: True
15 |
16 | ATTR:
17 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/PPLCNet_x1_0_person_attribute_945_infer.zip
18 | batch_size: 8
19 | enable: True
20 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_human_mot.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | visual: True
3 | warmup_frame: 50
4 |
5 | MOT:
6 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip
7 | tracker_config: deploy/pipeline/config/tracker_config.yml
8 | batch_size: 1
9 | enable: True
10 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_illegal_parking.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | visual: True
3 | warmup_frame: 50
4 |
5 | MOT:
6 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
7 | tracker_config: deploy/pipeline/config/tracker_config.yml
8 | batch_size: 1
9 | enable: True
10 |
11 | VEHICLE_PLATE:
12 | det_model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_det_infer.tar.gz
13 | det_limit_side_len: 736
14 | det_limit_type: "min"
15 | rec_model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_rec_infer.tar.gz
16 | rec_image_shape: [3, 48, 320]
17 | rec_batch_num: 6
18 | word_dict_path: deploy/pipeline/ppvehicle/rec_word_dict.txt
19 | enable: True
20 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_reid.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | visual: True
3 | warmup_frame: 50
4 |
5 | MOT:
6 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip
7 | tracker_config: deploy/pipeline/config/tracker_config.yml
8 | batch_size: 1
9 | enable: True
10 |
11 | REID:
12 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/reid_model.zip
13 | batch_size: 16
14 | enable: True
15 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_smoking.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | visual: True
3 | warmup_frame: 50
4 |
5 | MOT:
6 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip
7 | tracker_config: deploy/pipeline/config/tracker_config.yml
8 | batch_size: 1
9 | enable: True
10 |
11 | ID_BASED_DETACTION:
12 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ppyoloe_crn_s_80e_smoking_visdrone.zip
13 | batch_size: 8
14 | threshold: 0.6
15 | display_frames: 80
16 | skip_frame_num: 2
17 | enable: True
18 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_vehicle_attr.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | visual: True
3 | warmup_frame: 50
4 |
5 | DET:
6 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
7 | batch_size: 1
8 |
9 | MOT:
10 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
11 | tracker_config: deploy/pipeline/config/tracker_config.yml
12 | batch_size: 1
13 | enable: True
14 |
15 | VEHICLE_ATTR:
16 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/vehicle_attribute_model.zip
17 | batch_size: 8
18 | color_threshold: 0.5
19 | type_threshold: 0.5
20 | enable: True
21 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_vehicle_plate.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | visual: True
3 | warmup_frame: 50
4 |
5 | DET:
6 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
7 | batch_size: 1
8 |
9 | MOT:
10 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
11 | tracker_config: deploy/pipeline/config/tracker_config.yml
12 | batch_size: 1
13 | enable: True
14 |
15 | VEHICLE_PLATE:
16 | det_model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_det_infer.tar.gz
17 | det_limit_side_len: 736
18 | det_limit_type: "min"
19 | rec_model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_rec_infer.tar.gz
20 | rec_image_shape: [3, 48, 320]
21 | rec_batch_num: 6
22 | word_dict_path: deploy/pipeline/ppvehicle/rec_word_dict.txt
23 | enable: True
24 |
--------------------------------------------------------------------------------
/config/examples/infer_cfg_vehicle_violation.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | visual: True
3 | warmup_frame: 50
4 |
5 | DET:
6 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
7 | batch_size: 1
8 |
9 | MOT:
10 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
11 | tracker_config: deploy/pipeline/config/tracker_config.yml
12 | batch_size: 1
13 | skip_frame_num: -1 # preferably no more than 3
14 | enable: True
15 |
16 | LANE_SEG:
17 | lane_seg_config: deploy/pipeline/config/lane_seg_config.yml
18 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip
19 |
20 | VEHICLE_PRESSING:
21 | enable: True
22 |
23 | VEHICLE_RETROGRADE:
24 | frame_len: 8
25 | sample_freq: 7
26 | enable: True
27 | filter_horizontal_flag: True
28 | keep_right_flag: True
29 | deviation: 45
30 | move_scale: 0.01
31 | fence_line: [570, 163, 1030, 752] #[x1,y1,x2,y2] y2>y1.
32 |
--------------------------------------------------------------------------------
/config/infer_cfg_pphuman.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | attr_thresh: 0.8
3 | kpt_thresh: 0.2
4 | visual: True
5 | warmup_frame: 50
6 |
7 | DET:
8 | model_dir: output_inference/mot_ppyoloe_s_36e_pipeline/
9 | batch_size: 1
10 |
11 | MOT:
12 | model_dir: output_inference/mot_ppyoloe_s_36e_pipeline/
13 | tracker_config: deploy/pipeline/config/tracker_config.yml
14 | batch_size: 1
15 | skip_frame_num: 1 # preferably no more than 3
16 | enable: False
17 |
18 | KPT:
19 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/dark_hrnet_w32_256x192.zip
20 | batch_size: 8
21 |
22 | ATTR:
23 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/PPLCNet_x1_0_person_attribute_945_infer.zip
24 | batch_size: 8
25 | enable: False
26 |
27 | VIDEO_ACTION:
28 | model_dir: https://videotag.bj.bcebos.com/PaddleVideo-release2.3/ppTSM_fight.zip
29 | batch_size: 1
30 | frame_len: 8
31 | sample_freq: 7
32 | short_size: 340
33 | target_size: 320
34 | enable: False
35 |
36 | SKELETON_ACTION:
37 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/STGCN.zip
38 | batch_size: 1
39 | max_frames: 50
40 | display_frames: 80
41 | coord_size: [384, 512]
42 | enable: False
43 |
44 | ID_BASED_DETACTION:
45 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ppyoloe_crn_s_80e_smoking_visdrone.zip
46 | batch_size: 8
47 | threshold: 0.6
48 | display_frames: 80
49 | skip_frame_num: 2
50 | enable: False
51 |
52 | ID_BASED_CLSACTION:
53 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/PPHGNet_tiny_calling_halfbody.zip
54 | batch_size: 8
55 | threshold: 0.8
56 | display_frames: 80
57 | skip_frame_num: 2
58 | enable: False
59 |
60 | REID:
61 | model_dir: output_inference/reid_model/
62 | batch_size: 16
63 | enable: True
64 |
--------------------------------------------------------------------------------
/config/infer_cfg_ppvehicle.yml:
--------------------------------------------------------------------------------
1 | crop_thresh: 0.5
2 | visual: True
3 | warmup_frame: 50
4 |
5 | DET:
6 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
7 | batch_size: 1
8 |
9 | MOT:
10 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
11 | tracker_config: deploy/pipeline/config/tracker_config.yml
12 | batch_size: 1
13 | skip_frame_num: -1 # preferably no more than 3
14 | enable: False
15 |
16 | VEHICLE_PLATE:
17 | det_model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_det_infer.tar.gz
18 | det_limit_side_len: 736
19 | det_limit_type: "min"
20 | rec_model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_rec_infer.tar.gz
21 | rec_image_shape: [3, 48, 320]
22 | rec_batch_num: 6
23 | word_dict_path: deploy/pipeline/ppvehicle/rec_word_dict.txt
24 | enable: False
25 |
26 | VEHICLE_ATTR:
27 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/vehicle_attribute_model.zip
28 | batch_size: 8
29 | color_threshold: 0.5
30 | type_threshold: 0.5
31 | enable: False
32 |
33 | LANE_SEG:
34 | lane_seg_config: deploy/pipeline/config/lane_seg_config.yml
35 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip
36 |
37 | VEHICLE_PRESSING:
38 | enable: False
39 |
40 | VEHICLE_RETROGRADE:
41 | frame_len: 8
42 | sample_freq: 7
43 | enable: False
44 | filter_horizontal_flag: True
45 | keep_right_flag: True
46 | deviation: 23
47 | move_scale: 0.01
48 | fence_line: [] #[x1,y1,x2,y2] y2>y1.
49 |
--------------------------------------------------------------------------------
/config/lane_seg_config.yml:
--------------------------------------------------------------------------------
1 | type: PLSLaneseg
2 |
3 |
4 | PLSLaneseg:
5 | run_mode: 'paddle'
6 | batch_size: 1
7 | device: gpu
8 | min_subgraph_size: 3
9 | use_dynamic_shape: False
10 | trt_min_shape: [100,100]
11 | trt_max_shape: [2000,3000]
12 | trt_opt_shape: [512,1024]
13 | trt_calib_mode: False
14 | cpu_threads: 10
15 | enable_mkldnn: False #Enable to use mkldnn to speed up when using cpu.
16 |
17 | filter_horizontal_flag: True #Whether to filter horizontal roads
18 | horizontal_filtration_degree: 23
19 | horizontal_filtering_threshold: 0.25
20 |
--------------------------------------------------------------------------------
/config/tracker_config.yml:
--------------------------------------------------------------------------------
1 | # config of tracker for MOT SDE Detector, use 'OCSORTTracker' as default, 'JDETracker' here is just BYTETracker.
2 | # The tracker of MOT JDE Detector (such as FairMOT) is exported together with the model.
3 | # Here 'min_box_area' and 'vertical_ratio' are set for pedestrian, you can modify for other objects tracking.
4 |
5 | type: BOTSORTTracker # choose one tracker in ['JDETracker', 'OCSORTTracker', 'DeepSORTTracker','BOTSORTTracker']
6 | # When using for MTMCT(Multi-Target Multi-Camera Tracking), you should modify to 'DeepSORTTracker'
7 |
8 |
9 | # just as BYTETracker, used for FairMOT in PP-Tracking project and for ByteTrack in PP-Humanv1 project
10 | JDETracker:
11 | use_byte: True
12 | det_thresh: 0.3
13 | conf_thres: 0.6
14 | low_conf_thres: 0.1
15 | match_thres: 0.9
16 | min_box_area: 0
17 | vertical_ratio: 0 # 1.6 for pedestrian
18 |
19 |
20 | # used for OC-SORT in PP-Humanv2 project and PP-Vehicle project
21 | OCSORTTracker:
22 | det_thresh: 0.4
23 | max_age: 30
24 | min_hits: 3
25 | iou_threshold: 0.3
26 | delta_t: 3
27 | inertia: 0.2
28 | min_box_area: 0
29 | vertical_ratio: 0
30 | use_byte: False
31 | use_angle_cost: False
32 |
33 |
34 | # used for DeepSORT and MTMCT in PP-Tracking project
35 | DeepSORTTracker:
36 | input_size: [64, 192] # An unique operation to scale the sub-image of the selected detected boxes to a fixed size
37 | min_box_area: 0
38 | vertical_ratio: -1
39 | budget: 100
40 | max_age: 70
41 | n_init: 3
42 | metric_type: cosine
43 | matching_threshold: 0.2
44 | max_iou_distance: 0.9
45 |
46 | BOTSORTTracker:
47 | track_high_thresh: 0.3
48 | track_low_thresh: 0.2
49 | new_track_thresh: 0.4
50 | match_thresh: 0.7
51 | track_buffer: 30
52 | min_box_area: 0
53 | camera_motion: False
54 | cmc_method: 'sparseOptFlow' # only camera_motion is True,
55 | # sparseOptFlow | files (Vidstab GMC) | orb | ecc
56 |
--------------------------------------------------------------------------------
/datacollector.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import os
16 | import copy
17 | from collections import Counter
18 |
19 |
20 | class Result(object):
21 | def __init__(self):
22 | self.res_dict = {
23 | 'det': dict(),
24 | 'mot': dict(),
25 | 'attr': dict(),
26 | 'kpt': dict(),
27 | 'video_action': dict(),
28 | 'skeleton_action': dict(),
29 | 'reid': dict(),
30 | 'det_action': dict(),
31 | 'cls_action': dict(),
32 | 'vehicleplate': dict(),
33 | 'vehicle_attr': dict(),
34 | 'lanes': dict(),
35 | 'vehicle_press': dict(),
36 | 'vehicle_retrograde': dict()
37 | }
38 |
39 | def update(self, res, name):
40 | self.res_dict[name].update(res)
41 |
42 | def get(self, name):
43 | if name in self.res_dict and len(self.res_dict[name]) > 0:
44 | return self.res_dict[name]
45 | return None
46 |
47 | def clear(self, name):
48 | self.res_dict[name].clear()
49 |
50 |
51 | class DataCollector(object):
52 | """
53 | DataCollector of Pipeline, collect results in every frames and assign it to each track ids.
54 | mainly used in mtmct.
55 |
56 | data struct:
57 | collector:
58 | - [id1]: (all results of N frames)
59 | - frames(list of int): Nx[int]
60 | - rects(list of rect): Nx[rect(conf, xmin, ymin, xmax, ymax)]
61 | - features(list of array(256,)): Nx[array(256,)]
62 | - qualities(list of float): Nx[float]
63 | - attrs(list of attr): refer to attrs for details
64 | - kpts(list of kpts): refer to kpts for details
65 | - skeleton_action(list of skeleton_action): refer to skeleton_action for details
66 | ...
67 | - [idN]
68 | """
69 |
70 | def __init__(self):
71 | #id, frame, rect, score, label, attrs, kpts, skeleton_action
72 | self.mots = {
73 | "frames": [],
74 | "rects": [],
75 | "attrs": [],
76 | "kpts": [],
77 | "features": [],
78 | "qualities": [],
79 | "skeleton_action": [],
80 | "vehicleplate": []
81 | }
82 | self.collector = {}
83 |
84 | def append(self, frameid, Result):
85 | mot_res = Result.get('mot')#have
86 | attr_res = Result.get('attr')
87 | kpt_res = Result.get('kpt')
88 | skeleton_action_res = Result.get('skeleton_action')
89 | reid_res = Result.get('reid')#have
90 | vehicleplate_res = Result.get('vehicleplate')
91 |
92 | rects = []
93 | if reid_res is not None:
94 | rects = reid_res['rects']
95 | elif mot_res is not None:
96 | rects = mot_res['boxes']
97 | # ids =0
98 | for idx, mot_item in enumerate(rects):
99 | # self.collector.popitem()
100 | # print(mot_item)
101 | ids = int(mot_item[0])
102 | # print("ids %d idx %d" %(ids,idx))
103 | if ids not in self.collector:
104 |
105 | self.collector[ids] = copy.deepcopy(self.mots)
106 | # self.collector[ids]["frames"].clear()
107 | self.collector[ids]["frames"].append(frameid)
108 | # self.collector[ids]["rects"].clear()
109 | # print(len(self.collector[ids]["rects"]))
110 | # print(self.collector[ids]["rects"])
111 | self.collector[ids]["rects"].append([mot_item[2:]])
112 | if attr_res:
113 | self.collector[ids]["attrs"].append(attr_res['output'][idx])
114 | if kpt_res:
115 | self.collector[ids]["kpts"].append(
116 | [kpt_res['keypoint'][0][idx], kpt_res['keypoint'][1][idx]])
117 | if skeleton_action_res and (idx + 1) in skeleton_action_res:
118 | self.collector[ids]["skeleton_action"].append(
119 | skeleton_action_res[idx + 1])
120 | else:
121 | # action model generate result per X frames, Not available every frames
122 | self.collector[ids]["skeleton_action"].append(None)
123 | if reid_res:
124 |
125 | self.collector[ids]["features"].append(reid_res['features'][
126 | idx])
127 | if len(self.collector[ids]["features"])>5:
128 | self.collector[ids]["features"].pop()
129 | self.collector[ids]["qualities"].append(reid_res['qualities'][
130 | idx])
131 | if len(self.collector[ids]["qualities"])>5:
132 | self.collector[ids]["qualities"].pop()
133 |
134 | if vehicleplate_res and vehicleplate_res['plate'][idx] != "":
135 | self.collector[ids]["vehicleplate"].append(vehicleplate_res[
136 | 'plate'][idx])
137 | def update(self, frameid, Result):
138 | mot_res = Result.get('mot')
139 | attr_res = Result.get('attr')
140 | kpt_res = Result.get('kpt')
141 | skeleton_action_res = Result.get('skeleton_action')
142 | reid_res = Result.get('reid')
143 | vehicleplate_res = Result.get('vehicleplate')
144 |
145 | rects = []
146 | if reid_res is not None:
147 | rects = reid_res['rects']
148 | elif mot_res is not None:
149 | rects = mot_res['boxes']
150 |
151 | for idx, mot_item in enumerate(rects):
152 | ids = int(mot_item[0])
153 | if ids not in self.collector:
154 | self.collector[ids] = copy.deepcopy(self.mots)
155 | self.collector[ids]["frames"].append(frameid)
156 | self.collector[ids]["rects"].append([mot_item[2:]])
157 | if attr_res:
158 | self.collector[ids]["attrs"].append(attr_res['output'][idx])
159 | if kpt_res:
160 | self.collector[ids]["kpts"].append(
161 | [kpt_res['keypoint'][0][idx], kpt_res['keypoint'][1][idx]])
162 | if skeleton_action_res and (idx + 1) in skeleton_action_res:
163 | self.collector[ids]["skeleton_action"].append(
164 | skeleton_action_res[idx + 1])
165 | else:
166 | # action model generate result per X frames, Not available every frames
167 | self.collector[ids]["skeleton_action"].append(None)
168 | if reid_res:
169 | self.collector[ids]["features"]
170 |
171 | self.collector[ids]["features"].append(reid_res['features'][
172 | idx])
173 | self.collector[ids]["qualities"].append(reid_res['qualities'][
174 | idx])
175 | if vehicleplate_res and vehicleplate_res['plate'][idx] != "":
176 | self.collector[ids]["vehicleplate"].append(vehicleplate_res[
177 | 'plate'][idx])
178 | def get_res(self):
179 | return self.collector
180 |
181 | def get_carlp(self, trackid):
182 | lps = self.collector[trackid]["vehicleplate"]
183 | counter = Counter(lps)
184 | carlp = counter.most_common()
185 | if len(carlp) > 0:
186 | return carlp[0][0]
187 | else:
188 | return None
--------------------------------------------------------------------------------
/docs/images/ppvehicleplate.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/docs/images/ppvehicleplate.jpg
--------------------------------------------------------------------------------
/docs/tutorials/PPVehicle_QUICK_STARTED.md:
--------------------------------------------------------------------------------
1 | [English](PPVehicle_QUICK_STARTED_en.md) | 简体中文
2 |
3 | # PP-Vehicle快速开始
4 |
5 | ## 目录
6 |
7 | - [环境准备](#环境准备)
8 | - [模型下载](#模型下载)
9 | - [配置文件说明](#配置文件说明)
10 | - [预测部署](#预测部署)
11 | - [在线视频流](#在线视频流)
12 | - [Jetson部署说明](#Jetson部署说明)
13 | - [参数说明](#参数说明)
14 | - [方案介绍](#方案介绍)
15 | - [车辆检测](#车辆检测)
16 | - [车辆跟踪](#车辆跟踪)
17 | - [车牌识别](#车牌识别)
18 | - [属性识别](#属性识别)
19 | - [违章停车识别](#违章停车识别)
20 |
21 |
22 | ## 环境准备
23 |
24 | 环境要求: PaddleDetection版本 >= release/2.5 或 develop版本
25 |
26 | PaddlePaddle和PaddleDetection安装
27 |
28 | ```
29 | # PaddlePaddle CUDA10.1
30 | python -m pip install paddlepaddle-gpu==2.2.2.post101 -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html
31 |
32 | # PaddlePaddle CPU
33 | python -m pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple
34 |
35 | # 克隆PaddleDetection仓库
36 | cd
37 | git clone https://github.com/PaddlePaddle/PaddleDetection.git
38 |
39 | # 安装其他依赖
40 | cd PaddleDetection
41 | pip install -r requirements.txt
42 | ```
43 |
44 | 1. 详细安装文档参考[文档](../../../../docs/tutorials/INSTALL_cn.md)
45 | 2. 如果需要TensorRT推理加速(测速方式),请安装带`TensorRT版本Paddle`。您可以从[Paddle安装包](https://paddleinference.paddlepaddle.org.cn/v2.2/user_guides/download_lib.html#python)下载安装,或者按照[指导文档](https://www.paddlepaddle.org.cn/inference/master/optimize/paddle_trt.html)使用docker或自编译方式准备Paddle环境。
46 |
47 | ## 模型下载
48 |
49 | PP-Vehicle提供了目标检测、属性识别、行为识别、ReID预训练模型,以实现不同使用场景,用户可以直接下载使用
50 |
51 | | 任务 | 端到端速度(ms)| 模型方案 | 模型体积 |
52 | | :---------: | :-------: | :------: |:------: |
53 | | 车辆检测(高精度) | 25.7ms | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) | 182M |
54 | | 车辆检测(轻量级) | 13.2ms | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_s_36e_ppvehicle.zip) | 27M |
55 | | 车辆检测(超轻量级) | 10ms(Jetson AGX) | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/ppvehicle/ppyoloe_plus_crn_t_auxhead_320_60e_ppvehicle.tar.gz) | 17M |
56 | | 车辆跟踪(高精度) | 40ms | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) | 182M |
57 | | 车辆跟踪(轻量级) | 25ms | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_s_36e_ppvehicle.zip) | 27M |
58 | | 车辆跟踪(超轻量级) | 13.2ms(Jetson AGX) | [多目标跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/ppvehicle/ppyoloe_plus_crn_t_auxhead_320_60e_ppvehicle.tar.gz) | 17M |
59 | | 车牌识别 | 4.68ms | [车牌检测](https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_det_infer.tar.gz)
[车牌字符识别](https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_rec_infer.tar.gz) | 车牌检测:3.9M
车牌字符识别: 12M |
60 | | 车辆属性 | 7.31ms | [车辆属性](https://bj.bcebos.com/v1/paddledet/models/pipeline/vehicle_attribute_model.zip) | 7.2M |
61 | | 车道线检测 | 47ms | [车道线模型](https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip) | 47M |
62 |
63 | 下载模型后,解压至`./output_inference`文件夹。
64 |
65 | 在配置文件中,模型路径默认为模型的下载路径,如果用户不修改,则在推理时会自动下载对应的模型。
66 |
67 | **注意:**
68 |
69 | - 检测跟踪模型精度为公开数据集BDD100K-MOT和UA-DETRAC整合后的联合数据集PPVehicle的结果,具体参照[ppvehicle](../../../../configs/ppvehicle)
70 | - 预测速度为T4下,开启TensorRT FP16的效果, 模型预测速度包含数据预处理、模型预测、后处理全流程
71 |
72 | ## 配置文件说明
73 |
74 | PP-Vehicle相关配置位于```deploy/pipeline/config/infer_cfg_ppvehicle.yml```中,存放模型路径,完成不同功能需要设置不同的任务类型
75 |
76 | 功能及任务类型对应表单如下:
77 |
78 | | 输入类型 | 功能 | 任务类型 | 配置项 |
79 | |-------|-------|----------|-----|
80 | | 图片 | 属性识别 | 目标检测 属性识别 | DET ATTR |
81 | | 单镜头视频 | 属性识别 | 多目标跟踪 属性识别 | MOT ATTR |
82 | | 单镜头视频 | 车牌识别 | 多目标跟踪 车牌识别 | MOT VEHICLEPLATE |
83 |
84 | 例如基于视频输入的属性识别,任务类型包含多目标跟踪和属性识别,具体配置如下:
85 |
86 | ```
87 | crop_thresh: 0.5
88 | visual: True
89 | warmup_frame: 50
90 |
91 | MOT:
92 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
93 | tracker_config: deploy/pipeline/config/tracker_config.yml
94 | batch_size: 1
95 | enable: True
96 |
97 | VEHICLE_ATTR:
98 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/vehicle_attribute_model.zip
99 | batch_size: 8
100 | color_threshold: 0.5
101 | type_threshold: 0.5
102 | enable: True
103 | ```
104 |
105 | **注意:**
106 |
107 | - 如果用户需要实现不同任务,可以在配置文件对应enable选项设置为True。
108 | - 如果用户仅需要修改模型文件路径,可以在命令行中--config后面紧跟着 `-o MOT.model_dir=ppyoloe/` 进行修改即可,也可以手动修改配置文件中的相应模型路径,详细说明参考下方参数说明文档。
109 |
110 |
111 | ## 预测部署
112 |
113 | 1. 直接使用默认配置或者examples中配置文件,或者直接在`infer_cfg_ppvehicle.yml`中修改配置:
114 | ```
115 | # 例:车辆检测,指定配置文件路径和测试图片
116 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml --image_file=test_image.jpg --device=gpu
117 |
118 | # 例:车辆车牌识别,指定配置文件路径和测试视频
119 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/examples/infer_cfg_vehicle_plate.yml --video_file=test_video.mp4 --device=gpu
120 | ```
121 |
122 | 2. 使用命令行进行功能开启,或者模型路径修改:
123 | ```
124 | # 例:车辆跟踪,指定配置文件路径和测试视频,命令行中开启MOT模型并修改模型路径,命令行中指定的模型路径优先级高于配置文件
125 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml -o MOT.enable=True MOT.model_dir=ppyoloe_infer/ --video_file=test_video.mp4 --device=gpu
126 |
127 | # 例:车辆违章分析,指定配置文件和测试视频,命令行中指定违停区域设置、违停时间判断。
128 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/examples/infer_cfg_illegal_parking.yml \
129 | --video_file=../car_test.mov \
130 | --device=gpu \
131 | --draw_center_traj \
132 | --illegal_parking_time=3 \
133 | --region_type=custom \
134 | --region_polygon 600 300 1300 300 1300 800 600 800
135 |
136 | ```
137 |
138 | ### 在线视频流
139 |
140 | 在线视频流解码功能基于opencv的capture函数,支持rtsp、rtmp格式。
141 |
142 | - rtsp拉流预测
143 |
144 | 对rtsp拉流的支持,使用--rtsp RTSP [RTSP ...]参数指定一路或者多路rtsp视频流,如果是多路地址中间用空格隔开。(或者video_file后面的视频地址直接更换为rtsp流地址),示例如下:
145 | ```
146 | # 例:车辆属性识别,单路视频流
147 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/examples/infer_cfg_vehicle_attr.yml -o visual=False --rtsp rtsp://[YOUR_RTSP_SITE] --device=gpu
148 |
149 | # 例:车辆属性识别,多路视频流
150 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/examples/infer_cfg_vehicle_attr.yml -o visual=False --rtsp rtsp://[YOUR_RTSP_SITE1] rtsp://[YOUR_RTSP_SITE2] --device=gpu
151 | ```
152 |
153 | - 视频结果推流rtsp
154 |
155 | 预测结果进行rtsp推流,使用--pushurl rtsp:[IP] 推流到IP地址端,PC端可以使用[VLC播放器](https://vlc.onl/)打开网络流进行播放,播放地址为 `rtsp:[IP]/videoname`。其中`videoname`是预测的视频文件名,如果视频来源是本地摄像头则`videoname`默认为`output`.
156 | ```
157 | # 例:车辆属性识别,单路视频流,该示例播放地址为 rtsp://[YOUR_SERVER_IP]:8554/test_video
158 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/examples/infer_cfg_vehicle_attr.yml -o visual=False --video_file=test_video.mp4 --device=gpu --pushurl rtsp://[YOUR_SERVER_IP]:8554
159 | ```
160 | 注:
161 | 1. rtsp推流服务基于 [rtsp-simple-server](https://github.com/aler9/rtsp-simple-server), 如使用推流功能请先开启该服务.
162 | 使用方法很简单,以linux平台为例:1)下载对应平台release包;2)解压后在命令行执行命令 `./rtsp-simple-server`即可,成功后进入服务开启状态就可以接收视频流了。
163 | 2. rtsp推流如果模型处理速度跟不上会出现很明显的卡顿现象,建议跟踪模型使用ppyoloe_s版本,即修改配置中跟踪模型mot_ppyoloe_l_36e_pipeline.zip替换为mot_ppyoloe_s_36e_pipeline.zip。
164 |
165 | ### Jetson部署说明
166 |
167 | 由于Jetson平台算力相比服务器有较大差距,有如下使用建议:
168 |
169 | 1. 模型选择轻量级版本,我们最新提供了轻量级[PP-YOLOE-Plus Tiny模型](../../../../configs/ppvehicle/README.md),该模型在Jetson AGX上可以实现4路视频流20fps实时跟踪。
170 | 2. 如果需进一步提升速度,建议开启跟踪跳帧功能,推荐使用2或者3: `skip_frame_num: 3`,该功能当前默认关闭。
171 |
172 | 上述修改可以直接修改配置文件(推荐),也可以在命令行中修改(字段较长,不推荐)。
173 |
174 | PP-YOLOE-Plus Tiny模型在AGX平台不同功能开启时的速度如下:(测试视频跟踪车辆为1个)
175 |
176 | | 功能 | 平均每帧耗时(ms) | 运行帧率(fps) |
177 | |:----------|:----------|:----------|
178 | | 跟踪 | 13 | 77 |
179 | | 属性识别 | 20.2 | 49.4 |
180 | | 车牌识别 | - | - |
181 |
182 |
183 | ### 参数说明
184 |
185 | | 参数 | 是否必须|含义 |
186 | |-------|-------|----------|
187 | | --config | Yes | 配置文件路径 |
188 | | -o | Option | 覆盖配置文件中对应的配置 |
189 | | --image_file | Option | 需要预测的图片 |
190 | | --image_dir | Option | 要预测的图片文件夹路径 |
191 | | --video_file | Option | 需要预测的视频,或者rtsp流地址 |
192 | | --rtsp | Option | rtsp视频流地址,支持一路或者多路同时输入 |
193 | | --camera_id | Option | 用来预测的摄像头ID,默认为-1(表示不使用摄像头预测,可设置为:0 - (摄像头数目-1) ),预测过程中在可视化界面按`q`退出输出预测结果到:output/output.mp4|
194 | | --device | Option | 运行时的设备,可选择`CPU/GPU/XPU`,默认为`CPU`|
195 | | --pushurl | Option| 对预测结果视频进行推流的地址,以rtsp://开头,该选项优先级高于视频结果本地存储,打开时不再另外存储本地预测结果视频, 默认为空,表示没有开启|
196 | | --output_dir | Option|可视化结果保存的根目录,默认为output/|
197 | | --run_mode | Option |使用GPU时,默认为paddle, 可选(paddle/trt_fp32/trt_fp16/trt_int8)|
198 | | --enable_mkldnn | Option | CPU预测中是否开启MKLDNN加速,默认为False |
199 | | --cpu_threads | Option| 设置cpu线程数,默认为1 |
200 | | --trt_calib_mode | Option| TensorRT是否使用校准功能,默认为False。使用TensorRT的int8功能时,需设置为True,使用PaddleSlim量化后的模型时需要设置为False |
201 | | --do_entrance_counting | Option | 是否统计出入口流量,默认为False |
202 | | --draw_center_traj | Option | 是否绘制跟踪轨迹,默认为False |
203 | | --region_type | Option | 'horizontal'(默认值)、'vertical':表示流量统计方向选择;'custom':表示设置车辆禁停区域 |
204 | | --region_polygon | Option | 设置禁停区域多边形多点的坐标,无默认值 |
205 | | --illegal_parking_time | Option | 设置禁停时间阈值,单位秒(s),-1(默认值)表示不做检查 |
206 |
207 | ## 方案介绍
208 |
209 | PP-Vehicle 整体方案如下图所示:
210 |
211 |
212 |

213 |
214 |
215 |
216 | ### 车辆检测
217 | - 采用PP-YOLOE L 作为目标检测模型
218 | - 详细文档参考[PP-YOLOE](../../../../configs/ppyoloe/)和[检测跟踪文档](ppvehicle_mot.md)
219 |
220 | ### 车辆跟踪
221 | - 采用SDE方案完成车辆跟踪
222 | - 检测模型使用PP-YOLOE L(高精度)和S(轻量级)
223 | - 跟踪模块采用OC-SORT方案
224 | - 详细文档参考[OC-SORT](../../../../configs/mot/ocsort)和[检测跟踪文档](ppvehicle_mot.md)
225 |
226 | ### 属性识别
227 | - 使用PaddleClas提供的特色模型PP-LCNet,实现对车辆颜色及车型属性的识别。
228 | - 详细文档参考[属性识别](ppvehicle_attribute.md)
229 |
230 | ### 车牌识别
231 | - 使用PaddleOCR特色模型ch_PP-OCRv3_det+ch_PP-OCRv3_rec模型,识别车牌号码
232 | - 详细文档参考[车牌识别](ppvehicle_plate.md)
233 |
234 | ### 违章停车识别
235 | - 车辆跟踪模型使用高精度模型PP-YOLOE L,根据车辆的跟踪轨迹以及指定的违停区域判断是否违章停车,如果存在则展示违章停车车牌号。
236 | - 详细文档参考[违章停车识别](ppvehicle_illegal_parking.md)
237 |
238 | ### 违法分析-逆行
239 | - 违法分析-逆行,通过使用高精度分割模型PP-Seg,对车道线进行分割拟合,然后与车辆轨迹组合判断车辆行驶方向是否与道路方向一致。
240 | - 详细文档参考[违法分析-逆行](ppvehicle_retrograde.md)
241 |
242 | ### 违法分析-压线
243 | - 违法分析-逆行,通过使用高精度分割模型PP-Seg,对车道线进行分割拟合,然后与车辆区域是否覆盖实线区域,进行压线判断。
244 | - 详细文档参考[违法分析-压线](ppvehicle_press.md)
245 |
--------------------------------------------------------------------------------
/docs/tutorials/pphuman_attribute.md:
--------------------------------------------------------------------------------
1 | [English](pphuman_attribute_en.md) | 简体中文
2 |
3 | # PP-Human属性识别模块
4 |
5 | 行人属性识别在智慧社区,工业巡检,交通监控等方向都具有广泛应用,PP-Human中集成了属性识别模块,属性包含性别、年龄、帽子、眼镜、上衣下衣款式等。我们提供了预训练模型,用户可以直接下载使用。
6 |
7 | | 任务 | 算法 | 精度 | 预测速度(ms) |下载链接 |
8 | |:---------------------|:---------:|:------:|:------:| :---------------------------------------------------------------------------------: |
9 | | 行人检测/跟踪 | PP-YOLOE | mAP: 56.3
MOTA: 72.0 | 检测: 16.2ms
跟踪:22.3ms |[下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip) |
10 | | 行人属性高精度模型 | PP-HGNet_small | mA: 95.4 | 单人 1.54ms | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/PPHGNet_small_person_attribute_954_infer.zip) |
11 | | 行人属性轻量级模型 | PP-LCNet_x1_0 | mA: 94.5 | 单人 0.54ms | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/PPLCNet_x1_0_person_attribute_945_infer.zip) |
12 | | 行人属性精度与速度均衡模型 | PP-HGNet_tiny | mA: 95.2 | 单人 1.14ms | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/PPHGNet_tiny_person_attribute_952_infer.zip) |
13 |
14 |
15 | 1. 检测/跟踪模型精度为[MOT17](https://motchallenge.net/),[CrowdHuman](http://www.crowdhuman.org/),[HIEVE](http://humaninevents.org/)和部分业务数据融合训练测试得到。
16 | 2. 行人属性分析精度为[PA100k](https://github.com/xh-liu/HydraPlus-Net#pa-100k-dataset),[RAPv2](http://www.rapdataset.com/rapv2.html),[PETA](http://mmlab.ie.cuhk.edu.hk/projects/PETA.html)和部分业务数据融合训练测试得到
17 | 3. 预测速度为V100 机器上使用TensorRT FP16时的速度, 该处测速速度为模型预测速度
18 | 4. 属性模型应用依赖跟踪模型结果,请在[跟踪模型页面](./pphuman_mot.md)下载跟踪模型,依自身需求选择高精或轻量级下载。
19 | 5. 模型下载后解压放置在PaddleDetection/output_inference/目录下。
20 |
21 | ## 使用方法
22 |
23 | 1. 从上表链接中下载模型并解压到```PaddleDetection/output_inference```路径下,并修改配置文件中模型路径,也可默认自动下载模型。设置```deploy/pipeline/config/infer_cfg_pphuman.yml```中`ATTR`的enable: True
24 |
25 | `infer_cfg_pphuman.yml`中配置项说明:
26 | ```
27 | ATTR: #模块名称
28 | model_dir: output_inference/PPLCNet_x1_0_person_attribute_945_infer/ #模型路径
29 | batch_size: 8 #推理最大batchsize
30 | enable: False #功能是否开启
31 | ```
32 |
33 | 2. 图片输入时,启动命令如下(更多命令参数说明,请参考[快速开始-参数说明](./PPHuman_QUICK_STARTED.md#41-参数说明))。
34 | ```python
35 | #单张图片
36 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
37 | --image_file=test_image.jpg \
38 | --device=gpu \
39 |
40 | #图片文件夹
41 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
42 | --image_dir=images/ \
43 | --device=gpu \
44 |
45 | ```
46 | 3. 视频输入时,启动命令如下
47 | ```python
48 | #单个视频文件
49 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
50 | --video_file=test_video.mp4 \
51 | --device=gpu \
52 |
53 | #视频文件夹
54 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
55 | --video_dir=test_videos/ \
56 | --device=gpu \
57 | ```
58 |
59 | 4. 若修改模型路径,有以下两种方式:
60 |
61 | - 方法一:```./deploy/pipeline/config/infer_cfg_pphuman.yml```下可以配置不同模型路径,属性识别模型修改ATTR字段下配置
62 | - 方法二:命令行中--config后面紧跟着增加`-o ATTR.model_dir`修改模型路径:
63 | ```python
64 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml
65 | -o ATTR.model_dir=output_inference/PPLCNet_x1_0_person_attribute_945_infer/\
66 | --video_file=test_video.mp4 \
67 | --device=gpu
68 | ```
69 |
70 | 测试效果如下:
71 |
72 |
73 |

74 |
75 |
76 | 数据来源及版权归属:天覆科技,感谢提供并开源实际场景数据,仅限学术研究使用
77 |
78 | ## 方案说明
79 |
80 | 1. 目标检测/多目标跟踪获取图片/视频输入中的行人检测框,模型方案为PP-YOLOE,详细文档参考[PP-YOLOE](../../../configs/ppyoloe/README_cn.md)
81 | 2. 通过行人检测框的坐标在输入图像中截取每个行人
82 | 3. 使用属性识别分析每个行人对应属性,属性类型与PA100k数据集相同,具体属性列表如下:
83 | ```
84 | - 性别:男、女
85 | - 年龄:小于18、18-60、大于60
86 | - 朝向:朝前、朝后、侧面
87 | - 配饰:眼镜、帽子、无
88 | - 正面持物:是、否
89 | - 包:双肩包、单肩包、手提包
90 | - 上衣风格:带条纹、带logo、带格子、拼接风格
91 | - 下装风格:带条纹、带图案
92 | - 短袖上衣:是、否
93 | - 长袖上衣:是、否
94 | - 长外套:是、否
95 | - 长裤:是、否
96 | - 短裤:是、否
97 | - 短裙&裙子:是、否
98 | - 穿靴:是、否
99 | ```
100 |
101 | 4. 属性识别模型方案为[StrongBaseline](https://arxiv.org/pdf/2107.03576.pdf),模型结构更改为基于PP-HGNet、PP-LCNet的多分类网络结构,引入Weighted BCE loss提升模型效果。
102 |
103 | ## 参考文献
104 | ```
105 | @article{jia2020rethinking,
106 | title={Rethinking of pedestrian attribute recognition: Realistic datasets with efficient method},
107 | author={Jia, Jian and Huang, Houjing and Yang, Wenjie and Chen, Xiaotang and Huang, Kaiqi},
108 | journal={arXiv preprint arXiv:2005.11909},
109 | year={2020}
110 | }
111 | ```
112 |
--------------------------------------------------------------------------------
/docs/tutorials/pphuman_attribute_en.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](pphuman_attribute.md)
2 |
3 | # Attribute Recognition Modules of PP-Human
4 |
5 | Pedestrian attribute recognition has been widely used in the intelligent community, industrial, and transportation monitoring. Many attribute recognition modules have been gathered in PP-Human, including gender, age, hats, eyes, clothing and up to 26 attributes in total. Also, the pre-trained models are offered here and users can download and use them directly.
6 |
7 | | Task | Algorithm | Precision | Inference Speed(ms) | Download Link |
8 | |:---------------------|:---------:|:------:|:------:| :---------------------------------------------------------------------------------: |
9 | | High-Precision Model | PP-HGNet_small | mA: 95.4 | per person 1.54ms | [Download](https://bj.bcebos.com/v1/paddledet/models/pipeline/PPHGNet_small_person_attribute_954_infer.tar) |
10 | | Fast Model | PP-LCNet_x1_0 | mA: 94.5 | per person 0.54ms | [Download](https://bj.bcebos.com/v1/paddledet/models/pipeline/PPLCNet_x1_0_person_attribute_945_infer.tar) |
11 | | Balanced Model | PP-HGNet_tiny | mA: 95.2 | per person 1.14ms | [Download](https://bj.bcebos.com/v1/paddledet/models/pipeline/PPHGNet_tiny_person_attribute_952_infer.tar) |
12 |
13 | 1. The precision of pedestiran attribute analysis is obtained by training and testing on the dataset consist of [PA100k](https://github.com/xh-liu/HydraPlus-Net#pa-100k-dataset),[RAPv2](http://www.rapdataset.com/rapv2.html),[PETA](http://mmlab.ie.cuhk.edu.hk/projects/PETA.html) and some business data.
14 | 2. The inference speed is V100, the speed of using TensorRT FP16.
15 | 3. This model of Attribute is based on the result of tracking, please download tracking model in the [Page of Mot](./pphuman_mot_en.md). The High precision and Faster model are both available.
16 | 4. You should place the model unziped in the directory of `PaddleDetection/output_inference/`.
17 |
18 | ## Instruction
19 |
20 | 1. Download the model from the link in the above table, and unzip it to```./output_inference```, and set the "enable: True" in ATTR of infer_cfg_pphuman.yml
21 |
22 | The meaning of configs of `infer_cfg_pphuman.yml`:
23 | ```
24 | ATTR: #module name
25 | model_dir: output_inference/PPLCNet_x1_0_person_attribute_945_infer/ #model path
26 | batch_size: 8 #maxmum batchsize when inference
27 | enable: False #whether to enable this model
28 | ```
29 |
30 | 2. When inputting the image, run the command as follows (please refer to [QUICK_STARTED-Parameters](./PPHuman_QUICK_STARTED.md#41-参数说明) for more details):
31 | ```python
32 | #single image
33 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
34 | --image_file=test_image.jpg \
35 | --device=gpu \
36 |
37 | #image directory
38 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
39 | --image_dir=images/ \
40 | --device=gpu \
41 |
42 | ```
43 | 3. When inputting the video, run the command as follows:
44 | ```python
45 | #a single video file
46 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
47 | --video_file=test_video.mp4 \
48 | --device=gpu \
49 |
50 | #directory of videos
51 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
52 | --video_dir=test_videos/ \
53 | --device=gpu \
54 | ```
55 | 4. If you want to change the model path, there are two methods:
56 |
57 | - The first: In ```./deploy/pipeline/config/infer_cfg_pphuman.yml``` you can configurate different model paths. In attribute recognition models, you can modify the configuration in the field of ATTR.
58 | - The second: Add `-o ATTR.model_dir` in the command line following the --config to change the model path:
59 | ```python
60 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
61 | -o ATTR.model_dir=output_inference/PPLCNet_x1_0_person_attribute_945_infer/\
62 | --video_file=test_video.mp4 \
63 | --device=gpu
64 | ```
65 |
66 | The test result is:
67 |
68 |
69 |

70 |
71 |
72 | Data Source and Copyright:Skyinfor Technology. Thanks for the provision of actual scenario data, which are only used for academic research here.
73 |
74 | ## Introduction to the Solution
75 |
76 | 1. The PP-YOLOE model is used to handle detection boxs of input images/videos from object detection/ multi-object tracking. For details, please refer to the document [PP-YOLOE](../../../configs/ppyoloe).
77 | 2. Capture every pedestrian in the input images with the help of coordiantes of detection boxes.
78 | 3. Analyze the listed labels of pedestirans through attribute recognition. They are the same as those in the PA100k dataset. The label list is as follows:
79 | ```
80 | - Gender
81 | - Age: Less than 18; 18-60; Over 60
82 | - Orientation: Front; Back; Side
83 | - Accessories: Glasses; Hat; None
84 | - HoldObjectsInFront: Yes; No
85 | - Bag: BackPack; ShoulderBag; HandBag
86 | - TopStyle: UpperStride; UpperLogo; UpperPlaid; UpperSplice
87 | - BottomStyle: LowerStripe; LowerPattern
88 | - ShortSleeve: Yes; No
89 | - LongSleeve: Yes; No
90 | - LongCoat: Yes; No
91 | - Trousers: Yes; No
92 | - Shorts: Yes; No
93 | - Skirt&Dress: Yes; No
94 | - Boots: Yes; No
95 | ```
96 |
97 | 4. The model adopted in the attribute recognition is [StrongBaseline](https://arxiv.org/pdf/2107.03576.pdf), where the structure is the multi-class network structure based on PP-HGNet、PP-LCNet, and Weighted BCE loss is introduced for effect optimization.
98 |
99 | ## Reference
100 | ```
101 | @article{jia2020rethinking,
102 | title={Rethinking of pedestrian attribute recognition: Realistic datasets with efficient method},
103 | author={Jia, Jian and Huang, Houjing and Yang, Wenjie and Chen, Xiaotang and Huang, Kaiqi},
104 | journal={arXiv preprint arXiv:2005.11909},
105 | year={2020}
106 | }
107 | ```
108 |
--------------------------------------------------------------------------------
/docs/tutorials/pphuman_mot.md:
--------------------------------------------------------------------------------
1 | [English](pphuman_mot_en.md) | 简体中文
2 |
3 | # PP-Human检测跟踪模块
4 |
5 | 行人检测与跟踪在智慧社区,工业巡检,交通监控等方向都具有广泛应用,PP-Human中集成了检测跟踪模块,是关键点检测、属性行为识别等任务的基础。我们提供了预训练模型,用户可以直接下载使用。
6 |
7 | | 任务 | 算法 | 精度 | 预测速度(ms) |下载链接 |
8 | |:---------------------|:---------:|:------:|:------:| :---------------------------------------------------------------------------------: |
9 | | 行人检测/跟踪 | PP-YOLOE-l | mAP: 57.8
MOTA: 82.2 | 检测: 25.1ms
跟踪:31.8ms | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip) |
10 | | 行人检测/跟踪 | PP-YOLOE-s | mAP: 53.2
MOTA: 73.9 | 检测: 16.2ms
跟踪:21.0ms | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_s_36e_pipeline.zip) |
11 |
12 | 1. 检测/跟踪模型精度为[COCO-Person](http://cocodataset.org/), [CrowdHuman](http://www.crowdhuman.org/), [HIEVE](http://humaninevents.org/) 和部分业务数据融合训练测试得到,验证集为业务数据
13 | 2. 预测速度为T4 机器上使用TensorRT FP16时的速度, 速度包含数据预处理、模型预测、后处理全流程
14 |
15 | ## 使用方法
16 |
17 | 1. 从上表链接中下载模型并解压到```./output_inference```路径下,并修改配置文件中模型路径。默认为自动下载模型,无需做改动。
18 | 2. 图片输入时,是纯检测任务,启动命令如下
19 | ```python
20 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
21 | --image_file=test_image.jpg \
22 | --device=gpu
23 | ```
24 | 3. 视频输入时,是跟踪任务,注意首先设置infer_cfg_pphuman.yml中的MOT配置的`enable=True`,如果希望跳帧加速检测跟踪流程,可以设置`skip_frame_num: 2`,建议跳帧帧数最大不超过3:
25 | ```
26 | MOT:
27 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip
28 | tracker_config: deploy/pipeline/config/tracker_config.yml
29 | batch_size: 1
30 | skip_frame_num: 2
31 | enable: True
32 | ```
33 | 然后启动命令如下
34 | ```python
35 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
36 | --video_file=test_video.mp4 \
37 | --device=gpu
38 | ```
39 | 4. 若修改模型路径,有以下两种方式:
40 |
41 | - ```./deploy/pipeline/config/infer_cfg_pphuman.yml```下可以配置不同模型路径,检测和跟踪模型分别对应`DET`和`MOT`字段,修改对应字段下的路径为实际期望的路径即可。
42 | - 命令行中--config后面紧跟着增加`-o MOT.model_dir`修改模型路径:
43 | ```python
44 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
45 | -o MOT.model_dir=ppyoloe/\
46 | --video_file=test_video.mp4 \
47 | --device=gpu \
48 | --region_type=horizontal \
49 | --do_entrance_counting \
50 | --draw_center_traj
51 |
52 | ```
53 | **注意:**
54 | - `--do_entrance_counting`表示是否统计出入口流量,不设置即默认为False。
55 | - `--draw_center_traj`表示是否绘制跟踪轨迹,不设置即默认为False。注意绘制跟踪轨迹的测试视频最好是静止摄像头拍摄的。
56 | - `--region_type`表示流量计数的区域,当设置`--do_entrance_counting`时可选择`horizontal`或者`vertical`,默认是`horizontal`,表示以视频图片的中心水平线为出入口,同一物体框的中心点在相邻两秒内分别在区域中心水平线的两侧,即完成计数加一。
57 |
58 | 测试效果如下:
59 |
60 |
61 |

62 |
63 |
64 | 数据来源及版权归属:天覆科技,感谢提供并开源实际场景数据,仅限学术研究使用
65 |
66 | 5. 区域闯入判断和计数
67 |
68 | 注意首先设置infer_cfg_pphuman.yml中的MOT配置的enable=True,然后启动命令如下
69 | ```python
70 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
71 | --video_file=test_video.mp4 \
72 | --device=gpu \
73 | --draw_center_traj \
74 | --do_break_in_counting \
75 | --region_type=custom \
76 | --region_polygon 200 200 400 200 300 400 100 400
77 | ```
78 | **注意:**
79 | - 区域闯入的测试视频必须是静止摄像头拍摄的,镜头不能抖动或移动。
80 | - `--do_break_in_counting`表示是否进行区域出入后计数,不设置即默认为False。
81 | - `--region_type`表示流量计数的区域,当设置`--do_break_in_counting`时仅可选择`custom`,默认是`custom`,表示以用户自定义区域为出入口,同一物体框的下边界中点坐标在相邻两秒内从区域外到区域内,即完成计数加一。
82 | - `--region_polygon`表示用户自定义区域的多边形的点坐标序列,每两个为一对点坐标(x,y),**按顺时针顺序**连成一个**封闭区域**,至少需要3对点也即6个整数,默认值是`[]`,需要用户自行设置点坐标,如是四边形区域,坐标顺序是`左上、右上、右下、左下`。用户可以运行[此段代码](../../tools/get_video_info.py)获取所测视频的分辨率帧数,以及可以自定义画出自己想要的多边形区域的可视化并自己调整。
83 | 自定义多边形区域的可视化代码运行如下:
84 | ```python
85 | python get_video_info.py --video_file=demo.mp4 --region_polygon 200 200 400 200 300 400 100 400
86 | ```
87 | 快速画出想要的区域的小技巧:先任意取点得到图片,用画图工具打开,鼠标放到想要的区域点上会显示出坐标,记录下来并取整,作为这段可视化代码的region_polygon参数,并再次运行可视化,微调点坐标参数直至满意。
88 |
89 |
90 | 测试效果如下:
91 |
92 |
93 |

94 |
95 |
96 | ## 方案说明
97 |
98 | 1. 使用目标检测/多目标跟踪技术来获取图片/视频输入中的行人检测框,检测模型方案为PP-YOLOE,详细文档参考[PP-YOLOE](../../../../configs/ppyoloe)。
99 | 2. 多目标跟踪模型方案采用[ByteTrack](https://arxiv.org/pdf/2110.06864.pdf)和[OC-SORT](https://arxiv.org/pdf/2203.14360.pdf),采用PP-YOLOE替换原文的YOLOX作为检测器,采用BYTETracker和OCSORTTracker作为跟踪器,详细文档参考[ByteTrack](../../../../configs/mot/bytetrack)和[OC-SORT](../../../../configs/mot/ocsort)。
100 |
101 | ## 参考文献
102 | ```
103 | @article{zhang2021bytetrack,
104 | title={ByteTrack: Multi-Object Tracking by Associating Every Detection Box},
105 | author={Zhang, Yifu and Sun, Peize and Jiang, Yi and Yu, Dongdong and Yuan, Zehuan and Luo, Ping and Liu, Wenyu and Wang, Xinggang},
106 | journal={arXiv preprint arXiv:2110.06864},
107 | year={2021}
108 | }
109 |
110 | @article{cao2022observation,
111 | title={Observation-Centric SORT: Rethinking SORT for Robust Multi-Object Tracking},
112 | author={Cao, Jinkun and Weng, Xinshuo and Khirodkar, Rawal and Pang, Jiangmiao and Kitani, Kris},
113 | journal={arXiv preprint arXiv:2203.14360},
114 | year={2022}
115 | }
116 | ```
117 |
--------------------------------------------------------------------------------
/docs/tutorials/pphuman_mot_en.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](pphuman_mot.md)
2 |
3 | # Detection and Tracking Module of PP-Human
4 |
5 | Pedestrian detection and tracking is widely used in the intelligent community, industrial inspection, transportation monitoring and so on. PP-Human has the detection and tracking module, which is fundamental to keypoint detection, attribute action recognition, etc. Users enjoy easy access to pretrained models here.
6 |
7 | | Task | Algorithm | Precision | Inference Speed(ms) | Download Link |
8 | |:---------------------|:---------:|:------:|:------:| :---------------------------------------------------------------------------------: |
9 | | Pedestrian Detection/ Tracking | PP-YOLOE-l | mAP: 57.8
MOTA: 82.2 | Detection: 25.1ms
Tracking:31.8ms | [Download](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip) |
10 | | Pedestrian Detection/ Tracking | PP-YOLOE-s | mAP: 53.2
MOTA: 73.9 | Detection: 16.2ms
Tracking:21.0ms | [Download](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_s_36e_pipeline.zip) |
11 |
12 | 1. The precision of the pedestrian detection/ tracking model is obtained by trainning and testing on [COCO-Person](http://cocodataset.org/), [CrowdHuman](http://www.crowdhuman.org/), [HIEVE](http://humaninevents.org/) and some business data.
13 | 2. The inference speed is the speed of using TensorRT FP16 on T4, the total number of data pre-training, model inference, and post-processing.
14 |
15 | ## How to Use
16 |
17 | 1. Download models from the links of the above table and unizp them to ```./output_inference```.
18 | 2. When use the image as input, it's a detection task, the start command is as follows:
19 | ```python
20 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
21 | --image_file=test_image.jpg \
22 | --device=gpu
23 | ```
24 | 3. When use the video as input, it's a tracking task, first you should set the "enable: True" in MOT of infer_cfg_pphuman.yml. If you want skip some frames speed up the detection and tracking process, you can set `skip_frame_num: 2`, it is recommended that the maximum number of skip_frame_num should not exceed 3:
25 | ```
26 | MOT:
27 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip
28 | tracker_config: deploy/pipeline/config/tracker_config.yml
29 | batch_size: 1
30 | skip_frame_num: 2
31 | enable: True
32 | ```
33 | and then the start command is as follows:
34 | ```python
35 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
36 | --video_file=test_video.mp4 \
37 | --device=gpu
38 | ```
39 | 4. There are two ways to modify the model path:
40 |
41 | - In `./deploy/pipeline/config/infer_cfg_pphuman.yml`, you can configurate different model paths,which is proper only if you match keypoint models and action recognition models with the fields of `DET` and `MOT` respectively, and modify the corresponding path of each field into the expected path.
42 | - Add `-o MOT.model_dir` in the command line following the --config to change the model path:
43 |
44 | ```python
45 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
46 | -o MOT.model_dir=ppyoloe/\
47 | --video_file=test_video.mp4 \
48 | --device=gpu \
49 | --region_type=horizontal \
50 | --do_entrance_counting \
51 | --draw_center_traj
52 |
53 | ```
54 | **Note:**
55 |
56 | - `--do_entrance_counting` is whether to calculate flow at the gateway, and the default setting is False.
57 | - `--draw_center_traj` means whether to draw the track, and the default setting is False. It's worth noting that the test video of track drawing should be filmed by the still camera.
58 | - `--region_type` means the region type of flow counting. When set `--do_entrance_counting`, you can select from `horizontal` or `vertical`, the default setting is `horizontal`, means that the central horizontal line of the video picture is used as the entrance and exit, and when the central point of the same object box is on both sides of the central horizontal line of the area in two adjacent seconds, the counting plus one is completed.
59 |
60 | The test result is:
61 |
62 |
63 |

64 |
65 |
66 | Data source and copyright owner:Skyinfor Technology. Thanks for the provision of actual scenario data, which are only used for academic research here.
67 |
68 | 5. Break in and counting
69 |
70 | Please set the "enable: True" in MOT of infer_cfg_pphuman.yml at first, and then the start command is as follows:
71 | ```python
72 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml \
73 | --video_file=test_video.mp4 \
74 | --device=gpu \
75 | --draw_center_traj \
76 | --do_break_in_counting \
77 | --region_type=custom \
78 | --region_polygon 200 200 400 200 300 400 100 400
79 | ```
80 |
81 | **Note:**
82 | - `--do_break_in_counting` is whether to calculate flow when break in the user-defined region, and the default setting is False.
83 | - `--region_type` means the region type of flow counting. When set `--do_break_in_counting`, only `custom` can be selected, and the default is `custom`, which means that the user-defined region is used as the entrance and exit, and when the midpoint coords of the bottom boundary of the same object moves from outside to inside the region within two adjacent seconds, the counting plus one is completed.
84 | - `--region_polygon` means the point coords sequence of the polygon in the user-defined region. Every two integers are a pair of point coords (x,y), which are connected into a closed area in clockwise order. At least 3 pairs of points, that is, 6 integers, are required. The default value is `[]`, and the user needs to set the point coords by himself. Users can run this [code](../../tools/get_video_info.py) to obtain the resolution and frame number of the measured video, and can customize the visualization of drawing the polygon area they want and adjust it by themselves.
85 | The visualization code of the custom polygon region runs as follows:
86 | ```python
87 | python get_video_info.py --video_file=demo.mp4 --region_polygon 200 200 400 200 300 400 100 400
88 | ```
89 |
90 | The test result is:
91 |
92 |
93 |

94 |
95 |
96 |
97 | ## Introduction to the Solution
98 |
99 | 1. Get the pedestrian detection box of the image/ video input through object detection and multi-object tracking. The detection model is PP-YOLOE, please refer to [PP-YOLOE](../../../../configs/ppyoloe) for details.
100 |
101 | 2. The multi-object tracking solution is based on [ByteTrack](https://arxiv.org/pdf/2110.06864.pdf) and [OC-SORT](https://arxiv.org/pdf/2203.14360.pdf), and replace the original YOLOX with PP-YOLOE as the detector,and BYTETracker or OC-SORT Tracker as the tracker, please refer to [ByteTrack](../../../../configs/mot/bytetrack) and [OC-SORT](../../../../configs/mot/ocsort).
102 |
103 | ## Reference
104 | ```
105 | @article{zhang2021bytetrack,
106 | title={ByteTrack: Multi-Object Tracking by Associating Every Detection Box},
107 | author={Zhang, Yifu and Sun, Peize and Jiang, Yi and Yu, Dongdong and Yuan, Zehuan and Luo, Ping and Liu, Wenyu and Wang, Xinggang},
108 | journal={arXiv preprint arXiv:2110.06864},
109 | year={2021}
110 | }
111 | ```
112 |
--------------------------------------------------------------------------------
/docs/tutorials/pphuman_mtmct.md:
--------------------------------------------------------------------------------
1 | [English](pphuman_mtmct_en.md) | 简体中文
2 |
3 | # PP-Human跨镜头跟踪模块
4 |
5 | 跨镜头跟踪任务,是在单镜头跟踪的基础上,实现不同摄像头中人员的身份匹配关联。在安放、智慧零售等方向有较多的应用。
6 | PP-Human跨镜头跟踪模块主要目的在于提供一套简洁、高效的跨镜跟踪Pipeline,REID模型完全基于开源数据集训练。
7 |
8 | ## 使用方法
9 |
10 | 1. 下载模型 [行人跟踪](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_pipeline.zip)和[REID模型](https://bj.bcebos.com/v1/paddledet/models/pipeline/reid_model.zip) 并解压到```./output_inference```路径下,修改配置文件中模型路径。也可简单起见直接用默认配置,自动下载模型。 MOT模型请参考[mot说明](./pphuman_mot.md)文件下载。
11 |
12 | 2. 跨镜头跟踪模式下,要求输入的多个视频放在同一目录下,同时开启infer_cfg_pphuman.yml 中的REID选择中的enable=True, 命令如下:
13 | ```python
14 | python3 deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml --video_dir=[your_video_file_directory] --device=gpu
15 | ```
16 |
17 | 3. 相关配置在`./deploy/pipeline/config/infer_cfg_pphuman.yml`文件中修改:
18 |
19 | ```python
20 | python3 deploy/pipeline/pipeline.py
21 | --config deploy/pipeline/config/infer_cfg_pphuman.yml -o REID.model_dir=reid_best/
22 | --video_dir=[your_video_file_directory]
23 | --device=gpu
24 | ```
25 |
26 | ## 方案说明
27 |
28 | 跨镜头跟踪模块,主要由跨镜头跟踪Pipeline及REID模型两部分组成。
29 | 1. 跨镜头跟踪Pipeline
30 |
31 | ```
32 |
33 | 单镜头跟踪[id+bbox]
34 | │
35 | 根据bbox截取原图中目标——│
36 | │ │
37 | REID模型 质量评估(遮挡、完整度、亮度等)
38 | │ │
39 | [feature] [quality]
40 | │ │
41 | datacollector—————│
42 | │
43 | 特征排序、筛选
44 | │
45 | 多视频各id相似度计算
46 | │
47 | id聚类、重新分配id
48 | ```
49 |
50 | 2. 模型方案为[reid-strong-baseline](https://github.com/michuanhaohao/reid-strong-baseline), Backbone为ResNet50, 主要特色为模型结构简单。
51 | 本跨镜跟踪中所用REID模型在上述基础上,整合多个开源数据集并压缩模型特征到128维以提升泛化性能。大幅提升了在实际应用中的泛化效果。
52 |
53 | ### 其他建议
54 | - 提供的REID模型基于开源数据集训练得到,建议加入自有数据,训练更加强有力的REID模型,将非常明显提升跨镜跟踪效果。
55 | - 质量评估部分基于简单逻辑+OpenCV实现,效果有限,如果有条件建议针对性训练质量判断模型。
56 |
57 |
58 | ### 示例效果
59 |
60 | - camera 1:
61 |
62 |

63 |
64 |
65 | - camera 2:
66 |
67 |

68 |
69 |
70 |
71 | ## 参考文献
72 | ```
73 | @InProceedings{Luo_2019_CVPR_Workshops,
74 | author = {Luo, Hao and Gu, Youzhi and Liao, Xingyu and Lai, Shenqi and Jiang, Wei},
75 | title = {Bag of Tricks and a Strong Baseline for Deep Person Re-Identification},
76 | booktitle = {The IEEE Conference on Computer Vision and Pattern Recognition (CVPR) Workshops},
77 | month = {June},
78 | year = {2019}
79 | }
80 |
81 | @ARTICLE{Luo_2019_Strong_TMM,
82 | author={H. {Luo} and W. {Jiang} and Y. {Gu} and F. {Liu} and X. {Liao} and S. {Lai} and J. {Gu}},
83 | journal={IEEE Transactions on Multimedia},
84 | title={A Strong Baseline and Batch Normalization Neck for Deep Person Re-identification},
85 | year={2019},
86 | pages={1-1},
87 | doi={10.1109/TMM.2019.2958756},
88 | ISSN={1941-0077},
89 | }
90 | ```
91 |
--------------------------------------------------------------------------------
/docs/tutorials/pphuman_mtmct_en.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](pphuman_mtmct.md)
2 |
3 | # Multi-Target Multi-Camera Tracking Module of PP-Human
4 |
5 | Multi-target multi-camera tracking, or MTMCT, matches the identity of a person in different cameras based on the single-camera tracking. MTMCT is usually applied to the security system and the smart retailing.
6 | The MTMCT module of PP-Human aims to provide a multi-target multi-camera pipleline which is simple, and efficient.
7 |
8 | ## How to Use
9 |
10 | 1. Download [REID model](https://bj.bcebos.com/v1/paddledet/models/pipeline/reid_model.zip) and unzip it to ```./output_inference```. For the MOT model, please refer to [mot description](./pphuman_mot.md).
11 |
12 | 2. In the MTMCT mode, input videos are required to be put in the same directory. set the REID "enable: True" in the infer_cfg_pphuman.yml. The command line is:
13 | ```python
14 | python3 deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_pphuman.yml --video_dir=[your_video_file_directory] --device=gpu
15 | ```
16 |
17 | 3. Configuration can be modified in `./deploy/pipeline/config/infer_cfg_pphuman.yml`.
18 |
19 | ```python
20 | python3 deploy/pipeline/pipeline.py
21 | --config deploy/pipeline/config/infer_cfg_pphuman.yml -o REID.model_dir=reid_best/
22 | --video_dir=[your_video_file_directory]
23 | --device=gpu
24 | ```
25 |
26 | ## Intorduction to the Solution
27 |
28 | MTMCT module consists of the multi-target multi-camera tracking pipeline and the REID model.
29 |
30 | 1. Multi-Target Multi-Camera Tracking Pipeline
31 |
32 | ```
33 |
34 | single-camera tracking[id+bbox]
35 | │
36 | capture the target in the original image according to bbox——│
37 | │ │
38 | REID model quality assessment (covered or not, complete or not, brightness, etc.)
39 | │ │
40 | [feature] [quality]
41 | │ │
42 | datacollector—————│
43 | │
44 | sort out and filter features
45 | │
46 | calculate the similarity of IDs in the videos
47 | │
48 | make the IDs cluster together and rearrange them
49 | ```
50 |
51 | 2. The model solution is [reid-strong-baseline](https://github.com/michuanhaohao/reid-strong-baseline), with ResNet50 as the backbone.
52 |
53 | Under the above circumstances, the REID model used in MTMCT integrates open-source datasets and compresses model features to 128-dimensional features to optimize the generalization. In this way, the actual generalization result becomes much better.
54 |
55 | ### Other Suggestions
56 |
57 | - The provided REID model is obtained from open-source dataset training. It is recommended to add your own data to get a more powerful REID model, notably improving the MTMCT effect.
58 | - The quality assessment is based on simple logic +OpenCV, whose effect is limited. If possible, it is advisable to conduct specific training on the quality assessment model.
59 |
60 |
61 | ### Example
62 |
63 | - camera 1:
64 |
65 |

66 |
67 |
68 | - camera 2:
69 |
70 |

71 |
72 |
73 |
74 | ## Reference
75 | ```
76 | @InProceedings{Luo_2019_CVPR_Workshops,
77 | author = {Luo, Hao and Gu, Youzhi and Liao, Xingyu and Lai, Shenqi and Jiang, Wei},
78 | title = {Bag of Tricks and a Strong Baseline for Deep Person Re-Identification},
79 | booktitle = {The IEEE Conference on Computer Vision and Pattern Recognition (CVPR) Workshops},
80 | month = {June},
81 | year = {2019}
82 | }
83 |
84 | @ARTICLE{Luo_2019_Strong_TMM,
85 | author={H. {Luo} and W. {Jiang} and Y. {Gu} and F. {Liu} and X. {Liao} and S. {Lai} and J. {Gu}},
86 | journal={IEEE Transactions on Multimedia},
87 | title={A Strong Baseline and Batch Normalization Neck for Deep Person Re-identification},
88 | year={2019},
89 | pages={1-1},
90 | doi={10.1109/TMM.2019.2958756},
91 | ISSN={1941-0077},
92 | }
93 | ```
94 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_attribute.md:
--------------------------------------------------------------------------------
1 | [English](ppvehicle_attribute_en.md) | 简体中文
2 |
3 | # PP-Vehicle属性识别模块
4 |
5 | 车辆属性识别在智慧城市,智慧交通等方向具有广泛应用。在PP-Vehicle中,集成了车辆属性识别模块,可识别车辆颜色及车型属性的识别。
6 |
7 | | 任务 | 算法 | 精度 | 预测速度 | 下载链接|
8 | |-----------|------|-----------|----------|---------------|
9 | | 车辆检测/跟踪 | PP-YOLOE | mAP 63.9 | 38.67ms | [预测部署模型](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
10 | | 车辆属性识别 | PPLCNet | 90.81 | 7.31 ms | [预测部署模型](https://bj.bcebos.com/v1/paddledet/models/pipeline/vehicle_attribute_model.zip) |
11 |
12 |
13 | 注意:
14 | 1. 属性模型预测速度是基于NVIDIA T4, 开启TensorRT FP16得到。模型预测速度包含数据预处理、模型预测、后处理部分。
15 | 2. 关于PP-LCNet的介绍可以参考[PP-LCNet](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.4/docs/zh_CN/models/PP-LCNet.md)介绍,相关论文可以查阅[PP-LCNet paper](https://arxiv.org/abs/2109.15099)。
16 | 3. 属性模型的训练和精度测试均基于[VeRi数据集](https://www.v7labs.com/open-datasets/veri-dataset)。
17 |
18 |
19 | - 当前提供的预训练模型支持识别10种车辆颜色及9种车型,同VeRi数据集,具体如下:
20 |
21 | ```yaml
22 | # 车辆颜色
23 | - "yellow"
24 | - "orange"
25 | - "green"
26 | - "gray"
27 | - "red"
28 | - "blue"
29 | - "white"
30 | - "golden"
31 | - "brown"
32 | - "black"
33 |
34 | # 车型
35 | - "sedan"
36 | - "suv"
37 | - "van"
38 | - "hatchback"
39 | - "mpv"
40 | - "pickup"
41 | - "bus"
42 | - "truck"
43 | - "estate"
44 | ```
45 |
46 | ## 使用方法
47 |
48 | ### 配置项说明
49 |
50 | [配置文件](../../config/infer_cfg_ppvehicle.yml)中与属性相关的参数如下:
51 | ```
52 | VEHICLE_ATTR:
53 | model_dir: output_inference/vehicle_attribute_infer/ # 车辆属性模型调用路径
54 | batch_size: 8 # 模型预测时的batch_size大小
55 | color_threshold: 0.5 # 颜色属性阈值,需要置信度达到此阈值才会确定具体颜色,否则为'Unknown‘
56 | type_threshold: 0.5 # 车型属性阈值,需要置信度达到此阈值才会确定具体属性,否则为'Unknown‘
57 | enable: False # 是否开启该功能
58 | ```
59 |
60 | ### 使用命令
61 |
62 | 1. 从模型库下载`车辆检测/跟踪`, `车辆属性识别`两个预测部署模型并解压到`./output_inference`路径下;默认会自动下载模型,如果手动下载,需要修改模型文件夹为模型存放路径。
63 | 2. 修改配置文件中`VEHICLE_ATTR`项的`enable: True`,以启用该功能。
64 | 3. 图片输入时,启动命令如下(更多命令参数说明,请参考[快速开始-参数说明](./PPVehicle_QUICK_STARTED.md)):
65 |
66 | ```bash
67 | # 预测单张图片文件
68 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
69 | --image_file=test_image.jpg \
70 | --device=gpu
71 |
72 | # 预测包含一张或多张图片的文件夹
73 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
74 | --image_dir=images/ \
75 | --device=gpu
76 | ```
77 |
78 | 4. 视频输入时,启动命令如下:
79 |
80 | ```bash
81 | #预测单个视频文件
82 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
83 | --video_file=test_video.mp4 \
84 | --device=gpu
85 |
86 | #预测包含一个或多个视频的文件夹
87 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
88 | --video_dir=test_videos/ \
89 | --device=gpu
90 | ```
91 |
92 | 5. 若修改模型路径,有以下两种方式:
93 |
94 | - 方法一:`./deploy/pipeline/config/infer_cfg_ppvehicle.yml`下可以配置不同模型路径,属性识别模型修改`VEHICLE_ATTR`字段下配置
95 | - 方法二:直接在命令行中增加`-o`,以覆盖配置文件中的默认模型路径:
96 |
97 | ```bash
98 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
99 | --video_file=test_video.mp4 \
100 | --device=gpu \
101 | -o VEHICLE_ATTR.model_dir=output_inference/vehicle_attribute_infer
102 | ```
103 |
104 | 测试效果如下:
105 |
106 |
107 |

108 |
109 |
110 | ## 方案说明
111 | 车辆属性识别模型使用了[PaddleClas](https://github.com/PaddlePaddle/PaddleClas) 的超轻量图像分类方案(PULC,Practical Ultra Lightweight image Classification)。关于该模型的数据准备、训练、测试等详细内容,请见[PULC 车辆属性识别模型](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.4/docs/zh_CN/PULC/PULC_vehicle_attribute.md).
112 |
113 | 车辆属性识别模型选用了轻量级、高精度的PPLCNet。并在该模型的基础上,进一步使用了以下优化方案:
114 |
115 | - 使用SSLD预训练模型,在不改变推理速度的前提下,精度可以提升约0.5个百分点
116 | - 融合EDA数据增强策略,精度可以再提升0.52个百分点
117 | - 使用SKL-UGI知识蒸馏, 精度可以继续提升0.23个百分点
118 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_attribute_en.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](ppvehicle_attribute.md)
2 |
3 | # Attribute Recognition Module of PP-Vehicle
4 |
5 | Vehicle attribute recognition is widely used in smart cities, smart transportation and other scenarios. In PP-Vehicle, a vehicle attribute recognition module is integrated, which can identify vehicle color and model.
6 |
7 | | Task | Algorithm | Precision | Inference Speed | Download |
8 | |-----------|------|-----------|----------|---------------------|
9 | | Vehicle Detection/Tracking | PP-YOLOE | mAP 63.9 | 38.67ms | [Inference and Deployment Model](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
10 | | Vehicle Attribute Recognition | PPLCNet | 90.81 | 7.31 ms | [Inference and Deployment Model](https://bj.bcebos.com/v1/paddledet/models/pipeline/vehicle_attribute_model.zip) |
11 |
12 |
13 | Note:
14 | 1. The inference speed of the attribute model is obtained from the test on NVIDIA T4, with TensorRT FP16. The time includes data pre-process, model inference and post-process.
15 | 2. For introductions, please refer to [PP-LCNet Series](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.4/docs/en/models/PP-LCNet_en.md). Related paper is available on PP-LCNet paper
16 | 3. The training and test phase of vehicle attribute recognition model are both obtained from [VeRi dataset](https://www.v7labs.com/open-datasets/veri-dataset).
17 |
18 |
19 | - The provided pre-trained model supports 10 colors and 9 models, which is the same with VeRi dataset. The details are as follows:
20 |
21 | ```yaml
22 | # Vehicle Colors
23 | - "yellow"
24 | - "orange"
25 | - "green"
26 | - "gray"
27 | - "red"
28 | - "blue"
29 | - "white"
30 | - "golden"
31 | - "brown"
32 | - "black"
33 |
34 | # Vehicle Models
35 | - "sedan"
36 | - "suv"
37 | - "van"
38 | - "hatchback"
39 | - "mpv"
40 | - "pickup"
41 | - "bus"
42 | - "truck"
43 | - "estate"
44 | ```
45 |
46 | ## Instructions
47 |
48 | ### Description of Configuration
49 |
50 | Parameters related to vehicle attribute recognition in the [config file](../../config/infer_cfg_ppvehicle.yml) are as follows:
51 |
52 | ```yaml
53 | VEHICLE_ATTR:
54 | model_dir: output_inference/vehicle_attribute_infer/ # Path of the model
55 | batch_size: 8 # The size of the inference batch
56 | color_threshold: 0.5 # Threshold of color. Confidence is required to reach this threshold to determine the specific attribute, otherwise it will be 'Unknown‘.
57 | type_threshold: 0.5 # Threshold of vehicle model. Confidence is required to reach this threshold to determine the specific attribute, otherwise it will be 'Unknown‘.
58 | enable: False # Whether to enable this function
59 | ```
60 |
61 | ### How to Use
62 | 1. Download models `Vehicle Detection/Tracking` and `Vehicle Attribute Recognition` from the links in `Model Zoo` and unzip them to ```./output_inference```. The models are automatically downloaded by default. If you download them manually, you need to modify the `model_dir` as the model storage path to use this function.
63 |
64 | 2. Set the "enable: True" of `VEHICLE_ATTR` in infer_cfg_ppvehicle.yml.
65 |
66 | 3. For image input, please run these commands. (Description of more parameters, please refer to [QUICK_STARTED - Parameter_Description](./PPVehicle_QUICK_STARTED.md).
67 |
68 | ```bash
69 | # For single image
70 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
71 | --image_file=test_image.jpg \
72 | --device=gpu
73 |
74 | # For folder contains one or multiple images
75 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
76 | --image_dir=images/ \
77 | --device=gpu
78 | ```
79 |
80 | 4. For video input, please run these commands.
81 |
82 | ```bash
83 | # For single video
84 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
85 | --video_file=test_video.mp4 \
86 | --device=gpu
87 |
88 | # For folder contains one or multiple videos
89 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
90 | --video_dir=test_videos/ \
91 | --device=gpu
92 | ```
93 |
94 | 5. There are two ways to modify the model path:
95 |
96 | - Method 1:Set paths of each model in `./deploy/pipeline/config/infer_cfg_ppvehicle.yml`. For vehicle attribute recognition, the path should be modified under the `VEHICLE_ATTR` field.
97 | - Method 2: Directly add `-o` in command line to override the default model path in the configuration file:
98 |
99 | ```bash
100 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
101 | --video_file=test_video.mp4 \
102 | --device=gpu \
103 | -o VEHICLE_ATTR.model_dir=output_inference/vehicle_attribute_infer
104 | ```
105 |
106 | The result is shown as follow:
107 |
108 |
109 |

110 |
111 |
112 |
113 | ### Features to the Solution
114 |
115 | The vehicle attribute recognition model adopts PULC, Practical Ultra Lightweight image Classification from [PaddleClas](https://github.com/PaddlePaddle/PaddleClas). For details on data preparation, training, and testing of the model, please refer to [PULC Recognition Model of Vehicle Attribute](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.4/docs/en/PULC/PULC_vehicle_attribute_en.md).
116 |
117 | The vehicle attribute recognition model adopts the lightweight and high-precision PPLCNet. And on top of PPLCNet, our model optimized via::
118 |
119 | - Improved about 0.5 percentage points accuracy by using the SSLD pre-trained model without changing the inference speed.
120 | - Improved 0.52 percentage points accuracy further by integrating EDA data augmentation strategy.
121 | - Improved 0.23 percentage points accuracy by using SKL-UGI knowledge distillation.
122 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_illegal_parking.md:
--------------------------------------------------------------------------------
1 |
2 | # PP-Vehicle违章停车识别模块
3 |
4 | 禁停区域违章停车识别在车辆应用场景中有着非常广泛的应用,借助AI的力量可以减轻人力投入,精准快速识别出违停车辆并进一步采取如广播驱离行为。PP-Vehicle中基于车辆跟踪模型、车牌检测模型和车牌识别模型实现了违章停车识别功能,具体模型信息如下:
5 |
6 | | 任务 | 算法 | 精度 | 预测速度(ms) |预测模型下载链接 |
7 | |:---------------------|:---------:|:------:|:------:| :---------------------------------------------------------------------------------: |
8 | | 车辆检测/跟踪 | PP-YOLOE-l | mAP: 63.9 | - |[下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
9 | | 车牌检测模型 | ch_PP-OCRv3_det | hmean: 0.979 | - | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_det_infer.tar.gz) |
10 | | 车牌识别模型 | ch_PP-OCRv3_rec | acc: 0.773 | - | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_rec_infer.tar.gz) |
11 |
12 | 1. 跟踪模型使用PPVehicle数据集(整合了BDD100K-MOT和UA-DETRAC),是将BDD100K-MOT中的car, truck, bus, van和UA-DETRAC中的car, bus, van都合并为1类vehicle(1)后的数据集。
13 | 2. 车牌检测、识别模型使用PP-OCRv3模型在CCPD2019、CCPD2020混合车牌数据集上fine-tune得到。
14 |
15 | ## 使用方法
16 |
17 | 1. 用户可从上表链接中下载模型并解压到```PaddleDetection/output_inference```路径下,并修改配置文件中模型路径,也可默认自动下载模型。在```deploy/pipeline/config/examples/infer_cfg_illegal_parking.yml```中可手动设置三个模型的模型路径。
18 |
19 | `infer_cfg_illegal_parking.yml`中配置项说明:
20 | ```
21 | MOT: # 跟踪模块
22 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip # 跟踪模型路径
23 | tracker_config: deploy/pipeline/config/tracker_config.yml # 跟踪配置文件路径
24 | batch_size: 1 # 跟踪batch size
25 | enable: True # 是否开启跟踪功能
26 |
27 | VEHICLE_PLATE: # 车牌识别模块
28 | det_model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_det_infer.tar.gz # 车牌检测模型路径
29 | det_limit_side_len: 480 # 检测模型单边输入尺寸
30 | det_limit_type: "max" # 检测模型输入尺寸长短边选择,"max"表示长边
31 | rec_model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_rec_infer.tar.gz # 车牌识别模型路径
32 | rec_image_shape: [3, 48, 320] # 车牌识别模型输入尺寸
33 | rec_batch_num: 6 # 车牌识别batch size
34 | word_dict_path: deploy/pipeline/ppvehicle/rec_word_dict.txt # OCR模型查询字典
35 | enable: True # 是否开启车牌识别功能
36 | ```
37 |
38 | 2. 输入视频,启动命令如下
39 | ```python
40 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/examples/infer_cfg_illegal_parking.yml \
41 | --video_file=test_video.mp4 \
42 | --device=gpu \
43 | --draw_center_traj \
44 | --illegal_parking_time=5 \
45 | --region_type=custom \
46 | --region_polygon 100 1000 1000 1000 900 1700 0 1700
47 | ```
48 |
49 | 参数说明如下:
50 | - config:配置文件路径;
51 | - video_file:测试视频路径;
52 | - device:推理设备配置;
53 | - draw_center_traj:画出车辆中心运动轨迹;
54 | - illegal_parking_time:非法停车时间,单位为秒;
55 | - region_type:非法停车区域类型,custom表示自定义;
56 | - region_polygon:自定义非法停车多边形,至少为3个点。
57 |
58 | **注意:**
59 | - 违章停车的测试视频必须是静止摄像头拍摄的,镜头不能抖动或移动。
60 | - 判断车辆是否在违停区域内是**以车辆的中心点**作为参考,车辆擦边而过等场景不算作违章停车。
61 | - `--region_polygon`表示用户自定义区域的多边形的点坐标序列,每两个为一对点坐标(x,y),**按顺时针顺序**连成一个**封闭区域**,至少需要3对点也即6个整数,默认值是`[]`,需要用户自行设置点坐标,如是四边形区域,坐标顺序是`左上、右上、右下、左下`。用户可以运行[此段代码](../../tools/get_video_info.py)获取所测视频的分辨率帧数,以及可以自定义画出自己想要的多边形区域的可视化并自己调整。
62 | 自定义多边形区域的可视化代码运行如下:
63 | ```python
64 | python get_video_info.py --video_file=demo.mp4 --region_polygon 200 200 400 200 300 400 100 400
65 | ```
66 | 快速画出想要的区域的小技巧:先任意取点得到图片,用画图工具打开,鼠标放到想要的区域点上会显示出坐标,记录下来并取整,作为这段可视化代码的region_polygon参数,并再次运行可视化,微调点坐标参数直至满意。
67 |
68 |
69 | 3. 若修改模型路径,有以下两种方式:
70 |
71 | - 方法一:```./deploy/pipeline/config/examples/infer_cfg_illegal_parking.yml```下可以配置不同模型路径;
72 | - 方法二:命令行中--config配置项后面增加`-o VEHICLE_PLATE.det_model_dir=[YOUR_DETMODEL_PATH] VEHICLE_PLATE.rec_model_dir=[YOUR_RECMODEL_PATH]`修改模型路径。
73 |
74 |
75 | 测试效果如下:
76 |
77 |
78 |

79 |
80 |
81 | 可视化视频中左上角num后面的数值表示当前帧中车辆的数目;Total count表示画面中出现的车辆的总数,包括出现又消失的车辆。
82 |
83 | ## 方案说明
84 |
85 | 1. 目标检测/多目标跟踪获取图片/视频输入中的车辆检测框,模型方案为PP-YOLOE,详细文档参考[PP-YOLOE](../../../configs/ppyoloe/README_cn.md)
86 | 2. 基于跟踪算法获取每辆车的轨迹,如果车辆中心在违停区域内且在指定时间内未发生移动,则视为违章停车;
87 | 3. 使用车牌识别模型得到违章停车车牌并可视化。
88 |
89 | ## 参考资料
90 |
91 | 1. PaddeDetection特色检测模型[PP-YOLOE](../../../../configs/ppyoloe)。
92 | 2. Paddle字符识别模型库[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)。
93 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_illegal_parking_en.md:
--------------------------------------------------------------------------------
1 |
2 | # PP-Vehicle Illegal Parking Recognition Module
3 |
4 | Illegal parking recognition in no-parking areas has a very wide range of applications in vehicle application scenarios. With the help of AI, human input can be reduced, and illegally parked vehicles can be accurately and quickly identified, and further behaviors such as broadcasting to expel the vehicles can be performed. Based on the vehicle tracking model, license plate detection model and license plate recognition model, the PP-Vehicle realizes the illegal parking recognition function. The specific model information is as follows:
5 |
6 | | Task | Algorithm | Precision | Inference Speed(ms) |Inference Model Download Link |
7 | |:---------------------|:---------:|:------:|:------:| :---------------------------------------------------------------------------------: |
8 | | Vehicle Tracking | PP-YOLOE-l | mAP: 63.9 | - |[Link](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
9 | | Plate Detection | ch_PP-OCRv3_det | hmean: 0.979 | - | [Link](https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_det_infer.tar.gz) |
10 | | Plate Recognition | ch_PP-OCRv3_rec | acc: 0.773 | - | [Link](https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_rec_infer.tar.gz) |
11 |
12 | 1. The tracking model uses the PPVehicle dataset (integrating BDD100K-MOT and UA-DETRAC), which combines car, truck, bus, van in BDD100K-MOT and car, bus, and van in UA-DETRAC into one class which named vehicle (1).
13 | 2. The license plate detection and recognition model is fine-tuned on the CCPD2019 and CCPD2020 using the PP-OCRv3 model.
14 |
15 | ## Instructions
16 |
17 | 1. Users can download the model from the link in the table above and unzip it to the ``PaddleDetection/output_inference``` path, and modify the model path in the configuration file, or download the model automatically by default. The model paths for the three models can be manually set in ``deploy/pipeline/config/examples/infer_cfg_illegal_parking.yml```.
18 |
19 | Description of configuration items in `infer_cfg_illegal_parking.yml`:
20 | ```
21 | MOT: # Tracking Module
22 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip # Path of Tracking Model
23 | tracker_config: deploy/pipeline/config/tracker_config.yml # Config Path of Tracking
24 | batch_size: 1 # Tracking batch size
25 | enable: True # Whether to Enable Tracking Function
26 |
27 | VEHICLE_PLATE: # Plate Recognition Module
28 | det_model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_det_infer.tar.gz # Path of Plate Detection Model
29 | det_limit_side_len: 480 # Single Side Size of Detection Model
30 | det_limit_type: "max" # Detection model Input Size Selection of Long and Short Sides, "max" Represents the Long Side
31 | rec_model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_rec_infer.tar.gz # Path of Plate Recognition Model
32 | rec_image_shape: [3, 48, 320] # The Input Size of Plate Recognition Model
33 | rec_batch_num: 6 # Plate Recognition batch size
34 | word_dict_path: deploy/pipeline/ppvehicle/rec_word_dict.txt # OCR Model Look-up Table
35 | enable: True # Whether to Enable Plate Recognition Function
36 | ```
37 |
38 | 2. Input video, the command is as follows:
39 | ```python
40 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/examples/infer_cfg_illegal_parking.yml \
41 | --video_file=test_video.mp4 \
42 | --device=gpu \
43 | --draw_center_traj \
44 | --illegal_parking_time=5 \
45 | --region_type=custom \
46 | --region_polygon 100 1000 1000 1000 900 1700 0 1700
47 |
48 | The parameter description:
49 | - config: config path;
50 | - video_file: video path to be tested;
51 | - device: device to infe;
52 | - draw_center_traj: draw the trajectory of the center of the vehicle;
53 | - illegal_parking_time: illegal parking time, in seconds;
54 | - region_type: illegal parking region type, 'custom' means the region is customized;
55 | - region_polygon: customized illegal parking region which includes three points at least.
56 |
57 | 3. Methods to modify the path of model:
58 |
59 | - Method 1: Configure different model paths in ```./deploy/pipeline/config/examples/infer_cfg_illegal_parking.yml``` file;
60 | - Method2: In the command line, add `-o VEHICLE_PLATE.det_model_dir=[YOUR_DETMODEL_PATH] VEHICLE_PLATE.rec_model_dir=[YOUR_RECMODEL_PATH]` after the --config configuration item to modify the model path.
61 |
62 |
63 | Test Result:
64 |
65 |
66 |

67 |
68 |
69 |
70 | ## Method Description
71 |
72 | 1. Target multi-target tracking obtains the vehicle detection frame in the picture/video input. The model scheme is PP-YOLOE. For detailed documentation, refer to [PP-YOLOE](../../../configs/ppyoloe/README_cn. md)
73 | 2. Obtain the trajectory of each vehicle based on the tracking algorithm. If the center of the vehicle is in the illegal parking area and does not move within the specified time, it is considered illegal parking;
74 | 3. Use the license plate recognition model to get the illegal parking license plate and visualize it.
75 |
76 |
77 | ## References
78 |
79 | 1. Detection Model in PaddeDetection:[PP-YOLOE](../../../../configs/ppyoloe).
80 | 2. Character Recognition Model Library in Paddle: [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR).
81 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_mot.md:
--------------------------------------------------------------------------------
1 | [English](ppvehicle_mot_en.md) | 简体中文
2 |
3 | # PP-Vehicle车辆跟踪模块
4 |
5 | 【应用介绍】
6 | 车辆检测与跟踪在交通监控、自动驾驶等方向都具有广泛应用,PP-Vehicle中集成了检测跟踪模块,是车牌检测、车辆属性识别等任务的基础。我们提供了预训练模型,用户可以直接下载使用。
7 |
8 | 【模型下载】
9 | | 任务 | 算法 | 精度 | 预测速度(ms) |下载链接 |
10 | |:---------------------|:---------:|:------:|:------:| :---------------------------------------------------------------------------------: |
11 | | 车辆检测/跟踪 | PP-YOLOE-l | mAP: 63.9
MOTA: 50.1 | 检测: 25.1ms
跟踪:31.8ms | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
12 | | 车辆检测/跟踪 | PP-YOLOE-s | mAP: 61.3
MOTA: 46.8 | 检测: 16.2ms
跟踪:21.0ms | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_s_36e_ppvehicle.zip) |
13 |
14 | 1. 检测/跟踪模型精度为PPVehicle数据集训练得到,整合了BDD100K-MOT和UA-DETRAC,是将BDD100K-MOT中的`car, truck, bus, van`和UA-DETRAC中的`car, bus, van`都合并为1类`vehicle(1)`后的数据集,检测精度mAP是PPVehicle的验证集上测得,跟踪精度MOTA是在BDD100K-MOT的验证集上测得(`car, truck, bus, van`合并为1类`vehicle`)。训练具体流程请参照[ppvehicle](../../../../configs/ppvehicle)。
15 | 2. 预测速度为T4 机器上使用TensorRT FP16时的速度, 速度包含数据预处理、模型预测、后处理全流程。
16 |
17 | ## 使用方法
18 |
19 | 【配置项说明】
20 |
21 | 配置文件中与属性相关的参数如下:
22 | ```
23 | DET:
24 | model_dir: output_inference/mot_ppyoloe_l_36e_ppvehicle/ # 车辆检测模型调用路径
25 | batch_size: 1 # 模型预测时的batch_size大小
26 |
27 | MOT:
28 | model_dir: output_inference/mot_ppyoloe_l_36e_ppvehicle/ # 车辆跟踪模型调用路径
29 | tracker_config: deploy/pipeline/config/tracker_config.yml
30 | batch_size: 1 # 模型预测时的batch_size大小, 跟踪任务只能设置为1
31 | skip_frame_num: -1 # 跳帧预测的帧数,-1表示不进行跳帧,建议跳帧帧数最大不超过3
32 | enable: False # 是否开启该功能,使用跟踪前必须确保设置为True
33 | ```
34 |
35 | 【使用命令】
36 | 1. 从上表链接中下载模型并解压到```./output_inference```路径下,并修改配置文件中模型路径。默认为自动下载模型,无需做改动。
37 | 2. 图片输入时,是纯检测任务,启动命令如下
38 | ```python
39 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
40 | --image_file=test_image.jpg \
41 | --device=gpu
42 | ```
43 | 3. 视频输入时,是跟踪任务,注意首先设置infer_cfg_ppvehicle.yml中的MOT配置的`enable=True`,如果希望跳帧加速检测跟踪流程,可以设置`skip_frame_num: 2`,建议跳帧帧数最大不超过3:
44 | ```
45 | MOT:
46 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
47 | tracker_config: deploy/pipeline/config/tracker_config.yml
48 | batch_size: 1
49 | skip_frame_num: 2
50 | enable: True
51 | ```
52 | ```python
53 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
54 | --video_file=test_video.mp4 \
55 | --device=gpu
56 | ```
57 | 4. 若修改模型路径,有以下两种方式:
58 | - 方法一:```./deploy/pipeline/config/infer_cfg_ppvehicle.yml```下可以配置不同模型路径,检测和跟踪模型分别对应`DET`和`MOT`字段,修改对应字段下的路径为实际期望的路径即可。
59 | - 方法二:命令行中--config配置项后面增加`-o MOT.model_dir=[YOUR_DETMODEL_PATH]`修改模型路径。
60 | ```python
61 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
62 | --video_file=test_video.mp4 \
63 | --device=gpu \
64 | --region_type=horizontal \
65 | --do_entrance_counting \
66 | --draw_center_traj \
67 | -o MOT.model_dir=ppyoloe/
68 |
69 | ```
70 | **注意:**
71 | - `--do_entrance_counting`表示是否统计出入口流量,不设置即默认为False。
72 | - `--draw_center_traj`表示是否绘制跟踪轨迹,不设置即默认为False。注意绘制跟踪轨迹的测试视频最好是静止摄像头拍摄的。
73 | - `--region_type`表示流量计数的区域,当设置`--do_entrance_counting`时可选择`horizontal`或者`vertical`,默认是`horizontal`,表示以视频图片的中心水平线为出入口,同一物体框的中心点在相邻两秒内分别在区域中心水平线的两侧,即完成计数加一。
74 |
75 |
76 | 5. 区域闯入判断和计数
77 |
78 | 注意首先设置infer_cfg_ppvehicle.yml中的MOT配置的enable=True,然后启动命令如下
79 | ```python
80 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
81 | --video_file=test_video.mp4 \
82 | --device=gpu \
83 | --draw_center_traj \
84 | --do_break_in_counting \
85 | --region_type=custom \
86 | --region_polygon 200 200 400 200 300 400 100 400
87 | ```
88 | **注意:**
89 | - 区域闯入的测试视频必须是静止摄像头拍摄的,镜头不能抖动或移动。
90 | - `--do_break_in_counting`表示是否进行区域出入后计数,不设置即默认为False。
91 | - `--region_type`表示流量计数的区域,当设置`--do_break_in_counting`时仅可选择`custom`,默认是`custom`,表示以用户自定义区域为出入口,同一物体框的下边界中点坐标在相邻两秒内从区域外到区域内,即完成计数加一。
92 | - `--region_polygon`表示用户自定义区域的多边形的点坐标序列,每两个为一对点坐标(x,y),**按顺时针顺序**连成一个**封闭区域**,至少需要3对点也即6个整数,默认值是`[]`,需要用户自行设置点坐标,如是四边形区域,坐标顺序是`左上、右上、右下、左下`。用户可以运行[此段代码](../../tools/get_video_info.py)获取所测视频的分辨率帧数,以及可以自定义画出自己想要的多边形区域的可视化并自己调整。
93 | 自定义多边形区域的可视化代码运行如下:
94 | ```python
95 | python get_video_info.py --video_file=demo.mp4 --region_polygon 200 200 400 200 300 400 100 400
96 | ```
97 | 快速画出想要的区域的小技巧:先任意取点得到图片,用画图工具打开,鼠标放到想要的区域点上会显示出坐标,记录下来并取整,作为这段可视化代码的region_polygon参数,并再次运行可视化,微调点坐标参数直至满意。
98 |
99 |
100 | 【效果展示】
101 |
102 |
103 |

104 |
105 |
106 | ## 方案说明
107 |
108 | 【实现方案及特色】
109 | 1. 使用目标检测/多目标跟踪技术来获取图片/视频输入中的车辆检测框,检测模型方案为PP-YOLOE,详细文档参考[PP-YOLOE](../../../../configs/ppyoloe)和[ppvehicle](../../../../configs/ppvehicle)。
110 | 2. 多目标跟踪模型方案采用[OC-SORT](https://arxiv.org/pdf/2203.14360.pdf),采用PP-YOLOE替换原文的YOLOX作为检测器,采用OCSORTTracker作为跟踪器,详细文档参考[OC-SORT](../../../../configs/mot/ocsort)。
111 |
112 | ## 参考文献
113 | ```
114 | @article{cao2022observation,
115 | title={Observation-Centric SORT: Rethinking SORT for Robust Multi-Object Tracking},
116 | author={Cao, Jinkun and Weng, Xinshuo and Khirodkar, Rawal and Pang, Jiangmiao and Kitani, Kris},
117 | journal={arXiv preprint arXiv:2203.14360},
118 | year={2022}
119 | }
120 | ```
121 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_mot_en.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](ppvehicle_mot.md)
2 |
3 | # PP-Vehicle Vehicle Tracking Module
4 |
5 | 【Application Introduction】
6 |
7 | Vehicle detection and tracking are widely used in traffic monitoring and autonomous driving. The detection and tracking module is integrated in PP-Vehicle, providing a solid foundation for tasks including license plate detection and vehicle attribute recognition. We provide pre-trained models that can be directly used by developers.
8 |
9 | 【Model Download】
10 |
11 | | Task | Algorithm | Accuracy | Inference speed(ms) | Download Link |
12 | | -------------------------- | ---------- | ----------------------- | ------------------------------------ | ------------------------------------------------------------------------------------------ |
13 | | Vehicle Detection/Tracking | PP-YOLOE-l | mAP: 63.9
MOTA: 50.1 | Detection: 25.1ms
Tracking:31.8ms | [Link](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
14 | | Vehicle Detection/Tracking | PP-YOLOE-s | mAP: 61.3
MOTA: 46.8 | Detection: 16.2ms
Tracking:21.0ms | [Link](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_s_36e_ppvehicle.zip) |
15 |
16 | 1. The detection/tracking model uses the PPVehicle dataset ( which integrates BDD100K-MOT and UA-DETRAC). The dataset merged car, truck, bus, van from BDD100K-MOT and car, bus, van from UA-DETRAC all into 1 class vehicle(1). The detection accuracy mAP was tested on the test set of PPVehicle, and the tracking accuracy MOTA was obtained on the test set of BDD100K-MOT (`car, truck, bus, van` were combined into 1 class `vehicle`). For more details about the training procedure, please refer to [ppvehicle](../../../../configs/ppvehicle).
17 | 2. Inference speed is obtained at T4 with TensorRT FP16 enabled, which includes data pre-processing, model inference and post-processing.
18 |
19 | ## How To Use
20 |
21 | 【Config】
22 |
23 | The parameters associated with the attributes in the configuration file are as follows.
24 |
25 | ```
26 | DET:
27 | model_dir: output_inference/mot_ppyoloe_l_36e_ppvehicle/ # Vehicle detection model path
28 | batch_size: 1 # Batch_size size for model inference
29 |
30 | MOT:
31 | model_dir: output_inference/mot_ppyoloe_l_36e_ppvehicle/ # Vehicle tracking model path
32 | tracker_config: deploy/pipeline/config/tracker_config.yml
33 | batch_size: 1 # Batch_size size for model inference, 1 only for tracking task.
34 | skip_frame_num: -1 # Number of frames to skip, -1 means no skipping, the maximum skipped frames are recommended to be 3
35 | enable: False # Whether or not to enable this function, please make sure it is set to True before tracking
36 | ```
37 |
38 | 【Usage】
39 |
40 | 1. Download the model from the link in the table above and unzip it to ``. /output_inference`` and change the model path in the configuration file. The default is to download the model automatically, no changes are needed.
41 |
42 | 2. The image input will start a pure detection task, and the start command is as follows
43 |
44 | ```python
45 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
46 | --image_file=test_image.jpg \
47 | --device=gpu
48 | ```
49 |
50 | 3. Video input will start a tracking task. Please set `enable=True` for the MOT configuration in infer_cfg_ppvehicle.yml. If skip frames are needed for faster detection and tracking, it is recommended to set `skip_frame_num: 2` the maximum should not exceed 3.
51 |
52 | ```
53 | MOT:
54 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip
55 | tracker_config: deploy/pipeline/config/tracker_config.yml
56 | batch_size: 1
57 | skip_frame_num: 2
58 | enable: True
59 | ```
60 |
61 | ```python
62 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
63 | --video_file=test_video.mp4 \
64 | --device=gpu
65 | ```
66 |
67 | 4. There are two ways to modify the model path
68 |
69 | - Config different model path in```./deploy/pipeline/config/infer_cfg_ppvehicle.yml```. The detection and tracking models correspond to the `DET` and `MOT` fields respectively. Modify the path under the corresponding field to the actual path.
70 |
71 | - **[Recommand]** Add`-o MOT.model_dir=[YOUR_DETMODEL_PATH]` after the config in the command line to modify model path
72 |
73 | ```python
74 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
75 | --video_file=test_video.mp4 \
76 | --device=gpu \
77 | --region_type=horizontal \
78 | --do_entrance_counting \
79 | --draw_center_traj \
80 | -o MOT.model_dir=ppyoloe/
81 | ```
82 |
83 | **Note:**
84 |
85 | - `--do_entrance_counting` : Whether to count entrance/exit traffic flows, the default is False
86 |
87 | - `--draw_center_traj` : Whether to draw center trajectory, the default is False. Its input video is preferably taken from a still camera
88 |
89 | - `--region_type` : The region for traffic counting. When setting `--do_entrance_counting`, there are two options: `horizontal` or `vertical`. The default is `horizontal`, which means the center horizontal line of the video picture is the entrance and exit. When the center point of the same object frame is on both sides of the centre horizontal line of the region in two adjacent seconds, i.e. the count adds 1.
90 | 5. Regional break-in and counting
91 |
92 | Please set the MOT config: enable=True in `infer_cfg_ppvehicle.yml` before running the starting command:
93 |
94 | ```
95 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
96 | --video_file=test_video.mp4 \
97 | --device=gpu \
98 | --draw_center_traj \
99 | --do_break_in_counting \
100 | --region_type=custom \
101 | --region_polygon 200 200 400 200 300 400 100 400
102 | ```
103 |
104 | **Note:**
105 |
106 | - Test video of area break-ins must be taken from a still camera, with no shaky or moving footage.
107 |
108 | - `--do_break_in_counting`Indicates whether or not to count the entrance and exit of the area. The default is False.
109 |
110 | - `--region_type` indicates the region for traffic counting, when setting `--do_break_in_counting` only `custom` can be selected, and the default is `custom`. It means that the customized region is used as the entry and exit. When the coordinates of the lower boundary midpoint of the same object frame goes to the inside of the region within two adjacent seconds, i.e. the count adds one.
111 |
112 | - `--region_polygon` indicates a sequence of point coordinates for a polygon in a customized region. Every two are a pair of point coordinates (x,y). **In clockwise order** they are connected into a **closed region**, at least 3 pairs of points are needed (or 6 integers). The default value is `[]`. Developers need to set the point coordinates manually. If it is a quadrilateral region, the coordinate order is `top left, top right , bottom right, bottom left`. Developers can run [this code](... /... /tools/get_video_info.py) to get the resolution frames of the predicted video. It also supports customizing and adjusting the visualisation of the polygon area.
113 | The code for the visualisation of the customized polygon area runs as follows.
114 |
115 | ```python
116 | python get_video_info.py --video_file=demo.mp4 --region_polygon 200 200 400 200 300 400 100 400
117 | ```
118 |
119 | A quick tip for drawing customized area: first take any point to get the picture, open it with the drawing tool, mouse over the area point and the coordinates will be displayed, record it and round it up, use it as a region_polygon parameter for this visualisation code and run the visualisation again, and fine-tune the point coordinates parameter.
120 |
121 | 【Showcase】
122 |
123 |
124 |

125 |
126 |
127 | ## Solution
128 |
129 | 【Solution and feature】
130 |
131 | - PP-YOLOE is adopted for vehicle detection frame of object detection, multi-object tracking in the picture/video input. For details, please refer to [PP-YOLOE](... /... /... /configs/ppyoloe/README_cn.md) and [PPVehicle](../../../../configs/ppvehicle)
132 | - [OC-SORT](https://arxiv.org/pdf/2203.14360.pdf) is adopted as multi-object tracking model. PP-YOLOE replaced YOLOX as detector, and OCSORTTracker is the tracker. For more details, please refer to [OC-SORT](../../../../configs/mot/ocsort)
133 |
134 | ## Reference
135 |
136 | ```
137 | @article{cao2022observation,
138 | title={Observation-Centric SORT: Rethinking SORT for Robust Multi-Object Tracking},
139 | author={Cao, Jinkun and Weng, Xinshuo and Khirodkar, Rawal and Pang, Jiangmiao and Kitani, Kris},
140 | journal={arXiv preprint arXiv:2203.14360},
141 | year={2022}
142 | }
143 | ```
144 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_plate.md:
--------------------------------------------------------------------------------
1 | [English](ppvehicle_plate_en.md) | 简体中文
2 |
3 | # PP-Vehicle车牌识别模块
4 |
5 | 车牌识别,在车辆应用场景中有着非常广泛的应用,起到车辆身份识别的作用,比如车辆出入口自动闸机。PP-Vehicle中提供了车辆的跟踪及其车牌识别的功能,并提供模型下载:
6 |
7 | | 任务 | 算法 | 精度 | 预测速度(ms) |预测模型下载链接 |
8 | |:---------------------|:---------:|:------:|:------:| :---------------------------------------------------------------------------------: |
9 | | 车辆检测/跟踪 | PP-YOLOE-l | mAP: 63.9 | - |[下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
10 | | 车牌检测模型 | ch_PP-OCRv3_det | hmean: 0.979 | - | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_det_infer.tar.gz) |
11 | | 车牌识别模型 | ch_PP-OCRv3_rec | acc: 0.773 | - | [下载链接](https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_rec_infer.tar.gz) |
12 | 1. 跟踪模型使用PPVehicle数据集(整合了BDD100K-MOT和UA-DETRAC),是将BDD100K-MOT中的car, truck, bus, van和UA-DETRAC中的car, bus, van都合并为1类vehicle(1)后的数据集。
13 | 2. 车牌检测、识别模型使用PP-OCRv3模型在CCPD2019、CCPD2020混合车牌数据集上fine-tune得到。
14 |
15 | ## 使用方法
16 |
17 | 1. 从上表链接中下载模型并解压到```PaddleDetection/output_inference```路径下,并修改配置文件中模型路径,也可默认自动下载模型。设置```deploy/pipeline/config/infer_cfg_ppvehicle.yml```中`VEHICLE_PLATE`的enable: True
18 |
19 | `infer_cfg_ppvehicle.yml`中配置项说明:
20 | ```
21 | VEHICLE_PLATE: #模块名称
22 | det_model_dir: output_inference/ch_PP-OCRv3_det_infer/ #车牌检测模型路径
23 | det_limit_side_len: 480 #检测模型单边输入尺寸
24 | det_limit_type: "max" #检测模型输入尺寸长短边选择,"max"表示长边
25 | rec_model_dir: output_inference/ch_PP-OCRv3_rec_infer/ #车牌识别模型路径
26 | rec_image_shape: [3, 48, 320] #车牌识别模型输入尺寸
27 | rec_batch_num: 6 #车牌识别batchsize
28 | word_dict_path: deploy/pipeline/ppvehicle/rec_word_dict.txt #OCR模型查询字典
29 | basemode: "idbased" #流程类型,'idbased'表示基于跟踪模型
30 | enable: False #功能是否开启
31 | ```
32 |
33 | 2. 图片输入时,启动命令如下(更多命令参数说明,请参考[快速开始-参数说明](./PPVehicle_QUICK_STARTED.md#41-参数说明))。
34 | ```python
35 | #单张图片
36 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
37 | --image_file=test_image.jpg \
38 | --device=gpu \
39 |
40 | #图片文件夹
41 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
42 | --image_dir=images/ \
43 | --device=gpu \
44 |
45 | ```
46 |
47 | 3. 视频输入时,启动命令如下
48 | ```python
49 | #单个视频文件
50 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
51 | --video_file=test_video.mp4 \
52 | --device=gpu \
53 |
54 | #视频文件夹
55 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
56 | --video_dir=test_videos/ \
57 | --device=gpu \
58 | ```
59 |
60 | 4. 若修改模型路径,有以下两种方式:
61 |
62 | - 方法一:```./deploy/pipeline/config/infer_cfg_ppvehicle.yml```下可以配置不同模型路径,车牌识别模型修改`VEHICLE_PLATE`字段下配置
63 | - 方法二:命令行中--config配置项后面增加`-o VEHICLE_PLATE.det_model_dir=[YOUR_DETMODEL_PATH] VEHICLE_PLATE.rec_model_dir=[YOUR_RECMODEL_PATH]`修改模型路径。
64 |
65 |
66 | 测试效果如下:
67 |
68 |
69 |

70 |
71 |
72 |
73 | ## 方案说明
74 |
75 | 1. 目标检测/多目标跟踪获取图片/视频输入中的车辆检测框,模型方案为PP-YOLOE,详细文档参考[PP-YOLOE](../../../configs/ppyoloe/README_cn.md)
76 | 2. 通过车辆检测框的坐标在输入图像中截取每个车辆
77 | 3. 使用车牌检测模型在每张车辆截图中识别车牌所在位置,同理截取车牌区域,模型方案为PP-OCRv3_det模型,经CCPD数据集在车牌场景fine-tune得到。
78 | 4. 使用字符识别模型识别车牌中的字符。模型方案为PP-OCRv3_rec模型,经CCPD数据集在车牌场景fine-tune得到。
79 |
80 | **性能优化措施:**
81 |
82 | 1. 使用跳帧策略,每10帧做一次车牌检测,避免每帧做车牌检测的算力消耗。
83 | 2. 车牌结果稳定策略,避免单帧结果的波动,利用同一个id的历史所有车牌识别结果进行投票,得到该id最大可能的正确结果。
84 |
85 | ## 参考资料
86 |
87 | 1. PaddeDetection特色检测模型[PP-YOLOE](../../../../configs/ppyoloe)。
88 | 2. Paddle字符识别模型库[PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)。
89 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_plate_en.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](ppvehicle_plate.md)
2 |
3 | # PP-Vehicle License Plate Recognition Modules
4 |
5 | License plate recognition has a very wide range of applications with vehicle identification functions, such as automatic vehicle entrance/exit gates.
6 |
7 | PP-Vehicle supports vehicle tracking and license plate recognition. Models are available for download:
8 |
9 | | Task | Algorithm | Accuracy | Inference speed(ms) | Model Download |
10 | |:-------------------------- |:---------------:|:------------:|:-------------------:|:------------------------------------------------------------------------------------------:|
11 | | Vehicle Detection/Tracking | PP-YOLOE-l | mAP: 63.9 | - | [Link](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
12 | | Vehicle Detection Model | ch_PP-OCRv3_det | hmean: 0.979 | - | [Link](https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_det_infer.tar.gz) |
13 | | Vehicle Detection Model | ch_PP-OCRv3_rec | acc: 0.773 | - | [Link](https://bj.bcebos.com/v1/paddledet/models/pipeline/ch_PP-OCRv3_rec_infer.tar.gz) |
14 |
15 | 1. The tracking model uses the PPVehicle dataset ( which integrates BDD100K-MOT and UA-DETRAC). The dataset merged car, truck, bus, van from BDD100K-MOT and car, bus, van from UA-DETRAC all into 1 class vehicle(1).
16 | 2. License plate detection and recognition models were obtained from fine-tuned PP-OCRv3 model on the CCPD2019 and CCPD2020 mixed license plate datasets.
17 |
18 | ## How to Use
19 |
20 | 1. Download models from the above table and unzip it to```PaddleDetection/output_inference```, and modify the model path in the configuration file. Models can also be downloaded automatically by default: Set enable: True of `VEHICLE_PLATE` in `deploy/pipeline/config/infer_cfg_ppvehicle.yml`
21 |
22 | Config Description of `infer_cfg_ppvehicle.yml`:
23 |
24 | ```
25 | VEHICLE_PLATE: #模块名称
26 | det_model_dir: output_inference/ch_PP-OCRv3_det_infer/ #车牌检测模型路径
27 | det_limit_side_len: 480 #检测模型单边输入尺寸
28 | det_limit_type: "max" #检测模型输入尺寸长短边选择,"max"表示长边
29 | rec_model_dir: output_inference/ch_PP-OCRv3_rec_infer/ #车牌识别模型路径
30 | rec_image_shape: [3, 48, 320] #车牌识别模型输入尺寸
31 | rec_batch_num: 6 #车牌识别batchsize
32 | word_dict_path: deploy/pipeline/ppvehicle/rec_word_dict.txt #OCR模型查询字典
33 | basemode: "idbased" #流程类型,'idbased'表示基于跟踪模型
34 | enable: False #功能是否开启
35 | ```
36 |
37 | 2. For picture input, the start command is as follows (for more descriptions of the command parameters, please refer to [Quick Start - Parameter Description](. /PPVehicle_QUICK_STARTED.md#41-parameter description)).
38 |
39 | ```python
40 | #Single image
41 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
42 | --image_file=test_image.jpg \
43 | --device=gpu \
44 | #Image folder
45 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
46 | --image_dir=images/ \
47 | --device=gpu \
48 | ```
49 |
50 | 3. For video input, the start command is as follows
51 |
52 | ```bash
53 | #Single video
54 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
55 | --video_file=test_video.mp4 \
56 | --device=gpu \
57 |
58 | #Video folder
59 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
60 | --video_dir=test_videos/ \
61 | --device=gpu \
62 | ```
63 |
64 | 4. There are two ways to modify the model path
65 |
66 | - Config different model path in ```./deploy/pipeline/config/infer_cfg_ppvehicle.yml```, and modify`VEHICLE_PLATE`field to config license plate recognition model modification
67 | - **[Recommand]** Add`-o VEHICLE_PLATE.det_model_dir=[YOUR_DETMODEL_PATH] VEHICLE_PLATE.rec_model_dir=[YOUR_RECMODEL_PATH]` to config file in command line.
68 |
69 | The test results are as follows:
70 |
71 |
72 |

73 |
74 |
75 | ## Solutions
76 |
77 | 1. PP-YOLOE is adopted for vehicle detection frame of object detection, multi-object tracking in the picture/video input. For details, please refer to [PP-YOLOE](... /... /... /configs/ppyoloe/README_cn.md)
78 | 2. By using the coordinates of the vehicle detection frame, each vehicle's image is intercepted in the input image
79 | 3. Use the license plate detection model to identify the location of the license plate in each vehicle screenshot as well as the license plate area. The PP-OCRv3_det model is adopted as the solution, obtained from fine-tuned CCPD dataset in terms of number plate.
80 | 4. Use a character recognition model to identify characters in a number plate. The PP-OCRv3_det model is adopted as the solution, obtained from fine-tuned CCPD dataset in terms of number plate.
81 |
82 | **Performance optimization measures:**
83 |
84 | 1. Use a frame skipping strategy to detect license plates every 10 frames to reduce the computing workload.
85 | 2. Use the license plate result stabilization strategy to avoid the volatility of single frame results; use all historical license plate recognition results of the same id to gain the most likely result for that id.
86 |
87 | ## Reference
88 |
89 | 1. PaddeDetection featured detection model PP-YOLOE](../../../../configs/ppyoloe)。
90 | 2. Paddle OCR Model Library [PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)。
91 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_press.md:
--------------------------------------------------------------------------------
1 | [English](ppvehicle_press_en.md) | 简体中文
2 |
3 | # PP-Vehicle压实线识别模块
4 |
5 | 车辆压实线识别在智慧城市,智慧交通等方向具有广泛应用。在PP-Vehicle中,集成了车辆压实线识别模块,可识别车辆是否违章压实线。
6 |
7 | | 任务 | 算法 | 精度 | 预测速度 | 下载链接|
8 | |-----------|------|-----------|----------|---------------|
9 | | 车辆检测/跟踪 | PP-YOLOE | mAP 63.9 | 38.67ms | [预测部署模型](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
10 | | 车道线识别 | PP-liteseg | mIou 32.69 | 47 ms | [预测部署模型](https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip) |
11 |
12 |
13 | 注意:
14 | 1. 车辆检测/跟踪模型预测速度是基于NVIDIA T4, 开启TensorRT FP16得到。模型预测速度包含数据预处理、模型预测、后处理部分。
15 | 2. 车辆检测/跟踪模型的训练和精度测试均基于[VeRi数据集](https://www.v7labs.com/open-datasets/veri-dataset)。
16 | 3. 车道线模型预测速度基于Tesla P40,python端预测,模型预测速度包含数据预处理、模型预测、后处理部分。
17 | 4. 车道线模型训练和精度测试均基于[BDD100K-LaneSeg](https://bdd-data.berkeley.edu/portal.html#download)和[Apollo Scape](http://apolloscape.auto/lane_segmentation.html#to_dataset_href),两个数据集车道线分割[标签](https://bj.bcebos.com/v1/paddledet/data/mot/bdd100k/lane_dataset_label.zip)
18 |
19 |
20 | ## 使用方法
21 |
22 | ### 配置项说明
23 |
24 | [配置文件](../../config/infer_cfg_ppvehicle.yml)中与车辆压线相关的参数如下:
25 | ```
26 | VEHICLE_PRESSING:
27 | enable: True #是否开启功能
28 | LANE_SEG:
29 | lane_seg_config: deploy/pipeline/config/lane_seg_config.yml #车道线提取配置文件
30 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip #模型文件路径
31 | ```
32 | [车道线配置文件](../../config/lane_seg_config.yml)中与车道线提取相关的参数如下:
33 | ```
34 | type: PLSLaneseg #选择分割模型
35 |
36 | PLSLaneseg:
37 | batch_size: 1 #图片batch_size
38 | device: gpu #选择gpu还是cpu
39 | filter_flag: True #是否过滤水平方向道路线
40 | horizontal_filtration_degree: 23 #过滤水平方向车道线阈值,当分割出来的车道线最大倾斜角与
41 | #最小倾斜角差值小于阈值时,不进行过滤
42 | horizontal_filtering_threshold: 0.25 #确定竖直方向与水平方向分开阈值
43 | #thr = (min_degree+max_degree)*0.25
44 | #根据车道线倾斜角与thr的大小比较,将车道线分为垂直方向与水平方向
45 | ```
46 |
47 | ### 使用命令
48 |
49 | 1. 从模型库下载`车辆检测/跟踪`, `车道线识别`两个预测部署模型并解压到`./output_inference`路径下;默认会自动下载模型,如果手动下载,需要修改模型文件夹为模型存放路径。
50 | 2. 修改配置文件中`VEHICLE_PRESSING`项的`enable: True`,以启用该功能。
51 | 3. 图片输入时,启动命令如下(更多命令参数说明,请参考[快速开始-参数说明](./PPVehicle_QUICK_STARTED.md)):
52 |
53 | ```bash
54 | # 预测单张图片文件
55 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
56 | -o VEHICLE_PRESSING.enable=true
57 | --image_file=test_image.jpg \
58 | --device=gpu
59 |
60 | # 预测包含一张或多张图片的文件夹
61 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
62 | -o VEHICLE_PRESSING.enable=true
63 | --image_dir=images/ \
64 | --device=gpu
65 | ```
66 |
67 | 4. 视频输入时,启动命令如下:
68 |
69 | ```bash
70 | #预测单个视频文件
71 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
72 | -o VEHICLE_PRESSING.enable=true
73 | --video_file=test_video.mp4 \
74 | --device=gpu
75 |
76 | #预测包含一个或多个视频的文件夹
77 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
78 | --video_dir=test_videos/ \
79 | -o VEHICLE_PRESSING.enable=true
80 | --device=gpu
81 | ```
82 |
83 | 5. 若修改模型路径,有以下两种方式:
84 |
85 | - 方法一:`./deploy/pipeline/config/infer_cfg_ppvehicle.yml`下可以配置不同模型路径,车道线识别模型修改`LANE_SEG`字段下配置
86 | - 方法二:直接在命令行中增加`-o`,以覆盖配置文件中的默认模型路径:
87 |
88 | ```bash
89 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
90 | --video_file=test_video.mp4 \
91 | --device=gpu \
92 | -o VEHICLE_PRESSING.enable=true
93 | LANE_SEG.model_dir=output_inference
94 | ```
95 |
96 | 测试效果如下:
97 |
98 |
99 |

100 |
101 |
102 | ## 方案说明
103 | 1.车道线识别模型使用了[PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg) 的超轻量分割方案。训练样本[标签](https://bj.bcebos.com/v1/paddledet/data/mot/bdd100k/lane_dataset_label.zip)分为4类:
104 | 0 背景
105 | 1 双黄线
106 | 2 实线
107 | 3 虚线
108 | 车辆压线分析过滤虚线类;
109 |
110 | 2.车道线通过对分割结果聚类得到,且默认过滤水平方向车道线,若不过滤可在[车道线配置文件](../../config/lane_seg_config.yml)修改`filter_flag`参数;
111 |
112 | 3.车辆压线判断条件:车辆的检测框底边线与车道线是否有交点;
113 |
114 | **性能优化措施**
115 | 1.因摄像头视角原因,可以根据实际情况决定是否过滤水平方向车道线;
116 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_press_en.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](ppvehicle_press.md)
2 |
3 | # PP-Vehicle press line identification module
4 |
5 | Vehicle compaction line recognition is widely used in smart cities, smart transportation and other directions.
6 | In PP-Vehicle, a vehicle compaction line identification module is integrated to identify whether the vehicle is in violation of regulations.
7 |
8 | | task | algorithm | precision | infer speed | download|
9 | |-----------|------|-----------|----------|---------------|
10 | | Vehicle detection/tracking | PP-YOLOE | mAP 63.9 | 38.67ms | [infer deploy model](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
11 | | Lane line segmentation | PP-liteseg | mIou 32.69 | 47 ms | [infer deploy model](https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip) |
12 |
13 |
14 | Notes:
15 | 1. The prediction speed of vehicle detection/tracking model is based on NVIDIA T4 and TensorRT FP16. The model prediction speed includes data preprocessing, model prediction and post-processing.
16 | 2. The training and precision test of vehicle detection/tracking model are based on [VeRi](https://www.v7labs.com/open-datasets/veri-dataset).
17 | 3. The predicted speed of lane line segmentation model is based on Tesla P40 and python prediction. The predicted speed of the model includes data preprocessing, model prediction and post-processing.
18 | 4. Lane line model training and precision testing are based on [BDD100K-LaneSeg](https://bdd-data.berkeley.edu/portal.html#download)and [Apollo Scape](http://apolloscape.auto/lane_segmentation.html#to_dataset_href),The label data of the two data sets is in[Lane_dataset_label](https://bj.bcebos.com/v1/paddledet/data/mot/bdd100k/lane_dataset_label.zip)
19 |
20 |
21 | ## Instructions
22 |
23 | ### Description of Configuration
24 |
25 | The parameters related to vehicle line pressing in [config file](../../config/infer_cfg_ppvehicle.yml) is as follows:
26 | ```
27 | VEHICLE_PRESSING:
28 | enable: True #Whether to enable the funcion
29 | LANE_SEG:
30 | lane_seg_config: deploy/pipeline/config/lane_seg_config.yml #lane line seg config file
31 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip #model path
32 | ```
33 | The parameters related to Lane line segmentation in [lane line seg config file](../../config/lane_seg_config.yml)is as follows:
34 | ```
35 | type: PLSLaneseg #Select segmentation Model
36 |
37 | PLSLaneseg:
38 | batch_size: 1 #image batch_size
39 | device: gpu #device is gpu or cpu
40 | filter_flag: True #Whether to filter the horizontal direction road route
41 | horizontal_filtration_degree: 23 #Filter the threshold value of the lane line in the horizontal direction. When the difference between the maximum inclination angle and the minimum inclination angle of the segmented lane line is less than the threshold value, no filtering is performed
42 |
43 | horizontal_filtering_threshold: 0.25 #Determine the threshold value for separating the vertical direction from the horizontal direction thr=(min_degree+max_degree) * 0.25 Divide the lane line into vertical direction and horizontal direction according to the comparison between the gradient angle of the lane line and thr
44 | ```
45 | ### How to Use
46 |
47 | 1. Download 'vehicle detection/tracking' and 'lane line recognition' two prediction deployment models from the model base and unzip them to '/ output_ Invitation ` under the path; By default, the model will be downloaded automatically. If you download it manually, you need to modify the model folder as the model storage path.
48 |
49 | 2. Modify Profile ` VEHICLE_PRESSING ' -'enable: True' item to enable this function.
50 |
51 | 3. When inputting a picture, the startup command is as follows (for more command parameter descriptions,please refer to [QUICK_STARTED - Parameter_Description](./PPVehicle_QUICK_STARTED.md)
52 |
53 | ```bash
54 | # For single image
55 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
56 | -o VEHICLE_PRESSING.enable=true
57 | --image_file=test_image.jpg \
58 | --device=gpu
59 |
60 | # For folder contains one or multiple images
61 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
62 | -o VEHICLE_PRESSING.enable=true
63 | --image_dir=images/ \
64 | --device=gpu
65 | ```
66 |
67 | 4. For video input, please run these commands.
68 |
69 | ```bash
70 | #For single video
71 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
72 | -o VEHICLE_PRESSING.enable=true
73 | --video_file=test_video.mp4 \
74 | --device=gpu
75 |
76 | #For folder contains one or multiple videos
77 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
78 | --video_dir=test_videos/ \
79 | -o VEHICLE_PRESSING.enable=true
80 | --device=gpu
81 | ```
82 |
83 | 5. There are two ways to modify the model path:
84 |
85 | - 1.Set paths of each model in `./deploy/pipeline/config/infer_cfg_ppvehicle.yml`,For Lane line segmentation, the path should be modified under the `LANE_SEG`
86 | - 2.Directly add `-o` in command line to override the default model path in the configuration file:
87 |
88 | ```bash
89 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
90 | --video_file=test_video.mp4 \
91 | --device=gpu \
92 | -o VEHICLE_PRESSING.enable=true
93 | LANE_SEG.model_dir=output_inference
94 | ```
95 |
96 | The result is shown as follow:
97 |
98 |
99 |

100 |
101 |
102 | ## Features to the Solution
103 | 1.Lane line recognition model uses [PaddleSeg]( https://github.com/PaddlePaddle/PaddleSeg )Super lightweight segmentation scheme.Train [lable](https://bj.bcebos.com/v1/paddledet/data/mot/bdd100k/lane_dataset_label.zip)it is divided into four categories:
104 | 0 Background
105 | 1 Double yellow line
106 | 2 Solid line
107 | 3 Dashed line
108 | Lane line recognition filtering Dashed lines;
109 |
110 | 2.Lane lines are obtained by clustering segmentation results, and the horizontal lane lines are filtered by default. If not, you can modify the `filter_flag` in [lane line seg config file](../../config/lane_seg_config.yml);
111 |
112 | 3.Judgment conditions for vehicle line pressing: whether there is intersection between the bottom edge line of vehicle detection frame and lane line;
113 |
114 | **Performance optimization measures:**
115 | 1.Due to the camera angle, it can be decided whether to filter the lane line in the horizontal direction according to the actual situation;
116 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_retrograde.md:
--------------------------------------------------------------------------------
1 | [English](ppvehicle_retrograde_en.md) | 简体中文
2 |
3 | # PP-Vehicle车辆逆行识别模块
4 |
5 | 车辆逆行识别在智慧城市,智慧交通等方向具有广泛应用。在PP-Vehicle中,集成了车辆逆行识别模块,可识别车辆是否逆行。
6 |
7 | | 任务 | 算法 | 精度 | 预测速度 | 下载链接|
8 | |-----------|------|-----------|----------|---------------|
9 | | 车辆检测/跟踪 | PP-YOLOE | mAP 63.9 | 38.67ms | [预测部署模型](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
10 | | 车道线识别 | PP-liteseg | mIou 32.69 | 47 ms | [预测部署模型](https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip) |
11 |
12 |
13 | 注意:
14 | 1. 车辆检测/跟踪模型预测速度是基于NVIDIA T4, 开启TensorRT FP16得到。模型预测速度包含数据预处理、模型预测、后处理部分。
15 | 2. 车辆检测/跟踪模型的训练和精度测试均基于[VeRi数据集](https://www.v7labs.com/open-datasets/veri-dataset)。
16 | 3. 车道线模型预测速度基于Tesla P40,python端预测,模型预测速度包含数据预处理、模型预测、后处理部分。
17 | 4. 车道线模型训练和精度测试均基于[BDD100K-LaneSeg](https://bdd-data.berkeley.edu/portal.html#download.)和[Apollo Scape](http://apolloscape.auto/lane_segmentation.html#to_dataset_href)。两个数据集的标签文件[Lane_dataset_label](https://bj.bcebos.com/v1/paddledet/data/mot/bdd100k/lane_dataset_label.zip)
18 |
19 |
20 | ## 使用方法
21 |
22 | ### 配置项说明
23 |
24 | [配置文件](../../config/infer_cfg_ppvehicle.yml)中与车辆逆行识别模块相关的参数如下:
25 | ```
26 | LANE_SEG:
27 | lane_seg_config: deploy/pipeline/config/lane_seg_config.yml #车道线提取配置文件
28 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip #模型文件路径
29 |
30 | VEHICLE_RETROGRADE:
31 | frame_len: 8 #采样帧数
32 | sample_freq: 7 #采样频率
33 | enable: True #开启车辆逆行判断功能
34 | filter_horizontal_flag: False #是否过滤水平方向车辆
35 | keep_right_flag: True #按车辆靠右行驶规则,若车辆靠左行驶,则设为False
36 | deviation: 23 #过滤水平方向车辆的角度阈值,如果大于该角度则过滤
37 | move_scale: 0.01 #过滤静止车辆阈值,若车辆移动像素大于图片对角线*move_scale,则认为车辆移动,反之
38 | #车辆静止
39 | fence_line: [] #车道中间线坐标,格式[x1,y1,x2,y2] 且y2>y1。若为空,由程序根据车流方向自动判断
40 | ```
41 | [车道线配置文件](../../config/lane_seg_config.yml)中与车道线提取相关的参数如下:
42 | ```
43 | type: PLSLaneseg #选择分割模型
44 |
45 | PLSLaneseg:
46 | batch_size: 1 #图片batch_size
47 | device: gpu #选择gpu还是cpu
48 | filter_flag: True #是否过滤水平方向道路线
49 | horizontal_filtration_degree: 23 #过滤水平方向车道线阈值,当分割出来的车道线最大倾斜角与
50 | #最小倾斜角差值小于阈值时,不进行过滤
51 | horizontal_filtering_threshold: 0.25 #确定竖直方向与水平方向分开阈值
52 | #thr = (min_degree+max_degree)*0.25
53 | #根据车道线倾斜角与thr的大小比较,将车道线分为垂直方向与水平方向
54 | ```
55 |
56 | ### 使用命令
57 |
58 | 1. 从模型库下载`车辆检测/跟踪`, `车道线识别`两个预测部署模型并解压到`./output_inference`路径下;默认会自动下载模型,如果手动下载,需要修改模型文件夹为模型存放路径。
59 | 2. 修改配置文件中`VEHICLE_RETROGRADE`项的`enable: True`,以启用该功能。
60 |
61 |
62 |
63 | 3. 车辆逆行识别功能需要视频输入时,启动命令如下:
64 |
65 | ```bash
66 | #预测单个视频文件
67 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
68 | -o VEHICLE_RETROGRADE.enable=true \
69 | --video_file=test_video.mp4 \
70 | --device=gpu
71 |
72 | #预测包含一个或多个视频的文件夹
73 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
74 | -o VEHICLE_RETROGRADE.enable=true \
75 | --video_dir=test_video \
76 | --device=gpu
77 | ```
78 |
79 | 5. 若修改模型路径,有以下两种方式:
80 |
81 | - 方法一:`./deploy/pipeline/config/infer_cfg_ppvehicle.yml`下可以配置不同模型路径,车道线识别模型修改`LANE_SEG`字段下配置
82 | - 方法二:直接在命令行中增加`-o`,以覆盖配置文件中的默认模型路径:
83 |
84 | ```bash
85 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
86 | --video_file=test_video.mp4 \
87 | --device=gpu \
88 | -o LANE_SEG.model_dir=output_inference/
89 | VEHICLE_RETROGRADE.enable=true
90 |
91 | ```
92 | 测试效果如下:
93 |
94 |
95 |

96 |
97 |
98 | **注意:**
99 | - 车道线中间线自动判断条件:在采样的视频段内同时有两个相反方向的车辆,且判断一次后固定,不再更新;
100 | - 因摄像头角度以及2d视角问题,车道线中间线判断存在不准确情况;
101 | - 可在配置文件手动输入中间线坐标.参考[车辆违章配置文件](../../config/examples/infer_cfg_vehicle_violation.yml)
102 |
103 |
104 | ## 方案说明
105 | 1.车辆在采样视频段内,根据车道中间线的位置与车辆轨迹,判断车辆是否逆行,判断流程图:
106 |
107 |

108 |
109 |
110 | 2.车道线识别模型使用了[PaddleSeg](https://github.com/PaddlePaddle/PaddleSeg) 的超轻量分割方案。训练样本[标签](https://bj.bcebos.com/v1/paddledet/data/mot/bdd100k/lane_dataset_label.zip)分为4类:
111 | 0 背景
112 | 1 双黄线
113 | 2 实线
114 | 3 虚线
115 | 车辆逆行分析过滤虚线类;
116 |
117 | 3.车道线通过对分割结果聚类得到,且默认过滤水平方向车道线,若不过滤可在[车道线配置文件](../../config/lane_seg_config.yml)修改`filter_flag`参数;
118 |
119 | 4.车辆逆行判断默认过滤水平方向车辆,若不过滤可在[配置文件](../../config/infer_cfg_ppvehicle.yml)修改`filter_horizontal_flag`参数;
120 |
121 | 5.车辆逆行默认按靠右行驶规则判断,若修改,可在[配置文件](../../config/infer_cfg_ppvehicle.yml)修改`keep_right_flag`参数;
122 |
123 | **性能优化措施**:
124 | 1.因摄像头视角原因,可以根据实际情况决定是否过滤水平方向车道线与水平方向车辆;
125 |
126 | 2.车道中间线可手动输入;
127 |
--------------------------------------------------------------------------------
/docs/tutorials/ppvehicle_retrograde_en.md:
--------------------------------------------------------------------------------
1 | English | [简体中文](ppvehicle_retrograde.md)
2 |
3 | # PP-Vehicle vehicle retrograde identification module
4 |
5 | Vehicle reverse identification is widely used in smart cities, smart transportation and other directions. In PP-Vehicle, a vehicle retrograde identification module is integrated to identify whether the vehicle is retrograde.
6 |
7 | | task | algorithm | precision | infer speed | download|
8 | |-----------|------|-----------|----------|---------------|
9 | | Vehicle detection/tracking | PP-YOLOE | mAP 63.9 | 38.67ms | [infer deploy model](https://bj.bcebos.com/v1/paddledet/models/pipeline/mot_ppyoloe_l_36e_ppvehicle.zip) |
10 | | Lane line segmentation | PP-liteseg | mIou 32.69 | 47 ms | [infer deploy model](https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip) |
11 |
12 |
13 | Notes:
14 | 1. The prediction speed of vehicle detection/tracking model is based on NVIDIA T4 and TensorRT FP16. The model prediction speed includes data preprocessing, model prediction and post-processing.
15 | 2. The training and precision test of vehicle detection/tracking model are based on [VeRi](https://www.v7labs.com/open-datasets/veri-dataset).
16 | 3. The predicted speed of lane line segmentation model is based on Tesla P40 and python prediction. The predicted speed of the model includes data preprocessing, model prediction and post-processing.
17 | 4. Lane line model training and precision testing are based on [BDD100K-LaneSeg](https://bdd-data.berkeley.edu/portal.html#download) and [Apollo Scape](http://apolloscape.auto/lane_segmentation.html#to_dataset_href),The label data of the two data sets is in [Lane_dataset_label](https://bj.bcebos.com/v1/paddledet/data/mot/bdd100k/lane_dataset_label.zip)
18 |
19 |
20 |
21 | ## Instructions
22 |
23 | ### Description of Configuration
24 |
25 | [The parameters related to vehicle retrograde in [config file](../../config/infer_cfg_ppvehicle.yml) is as follows:
26 | ```
27 | LANE_SEG:
28 | lane_seg_config: deploy/pipeline/config/lane_seg_config.yml #lane line seg config file
29 | model_dir: https://bj.bcebos.com/v1/paddledet/models/pipeline/pp_lite_stdc2_bdd100k.zip #model path
30 |
31 | VEHICLE_RETROGRADE:
32 | frame_len: 8 #Number of sampling frames
33 | sample_freq: 7 #sampling frequency
34 | enable: True #Whether to enable the funcion
35 | filter_horizontal_flag: False #Whether to filter vehicles in horizontal direction
36 | keep_right_flag: True #According to the right driving rule, if the vehicle keeps left driving, it is set as False
37 | deviation: 23 #Filter the horizontal angle vehicles threshold. If it is greater than this angle, filter
38 | move_scale: 0.01 #Filter the threshold value of stationary vehicles. If the vehicle moving pixel is greater than the image diagonal * move_scale, the vehicle is considered moving, otherwise, the vehicle is stationary
39 | fence_line: [] #Lane centerline coordinates, format[x1,y1,x2,y2] and y2>y1. If it is empty, the program will automatically judge according to the direction of traffic flow
40 | ```
41 | The parameters related to Lane line segmentation in [lane line seg config file](../../config/lane_seg_config.yml)is as follows:
42 | ```
43 | type: PLSLaneseg #Select segmentation Model
44 |
45 | PLSLaneseg:
46 | batch_size: 1 #image batch_size
47 | device: gpu #device is gpu or cpu
48 | filter_flag: True #Whether to filter the horizontal direction road route
49 | horizontal_filtration_degree: 23 #Filter the threshold value of the lane line in the horizontal direction. When the difference between the maximum inclination angle and the minimum inclination angle of the segmented lane line is less than the threshold value, no filtering is performed
50 |
51 | horizontal_filtering_threshold: 0.25 #Determine the threshold value for separating the vertical direction from the horizontal direction thr=(min_degree+max_degree) * 0.25 Divide the lane line into vertical direction and horizontal direction according to the comparison between the gradient angle of the lane line and thr
52 | ```
53 |
54 | ### How to Use
55 |
56 | 1. Download 'vehicle detection/tracking' and 'lane line recognition' two prediction deployment models from the model base and unzip them to '/ output_ Invitation ` under the path; By default, the model will be downloaded automatically. If you download it manually, you need to modify the model folder as the model storage path.
57 | 2. Modify Profile`VEHICLE_RETROGRADE`-`enable: True`, item to enable this function.
58 |
59 |
60 |
61 | 3. When video input is required for vehicle retrograde recognition function, the starting command is as follows:
62 |
63 | ```bash
64 | #For single video
65 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
66 | -o VEHICLE_RETROGRADE.enable=true \
67 | --video_file=test_video.mp4 \
68 | --device=gpu
69 |
70 | #For folder contains one or multiple videos
71 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
72 | -o VEHICLE_RETROGRADE.enable=true \
73 | --video_dir=test_video \
74 | --device=gpu
75 | ```
76 |
77 | 5. There are two ways to modify the model path:
78 |
79 | - 1.Set paths of each model in `./deploy/pipeline/config/infer_cfg_ppvehicle.yml`,For Lane line segmentation, the path should be modified under the `LANE_SEG`
80 | - 2.Directly add `-o` in command line to override the default model path in the configuration file:
81 |
82 | ```bash
83 | python deploy/pipeline/pipeline.py --config deploy/pipeline/config/infer_cfg_ppvehicle.yml \
84 | --video_file=test_video.mp4 \
85 | --device=gpu \
86 | -o LANE_SEG.model_dir=output_inference/
87 | VEHICLE_RETROGRADE.enable=true
88 |
89 | ```
90 | The result is shown as follow:
91 |
92 |
93 |

94 |
95 |
96 | **Note:**
97 | - Automatic judgment condition of lane line middle line: there are two vehicles in opposite directions in the sampled video segment, and the judgment is fixed after one time and will not be updated;
98 | - Due to camera angle and 2d visual angle problems, the judgment of lane line middle line is inaccurate.
99 | - You can manually enter the middle line coordinates in the configuration file.Example as [infer_cfg_vehicle_violation.yml](../../config/examples/infer_cfg_vehicle_violation.yml)
100 |
101 |
102 | ## Features to the Solution
103 | 1.In the sampling video segment, judge whether the vehicle is retrograde according to the location of the lane centerline and the vehicle track, and determine the flow chart:
104 |
105 |

106 |
107 |
108 | 2.Lane line recognition model uses [PaddleSeg]( https://github.com/PaddlePaddle/PaddleSeg )Super lightweight segmentation scheme.Train [lable](https://bj.bcebos.com/v1/paddledet/data/mot/bdd100k/lane_dataset_label.zip)it is divided into four categories:
109 | 0 Background
110 | 1 Double yellow line
111 | 2 Solid line
112 | 3 Dashed line
113 | Lane line recognition filtering Dashed lines;
114 |
115 | 3.Lane lines are obtained by clustering segmentation results, and the horizontal lane lines are filtered by default. If not, you can modify the `filter_flag` in [lane line seg config file](../../config/lane_seg_config.yml);
116 |
117 | 4.The vehicles in the horizontal direction are filtered by default when judging the vehicles in the reverse direction. If not, you can modify the `filter_horizontal_flag` in [config file](../../config/infer_cfg_ppvehicle.yml);
118 |
119 | 5.The vehicle will be judged according to the right driving rule by default.If not, you can modify the `keep_right_flag` in [config file](../../config/infer_cfg_ppvehicle.yml);
120 |
121 |
122 | **Performance optimization measures:**
123 | 1.Due to the camera's viewing angle, it can be decided whether to filter the lane lines and vehicles in the horizontal direction according to the actual situation;
124 |
125 | 2.The lane middle line can be manually entered;
126 |
--------------------------------------------------------------------------------
/mtmct.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/mtmct.gif
--------------------------------------------------------------------------------
/pipe_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import time
16 | import os
17 | import ast
18 | import glob
19 | import yaml
20 | import copy
21 | import numpy as np
22 | import subprocess as sp
23 |
24 | from python.keypoint_preprocess import EvalAffine, TopDownEvalAffine, expand_crop
25 |
26 |
27 | class Times(object):
28 | def __init__(self):
29 | self.time = 0.
30 | # start time
31 | self.st = 0.
32 | # end time
33 | self.et = 0.
34 |
35 | def start(self):
36 | self.st = time.time()
37 |
38 | def end(self, repeats=1, accumulative=True):
39 | self.et = time.time()
40 | if accumulative:
41 | self.time += (self.et - self.st) / repeats
42 | else:
43 | self.time = (self.et - self.st) / repeats
44 |
45 | def reset(self):
46 | self.time = 0.
47 | self.st = 0.
48 | self.et = 0.
49 |
50 | def value(self):
51 | return round(self.time, 4)
52 |
53 |
54 | class PipeTimer(Times):
55 | def __init__(self):
56 | super(PipeTimer, self).__init__()
57 | self.total_time = Times()
58 | self.module_time = {
59 | 'det': Times(),
60 | 'mot': Times(),
61 | 'attr': Times(),
62 | 'kpt': Times(),
63 | 'video_action': Times(),
64 | 'skeleton_action': Times(),
65 | 'reid': Times(),
66 | 'det_action': Times(),
67 | 'cls_action': Times(),
68 | 'vehicle_attr': Times(),
69 | 'vehicleplate': Times(),
70 | 'lanes': Times(),
71 | 'vehicle_press': Times(),
72 | 'vehicle_retrograde': Times()
73 | }
74 | self.img_num = 0
75 | self.track_num = 0
76 |
77 | def get_total_time(self):
78 | total_time = self.total_time.value()
79 | total_time = round(total_time, 4)
80 | average_latency = total_time / max(1, self.img_num)
81 | qps = 0
82 | if total_time > 0:
83 | qps = 1 / average_latency
84 | return total_time, average_latency, qps
85 |
86 | def info(self):
87 | total_time, average_latency, qps = self.get_total_time()
88 | print("------------------ Inference Time Info ----------------------")
89 | print("total_time(ms): {}, img_num: {}".format(total_time * 1000,
90 | self.img_num))
91 |
92 | for k, v in self.module_time.items():
93 | v_time = round(v.value(), 4)
94 | if v_time > 0 and k in ['det', 'mot', 'video_action']:
95 | print("{} time(ms): {}; per frame average time(ms): {}".format(
96 | k, v_time * 1000, v_time * 1000 / self.img_num))
97 | elif v_time > 0:
98 | print("{} time(ms): {}; per trackid average time(ms): {}".
99 | format(k, v_time * 1000, v_time * 1000 / self.track_num))
100 |
101 | print("average latency time(ms): {:.2f}, QPS: {:2f}".format(
102 | average_latency * 1000, qps))
103 | return qps
104 |
105 | def report(self, average=False):
106 | dic = {}
107 | dic['total'] = round(self.total_time.value() / max(1, self.img_num),
108 | 4) if average else self.total_time.value()
109 | dic['det'] = round(self.module_time['det'].value() /
110 | max(1, self.img_num),
111 | 4) if average else self.module_time['det'].value()
112 | dic['mot'] = round(self.module_time['mot'].value() /
113 | max(1, self.img_num),
114 | 4) if average else self.module_time['mot'].value()
115 | dic['attr'] = round(self.module_time['attr'].value() /
116 | max(1, self.img_num),
117 | 4) if average else self.module_time['attr'].value()
118 | dic['kpt'] = round(self.module_time['kpt'].value() /
119 | max(1, self.img_num),
120 | 4) if average else self.module_time['kpt'].value()
121 | dic['video_action'] = self.module_time['video_action'].value()
122 | dic['skeleton_action'] = round(
123 | self.module_time['skeleton_action'].value() / max(1, self.img_num),
124 | 4) if average else self.module_time['skeleton_action'].value()
125 |
126 | dic['img_num'] = self.img_num
127 | return dic
128 |
129 |
130 | class PushStream(object):
131 | def __init__(self, pushurl="rtsp://127.0.0.1:8554/"):
132 | self.command = ""
133 | # 自行设置
134 | self.pushurl = pushurl
135 |
136 | def initcmd(self, fps, width, height):
137 | self.command = [
138 | 'ffmpeg', '-y', '-f', 'rawvideo', '-vcodec', 'rawvideo', '-pix_fmt',
139 | 'bgr24', '-s', "{}x{}".format(width, height), '-r', str(fps), '-i',
140 | '-', '-pix_fmt', 'yuv420p', '-f', 'rtsp', self.pushurl
141 | ]
142 | self.pipe = sp.Popen(self.command, stdin=sp.PIPE)
143 |
144 |
145 | def get_test_images(infer_dir, infer_img):
146 | """
147 | Get image path list in TEST mode
148 | """
149 | assert infer_img is not None or infer_dir is not None, \
150 | "--infer_img or --infer_dir should be set"
151 | assert infer_img is None or os.path.isfile(infer_img), \
152 | "{} is not a file".format(infer_img)
153 | assert infer_dir is None or os.path.isdir(infer_dir), \
154 | "{} is not a directory".format(infer_dir)
155 |
156 | # infer_img has a higher priority
157 | if infer_img and os.path.isfile(infer_img):
158 | return [infer_img]
159 |
160 | images = set()
161 | infer_dir = os.path.abspath(infer_dir)
162 | assert os.path.isdir(infer_dir), \
163 | "infer_dir {} is not a directory".format(infer_dir)
164 | exts = ['jpg', 'jpeg', 'png', 'bmp']
165 | exts += [ext.upper() for ext in exts]
166 | for ext in exts:
167 | images.update(glob.glob('{}/*.{}'.format(infer_dir, ext)))
168 | images = list(images)
169 |
170 | assert len(images) > 0, "no image found in {}".format(infer_dir)
171 | print("Found {} inference images in total.".format(len(images)))
172 |
173 | return images
174 |
175 |
176 | def crop_image_with_det(batch_input, det_res, thresh=0.3):
177 | boxes = det_res['boxes']
178 | score = det_res['boxes'][:, 1]
179 | boxes_num = det_res['boxes_num']
180 | start_idx = 0
181 | crop_res = []
182 | for b_id, input in enumerate(batch_input):
183 | boxes_num_i = boxes_num[b_id]
184 | if boxes_num_i == 0:
185 | continue
186 | boxes_i = boxes[start_idx:start_idx + boxes_num_i, :]
187 | score_i = score[start_idx:start_idx + boxes_num_i]
188 | res = []
189 | for box, s in zip(boxes_i, score_i):
190 | if s > thresh:
191 | crop_image, new_box, ori_box = expand_crop(input, box)
192 | if crop_image is not None:
193 | res.append(crop_image)
194 | crop_res.append(res)
195 | return crop_res
196 |
197 |
198 | def normal_crop(image, rect):
199 | imgh, imgw, c = image.shape
200 | label, conf, xmin, ymin, xmax, ymax = [int(x) for x in rect.tolist()]
201 | org_rect = [xmin, ymin, xmax, ymax]
202 | if label != 0:
203 | return None, None, None
204 | xmin = max(0, xmin)
205 | ymin = max(0, ymin)
206 | xmax = min(imgw, xmax)
207 | ymax = min(imgh, ymax)
208 | return image[ymin:ymax, xmin:xmax, :], [xmin, ymin, xmax, ymax], org_rect
209 |
210 |
211 | def crop_image_with_mot(input, mot_res, expand=True):
212 | res = mot_res['boxes']
213 | crop_res = []
214 | new_bboxes = []
215 | ori_bboxes = []
216 | for box in res:
217 | if expand:
218 | crop_image, new_bbox, ori_bbox = expand_crop(input, box[1:])
219 | else:
220 | crop_image, new_bbox, ori_bbox = normal_crop(input, box[1:])
221 | if crop_image is not None:
222 | crop_res.append(crop_image)
223 | new_bboxes.append(new_bbox)
224 | ori_bboxes.append(ori_bbox)
225 | return crop_res, new_bboxes, ori_bboxes
226 |
227 |
228 | def parse_mot_res(input):
229 | mot_res = []
230 | boxes, scores, ids = input[0]
231 | for box, score, i in zip(boxes[0], scores[0], ids[0]):
232 | xmin, ymin, w, h = box
233 | res = [i, 0, score, xmin, ymin, xmin + w, ymin + h]
234 | mot_res.append(res)
235 | return {'boxes': np.array(mot_res)}
236 |
237 |
238 | def refine_keypoint_coordinary(kpts, bbox, coord_size):
239 | """
240 | This function is used to adjust coordinate values to a fixed scale.
241 | """
242 | tl = bbox[:, 0:2]
243 | wh = bbox[:, 2:] - tl
244 | tl = np.expand_dims(np.transpose(tl, (1, 0)), (2, 3))
245 | wh = np.expand_dims(np.transpose(wh, (1, 0)), (2, 3))
246 | target_w, target_h = coord_size
247 | res = (kpts - tl) / wh * np.expand_dims(
248 | np.array([[target_w], [target_h]]), (2, 3))
249 | return res
250 |
251 |
252 | def parse_mot_keypoint(input, coord_size):
253 | parsed_skeleton_with_mot = {}
254 | ids = []
255 | skeleton = []
256 | for tracker_id, kpt_seq in input:
257 | ids.append(tracker_id)
258 | kpts = np.array(kpt_seq.kpts, dtype=np.float32)[:, :, :2]
259 | kpts = np.expand_dims(np.transpose(kpts, [2, 0, 1]),
260 | -1) #T, K, C -> C, T, K, 1
261 | bbox = np.array(kpt_seq.bboxes, dtype=np.float32)
262 | skeleton.append(refine_keypoint_coordinary(kpts, bbox, coord_size))
263 | parsed_skeleton_with_mot["mot_id"] = ids
264 | parsed_skeleton_with_mot["skeleton"] = skeleton
265 | return parsed_skeleton_with_mot
--------------------------------------------------------------------------------
/pphuman/__pycache__/action_infer.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/pphuman/__pycache__/action_infer.cpython-38.pyc
--------------------------------------------------------------------------------
/pphuman/__pycache__/action_utils.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/pphuman/__pycache__/action_utils.cpython-38.pyc
--------------------------------------------------------------------------------
/pphuman/__pycache__/attr_infer.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/pphuman/__pycache__/attr_infer.cpython-38.pyc
--------------------------------------------------------------------------------
/pphuman/__pycache__/mtmct.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/pphuman/__pycache__/mtmct.cpython-38.pyc
--------------------------------------------------------------------------------
/pphuman/__pycache__/reid.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/pphuman/__pycache__/reid.cpython-38.pyc
--------------------------------------------------------------------------------
/pphuman/__pycache__/video_action_infer.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/pphuman/__pycache__/video_action_infer.cpython-38.pyc
--------------------------------------------------------------------------------
/pphuman/__pycache__/video_action_preprocess.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/pphuman/__pycache__/video_action_preprocess.cpython-38.pyc
--------------------------------------------------------------------------------
/pphuman/action_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 |
16 | class KeyPointSequence(object):
17 | def __init__(self, max_size=100):
18 | self.frames = 0
19 | self.kpts = []
20 | self.bboxes = []
21 | self.max_size = max_size
22 |
23 | def save(self, kpt, bbox):
24 | self.kpts.append(kpt)
25 | self.bboxes.append(bbox)
26 | self.frames += 1
27 | if self.frames == self.max_size:
28 | return True
29 | return False
30 |
31 |
32 | class KeyPointBuff(object):
33 | def __init__(self, max_size=100):
34 | self.flag_track_interrupt = False
35 | self.keypoint_saver = dict()
36 | self.max_size = max_size
37 | self.id_to_pop = set()
38 | self.flag_to_pop = False
39 |
40 | def get_state(self):
41 | return self.flag_to_pop
42 |
43 | def update(self, kpt_res, mot_res):
44 | kpts = kpt_res.get('keypoint')[0]
45 | bboxes = kpt_res.get('bbox')
46 | mot_bboxes = mot_res.get('boxes')
47 | updated_id = set()
48 |
49 | for idx in range(len(kpts)):
50 | tracker_id = mot_bboxes[idx, 0]
51 | updated_id.add(tracker_id)
52 |
53 | kpt_seq = self.keypoint_saver.get(tracker_id,
54 | KeyPointSequence(self.max_size))
55 | is_full = kpt_seq.save(kpts[idx], bboxes[idx])
56 | self.keypoint_saver[tracker_id] = kpt_seq
57 |
58 | #Scene1: result should be popped when frames meet max size
59 | if is_full:
60 | self.id_to_pop.add(tracker_id)
61 | self.flag_to_pop = True
62 |
63 | #Scene2: result of a lost tracker should be popped
64 | interrupted_id = set(self.keypoint_saver.keys()) - updated_id
65 | if len(interrupted_id) > 0:
66 | self.flag_to_pop = True
67 | self.id_to_pop.update(interrupted_id)
68 |
69 | def get_collected_keypoint(self):
70 | """
71 | Output (List): List of keypoint results for Skeletonbased Recognition task, where
72 | the format of each element is [tracker_id, KeyPointSequence of tracker_id]
73 | """
74 | output = []
75 | for tracker_id in self.id_to_pop:
76 | output.append([tracker_id, self.keypoint_saver[tracker_id]])
77 | del (self.keypoint_saver[tracker_id])
78 | self.flag_to_pop = False
79 | self.id_to_pop.clear()
80 | return output
81 |
82 |
83 | class ActionVisualHelper(object):
84 | def __init__(self, frame_life=20):
85 | self.frame_life = frame_life
86 | self.action_history = {}
87 |
88 | def get_visualize_ids(self):
89 | id_detected = self.check_detected()
90 | return id_detected
91 |
92 | def check_detected(self):
93 | id_detected = set()
94 | deperate_id = []
95 | for mot_id in self.action_history:
96 | self.action_history[mot_id]["life_remain"] -= 1
97 | if int(self.action_history[mot_id]["class"]) == 0:
98 | id_detected.add(mot_id)
99 | if self.action_history[mot_id]["life_remain"] == 0:
100 | deperate_id.append(mot_id)
101 | for mot_id in deperate_id:
102 | del (self.action_history[mot_id])
103 | return id_detected
104 |
105 | def update(self, action_res_list):
106 | for mot_id, action_res in action_res_list:
107 | if mot_id in self.action_history:
108 | if int(action_res["class"]) != 0 and int(self.action_history[
109 | mot_id]["class"]) == 0:
110 | continue
111 | action_info = self.action_history.get(mot_id, {})
112 | action_info["class"] = action_res["class"]
113 | action_info["life_remain"] = self.frame_life
114 | self.action_history[mot_id] = action_info
115 |
--------------------------------------------------------------------------------
/pphuman/reid.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import os
16 | import sys
17 | import cv2
18 | import numpy as np
19 | # add deploy path of PaddleDetection to sys.path
20 | parent_path = os.path.abspath(os.path.join(__file__, *(['..'] * 2)))
21 | sys.path.insert(0, parent_path)
22 |
23 | from python.infer import PredictConfig
24 | from pptracking.python.det_infer import load_predictor
25 | from python.utils import Timer
26 |
27 |
28 | class ReID(object):
29 | """
30 | ReID of SDE methods
31 |
32 | Args:
33 | pred_config (object): config of model, defined by `Config(model_dir)`
34 | model_dir (str): root path of model.pdiparams, model.pdmodel and infer_cfg.yml
35 | device (str): Choose the device you want to run, it can be: CPU/GPU/XPU/NPU, default is CPU
36 | run_mode (str): mode of running(paddle/trt_fp32/trt_fp16)
37 | batch_size (int): size of per batch in inference, default 50 means at most
38 | 50 sub images can be made a batch and send into ReID model
39 | trt_min_shape (int): min shape for dynamic shape in trt
40 | trt_max_shape (int): max shape for dynamic shape in trt
41 | trt_opt_shape (int): opt shape for dynamic shape in trt
42 | trt_calib_mode (bool): If the model is produced by TRT offline quantitative
43 | calibration, trt_calib_mode need to set True
44 | cpu_threads (int): cpu threads
45 | enable_mkldnn (bool): whether to open MKLDNN
46 | """
47 |
48 | def __init__(self,
49 | model_dir,
50 | device='CPU',
51 | run_mode='paddle',
52 | batch_size=50,
53 | trt_min_shape=1,
54 | trt_max_shape=1088,
55 | trt_opt_shape=608,
56 | trt_calib_mode=False,
57 | cpu_threads=4,
58 | enable_mkldnn=False):
59 | self.pred_config = self.set_config(model_dir)
60 | self.predictor, self.config = load_predictor(
61 | model_dir,
62 | run_mode=run_mode,
63 | batch_size=batch_size,
64 | min_subgraph_size=self.pred_config.min_subgraph_size,
65 | device=device,
66 | use_dynamic_shape=self.pred_config.use_dynamic_shape,
67 | trt_min_shape=trt_min_shape,
68 | trt_max_shape=trt_max_shape,
69 | trt_opt_shape=trt_opt_shape,
70 | trt_calib_mode=trt_calib_mode,
71 | cpu_threads=cpu_threads,
72 | enable_mkldnn=enable_mkldnn)
73 | self.det_times = Timer()
74 | self.cpu_mem, self.gpu_mem, self.gpu_util = 0, 0, 0
75 | self.batch_size = batch_size
76 | self.input_wh = (128, 256)
77 |
78 | @classmethod
79 | def init_with_cfg(cls, args, cfg):
80 | return cls(model_dir=cfg['model_dir'],
81 | batch_size=cfg['batch_size'],
82 | device=args.device,
83 | run_mode=args.run_mode,
84 | trt_min_shape=args.trt_min_shape,
85 | trt_max_shape=args.trt_max_shape,
86 | trt_opt_shape=args.trt_opt_shape,
87 | trt_calib_mode=args.trt_calib_mode,
88 | cpu_threads=args.cpu_threads,
89 | enable_mkldnn=args.enable_mkldnn)
90 |
91 | def set_config(self, model_dir):
92 | return PredictConfig(model_dir)
93 |
94 | def check_img_quality(self, crop, bbox, xyxy):
95 | if crop is None:
96 | return None
97 | #eclipse
98 | eclipse_quality = 1.0
99 | inner_rect = np.zeros(xyxy.shape)
100 | inner_rect[:, :2] = np.maximum(xyxy[:, :2], bbox[None, :2])
101 | inner_rect[:, 2:] = np.minimum(xyxy[:, 2:], bbox[None, 2:])
102 | wh_array = inner_rect[:, 2:] - inner_rect[:, :2]
103 | filt = np.logical_and(wh_array[:, 0] > 0, wh_array[:, 1] > 0)
104 | wh_array = wh_array[filt]
105 | if wh_array.shape[0] > 1:
106 | eclipse_ratio = wh_array / (bbox[2:] - bbox[:2])
107 | eclipse_area_ratio = eclipse_ratio[:, 0] * eclipse_ratio[:, 1]
108 | ear_lst = eclipse_area_ratio.tolist()
109 | ear_lst.sort(reverse=True)
110 | eclipse_quality = 1.0 - ear_lst[1]
111 | bbox_wh = (bbox[2:] - bbox[:2])
112 | height_quality = bbox_wh[1] / (bbox_wh[0] * 2)
113 | eclipse_quality = min(eclipse_quality, height_quality)
114 |
115 | #definition
116 | cropgray = cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY)
117 | definition = int(cv2.Laplacian(cropgray, cv2.CV_64F, ksize=3).var())
118 | brightness = int(cropgray.mean())
119 | bd_quality = min(1., brightness / 50.)
120 |
121 | eclipse_weight = 0.7
122 | return eclipse_quality * eclipse_weight + bd_quality * (1 -
123 | eclipse_weight)
124 |
125 | def normal_crop(self, image, rect):
126 | imgh, imgw, c = image.shape
127 | label, conf, xmin, ymin, xmax, ymax = [int(x) for x in rect.tolist()]
128 | xmin = max(0, xmin)
129 | ymin = max(0, ymin)
130 | xmax = min(imgw, xmax)
131 | ymax = min(imgh, ymax)
132 | if label != 0 or xmax <= xmin or ymax <= ymin:
133 | print("Warning! label missed!!")
134 | return None, None, None
135 | return image[ymin:ymax, xmin:xmax, :]
136 |
137 | # mot output format: id, class, score, xmin, ymin, xmax, ymax
138 | def crop_image_with_mot(self, image, mot_res):
139 | res = mot_res['boxes']
140 | crop_res = []
141 | img_quality = []
142 | rects = []
143 | for box in res:
144 | crop_image = self.normal_crop(image, box[1:])
145 | quality_item = self.check_img_quality(crop_image, box[3:],
146 | res[:, 3:])
147 | if crop_image is not None:
148 | crop_res.append(crop_image)
149 | img_quality.append(quality_item)
150 | rects.append(box)
151 | return crop_res, img_quality, rects
152 |
153 | def preprocess(self,
154 | imgs,
155 | mean=[0.485, 0.456, 0.406],
156 | std=[0.229, 0.224, 0.225]):
157 | im_batch = []
158 | for img in imgs:
159 | img = cv2.resize(img, self.input_wh)
160 | img = img.astype('float32') / 255.
161 | img -= np.array(mean)
162 | img /= np.array(std)
163 | im_batch.append(img.transpose((2, 0, 1)))
164 | inputs = {}
165 | inputs['x'] = np.array(im_batch).astype('float32')
166 | return inputs
167 |
168 | def predict(self, crops, repeats=1, add_timer=True, seq_name=''):
169 | # preprocess
170 | if add_timer:
171 | self.det_times.preprocess_time_s.start()
172 | inputs = self.preprocess(crops)
173 | input_names = self.predictor.get_input_names()
174 | for i in range(len(input_names)):
175 | input_tensor = self.predictor.get_input_handle(input_names[i])
176 | input_tensor.copy_from_cpu(inputs[input_names[i]])
177 |
178 | if add_timer:
179 | self.det_times.preprocess_time_s.end()
180 | self.det_times.inference_time_s.start()
181 |
182 | # model prediction
183 | for i in range(repeats):
184 | self.predictor.run()
185 | output_names = self.predictor.get_output_names()
186 | feature_tensor = self.predictor.get_output_handle(output_names[0])
187 | pred_embs = feature_tensor.copy_to_cpu()
188 | if add_timer:
189 | self.det_times.inference_time_s.end(repeats=repeats)
190 | self.det_times.postprocess_time_s.start()
191 |
192 | if add_timer:
193 | self.det_times.postprocess_time_s.end()
194 | self.det_times.img_num += 1
195 | return pred_embs
196 |
197 | def predict_batch(self, imgs, batch_size=4):
198 | batch_feat = []
199 | for b in range(0, len(imgs), batch_size):
200 | b_end = min(len(imgs), b + batch_size)
201 | batch_imgs = imgs[b:b_end]
202 | feat = self.predict(batch_imgs)
203 | batch_feat.extend(feat.tolist())
204 |
205 | return batch_feat
206 |
--------------------------------------------------------------------------------
/ppvehicle/__pycache__/lane_seg_infer.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/ppvehicle/__pycache__/lane_seg_infer.cpython-38.pyc
--------------------------------------------------------------------------------
/ppvehicle/__pycache__/vehicle_attr.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/ppvehicle/__pycache__/vehicle_attr.cpython-38.pyc
--------------------------------------------------------------------------------
/ppvehicle/__pycache__/vehicle_plate.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/ppvehicle/__pycache__/vehicle_plate.cpython-38.pyc
--------------------------------------------------------------------------------
/ppvehicle/__pycache__/vehicle_plateutils.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/ppvehicle/__pycache__/vehicle_plateutils.cpython-38.pyc
--------------------------------------------------------------------------------
/ppvehicle/__pycache__/vehicle_pressing.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/ppvehicle/__pycache__/vehicle_pressing.cpython-38.pyc
--------------------------------------------------------------------------------
/ppvehicle/__pycache__/vehicle_retrograde.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/ppvehicle/__pycache__/vehicle_retrograde.cpython-38.pyc
--------------------------------------------------------------------------------
/ppvehicle/__pycache__/vehicleplate_postprocess.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/ppvehicle/__pycache__/vehicleplate_postprocess.cpython-38.pyc
--------------------------------------------------------------------------------
/ppvehicle/lane_seg_infer.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import argparse
16 | import codecs
17 | import os
18 |
19 | import yaml
20 | import numpy as np
21 | import cv2
22 | from sklearn.cluster import DBSCAN
23 | from pptracking.python.det_infer import load_predictor
24 |
25 |
26 | class LaneSegPredictor:
27 | def __init__(self, lane_seg_config, model_dir):
28 | """
29 | Prepare for prediction.
30 | The usage and docs of paddle inference, please refer to
31 | https://paddleinference.paddlepaddle.org.cn/product_introduction/summary.html
32 | """
33 | if not os.path.exists(lane_seg_config):
34 | raise ValueError("Cannot find : {},".format(lane_seg_config))
35 |
36 | args = yaml.safe_load(open(lane_seg_config))
37 | self.model_dir = model_dir
38 | self.args = args[args['type']]
39 |
40 | self.shape = None
41 | self.filter_horizontal_flag = self.args['filter_horizontal_flag']
42 | self.horizontal_filtration_degree = self.args[
43 | 'horizontal_filtration_degree']
44 | self.horizontal_filtering_threshold = self.args[
45 | 'horizontal_filtering_threshold']
46 |
47 | try:
48 | self.predictor, _ = load_predictor(
49 | model_dir=self.model_dir,
50 | run_mode=self.args['run_mode'],
51 | batch_size=self.args['batch_size'],
52 | device=self.args['device'],
53 | min_subgraph_size=self.args['min_subgraph_size'],
54 | use_dynamic_shape=self.args['use_dynamic_shape'],
55 | trt_min_shape=self.args['trt_min_shape'],
56 | trt_max_shape=self.args['trt_max_shape'],
57 | trt_opt_shape=self.args['trt_opt_shape'],
58 | trt_calib_mode=self.args['trt_calib_mode'],
59 | cpu_threads=self.args['cpu_threads'],
60 | enable_mkldnn=self.args['enable_mkldnn'])
61 | except Exception as e:
62 | print(str(e))
63 | exit()
64 |
65 | def run(self, img):
66 |
67 | input_names = self.predictor.get_input_names()
68 | input_handle = self.predictor.get_input_handle(input_names[0])
69 | output_names = self.predictor.get_output_names()
70 | output_handle = self.predictor.get_output_handle(output_names[0])
71 |
72 | img = np.array(img)
73 | self.shape = img.shape[1:3]
74 | img = self.normalize(img)
75 | img = np.transpose(img, (0, 3, 1, 2))
76 | input_handle.reshape(img.shape)
77 | input_handle.copy_from_cpu(img)
78 |
79 | self.predictor.run()
80 |
81 | results = output_handle.copy_to_cpu()
82 | results = self.postprocess(results)
83 |
84 | return self.get_line(results)
85 |
86 | def normalize(self, im, mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)):
87 | mean = np.array(mean)[np.newaxis, np.newaxis, :]
88 | std = np.array(std)[np.newaxis, np.newaxis, :]
89 | im = im.astype(np.float32, copy=False) / 255.0
90 | im -= mean
91 | im /= std
92 | return im
93 |
94 | def postprocess(self, pred):
95 |
96 | pred = np.argmax(pred, axis=1)
97 | pred[pred == 3] = 0
98 | pred[pred > 0] = 255
99 |
100 | return pred
101 |
102 | def get_line(self, results):
103 | lines = []
104 | directions = []
105 | for i in range(results.shape[0]):
106 | line, direction = self.hough_line(np.uint8(results[i]))
107 | lines.append(line)
108 | directions.append(direction)
109 | return lines, directions
110 |
111 | def get_distance(self, array_1, array_2):
112 | lon_a = array_1[0]
113 | lat_a = array_1[1]
114 | lon_b = array_2[0]
115 | lat_b = array_2[1]
116 |
117 | s = pow(pow((lat_b - lat_a), 2) + pow((lon_b - lon_a), 2), 0.5)
118 | return s
119 |
120 | def get_angle(self, array):
121 | import math
122 | x1, y1, x2, y2 = array
123 | a_x = x2 - x1
124 | a_y = y2 - y1
125 | angle1 = math.atan2(a_y, a_x)
126 | angle1 = int(angle1 * 180 / math.pi)
127 | if angle1 > 90:
128 | angle1 = 180 - angle1
129 | return angle1
130 |
131 | def get_proportion(self, lines):
132 |
133 | proportion = 0.0
134 | h, w = self.shape
135 | for line in lines:
136 | x1, y1, x2, y2 = line
137 | length = abs(y2 - y1) / h + abs(x2 - x1) / w
138 | proportion = proportion + length
139 |
140 | return proportion
141 |
142 | def line_cluster(self, linesP):
143 |
144 | points = []
145 | for i in range(0, len(linesP)):
146 | l = linesP[i]
147 | x_center = (float(
148 | (max(l[2], l[0]) - min(l[2], l[0]))) / 2.0 + min(l[2], l[0]))
149 | y_center = (float(
150 | (max(l[3], l[1]) - min(l[3], l[1]))) / 2.0 + min(l[3], l[1]))
151 | points.append([x_center, y_center])
152 |
153 | dbscan = DBSCAN(
154 | eps=50, min_samples=2, metric=self.get_distance).fit(points)
155 |
156 | labels = dbscan.labels_
157 | n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
158 | cluster_list = list([] for i in range(n_clusters_))
159 | if linesP is not None:
160 | for i in range(0, len(linesP)):
161 | if labels[i] == -1:
162 | continue
163 | l = linesP[i]
164 | x1, y1, x2, y2 = l
165 | if y2 >= y1:
166 | cluster_list[labels[i]].append([x1, y1, x2, y2])
167 | else:
168 | ll = [x2, y2, x1, y1]
169 | cluster_list[labels[i]].append(ll)
170 |
171 | return cluster_list
172 |
173 | def hough_line(self,
174 | binary_img,
175 | min_line=50,
176 | min_line_points=50,
177 | max_line_gap=10):
178 | linesP = cv2.HoughLinesP(binary_img, 1, np.pi / 180, min_line, None,
179 | min_line_points, max_line_gap)
180 | if linesP is None:
181 | return [], None
182 |
183 | coarse_cluster_list = self.line_cluster(linesP[:, 0])
184 | filter_lines_output, direction = self.filter_lines(coarse_cluster_list)
185 |
186 | return filter_lines_output, direction
187 |
188 | def filter_lines(self, coarse_cluster_list):
189 |
190 | lines = []
191 | angles = []
192 | for i in range(len(coarse_cluster_list)):
193 | if len(coarse_cluster_list[i]) == 0:
194 | continue
195 | coarse_cluster_list[i] = np.array(coarse_cluster_list[i])
196 | distance = abs(coarse_cluster_list[i][:, 3] - coarse_cluster_list[i]
197 | [:, 1]) + abs(coarse_cluster_list[i][:, 2] -
198 | coarse_cluster_list[i][:, 0])
199 | l = coarse_cluster_list[i][np.argmax(distance)]
200 | angles.append(self.get_angle(l))
201 | lines.append(l)
202 |
203 | if len(lines) == 0:
204 | return [], None
205 | if not self.filter_horizontal_flag:
206 | return lines, None
207 |
208 | #filter horizontal roads
209 | angles = np.array(angles)
210 |
211 | max_angle, min_angle = np.max(angles), np.min(angles)
212 |
213 | if (max_angle - min_angle) < self.horizontal_filtration_degree:
214 | return lines, np.mean(angles)
215 |
216 | thr_angle = (
217 | max_angle + min_angle) * self.horizontal_filtering_threshold
218 | lines = np.array(lines)
219 |
220 | min_angle_line = lines[np.where(angles < thr_angle)]
221 | max_angle_line = lines[np.where(angles >= thr_angle)]
222 |
223 | max_angle_line_pro = self.get_proportion(max_angle_line)
224 | min_angle_line_pro = self.get_proportion(min_angle_line)
225 |
226 | if max_angle_line_pro >= min_angle_line_pro:
227 | angle_list = angles[np.where(angles >= thr_angle)]
228 | return max_angle_line, np.mean(angle_list)
229 | else:
230 | angle_list = angles[np.where(angles < thr_angle)]
231 | return min_angle_line, np.mean(angle_list)
232 |
--------------------------------------------------------------------------------
/ppvehicle/vehicle_attr.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import os
16 | import yaml
17 | import glob
18 |
19 | import cv2
20 | import numpy as np
21 | import math
22 | import paddle
23 | import sys
24 | try:
25 | from collections.abc import Sequence
26 | except Exception:
27 | from collections import Sequence
28 |
29 | # add deploy path of PaddleDetection to sys.path
30 | parent_path = os.path.abspath(os.path.join(__file__, *(['..'] * 3)))
31 | sys.path.insert(0, parent_path)
32 |
33 | from paddle.inference import Config, create_predictor
34 | from python.utils import argsparser, Timer, get_current_memory_mb
35 | from python.benchmark_utils import PaddleInferBenchmark
36 | from python.infer import Detector, print_arguments
37 | from pipeline.pphuman.attr_infer import AttrDetector
38 |
39 |
40 | class VehicleAttr(AttrDetector):
41 | """
42 | Args:
43 | model_dir (str): root path of model.pdiparams, model.pdmodel and infer_cfg.yml
44 | device (str): Choose the device you want to run, it can be: CPU/GPU/XPU/NPU, default is CPU
45 | run_mode (str): mode of running(paddle/trt_fp32/trt_fp16)
46 | batch_size (int): size of pre batch in inference
47 | trt_min_shape (int): min shape for dynamic shape in trt
48 | trt_max_shape (int): max shape for dynamic shape in trt
49 | trt_opt_shape (int): opt shape for dynamic shape in trt
50 | trt_calib_mode (bool): If the model is produced by TRT offline quantitative
51 | calibration, trt_calib_mode need to set True
52 | cpu_threads (int): cpu threads
53 | enable_mkldnn (bool): whether to open MKLDNN
54 | type_threshold (float): The threshold of score for vehicle type recognition.
55 | color_threshold (float): The threshold of score for vehicle color recognition.
56 | """
57 |
58 | def __init__(self,
59 | model_dir,
60 | device='CPU',
61 | run_mode='paddle',
62 | batch_size=1,
63 | trt_min_shape=1,
64 | trt_max_shape=1280,
65 | trt_opt_shape=640,
66 | trt_calib_mode=False,
67 | cpu_threads=1,
68 | enable_mkldnn=False,
69 | output_dir='output',
70 | color_threshold=0.5,
71 | type_threshold=0.5):
72 | super(VehicleAttr, self).__init__(
73 | model_dir=model_dir,
74 | device=device,
75 | run_mode=run_mode,
76 | batch_size=batch_size,
77 | trt_min_shape=trt_min_shape,
78 | trt_max_shape=trt_max_shape,
79 | trt_opt_shape=trt_opt_shape,
80 | trt_calib_mode=trt_calib_mode,
81 | cpu_threads=cpu_threads,
82 | enable_mkldnn=enable_mkldnn,
83 | output_dir=output_dir)
84 | self.color_threshold = color_threshold
85 | self.type_threshold = type_threshold
86 | self.result_history = {}
87 | self.color_list = [
88 | "yellow", "orange", "green", "gray", "red", "blue", "white",
89 | "golden", "brown", "black"
90 | ]
91 | self.type_list = [
92 | "sedan", "suv", "van", "hatchback", "mpv", "pickup", "bus", "truck",
93 | "estate"
94 | ]
95 |
96 | @classmethod
97 | def init_with_cfg(cls, args, cfg):
98 | return cls(model_dir=cfg['model_dir'],
99 | batch_size=cfg['batch_size'],
100 | color_threshold=cfg['color_threshold'],
101 | type_threshold=cfg['type_threshold'],
102 | device=args.device,
103 | run_mode=args.run_mode,
104 | trt_min_shape=args.trt_min_shape,
105 | trt_max_shape=args.trt_max_shape,
106 | trt_opt_shape=args.trt_opt_shape,
107 | trt_calib_mode=args.trt_calib_mode,
108 | cpu_threads=args.cpu_threads,
109 | enable_mkldnn=args.enable_mkldnn)
110 |
111 | def postprocess(self, inputs, result):
112 | # postprocess output of predictor
113 | im_results = result['output']
114 | batch_res = []
115 | for res in im_results:
116 | res = res.tolist()
117 | attr_res = []
118 | color_res_str = "Color: "
119 | type_res_str = "Type: "
120 | color_idx = np.argmax(res[:10])
121 | type_idx = np.argmax(res[10:])
122 |
123 | if res[color_idx] >= self.color_threshold:
124 | color_res_str += self.color_list[color_idx]
125 | else:
126 | color_res_str += "Unknown"
127 | attr_res.append(color_res_str)
128 |
129 | if res[type_idx + 10] >= self.type_threshold:
130 | type_res_str += self.type_list[type_idx]
131 | else:
132 | type_res_str += "Unknown"
133 | attr_res.append(type_res_str)
134 |
135 | batch_res.append(attr_res)
136 | result = {'output': batch_res}
137 | return result
138 |
139 |
140 | if __name__ == '__main__':
141 | paddle.enable_static()
142 | parser = argsparser()
143 | FLAGS = parser.parse_args()
144 | print_arguments(FLAGS)
145 | FLAGS.device = FLAGS.device.upper()
146 | assert FLAGS.device in ['CPU', 'GPU', 'XPU', 'NPU'
147 | ], "device should be CPU, GPU, NPU or XPU"
148 | assert not FLAGS.use_gpu, "use_gpu has been deprecated, please use --device"
149 |
150 | main()
151 |
--------------------------------------------------------------------------------
/ppvehicle/vehicle_pressing.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2022 PaddlePaddle Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | import os
16 |
17 | import numpy as np
18 | import math
19 |
20 |
21 | class VehiclePressingRecognizer(object):
22 | def __init__(self, cfg):
23 | self.cfg = cfg
24 |
25 | def judge(self, Ax1, Ay1, Ax2, Ay2, Bx1, By1, Bx2, By2):
26 |
27 | if (max(Ax1,Ax2)>=min(Bx1,Bx2) and min(Ax1,Ax2)<=max(Bx1,Bx2)) and \
28 | (max(Ay1,Ay2)>=min(By1,By2) and min(Ay1,Ay2)<=max(By1,By2)):
29 |
30 | if ((Bx1-Ax1)*(Ay2-Ay1)-(By1-Ay1)*(Ax2-Ax1)) * ((Bx2-Ax1)*(Ay2-Ay1)-(By2-Ay1)*(Ax2-Ax1))<=0 \
31 | and ((Ax1-Bx1)*(By2-By1)-(Ay1-By1)*(Bx2-Bx1)) * ((Ax2-Bx1)*(By2-By1)-(Ay2-By1)*(Bx2-Bx1)) <=0:
32 | return True
33 | else:
34 | return False
35 | else:
36 | return False
37 |
38 | def is_intersect(self, line, bbox):
39 | Ax1, Ay1, Ax2, Ay2 = line
40 |
41 | xmin, ymin, xmax, ymax = bbox
42 |
43 | bottom = self.judge(Ax1, Ay1, Ax2, Ay2, xmin, ymax, xmax, ymax)
44 | return bottom
45 |
46 | def run(self, lanes, det_res):
47 | intersect_bbox_list = []
48 | start_idx, boxes_num_i = 0, 0
49 |
50 | for i in range(len(lanes)):
51 | lane = lanes[i]
52 | if det_res is not None:
53 | det_res_i = {}
54 | boxes_num_i = det_res['boxes_num'][i]
55 | det_res_i['boxes'] = det_res['boxes'][start_idx:start_idx +
56 | boxes_num_i, :]
57 | intersect_bbox = []
58 |
59 | for line in lane:
60 | for bbox in det_res_i['boxes']:
61 | if self.is_intersect(line, bbox[2:]):
62 | intersect_bbox.append(bbox)
63 | intersect_bbox_list.append(intersect_bbox)
64 |
65 | start_idx += boxes_num_i
66 |
67 | return intersect_bbox_list
68 |
69 | def mot_run(self, lanes, det_res):
70 |
71 | intersect_bbox_list = []
72 | if det_res is None:
73 | return intersect_bbox_list
74 | lanes_res = lanes['output']
75 | for i in range(len(lanes_res)):
76 | lane = lanes_res[i]
77 | for line in lane:
78 | for bbox in det_res:
79 | if self.is_intersect(line, bbox[3:]):
80 | intersect_bbox_list.append(bbox)
81 | return intersect_bbox_list
--------------------------------------------------------------------------------
/tools/ccpd2ocr_all.py:
--------------------------------------------------------------------------------
1 | import cv2
2 | import os
3 | import json
4 | from tqdm import tqdm
5 | import numpy as np
6 |
7 | provinces = [
8 | "皖", "沪", "津", "渝", "冀", "晋", "蒙", "辽", "吉", "黑", "苏", "浙", "京", "闽", "赣",
9 | "鲁", "豫", "鄂", "湘", "粤", "桂", "琼", "川", "贵", "云", "藏", "陕", "甘", "青", "宁",
10 | "新", "警", "学", "O"
11 | ]
12 | alphabets = [
13 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q',
14 | 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'O'
15 | ]
16 | ads = [
17 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q',
18 | 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '0', '1', '2', '3', '4', '5',
19 | '6', '7', '8', '9', 'O'
20 | ]
21 |
22 |
23 | def make_label_2020(img_dir, save_gt_folder, phase):
24 | crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs')
25 | os.makedirs(crop_img_save_dir, exist_ok=True)
26 |
27 | f_det = open(
28 | os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8')
29 | f_rec = open(
30 | os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8')
31 |
32 | i = 0
33 | for filename in tqdm(os.listdir(os.path.join(img_dir, phase))):
34 | str_list = filename.split('-')
35 | if len(str_list) < 5:
36 | continue
37 | coord_list = str_list[3].split('_')
38 | txt_list = str_list[4].split('_')
39 | boxes = []
40 | for coord in coord_list:
41 | boxes.append([int(x) for x in coord.split("&")])
42 | boxes = [boxes[2], boxes[3], boxes[0], boxes[1]]
43 | lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[
44 | 1])] + ''.join([ads[int(x)] for x in txt_list[2:]])
45 |
46 | # det
47 | det_info = [{'points': boxes, 'transcription': lp_number}]
48 | f_det.write('{}\t{}\n'.format(
49 | os.path.join("CCPD2020/ccpd_green", phase, filename),
50 | json.dumps(
51 | det_info, ensure_ascii=False)))
52 |
53 | # rec
54 | boxes = np.float32(boxes)
55 | img = cv2.imread(os.path.join(img_dir, phase, filename))
56 | # crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())]
57 | crop_img = get_rotate_crop_image(img, boxes)
58 | crop_img_save_filename = '{}_{}.jpg'.format(i, '_'.join(txt_list))
59 | crop_img_save_path = os.path.join(crop_img_save_dir,
60 | crop_img_save_filename)
61 | cv2.imwrite(crop_img_save_path, crop_img)
62 | f_rec.write('{}/{}/crop_imgs/{}\t{}\n'.format(
63 | "CCPD2020/PPOCR", phase, crop_img_save_filename, lp_number))
64 | i += 1
65 | f_det.close()
66 | f_rec.close()
67 |
68 |
69 | def make_label_2019(list_dir, save_gt_folder, phase):
70 | crop_img_save_dir = os.path.join(save_gt_folder, phase, 'crop_imgs')
71 | os.makedirs(crop_img_save_dir, exist_ok=True)
72 |
73 | f_det = open(
74 | os.path.join(save_gt_folder, phase, 'det.txt'), 'w', encoding='utf-8')
75 | f_rec = open(
76 | os.path.join(save_gt_folder, phase, 'rec.txt'), 'w', encoding='utf-8')
77 |
78 | with open(os.path.join(list_dir, phase + ".txt"), 'r') as rf:
79 | imglist = rf.readlines()
80 |
81 | i = 0
82 | for idx, filename in enumerate(imglist):
83 | if idx % 1000 == 0:
84 | print("{}/{}".format(idx, len(imglist)))
85 | filename = filename.strip()
86 | str_list = filename.split('-')
87 | if len(str_list) < 5:
88 | continue
89 | coord_list = str_list[3].split('_')
90 | txt_list = str_list[4].split('_')
91 | boxes = []
92 | for coord in coord_list:
93 | boxes.append([int(x) for x in coord.split("&")])
94 | boxes = [boxes[2], boxes[3], boxes[0], boxes[1]]
95 | lp_number = provinces[int(txt_list[0])] + alphabets[int(txt_list[
96 | 1])] + ''.join([ads[int(x)] for x in txt_list[2:]])
97 |
98 | # det
99 | det_info = [{'points': boxes, 'transcription': lp_number}]
100 | f_det.write('{}\t{}\n'.format(
101 | os.path.join("CCPD2019", filename),
102 | json.dumps(
103 | det_info, ensure_ascii=False)))
104 |
105 | # rec
106 | boxes = np.float32(boxes)
107 | imgpath = os.path.join(list_dir[:-7], filename)
108 | img = cv2.imread(imgpath)
109 | # crop_img = img[int(boxes[:,1].min()):int(boxes[:,1].max()),int(boxes[:,0].min()):int(boxes[:,0].max())]
110 | crop_img = get_rotate_crop_image(img, boxes)
111 | crop_img_save_filename = '{}_{}.jpg'.format(i, '_'.join(txt_list))
112 | crop_img_save_path = os.path.join(crop_img_save_dir,
113 | crop_img_save_filename)
114 | cv2.imwrite(crop_img_save_path, crop_img)
115 | f_rec.write('{}/{}/crop_imgs/{}\t{}\n'.format(
116 | "CCPD2019/PPOCR", phase, crop_img_save_filename, lp_number))
117 | i += 1
118 | f_det.close()
119 | f_rec.close()
120 |
121 |
122 | def get_rotate_crop_image(img, points):
123 | '''
124 | img_height, img_width = img.shape[0:2]
125 | left = int(np.min(points[:, 0]))
126 | right = int(np.max(points[:, 0]))
127 | top = int(np.min(points[:, 1]))
128 | bottom = int(np.max(points[:, 1]))
129 | img_crop = img[top:bottom, left:right, :].copy()
130 | points[:, 0] = points[:, 0] - left
131 | points[:, 1] = points[:, 1] - top
132 | '''
133 | assert len(points) == 4, "shape of points must be 4*2"
134 | img_crop_width = int(
135 | max(
136 | np.linalg.norm(points[0] - points[1]),
137 | np.linalg.norm(points[2] - points[3])))
138 | img_crop_height = int(
139 | max(
140 | np.linalg.norm(points[0] - points[3]),
141 | np.linalg.norm(points[1] - points[2])))
142 | pts_std = np.float32([[0, 0], [img_crop_width, 0],
143 | [img_crop_width, img_crop_height],
144 | [0, img_crop_height]])
145 | M = cv2.getPerspectiveTransform(points, pts_std)
146 | dst_img = cv2.warpPerspective(
147 | img,
148 | M, (img_crop_width, img_crop_height),
149 | borderMode=cv2.BORDER_REPLICATE,
150 | flags=cv2.INTER_CUBIC)
151 | dst_img_height, dst_img_width = dst_img.shape[0:2]
152 | if dst_img_height * 1.0 / dst_img_width >= 1.5:
153 | dst_img = np.rot90(dst_img)
154 | return dst_img
155 |
156 |
157 | img_dir = './CCPD2020/ccpd_green'
158 | save_gt_folder = './CCPD2020/PPOCR'
159 | # phase = 'train' # change to val and test to make val dataset and test dataset
160 | for phase in ['train', 'val', 'test']:
161 | make_label_2020(img_dir, save_gt_folder, phase)
162 |
163 | list_dir = './CCPD2019/splits/'
164 | save_gt_folder = './CCPD2019/PPOCR'
165 |
166 | for phase in ['train', 'val', 'test']:
167 | make_label_2019(list_dir, save_gt_folder, phase)
168 |
--------------------------------------------------------------------------------
/tools/clip_video.py:
--------------------------------------------------------------------------------
1 | import cv2
2 |
3 |
4 | def cut_video(video_path, frameToStart, frametoStop, saved_video_path):
5 | cap = cv2.VideoCapture(video_path)
6 | FPS = cap.get(cv2.CAP_PROP_FPS)
7 |
8 | TOTAL_FRAME = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 获取视频总帧数
9 |
10 | size = (cap.get(cv2.CAP_PROP_FRAME_WIDTH),
11 | cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
12 |
13 | videoWriter = cv2.VideoWriter(
14 | saved_video_path,
15 | apiPreference=0,
16 | fourcc=cv2.VideoWriter_fourcc(* 'mp4v'),
17 | fps=FPS,
18 | frameSize=(int(size[0]), int(size[1])))
19 |
20 | COUNT = 0
21 | while True:
22 | success, frame = cap.read()
23 | if success:
24 | COUNT += 1
25 | if COUNT <= frametoStop and COUNT > frameToStart: # 选取起始帧
26 | videoWriter.write(frame)
27 | else:
28 | print("cap.read failed!")
29 | break
30 | if COUNT > frametoStop:
31 | break
32 |
33 | cap.release()
34 | videoWriter.release()
35 |
36 | print(saved_video_path)
37 |
--------------------------------------------------------------------------------
/tools/create_dataset_list.py:
--------------------------------------------------------------------------------
1 | # coding: utf8
2 | # Copyright (c) 2023 PaddlePaddle Authors. All Rights Reserve.
3 | #
4 | # Licensed under the Apache License, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | import glob
17 | import os.path
18 | import argparse
19 | import warnings
20 |
21 |
22 | def parse_args():
23 | parser = argparse.ArgumentParser(
24 | description='PaddleSeg generate file list on cityscapes or your customized dataset.'
25 | )
26 | parser.add_argument('dataset_root', help='dataset root directory', type=str)
27 | parser.add_argument(
28 | '--type',
29 | help='dataset type: \n'
30 | '- cityscapes \n'
31 | '- custom(default)',
32 | default="custom",
33 | type=str)
34 | parser.add_argument(
35 | '--separator',
36 | dest='separator',
37 | help='file list separator',
38 | default=" ",
39 | type=str)
40 | parser.add_argument(
41 | '--folder',
42 | help='the folder names of images and labels',
43 | type=str,
44 | nargs=2,
45 | default=['images', 'labels'])
46 | parser.add_argument(
47 | '--second_folder',
48 | help='the second-level folder names of train set, validation set, test set',
49 | type=str,
50 | nargs='*',
51 | default=['train', 'val', 'test'])
52 | parser.add_argument(
53 | '--format',
54 | help='data format of images and labels, e.g. jpg or png.',
55 | type=str,
56 | nargs=2,
57 | default=['jpg', 'png'])
58 | parser.add_argument(
59 | '--postfix',
60 | help='postfix of images or labels',
61 | type=str,
62 | nargs=2,
63 | default=['', ''])
64 |
65 | return parser.parse_args()
66 |
67 |
68 | def get_files(image_or_label, dataset_split, args):
69 | dataset_root = args.dataset_root
70 | postfix = args.postfix
71 | format = args.format
72 | folder = args.folder
73 |
74 | pattern = '*%s.%s' % (postfix[image_or_label], format[image_or_label])
75 |
76 | search_files = os.path.join(dataset_root, folder[image_or_label],
77 | dataset_split, pattern)
78 | search_files2 = os.path.join(dataset_root, folder[image_or_label],
79 | dataset_split, "*", pattern) # 包含子目录
80 | search_files3 = os.path.join(dataset_root, folder[image_or_label],
81 | dataset_split, "*", "*", pattern) # 包含三级目录
82 | search_files4 = os.path.join(dataset_root, folder[image_or_label],
83 | dataset_split, "*", "*", "*",
84 | pattern) # 包含四级目录
85 | search_files5 = os.path.join(dataset_root, folder[image_or_label],
86 | dataset_split, "*", "*", "*", "*",
87 | pattern) # 包含五级目录
88 |
89 | filenames = glob.glob(search_files)
90 | filenames2 = glob.glob(search_files2)
91 | filenames3 = glob.glob(search_files3)
92 | filenames4 = glob.glob(search_files4)
93 | filenames5 = glob.glob(search_files5)
94 |
95 | filenames = filenames + filenames2 + filenames3 + filenames4 + filenames5
96 |
97 | return sorted(filenames)
98 |
99 |
100 | def generate_list(args):
101 | dataset_root = args.dataset_root
102 | separator = args.separator
103 |
104 | for dataset_split in args.second_folder:
105 | print("Creating {}.txt...".format(dataset_split))
106 | image_files = get_files(0, dataset_split, args)
107 | label_files = get_files(1, dataset_split, args)
108 | if not image_files:
109 | img_dir = os.path.join(dataset_root, args.folder[0], dataset_split)
110 | warnings.warn("No images in {} !!!".format(img_dir))
111 | num_images = len(image_files)
112 |
113 | if not label_files:
114 | label_dir = os.path.join(dataset_root, args.folder[1],
115 | dataset_split)
116 | warnings.warn("No labels in {} !!!".format(label_dir))
117 | num_label = len(label_files)
118 |
119 | if num_images != num_label and num_label > 0:
120 | raise Exception(
121 | "Number of images = {} number of labels = {} \n"
122 | "Either number of images is equal to number of labels, "
123 | "or number of labels is equal to 0.\n"
124 | "Please check your dataset!".format(num_images, num_label))
125 |
126 | file_list = os.path.join(dataset_root, dataset_split + '.txt')
127 | with open(file_list, "w") as f:
128 | for item in range(num_images):
129 | left = image_files[item].replace(dataset_root, '', 1)
130 | if left[0] == os.path.sep:
131 | left = left.lstrip(os.path.sep)
132 |
133 | try:
134 | right = label_files[item].replace(dataset_root, '', 1)
135 | if right[0] == os.path.sep:
136 | right = right.lstrip(os.path.sep)
137 | line = left + separator + right + '\n'
138 | except:
139 | line = left + '\n'
140 |
141 | f.write(line)
142 | print(line)
143 |
144 |
145 | if __name__ == '__main__':
146 | args = parse_args()
147 | generate_list(args)
148 |
--------------------------------------------------------------------------------
/tools/get_video_info.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import cv2
4 | import numpy as np
5 | import argparse
6 |
7 |
8 | def argsparser():
9 | parser = argparse.ArgumentParser(description=__doc__)
10 | parser.add_argument(
11 | "--video_file",
12 | type=str,
13 | default=None,
14 | help="Path of video file, `video_file` or `camera_id` has a highest priority."
15 | )
16 | parser.add_argument(
17 | '--region_polygon',
18 | nargs='+',
19 | type=int,
20 | default=[],
21 | help="Clockwise point coords (x0,y0,x1,y1...) of polygon of area when "
22 | "do_break_in_counting. Note that only support single-class MOT and "
23 | "the video should be taken by a static camera.")
24 | return parser
25 |
26 |
27 | def get_video_info(video_file, region_polygon):
28 | entrance = []
29 | assert len(region_polygon
30 | ) % 2 == 0, "region_polygon should be pairs of coords points."
31 | for i in range(0, len(region_polygon), 2):
32 | entrance.append([region_polygon[i], region_polygon[i + 1]])
33 |
34 | if not os.path.exists(video_file):
35 | print("video path '{}' not exists".format(video_file))
36 | sys.exit(-1)
37 | capture = cv2.VideoCapture(video_file)
38 | width = int(capture.get(cv2.CAP_PROP_FRAME_WIDTH))
39 | height = int(capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
40 | print("video width: %d, height: %d" % (width, height))
41 | np_masks = np.zeros((height, width, 1), np.uint8)
42 |
43 | entrance = np.array(entrance)
44 | cv2.fillPoly(np_masks, [entrance], 255)
45 |
46 | fps = int(capture.get(cv2.CAP_PROP_FPS))
47 | frame_count = int(capture.get(cv2.CAP_PROP_FRAME_COUNT))
48 | print("video fps: %d, frame_count: %d" % (fps, frame_count))
49 | cnt = 0
50 | while (1):
51 | ret, frame = capture.read()
52 | cnt += 1
53 | if cnt == 3: break
54 |
55 | alpha = 0.3
56 | img = np.array(frame).astype('float32')
57 | mask = np_masks[:, :, 0]
58 | color_mask = [0, 0, 255]
59 | idx = np.nonzero(mask)
60 | color_mask = np.array(color_mask)
61 | img[idx[0], idx[1], :] *= 1.0 - alpha
62 | img[idx[0], idx[1], :] += alpha * color_mask
63 | cv2.imwrite('region_vis.jpg', img)
64 |
65 |
66 | if __name__ == "__main__":
67 | parser = argsparser()
68 | FLAGS = parser.parse_args()
69 | get_video_info(FLAGS.video_file, FLAGS.region_polygon)
70 |
71 | # python get_video_info.py --video_file=demo.mp4 --region_polygon 200 200 400 200 300 400 100 400
72 |
--------------------------------------------------------------------------------
/tools/split_fight_train_test_dataset.py:
--------------------------------------------------------------------------------
1 | import os
2 | import glob
3 | import random
4 | import fnmatch
5 | import re
6 | import sys
7 |
8 | class_id = {"nofight": 0, "fight": 1}
9 |
10 |
11 | def get_list(path, key_func=lambda x: x[-11:], rgb_prefix='img_', level=1):
12 | if level == 1:
13 | frame_folders = glob.glob(os.path.join(path, '*'))
14 | elif level == 2:
15 | frame_folders = glob.glob(os.path.join(path, '*', '*'))
16 | else:
17 | raise ValueError('level can be only 1 or 2')
18 |
19 | def count_files(directory):
20 | lst = os.listdir(directory)
21 | cnt = len(fnmatch.filter(lst, rgb_prefix + '*'))
22 | return cnt
23 |
24 | # check RGB
25 | video_dict = {}
26 | for f in frame_folders:
27 | cnt = count_files(f)
28 | k = key_func(f)
29 | if level == 2:
30 | k = k.split("/")[0]
31 |
32 | video_dict[f] = str(cnt) + " " + str(class_id[k])
33 |
34 | return video_dict
35 |
36 |
37 | def fight_splits(video_dict, train_percent=0.8):
38 | videos = list(video_dict.keys())
39 |
40 | train_num = int(len(videos) * train_percent)
41 |
42 | train_list = []
43 | val_list = []
44 |
45 | random.shuffle(videos)
46 |
47 | for i in range(train_num):
48 | train_list.append(videos[i] + " " + str(video_dict[videos[i]]))
49 | for i in range(train_num, len(videos)):
50 | val_list.append(videos[i] + " " + str(video_dict[videos[i]]))
51 |
52 | print("train:", len(train_list), ",val:", len(val_list))
53 |
54 | with open("fight_train_list.txt", "w") as f:
55 | for item in train_list:
56 | f.write(item + "\n")
57 |
58 | with open("fight_val_list.txt", "w") as f:
59 | for item in val_list:
60 | f.write(item + "\n")
61 |
62 |
63 | if __name__ == "__main__":
64 | frame_dir = sys.argv[1] # "rawframes"
65 | level = sys.argv[2] # 2
66 | train_percent = sys.argv[3] # 0.8
67 |
68 | if level == 2:
69 |
70 | def key_func(x):
71 | return '/'.join(x.split('/')[-2:])
72 | else:
73 |
74 | def key_func(x):
75 | return x.split('/')[-1]
76 |
77 | video_dict = get_list(frame_dir, key_func=key_func, level=level)
78 | print("number:", len(video_dict))
79 |
80 | fight_splits(video_dict, train_percent)
81 |
--------------------------------------------------------------------------------
/录屏 2023年07月26日 10时13 -big-original.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mianfeng/paddle_MTMCT/3577ed115fe191053b5955c11746389cd85e35b0/录屏 2023年07月26日 10时13 -big-original.gif
--------------------------------------------------------------------------------