基于视频的行人重识别结果可视化

Posted 花椒蛋糕

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于视频的行人重识别结果可视化相关的知识,希望对你有一定的参考价值。

基于视频的行人重识别结果可视化

基于视频的行人重识别结果可视化

在网上搜集了很多帖子,想要白嫖可视化代码。但是发现并没有人分享,是视频重识别太小众了还单帧重识别太受宠了!!!!
为此在郑哲东的基础上改出了基于视频的行人重识别结果可视化。
郑哲东大佬的代码先放在这里:https://github.com/layumi/Person_reID_baseline_pytorch
单帧可视化的代码就是里面的demo.py
言归正传,开始向视频方向延申。

数据集读取

我们这里用的是Mars数据集,就不再赘述了,想要了解详情的去看余慈reid大佬的帖子:基于视频的行人再识别(2):数据集管理data_manager

标准的loader流程

#######################################################################
# dataleader
def data_loader():
    dataset = data_manager.init_dataset(name=args.dataset)
    
    transform_test = T.Compose([
        T.Resize((args.height, args.width)),
        T.ToTensor(),
        T.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
    ])

    pin_memory = True if use_gpu else False
    
    queryloader = DataLoader(
        VideoDataset(dataset.query, seq_len=args.seq_len, sample='dense', transform=transform_test),
        batch_size=args.test_batch, shuffle=False, num_workers=args.workers,
        pin_memory=pin_memory, drop_last=False,
    )

    galleryloader = DataLoader(
        VideoDataset(dataset.gallery, seq_len=args.seq_len, sample='dense', transform=transform_test),
        batch_size=args.test_batch, shuffle=False, num_workers=args.workers,
        pin_memory=pin_memory, drop_last=False,
    )
    return dataset, trainloader, queryloader, galleryloader
#######################################################################

test结果保存

苦于测试耗时太长,因此将测试的结果保存,用于后续Rank可视化。保存cam是为了对齐,然而在实际操作中发现是多余的,可以省略,当然label还是要存的。

torch.save(qf, 'query_feature.pt')
torch.save(gf, 'gallery_feature.pt')
io.savemat('save_result.mat', 'query_cam':q_camids,
                               'query_label':q_pids,
                               'gallery_cam':g_camids,
                               'gallery_label':g_pids,
                              )

结果读取

接下来当然是读取了。

image_datasets = data_loader()[0]
# print(image_datasets)

result = scipy.io.loadmat('save_result.mat')
query_feature = torch.load('query_feature.pt')
gallery_feature = torch.load('gallery_feature.pt')

query_cam = result['query_cam'][0]
query_label = result['query_label'][0]
gallery_cam = result['gallery_cam'][0]
gallery_label = result['gallery_label'][0]

query_feature = query_feature.cuda()
gallery_feature = gallery_feature.cuda()

gallery排序

因为都是按照label做的排序,所以这里还是沿用的郑大佬的方法,没有做修改,具体流程就是在排除掉相同ID和相同cam的情况下,按照CMC曲线做降序排序,返回的index就是Rank排序的list。

#######################################################################
# sort the images
def sort_img(qf, ql, qc, gf, gl, gc):
    query = qf.view(-1, 1)
    # print(query.shape)
    score = torch.mm(gf, query)
    score = score.squeeze(1).cpu()
    score = score.numpy()
    # predict index
    index = np.argsort(score)  # from small to large
    index = index[::-1]
    query_index = np.argwhere(gl == ql)
    # same camera
    camera_index = np.argwhere(gc == qc)
    
    junk_index1 = np.argwhere(gl == -1)
    junk_index2 = np.intersect1d(query_index, camera_index)
    junk_index = np.append(junk_index2, junk_index1)

    mask = np.in1d(index, junk_index, invert=True)
    index = index[mask]
    return index
#######################################################################

然后丢一个id进行排序就可以了,说白了就是在gallery里找与query_indel相似度最高的排序。

i = opts.query_index
index = sort_img(query_feature[i], query_label[i], query_cam[i], gallery_feature, gallery_label, gallery_cam)

结果可视化

这里做6帧的Rank-4可视化,当然想做的其他的可以自行修改,为了美观嘛,做成两排的,每排3帧

########################################################################
# Visualize the rank result
img_paths, pid, camid = image_datasets.query[i]
query_label = query_label[i]
try:  # Visualize Ranking Result
    # Graphical User Interface is needed
    fig = plt.figure(figsize=(16, 4))
    for i in range(2):
        for j in range(3):
            ax = plt.subplot(2, 15, (1 if i == 0 else 16) + j)
            ax.axis('off')
            imshow(img_paths[(0 if i == 0 else 2) + j], 'query')
    
    for i in range(4):	# 要做其他Rank排序,将range(4)改成想要的list就行
        for j in range(2):
            for k in range(3):
                ax = plt.subplot(2, 15, (1 if j == 0 else 16) + i * 3 + k + 3)
                ax.axis('off')
                img_path, pid, camid = image_datasets.gallery[index[i]]
                label = gallery_label[index[i]]
                imshow(img_path[(0 if j == 0 else 2) + k])
                if label == query_label:
                    ax.set_title('%d' % (i + 1), color='green')
                else:
                    ax.set_title('%d' % (i + 1), color='red')

结果

能达到效果就行了,要什么自行车,样式就懒得改了,想找个有错误检索的还挺不容易,哈哈。

结束语

基于视频的行人重识别结果可视化就介绍到这里。
若有问题,欢迎大家和我交流。

行人重识别计算机视觉进阶系列 第一课 基础知识

【行人重识别】🖐计算机视觉进阶系列🖐 第一课 基础知识

概述

行人重识别 (Person Re-Identification) 是利用计算机视觉技术判断图片或视频中是否存在特定行人的技术. 行人重识别技术可以帮助我们在多摄像头的复杂场景中快速定位查找到指定目标的所有结果. 行人重识别技术在智能安防, 监控等领域有者巨大的前景. 今天小白就带大家来一起学习一下行人重识别的技术.

行人重识别

行人重识别 (Person Re-Identification) 是利用计算机视觉技术判断图片或视频中是否存在特定行人的技术.


行人重识别面临的挑战:

  1. 图像分辨率低
  2. 遮挡
  3. 视角, 姿势变化
  4. 光照变化
  5. 视觉模糊性

rank-1

rank-1 即预测最高概率的标签与真实标签占比的百分比, 即第一张返回的图像正确的百分比. 例如, 模型识别了 100 只猪, 但实际上, 里面 90 只是猪, 10 只是大象. rank-1 的值就为 90/100 = 90%.

mAP

mAP (Mean Average Precision) 即 AP 的平均值.

ap 的计算过程:

  • 找到第一张返回图片正确的位置, 取得 P r e c i s i o n 1 = i n d e x p 1 i n d e x t o t a l Precision_1 = \\frac index_p1 index_total Precision1=indextotalindexp1
  • 找到第二章返回图片正确的位置, 取得 P r e c i s i o n 2 = i n d e x p 2 i n d e x t o t a l Precision_2 = \\frac index_p2 index_total Precision2=indextotalindexp2
  • 重复以上步骤, 取得 A P = P r e c i s i o n 1 + P r e c i s i o n 2 + . . . + P r e c i s i o n n n AP = \\frac Precision_1 + Precision_2 + ... + Precision_n n AP=nPrecision1+Precision2+...+Precisionn

损失函数

行人重识别通常使用的函数为分类损失 + Triplet Loss, 增加 Triplet 可以使得特征提取的更好. 下面我们就分别来讲解一下.

交叉熵

交叉熵 (Cross Entropy) 是分类任务最常用的一种损失, 可以帮助我们求得目标与预测值之间的差距. 关于交叉熵的具体推导流程请大家自行百度, 在这里就不过多赘述.

Triplet Loss

Triplet Loss 是深度学习的一种损失函数, 主要用于训练差异性小的样本.

Triplet Loss 由三个部分组成, 分别为:

  1. 锚 (Anchor): 当前数据
  2. 正示例 (Positive): 和锚为同一人的数据
  3. 负示例 (Negative): 和锚为不同人的数据

Triplet Loss 计算流程:

  1. 分别对三份数据进行编码
  2. 分别将三份数据经过相同的网络
  3. 计算三份数据之间的差异
  4. 通过差值来更新权重参数

Triplet Loss 训练的目标是拉近锚 (Anchor) 与正示例 (Positive) 的距离, 拉远锚 (Anchor) 与负示例 (Negative) 的距离.

Triplet Loss 公式:

∣ ∣ f ( A ) − f ( P ) ∣ ∣ 2 − ∣ ∣ f ( A ) − f ( N ) ∣ ∣ 2 + a ≤ 0 || f(A) - f(P)||^2 - || f(A) - f(N)||^2 + a \\le 0 f(A)f(P)2f(A)f(N)2+a0

我们可以看到
公式中存在一个 a a a, 也被称作间隔 (Margin), 表示 d(A, P) 与 d(A, N) 至少相差多少, 从而避免模型走捷径将正示例和负示例的距离训练的相等.

Hard Negative

Hard Negative 即难以正确分类的样本. 在行人重识别中, 我们会尽量挑选和正示例相近的负示例 d(A, P) ≈ \\approx d(A, N), 从而使模型多进行训练以达到更好的效果.

以上是关于基于视频的行人重识别结果可视化的主要内容,如果未能解决你的问题,请参考以下文章

行人重识别在深度上有啥问题可以提

目标跟踪检测算法(四)——多目标扩展

跨膜态行人重识别 综述,查阅许多资料,详细解释,适合以前没有基础的同学学习。

基于深度学习的口罩检测系统(Python+清新界面+数据集)

行人车辆检测与计数系统(Python+YOLOv5深度学习模型+清新界面)

打电话,玩手机摔倒行人行为识别