Video_based_ReID_01

ビデオベースの歩行者の再識別-01

1.火星のデータセットを知る

ビデオ歩行者の再認識に関する研究は、基本的に火星のデータセットをバイパスすることはできません。ビデオ歩行者の再認識のためのより認識されたデータセットとして、各トップ号の優れた論文は火星のデータセットのランクを向上させています。

それで、最初に、このデータセットを知ってみましょう:
データセットアドレス
情報ファイル

上記のリンクのコンテンツをダウンロードし、解凍して次の方法で保存します。
ここに画像の説明を挿入次に、これらのフォルダーのコンテンツについて説明します。

1.1 bbox_train

bbox_trainフォルダーには、625個のサブフォルダー(625個の歩行者IDを表す)があり、合計8,298個のトラックレットと合計509,914個の画像が含まれています。
ここに画像の説明を挿入注:ここでのフォルダーの名前は連続していません!

任意のフォルダを開いて、これらの内容を確認してください:(ファイル名の後に説明されています)
ここに画像の説明を挿入

1.2 bbox_test

bbox_testフォルダーには合計636個のサブフォルダー(636個の歩行者IDを表す)、合計12,180個のトラックレット(トラックレット)、合計681,089枚の画像があります。実験では、このフォルダはギャラリー+クエリに分割されました。これについては、infoフォルダで説明します。
ここに画像の説明を挿入それらは連続的ではないことに注意してください!

00-1という名前のサブフォルダーは、役に立たない画像コレクションを表し、対応する歩行者IDは**-1 **に設定され、pid = -1の画像は通常アルゴリズムで無視されます。
ここに画像の説明を挿入

名前0000サブフォルダーでは、対応する歩行者IDが0に設定されています。これは、干渉要因を示し、検索の精度に悪影響を及ぼします。
ここに画像の説明を挿入

1.3情報

infoフォルダーには、データセットの使用を容易にするために、データセット全体の情報を含む5つのサブファイルが含まれています。ここに画像の説明を挿入

1.3.1 train_name.txt

このtxtファイルには、bbox_trainフォルダー内のすべての画像の名前が、合計509,914行(509914画像に対応)で順番に保存されます。
ここに画像の説明を挿入画像名の説明:
例として0001 C1 T0001F0001.jpg。
0001 bbox_trainフォルダに対応する0001サブフォルダ名であり、歩行者のIDを表し
、C1は、この画像が第1のカメラ(6台のカメラの合計)の下で撮影されたことを示す、カメラのIDを表し、
T0001がに関して前記しましたこの歩行者用ビデオセグメントの最初の
短いビデオ(トラックレット)。F0001は、この画像がこの短いビデオ(トラックレット)の最初のフレームであることを示します。各短いビデオ(トラックレット)では、フレーム数はF0001から始まります。

1.3.2 test_name.txt

同様に、このtxtファイルには、bbox_testフォルダー内のすべての画像の名前が順番に格納され、合計681,089行になります。

1.3.3tracks_train_info.mat

.mat形式のファイルは、matlabによって保存されたファイルです。matlabで開くと、8298 * 4マトリックスであることがわかります。
マトリックスの各行はトラックレットを表し、
1列目と2列目は画像のシーケンス番号(開始、終了)を表し、train_name.txtファイルの行番号に対応します
。3列目は歩行者ID用です。bbox_trainフォルダー内の対応するサブフォルダーの名前。4
番目の列は対応するカメラID(合計6台のカメラ)です。
ここに画像の説明を挿入ここに画像の説明を挿入2枚の写真の比較に注意してください〜

1.3.4tracks_train_info.mat

このファイルをmatlabで開くと、12180 * 4の行列であることがわかります。
マトリックスの各行はトラックレットを表し、
1列目と2列目は、test_name.txtファイルの行番号に対応する画像のシリアル番号を表します
。3列目は、bbox_testにある歩行者のIDです。folder対応するサブフォルダーの名前。4
番目の列は対応するカメラID(合計6台のカメラ)です。
上記と同様〜

1.3.5 query_IDX.mat

このファイルをmatlabで開くと、1 * 1980マトリックス(1980クエリIDを選択)であり、各列が上記のtracks_test_info.matファイルの最初の数行に対応していることがわかります
たとえば、1978列の値は12177で、これはtracks_test_info.matファイルの行12177に対応します(1行は1トラックに対応します)。
12177行目では、そのid = 1496(歩行者ID)を確認できます。同じid = 1496の線にも12166、12167などがあることを見つけるのは難しくありません(歩行者は複数の軌道に対応します)。
実際、これは、1496という名前のサブフォルダー(歩行者IDは1496)に、複数の短いビデオ(トラックレット)があることを意味します。
すべてのクエリがIDを設定しているわけではなく、ギャラリーには同じIDの歩行者に対応する行があることに注意してください。1980年のクエリIDのうち、有効なIDの数(ギャラリーには同じIDの行があります)= 1840。
つまり、一部のフォルダーには1つのトラックレットしかありません。

ここに画像の説明を挿入

1.4まとめ

一般に:

  • 1つのトレーニングセットは複数の歩行者IDに対応し、1つのIDは複数のトラックに対応し、1つのトラックは複数の写真に対応します。
  • トレーニングセットとテストレベルに重複する歩行者IDはありません
  • テストセットの選択された部分がクエリとして使用されます

2.火星データセット管理data_manager

以前に歩行者の再認識を導入するときに、この部分も含まれています。目的は、ハードディスク内の火星データセットをデータセットにカプセル化することです。

ほとんどの方法は同じですが、コードを直接貼り付けるだけです。

# 导入相关包
from __future__ import print_function, absolute_import
import os
import glob
import re
import sys
import urllib
import tarfile
import zipfile
import os.path as osp
from scipy.io import loadmat
import numpy as np
import random

from utils.util import mkdir_if_missing, write_json, read_json

"""Dataset classes"""

# 定义类方法 
class Mars(object):
    """
    MARS

    Reference:
    Zheng et al. MARS: A Video Benchmark for Large-Scale Person Re-identification. ECCV 2016.
    
    Dataset statistics:
    # identities: 1261
    # tracklets: 8298 (train) + 1980 (query) + 9330 (gallery)
    # cameras: 6

    Args:
        min_seq_len (int): tracklet with length shorter than this value will be discarded (default: 0).
    """
    # 设置mars路径 这个要根据自己文件夹中存放数据集的位置
    root = '/home/user/桌面/code/data/mars'
    # 读取对应文件夹路径
    train_name_path = osp.join(root, 'info/train_name.txt')
    test_name_path = osp.join(root, 'info/test_name.txt')
    track_train_info_path = osp.join(root, 'info/tracks_train_info.mat')
    track_test_info_path = osp.join(root, 'info/tracks_test_info.mat')
    query_IDX_path = osp.join(root, 'info/query_IDX.mat')
	
	# 初始化类方法
    def __init__(self, min_seq_len=0):
    	# 1 提高工程性 确保文件都存在 
        self._check_before_run()

        # 2 prepare meta data
        # 获得所有的训练集图片名字,放在train_names列表中;
        # 获取所有测试集图片名字,放在test_names 列表中。
        train_names = self._get_names(self.train_name_path)
        test_names = self._get_names(self.test_name_path)
        # 使用loadmat()函数读取.mat文件,它读取出来的data是字典格式的,通过['track_train_info']这个key,找到对应的value。获得的是一个数组格式数据。
        track_train = loadmat(self.track_train_info_path)['track_train_info'] # numpy.ndarray (8298, 4) 8298tracks  4:start、end、id、cid
        track_test = loadmat(self.track_test_info_path)['track_test_info'] # numpy.ndarray (12180, 4) 12180tracks  4:start、end、id、cid
        query_IDX = loadmat(self.query_IDX_path)['query_IDX'].squeeze() # numpy.ndarray (1980,) 
        # 查询集的行号减一,跟track_test中的行号索引保持一致。
        query_IDX -= 1 # index from 0
        # 根据 query_IDX行号索引,找到track_test中对应行的数据  numpy.ndarray (1980, 4)
        track_query = track_test[query_IDX,:]
        # 图库集的行号 = 原始的track_test行号 - query_IDX中包含的行号
        gallery_IDX = [i for i in range(track_test.shape[0]) if i not in query_IDX]
        # 根据图库集行号,在track_test中找到对应行的数据,numpy.ndarray (1980, 4)
        track_gallery = track_test[gallery_IDX,:]
		# 3 数据处理
        train, num_train_tracklets, num_train_pids, num_train_imgs = \
          self._process_data(train_names, track_train, home_dir='bbox_train', relabel=True, min_seq_len=min_seq_len)

        query, num_query_tracklets, num_query_pids, num_query_imgs = \
          self._process_data(test_names, track_query, home_dir='bbox_test', relabel=False, min_seq_len=min_seq_len)

        gallery, num_gallery_tracklets, num_gallery_pids, num_gallery_imgs = \
          self._process_data(test_names, track_gallery, home_dir='bbox_test', relabel=False, min_seq_len=min_seq_len)
		
        num_imgs_per_tracklet = num_train_imgs + num_query_imgs + num_gallery_imgs
        min_num = np.min(num_imgs_per_tracklet)
        max_num = np.max(num_imgs_per_tracklet)
        avg_num = np.mean(num_imgs_per_tracklet)

        num_total_pids = num_train_pids + num_query_pids
        num_total_tracklets = num_train_tracklets + num_query_tracklets + num_gallery_tracklets

        print("=> MARS loaded")
        print("Dataset statistics:")
        print("  ------------------------------")
        print("  subset   | # ids | # tracklets")
        print("  ------------------------------")
        print("  train    | {:5d} | {:8d}".format(num_train_pids, num_train_tracklets))
        print("  query    | {:5d} | {:8d}".format(num_query_pids, num_query_tracklets))
        print("  gallery  | {:5d} | {:8d}".format(num_gallery_pids, num_gallery_tracklets))
        print("  ------------------------------")
        print("  total    | {:5d} | {:8d}".format(num_total_pids, num_total_tracklets))
        print("  number of images per tracklet: {} ~ {}, average {:.1f}".format(min_num, max_num, avg_num))
        print("  ------------------------------")

        self.train = train
        self.query = query
        self.gallery = gallery

        self.num_train_pids = num_train_pids
        self.num_query_pids = num_query_pids
        self.num_gallery_pids = num_gallery_pids
        
	# 检验文件是否存在
    def _check_before_run(self):
        """Check if all files are available before going deeper"""
        if not osp.exists(self.root):
            raise RuntimeError("'{}' is not available".format(self.root))
        if not osp.exists(self.train_name_path):
            raise RuntimeError("'{}' is not available".format(self.train_name_path))
        if not osp.exists(self.test_name_path):
            raise RuntimeError("'{}' is not available".format(self.test_name_path))
        if not osp.exists(self.track_train_info_path):
            raise RuntimeError("'{}' is not available".format(self.track_train_info_path))
        if not osp.exists(self.track_test_info_path):
            raise RuntimeError("'{}' is not available".format(self.track_test_info_path))
        if not osp.exists(self.query_IDX_path):
            raise RuntimeError("'{}' is not available".format(self.query_IDX_path))

	# 获取txt文件中的字符串(图片名字),放在names列表中。
    def _get_names(self, fpath):
        names = []
        with open(fpath, 'r') as f:
            for line in f:
                new_line = line.rstrip()
                names.append(new_line)
        return names
        
	# 对获得的数据按照规则进行截断 获得tracklets, num_tracklets, num_pids, num_imgs_per_tracklet
    def _process_data(self, names, meta_data, home_dir=None, relabel=False, min_seq_len=0):
        assert home_dir in ['bbox_train', 'bbox_test']
        num_tracklets = meta_data.shape[0]
        pid_list = list(set(meta_data[:,2].tolist()))
        num_pids = len(pid_list)

        if relabel: pid2label = {
    
    pid:label for label, pid in enumerate(pid_list)}
        tracklets = []
        num_imgs_per_tracklet = []

        #txt_name = self.root + home_dir + str(len(meta_data)) + '.txt'
        #fid = open(txt_name, "w")

        for tracklet_idx in range(num_tracklets):
            data = meta_data[tracklet_idx,...]
            start_index, end_index, pid, camid = data
            if pid == -1: continue # junk images are just ignored
            assert 1 <= camid <= 6
            if relabel: pid = pid2label[pid]
            camid -= 1 # index starts from 0
            img_names = names[start_index-1:end_index]

            # make sure image names correspond to the same person
            pnames = [img_name[:4] for img_name in img_names]
            assert len(set(pnames)) == 1, "Error: a single tracklet contains different person images"

            # make sure all images are captured under the same camera
            camnames = [img_name[5] for img_name in img_names]
            assert len(set(camnames)) == 1, "Error: images are captured under different cameras!"

            # append image names with directory information
            img_paths = [osp.join(self.root, home_dir, img_name[:4], img_name) for img_name in img_names]
            if len(img_paths) >= min_seq_len:
                img_paths = tuple(img_paths)
                tracklets.append((img_paths, pid, camid))
                num_imgs_per_tracklet.append(len(img_paths))
                #fid.write(img_names[0] + '\n')
 
        #fid.close()
        num_tracklets = len(tracklets)

        return tracklets, num_tracklets, num_pids, num_imgs_per_tracklet

"""Create dataset"""

__factory = {
    
    
    'mars': Mars,
    'ilidsvid': iLIDSVID,
    'prid': PRID,
}

def get_names():
    return __factory.keys()

def init_dataset(name, *args, **kwargs):
    if name not in __factory.keys():
        raise KeyError("Unknown dataset: {}".format(name))
    return __factory[name](*args, **kwargs)

# test
if __name__ == '__main__':

    init_dataset(name="mars")
    #dataset = Market1501()
    #dataset = Mars()



結果:
ここに画像の説明を挿入説明:

  • トレーニングセット:
    • ID 625、合計8298の軌道
  • テストセット:
    • クエリ626idは1980トラックを選択しました(すべてが有効というわけではなく、歩行者は1つのトラックしか持っていない可能性があります)
    • ギャラリー622ID、残りの9330の軌跡

合計1251人の歩行者ID、train + query、8298 + 1980 + 9330 = 19608の軌跡

おすすめ

転載: blog.csdn.net/qq_37747189/article/details/115263678