• 行人属性识别一:训练PA100k数据集


    序言

    最近在做行人属性识别相关的任务,本文用于记录训练过程,供以后复习查阅。

    目前网上可用的行人属性识别仓库还是比较多的,比如前段时间百度开源的PP-Human属性识别PULC 人体属性识别,以及京东的JDAI-CV/fast-reid都是比较优秀的工作,但是这里不打算用以上的项目,追述到源头,发现百度和京东的行人属性识别都是基于Rethinking_of_PAR该项目进行,所以我直接研究此项目即可,本文也将基于这个项目进行训练,以及后续的修改模型和训练自己的数据集。

    行人属性识别数据集最新指标 :https://paperswithcode.com/task/pedestrian-attribute-recognition/

    其他相关项目:

    一、数据集准备

    训练基于PA100k数据集,PA-100K数据集是迄今为止用于行人属性识别的最大数据集,其中包含从室外监控摄像头收集的总共100000张行人图像,每张图像都有26个常用属性。根据官方设置,整个数据集随机分为80000个训练图像、10000个验证图像和10000个测试图像。

    这里我将数据集打包放在我的百度云盘中供需要下载,链接: https://pan.baidu.com/s/1WLWCZujhENVAL0Iz0BXnQQ 密码: iulh,下载下来后解压得到图片和.mat标签文件,将release_data文件夹重命名为data,先放置一边。

    clone训练仓库下来:

    git clone https://github.com/valencebond/Rethinking_of_PAR.git
    cd Rethinking_of_PAR
    
    • 1
    • 2

    这个仓库提供了很多行人属性数据集的训练方式,各个数据集训练的精度指标如下:
    在这里插入图片描述
    这里我只针对PA100k进行训练,其他数据集准备方式大同小异,因为作者没有提供预训练好的模型(谷歌云盘失效了),所以如果你想测试的话,需要自己先跑一遍训练,训练时间并没有很长。

    因为该项目读取的是.pkl格式的标注文件,所以需要解析上面下载的.mat,并保存为.pkl文件,幸运的是作者也把准备的脚本提供了,在dataset/pedes_attr/preprocess/format_pa100k.py中,在使用format_pa100k.py脚本文件之前,需要先阅读一下dataset/pedes_attr/annotation.md,该文件的大致内容简单来说就是,需要将数据集的各个属性按照如下标准从头到脚排序一下,统一的属性顺序为:

    1. head region
    2. upper region
    3. lower region
    4. foot region
    5. accessory/bag
    6. age
    7. gender
    8. others

    对于pa100k,26个属性排序后的新顺序为:

    num_in_group = [2, 6, 6, 1, 4, 7]

    ‘Hat’,‘Glasses’, [7,8] 2
    ‘ShortSleeve’,‘LongSleeve’,‘UpperStride’,‘UpperLogo’,‘UpperPlaid’,‘UpperSplice’, [13,14,15,16,17,18] 6
    ‘LowerStripe’,‘LowerPattern’,‘LongCoat’,‘Trousers’,‘Shorts’,‘Skirt&Dress’, [19,20,21,22,23,24] 6
    ‘boots’ [25] 1
    ‘HandBag’,‘ShoulderBag’,‘Backpack’,‘HoldObjectsInFront’, [9,10,11,12] 4
    ‘AgeOver60’,‘Age18-60’,‘AgeLess18’, [1,2,3] 3
    ‘Female’ [0] 1
    ‘Front’,‘Side’,‘Back’, [4,5,6] 3

    permutation = [7,8,13,14,15,16,17,18,19,20,21,22,23,24,25,9,10,11,12,1,2,3,0,4,5,6]

    所以再去阅读format_pa100k.py文件就清晰多了,根据刚才下载的数据集路径,修改相关配置,然后运行后得到dataset_all.pkl文件,需要注意的是,如果没有将数据集存放在./data/PA100k下的话,而是存放外部文件夹的话,加载数据集时会报错,需要修改此处tools/function.py:
    在这里插入图片描述
    改成你的数据集路径,不然默认加载./data里的,看着修改就好了。

    二、开始训练

    修改configs/pedes_baseline/pa100k.yaml配置文件中的相关配置,批次大小、长宽、backbone等,修改完直接在终端中运行:

    python train.py --cfg ./configs/pedes_baseline/pa100k.yaml
    
    • 1

    出现如下界面,即训练开始:
    在这里插入图片描述
    如果觉得打印的间隔太长,可以修改文件中的打印间隔:
    在这里插入图片描述
    训练结束后模型保存在exp_result文件夹中的pa100k/img_model,只有一个模型,因为该模型的名字在训练时由时间戳确定,所以后面以更优精度保存下来的模型都会覆盖该模型,如果想修改模型保存的名字,可以修改该行代码:
    在这里插入图片描述
    保存下来的模型名字带有最优的epoch和最优精度信息,看起来更加简单明了一点。

    训练得到的最优精度为:
    在这里插入图片描述

    三、模型测试

    因为作者没有提供单独测试某张图片的代码,所以我基于infer.py文件进行修改,得到demo.py文件,用于测试单张或者文件夹内多张图片功能:

    import argparse
    import json
    import os
    os.environ['CUDA_VISIBLE_DEVICES'] = '0'
    import pickle
    
    from dataset.augmentation import get_transform
    from dataset.multi_label.coco import COCO14
    from metrics.pedestrian_metrics import get_pedestrian_metrics
    from models.model_factory import build_backbone, build_classifier
    
    import numpy as np
    import torch
    from torch.utils.data import DataLoader
    from tqdm import tqdm
    from PIL import Image
    from configs import cfg, update_config
    from dataset.pedes_attr.pedes import PedesAttr
    from metrics.ml_metrics import get_map_metrics, get_multilabel_metrics
    from models.base_block import FeatClassifier
    # from models.model_factory import model_dict, classifier_dict
    
    from tools.function import get_model_log_path, get_reload_weight
    from tools.utils import set_seed, str2bool, time_str
    from models.backbone import swin_transformer, resnet, bninception,repvgg
    
    set_seed(605)
    
    clas_name = ['Hat','Glasses','ShortSleeve','LongSleeve','UpperStride','UpperLogo','UpperPlaid','UpperSplice','LowerStripe','LowerPattern','LongCoat','Trousers','Shorts','Skirt&Dress','boots','HandBag','ShoulderBag','Backpack',,'HoldObjectsInFront','AgeOver60','Age18-60','AgeLess18','Female','Front','Side','Back']
    
    def main(cfg, args):
        exp_dir = os.path.join('exp_result', cfg.DATASET.NAME)
        model_dir, log_dir = get_model_log_path(exp_dir, cfg.NAME)
    
        train_tsfm, valid_tsfm = get_transform(cfg)
        print(valid_tsfm)
    
        backbone, c_output = build_backbone(cfg.BACKBONE.TYPE, cfg.BACKBONE.MULTISCALE)
    
    
        classifier = build_classifier(cfg.CLASSIFIER.NAME)(
            nattr=26,
            c_in=c_output,
            bn=cfg.CLASSIFIER.BN,
            pool=cfg.CLASSIFIER.POOLING,
            scale =cfg.CLASSIFIER.SCALE
        )
    
        model = FeatClassifier(backbone, classifier)
    
        if torch.cuda.is_available():
            model = torch.nn.DataParallel(model).cuda()
    
        model = get_reload_weight(model_dir, model, pth='best_11_0.8044.pth')                               # 修改此处的模型名字
        model.eval()
    
        with torch.no_grad():
            for name in os.listdir(args.test_img):
                print(name)
                img = Image.open(os.path.join(args.test_img,name))
                img = valid_tsfm(img).cuda()
                img = img.view(1, *img.size())
                valid_logits, attns = model(img)
    
                valid_probs = torch.sigmoid(valid_logits[0]).cpu().numpy()
                valid_probs = valid_probs[0]>0.5
    
                res = []
                for i,val in enumerate(valid_probs):
                    if val:
                        res.append(clas_name[i])
                    if i ==14 and val==False:
                        res.append("male")
                print(res)
                print()
    
    def argument_parser():
        parser = argparse.ArgumentParser(description="attribute recognition",
                                         formatter_class=argparse.ArgumentDefaultsHelpFormatter)
        parser.add_argument(
            "--test_img", help="test images", type=str,
            default="./test_imgs",
    
        )
        parser.add_argument(
            "--cfg", help="decide which cfg to use", type=str,
        )
        parser.add_argument("--debug", type=str2bool, default="true")
    
        args = parser.parse_args()
    
        return args
    
    if __name__ == '__main__':
        args = argument_parser()
        update_config(cfg, args)
    
        main(cfg, args)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    运行命令:python demo.py --cfg ./configs/pedes_baseline/pa100k.yaml --test_img ./test_imgs,得到类似如下结果:
    在这里插入图片描述

    我这里的结果是将列表里的英文翻译成中文显示处理,至此训练结束,下一篇将写如何修改添加新的网络进行训练。

  • 相关阅读:
    10.11作业
    kafka脚本总结
    http服务
    Spring Boot Actuator - Spring Boot 应用监控
    冷热电气多能互补的微能源网鲁棒优化调度附Matlab代码
    [计算机网络基础]数据链路层
    链接脚本(1) --- 在默认的链接脚本中插入段
    代码随想录 -- day49 -- 121. 买卖股票的最佳时机 、122.买卖股票的最佳时机II
    MySQL派生表合并优化的原理和实现
    SpringMVC 启动流程源码分析
  • 原文地址:https://blog.csdn.net/qq_39056987/article/details/126385564