|
| 1 | +简体中文 | [English](./ppvehicle_attribute_en.md) |
| 2 | + |
| 3 | +# 车辆属性识别任务二次开发 |
| 4 | + |
| 5 | +## 数据准备 |
| 6 | + |
| 7 | +### 数据格式 |
| 8 | + |
| 9 | +车辆属性模型采用VeRi数据集的属性,共计10种车辆颜色及9种车型, 具体如下: |
| 10 | +``` |
| 11 | +# 车辆颜色 |
| 12 | +- "yellow" |
| 13 | +- "orange" |
| 14 | +- "green" |
| 15 | +- "gray" |
| 16 | +- "red" |
| 17 | +- "blue" |
| 18 | +- "white" |
| 19 | +- "golden" |
| 20 | +- "brown" |
| 21 | +- "black" |
| 22 | +
|
| 23 | +# 车型 |
| 24 | +- "sedan" |
| 25 | +- "suv" |
| 26 | +- "van" |
| 27 | +- "hatchback" |
| 28 | +- "mpv" |
| 29 | +- "pickup" |
| 30 | +- "bus" |
| 31 | +- "truck" |
| 32 | +- "estate" |
| 33 | +``` |
| 34 | + |
| 35 | +在标注文件中使用长度为19的序列来表示上述属性。 |
| 36 | + |
| 37 | +举例: |
| 38 | + |
| 39 | +[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0] |
| 40 | + |
| 41 | +前10位中,位序号0的值为1,表示车辆颜色为`"yellow"`。 |
| 42 | + |
| 43 | +后9位中,位序号11的值为1,表示车型为`"suv"`。 |
| 44 | + |
| 45 | + |
| 46 | +### 数据标注 |
| 47 | + |
| 48 | +理解了上面`数据格式`的含义后,就可以进行数据标注的工作。其本质是:每张车辆的图片,建立一组长度为19的标注项,分别对应各项属性值。 |
| 49 | + |
| 50 | +举例: |
| 51 | + |
| 52 | +对于一张原始图片, |
| 53 | + |
| 54 | +1) 使用检测框,标注图片中每台车辆的位置。 |
| 55 | + |
| 56 | +2) 每一个检测框(对应每辆车),包含一组19位的属性值数组,数组的每一位以0或1表示。对应上述19个属性分类。例如,如果颜色是'orange',则数组索引为1的位置值为1,如果车型是'sedan',则数组索引为10的位置值为1。 |
| 57 | + |
| 58 | +标注完成后利用检测框将每辆车截取成只包含单辆车的图片,则图片与19位属性标注建立了对应关系。也可先截取再进行标注,效果相同。 |
| 59 | + |
| 60 | + |
| 61 | +## 模型训练 |
| 62 | + |
| 63 | +数据标注完成后,就可以拿来做模型的训练,完成自定义模型的优化工作。 |
| 64 | + |
| 65 | +其主要有两步工作需要完成:1)将数据与标注数据整理成训练格式。2)修改配置文件开始训练。 |
| 66 | + |
| 67 | +### 训练数据格式 |
| 68 | + |
| 69 | +训练数据包括训练使用的图片和一个训练列表train.txt,其具体位置在训练配置中指定,其放置方式示例如下: |
| 70 | +``` |
| 71 | +Attribute/ |
| 72 | +|-- data 训练图片文件夹 |
| 73 | +| |-- 00001.jpg |
| 74 | +| |-- 00002.jpg |
| 75 | +| `-- 0000x.jpg |
| 76 | +`-- train.txt 训练数据列表 |
| 77 | +
|
| 78 | +``` |
| 79 | + |
| 80 | +train.txt文件内为所有训练图片名称(相对于根路径的文件路径)+ 19个标注值 |
| 81 | + |
| 82 | +其每一行表示一辆车的图片和标注结果。其格式为: |
| 83 | + |
| 84 | +``` |
| 85 | +00001.jpg 0,0,1,0,.... |
| 86 | +``` |
| 87 | + |
| 88 | +注意:1)图片与标注值之间是以Tab[\t]符号隔开, 2)标注值之间是以逗号[,]隔开。该格式不能错,否则解析失败。 |
| 89 | + |
| 90 | +### 修改配置开始训练 |
| 91 | + |
| 92 | +首先执行以下命令下载训练代码(更多环境问题请参考[Install_PaddleClas](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.4/docs/en/installation/install_paddleclas_en.md)): |
| 93 | + |
| 94 | +```shell |
| 95 | +git clone https://github.com/PaddlePaddle/PaddleClas |
| 96 | +``` |
| 97 | + |
| 98 | +需要在[配置文件](https://github.com/PaddlePaddle/PaddleClas/blob/release/2.4/ppcls/configs/PULC/vehicle_attribute/PPLCNet_x1_0.yaml)中,修改的配置项如下: |
| 99 | +```yaml |
| 100 | +DataLoader: |
| 101 | + Train: |
| 102 | + dataset: |
| 103 | + name: MultiLabelDataset |
| 104 | + image_root: "dataset/VeRi/" # the root path of training images |
| 105 | + cls_label_path: "dataset/VeRi/train_list.txt" # the location of the training list file |
| 106 | + label_ratio: True |
| 107 | + transform_ops: |
| 108 | + ... |
| 109 | + |
| 110 | + Eval: |
| 111 | + dataset: |
| 112 | + name: MultiLabelDataset |
| 113 | + image_root: "dataset/VeRi/" # the root path of evaluation images |
| 114 | + cls_label_path: "dataset/VeRi/val_list.txt" # the location of the evaluation list file |
| 115 | + label_ratio: True |
| 116 | + transform_ops: |
| 117 | + ... |
| 118 | +``` |
| 119 | +
|
| 120 | +注意: |
| 121 | +1. 这里image_root路径+train.txt中图片相对路径,对应图片的完整路径位置。 |
| 122 | +2. 如果有修改属性数量,则还需修改内容配置项中属性种类数量: |
| 123 | +```yaml |
| 124 | +# model architecture |
| 125 | +Arch: |
| 126 | + name: "PPLCNet_x1_0" |
| 127 | + pretrained: True |
| 128 | + use_ssld: True |
| 129 | + class_num: 19 #属性种类数量 |
| 130 | +``` |
| 131 | +
|
| 132 | +然后运行以下命令开始训练。 |
| 133 | +
|
| 134 | +``` |
| 135 | +#多卡训练 |
| 136 | +export CUDA_VISIBLE_DEVICES=0,1,2,3 |
| 137 | +python3 -m paddle.distributed.launch \ |
| 138 | + --gpus="0,1,2,3" \ |
| 139 | + tools/train.py \ |
| 140 | + -c ./ppcls/configs/PULC/vehicle_attribute/PPLCNet_x1_0.yaml |
| 141 | + |
| 142 | +#单卡训练 |
| 143 | +python3 tools/train.py \ |
| 144 | + -c ./ppcls/configs/PULC/vehicle_attribute/PPLCNet_x1_0.yaml |
| 145 | +``` |
| 146 | + |
| 147 | +训练完成后可以执行以下命令进行性能评估: |
| 148 | +``` |
| 149 | +#多卡评估 |
| 150 | +export CUDA_VISIBLE_DEVICES=0,1,2,3 |
| 151 | +python3 -m paddle.distributed.launch \ |
| 152 | + --gpus="0,1,2,3" \ |
| 153 | + tools/eval.py \ |
| 154 | + -c ./ppcls/configs/PULC/vehicle_attribute/PPLCNet_x1_0.yaml \ |
| 155 | + -o Global.pretrained_model=./output/PPLCNet_x1_0/best_model |
| 156 | +
|
| 157 | +#单卡评估 |
| 158 | +python3 tools/eval.py \ |
| 159 | + -c ./ppcls/configs/PULC/vehicle_attribute/PPLCNet_x1_0.yaml \ |
| 160 | + -o Global.pretrained_model=./output/PPLCNet_x1_0/best_model |
| 161 | +``` |
| 162 | + |
| 163 | + |
| 164 | +### 模型导出 |
| 165 | + |
| 166 | +使用下述命令将训练好的模型导出为预测部署模型。 |
| 167 | + |
| 168 | +``` |
| 169 | +python3 tools/export_model.py \ |
| 170 | + -c ./ppcls/configs/PULC/vehicle_attribute/PPLCNet_x1_0.yaml \ |
| 171 | + -o Global.pretrained_model=output/PPLCNet_x1_0/best_model \ |
| 172 | + -o Global.save_inference_dir=deploy/models/PPLCNet_x1_0_vehicle_attribute_model |
| 173 | +``` |
| 174 | + |
| 175 | +导出模型后,如果希望在PP-Vehicle中使用,则需要下载[预测部署模型](https://bj.bcebos.com/v1/paddledet/models/pipeline/vehicle_attribute_model.zip),解压并将其中的配置文件`infer_cfg.yml`文件,放置到导出的模型文件夹`PPLCNet_x1_0_vehicle_attribute_model`中。 |
| 176 | + |
| 177 | +使用时在PP-Vehicle中的配置文件`./deploy/pipeline/config/infer_cfg_ppvehicle.yml`中修改新的模型路径`model_dir`项,并开启功能`enable: True`。 |
| 178 | +``` |
| 179 | +VEHICLE_ATTR: |
| 180 | + model_dir: [YOUR_DEPLOY_MODEL_DIR]/PPLCNet_x1_0_vehicle_attribute_infer/ #新导出的模型路径位置 |
| 181 | + enable: True #开启功能 |
| 182 | +``` |
| 183 | +然后可以使用-->至此即完成新增属性类别识别任务。 |
| 184 | + |
| 185 | +## 属性增减 |
| 186 | + |
| 187 | +该过程与行人属性的增减过程相似,如果需要增加、减少属性数量,则需要: |
| 188 | + |
| 189 | +1)标注时需增加新属性类别信息或删减属性类别信息; |
| 190 | + |
| 191 | +2)对应修改训练中train.txt所使用的属性数量和名称; |
| 192 | + |
| 193 | +3)修改训练配置,例如``PaddleClas/blob/develop/ppcls/configs/PULC/vehicle_attribute/PPLCNet_x1_0.yaml``文件中的属性数量,详细见上述`修改配置开始训练`部分。 |
| 194 | + |
| 195 | +增加属性示例: |
| 196 | + |
| 197 | +1. 在标注数据时在19位后继续增加新的属性标注数值; |
| 198 | +2. 在train.txt文件的标注数值中也增加新的属性数值。 |
| 199 | +3. 注意属性类型在train.txt中属性数值列表中的位置的对应关系需要固定。 |
| 200 | + |
| 201 | +<div width="500" align="center"> |
| 202 | + <img src="../../images/add_attribute.png"/> |
| 203 | +</div> |
| 204 | + |
| 205 | +删减属性同理。 |
| 206 | + |
| 207 | + |
| 208 | +## 修改后处理代码 |
| 209 | + |
| 210 | +修改了属性定义后,pipeline后处理部分也需要做相应修改,主要影响结果可视化时的显示结果。 |
| 211 | + |
| 212 | +相应代码在[文件](https://github.com/PaddlePaddle/PaddleDetection/blob/develop/deploy/pipeline/ppvehicle/vehicle_attr.py#L108)中`postprocess`函数。 |
| 213 | + |
| 214 | +其函数实现说明如下: |
| 215 | + |
| 216 | +```python |
| 217 | + # 在类的初始化函数中,定义了颜色/车型的名称 |
| 218 | + self.color_list = [ |
| 219 | + "yellow", "orange", "green", "gray", "red", "blue", "white", |
| 220 | + "golden", "brown", "black" |
| 221 | + ] |
| 222 | + self.type_list = [ |
| 223 | + "sedan", "suv", "van", "hatchback", "mpv", "pickup", "bus", "truck", |
| 224 | + "estate" |
| 225 | + ] |
| 226 | + |
| 227 | + ... |
| 228 | + |
| 229 | + def postprocess(self, inputs, result): |
| 230 | + # postprocess output of predictor |
| 231 | + im_results = result['output'] |
| 232 | + batch_res = [] |
| 233 | + for res in im_results: |
| 234 | + res = res.tolist() |
| 235 | + attr_res = [] |
| 236 | + color_res_str = "Color: " |
| 237 | + type_res_str = "Type: " |
| 238 | + color_idx = np.argmax(res[:10]) # 前10项表示各项颜色得分,取得分最大项作为颜色结果 |
| 239 | + type_idx = np.argmax(res[10:]) # 后9项表示各项车型得分,取得分最大项作为车型结果 |
| 240 | + |
| 241 | + # 颜色和车型的得分都需要超过对应阈值,否则视为'UnKnown' |
| 242 | + if res[color_idx] >= self.color_threshold: |
| 243 | + color_res_str += self.color_list[color_idx] |
| 244 | + else: |
| 245 | + color_res_str += "Unknown" |
| 246 | + attr_res.append(color_res_str) |
| 247 | + |
| 248 | + if res[type_idx + 10] >= self.type_threshold: |
| 249 | + type_res_str += self.type_list[type_idx] |
| 250 | + else: |
| 251 | + type_res_str += "Unknown" |
| 252 | + attr_res.append(type_res_str) |
| 253 | + |
| 254 | + batch_res.append(attr_res) |
| 255 | + result = {'output': batch_res} |
| 256 | + return result |
| 257 | +``` |
0 commit comments