Person Re-Identification(ReID行人重识别)

Person Re-Identification(ReID行人重识别)_第1张图片

ReID?
ReID是图像检索的子任务,它主要的目的是:利用计算机视觉技术对特定行人进行跨视域匹配和检索。所谓跨视域即是图片来自于不同的摄像头,这样可以用于智能视频监控(如无人超市)、刑侦(追捕嫌疑人)、交管(追踪车辆等)等等应用场景。如上图,需要检索到同一个人(查询图像query)在各个摄像头下图片集(候选行人库gallery)的相关图片。

Person Re-Identification(ReID行人重识别)_第2张图片

困难点
困难点主要在于ReID任务的跨视域特性有:

  • 摄像头分辨率不同
  • 拍摄角度不一 致
  • 光照条件不同
  • 背景变化大
  • 人体属于非刚性目标,外观会因姿态、遮挡、光照、背景、行人错位等等的干扰,如上图
  • 行人数据集采集标注困难

ReID的实现流程图
时间中需要完成包括行人检测和再识别两部分任务,即下图的person detection和后面的person reID,研究上主要侧重于识别的部分(查询图像query集和候选行人库gallery集都是经过detector裁剪好的行人框)。

识别部分分为feature extraction和similarity measurement,即特征提取和相似度度量。

  • 特征提取:学习在不同摄像头下图片中的行人特征
  • 相似度度量 :比较特征以排序检索
    Person Re-Identification(ReID行人重识别)_第3张图片

依据流程,数据集实际分为了训练集、验证集、Query、Gallery四个部分。即在训练集上进行模型的训练,得到模型后对Query与Gallery中的图片提取特征计算相似度,对于每个Query在Gallery中找出前N个与其相似的图片。

├── Market/
│   ├── bounding_box_test/          /* Files for testing (candidate images pool)19732张
│   ├── bounding_box_train/         /* Files for training,12936张
│   ├── gt_bbox/                    /* Files for multiple query testing,3368张,对应query,在评估时使用
│   ├── gt_query/                   /* We do not use it 
│   ├── query/                      /* Files for testing (query images)3368张查询,会到test中寻找

数据集实例如上,值得注意的是训练集的人和测试集的人没有重复的。比如market里面有751名个人用于训练,另外有750个人用于测试。

如果Gallery中没有Query怎么办?
这种情况实际中很可能会存在,但或许ReID的目的不是为了精确的找到Query,而是返回一个候选列表帮助人工筛选,这样不存在也可能很快发现。

single shot 和muti shot
single shot是指gallery中每个人的图像为一张(N=1),而muti shot是指gallery中每个人的图像为N>1张图像,同样的Rank-1下,一般N越大,得到的识别率越高。

query = qf.view(-1,1)
# print(query.shape)
score = torch.mm(gf,query) # Cosine Distance
score = score.squeeze(1).cpu()
score = score.numpy()
# predict index
index = np.argsort(score)  #from small to large
index = index[::-1]

主要流行的解决方法
主要有三种,基于表征,加入局部信息,引入生成对抗。

  • 基于预测。即两张图片输入网络,预测其“相同”或者“不同”。
  • 基于分类。即一张图片输入网络,分类映射其该图片的任务ID。
  • 基于三元组。即给出正例负例图片对,重点拉开不同类图片之间的差距。
  • 基于局部身体部件。提取局部特征增大信息量,还可以解决部分遮挡问题。
  • 基于水平分块。分块后可以对齐局部以减缓分辨率问题和局部的不稳定。
  • 基于注意力机制。这种方法是加强局部信息的终极版,自行关注重要区域,还可以引导学习区域性信息。
  • 基于行人姿态生成。输入图片得到行人姿态,引入姿态信息加强。
  • 基于图像风格转换。主要解决各个场景的风格不一致问题,使用GAN来跨域迁移风格生成,用于数据增广是很好的。

来自中文综述论文

卢健,陈旭,罗毛欣,王航英. 深度学习行人再识别研究综述. 

实际上应该还有很多其他的方法,比如人体属性,骨架Graph等等,还有涉及无监督和跨模态的任务等等。

当前一些sota方法的实现与表现
多蹲蹲顶会和开源就好…

  • 可能是目前最强的开源code:https://github.com/layumi/Person_reID_baseline_pytorch/tree/master/leaderboard
  • 还有一个视频:https://www.bilibili.com/video/BV1Mx411871F
  • 超全随笔:https://www.cnblogs.com/orangecyh/category/1570883.html
  • 知乎讨论:https://www.zhihu.com/question/46943328
  • 论文泛读:https://blog.csdn.net/u013982164/article/details/79608100
  • https://blog.csdn.net/weixin_41427758/article/details/81187997

简单注释一下基模型的代码:

class ClassBlock(nn.Module):
    def __init__(self, input_dim, class_num, droprate, relu=False, bnorm=True, num_bottleneck=512, linear=True, return_f = False):
        super(ClassBlock, self).__init__()
        self.return_f = return_f
        add_block = [] #图像特征抽象
        if linear: #多个mlp
            add_block += [nn.Linear(input_dim, num_bottleneck)]
        else:
            num_bottleneck = input_dim
        if bnorm: #bn层
            add_block += [nn.BatchNorm1d(num_bottleneck)]
        if relu: #激活函数
            add_block += [nn.LeakyReLU(0.1)]
        if droprate>0: #dropout
            add_block += [nn.Dropout(p=droprate)]
        add_block = nn.Sequential(*add_block) #把多个mlp串起来
        add_block.apply(weights_init_kaiming) #然后应用kaiming初始化

        classifier = [] #分类器网络
        classifier += [nn.Linear(num_bottleneck, class_num)] #也是mlp得到分类ID数目
        classifier = nn.Sequential(*classifier)
        classifier.apply(weights_init_classifier)

        self.add_block = add_block #特征抽取
        self.classifier = classifier #映射到ID
    def forward(self, x):
        x = self.add_block(x) #先得到特征
        if self.return_f: #再分类
            f = x
            x = self.classifier(x)
            return x,f
        else:
            x = self.classifier(x)
            return x

这个基方案可以搭得更深就是了如 AlexNet, VGG16, ResNet and DenseNet等等,还想注释一下PCB。
Person Re-Identification(ReID行人重识别)_第4张图片
PCB(Part-Based Convolutional Baseline)将行人图片均匀划分为6个部件并提取特征,用6个分类的损失函数进行模型训练。这么做的意义是能够基于行人结构分割的先验知识驱使,比如part1就是行人的头部。

class PCB(nn.Module):
    def __init__(self, class_num ):
        super(PCB, self).__init__()

        self.part = 6 # 切成6份
        model_ft = models.resnet50(pretrained=True)#用resnet50提特征
        self.model = model_ft
        self.avgpool = nn.AdaptiveAvgPool2d((self.part,1))
        self.dropout = nn.Dropout(p=0.5)
        # remove the final downsample
        self.model.layer4[0].downsample[0].stride = (1,1)
        self.model.layer4[0].conv2.stride = (1,1)
        # 定义6分类
        for i in range(self.part):
            name = 'classifier'+str(i)
            setattr(self, name, ClassBlock(2048, class_num, droprate=0.5, relu=False, bnorm=True, num_bottleneck=256))

    def forward(self, x): #逐层前向就行
        x = self.model.conv1(x)
        x = self.model.bn1(x)
        x = self.model.relu(x)
        x = self.model.maxpool(x)
        
        x = self.model.layer1(x)
        x = self.model.layer2(x)
        x = self.model.layer3(x)
        x = self.model.layer4(x)
        x = self.avgpool(x)
        x = self.dropout(x)
        part = {
     }
        predict = {
     }
        # 6个部分的特征 batchsize*2048*6
        for i in range(self.part):
            part[i] = torch.squeeze(x[:,:,i])
            name = 'classifier'+str(i)
            c = getattr(self,name)
            predict[i] = c(part[i])

        # sum prediction
        #y = predict[0]
        #for i in range(self.part-1):
        #    y += predict[i+1]
        y = []
        for i in range(self.part):
            y.append(predict[i])
        return y

当然还有一些更复杂的模型咯,更多的论文都可以参考上面的那个开源。

数据集
现有的数据集都不是很大,ID和摄像头都不是很多。
Person Re-Identification(ReID行人重识别)_第5张图片

评价指标
一般使用rank-n,即搜索结果中最靠前(置信度分数最高)的n张图有正确结果的概率。
例如: lable ID为行人0001,在100个样本中搜索。

  • 如果识别结果是0001、0051、0013、0004、0015……,则此时rank-1的正确率为100%;rank-2的正确率也为100%;rank-5的正确率也为100%;
  • 如果识别结果是0051、0001、0013、0004、0015……,则此时rank-1的正确率为0%;rank-2的正确率为100%;rank-5的正确率也为100%;

Person Re-Identification(ReID行人重识别)_第6张图片

怎么真实应用?
真实场景中的情况,和公共数据集的数据是不一样的,往往是需要从原视频/图像的一整张大图中,先做检测找出小人,然后才在所建立的gallery里面进行查询和检索的。

你可能感兴趣的:(深度学习,ReID,行人重识别,person,re-id,PCB)