21def eval_cuhk03(distmat, q_feats, g_feats, q_pids, g_pids, q_camids, g_camids, max_rank, use_distmat):
22 """Evaluation with cuhk03 metric
23 Key: one image for each gallery identity is randomly sampled for each query identity.
24 Random sampling is performed num_repeats times.
28 num_q, num_g = distmat.shape
29 dim = q_feats.shape[1]
31 index = faiss.IndexFlatL2(dim)
34 indices = np.argsort(distmat, axis=1)
36 _, indices = index.search(q_feats, k=num_g)
41 'Note: number of gallery samples is quite small, got {}'.
45 matches = (g_pids[indices] == q_pids[:, np.newaxis]).astype(np.int32)
52 for q_idx
in range(num_q):
55 q_camid = q_camids[q_idx]
58 order = indices[q_idx]
59 remove = (g_pids[order] == q_pid) & (g_camids[order] == q_camid)
60 keep = np.invert(remove)
63 raw_cmc = matches[q_idx][
65 if not np.any(raw_cmc):
69 kept_g_pids = g_pids[order][keep]
70 g_pids_dict = defaultdict(list)
71 for idx, pid
in enumerate(kept_g_pids):
72 g_pids_dict[pid].append(idx)
75 for repeat_idx
in range(num_repeats):
76 mask = np.zeros(len(raw_cmc), dtype=np.bool)
77 for _, idxs
in g_pids_dict.items():
79 rnd_idx = np.random.choice(idxs)
81 masked_raw_cmc = raw_cmc[mask]
82 _cmc = masked_raw_cmc.cumsum()
84 cmc += _cmc[:max_rank].astype(np.float32)
89 num_rel = raw_cmc.sum()
90 tmp_cmc = raw_cmc.cumsum()
91 tmp_cmc = [x / (i + 1.)
for i, x
in enumerate(tmp_cmc)]
92 tmp_cmc = np.asarray(tmp_cmc) * raw_cmc
93 AP = tmp_cmc.sum() / num_rel
97 assert num_valid_q > 0,
'Error: all query identities do not appear in gallery'
99 all_cmc = np.asarray(all_cmc).astype(np.float32)
100 all_cmc = all_cmc.sum(0) / num_valid_q
101 mAP = np.mean(all_AP)
106def eval_market1501(distmat, q_feats, g_feats, q_pids, g_pids, q_camids, g_camids, max_rank, use_distmat):
107 """Evaluation with market1501 metric
108 Key: for each query identity, its gallery images from the same camera view are discarded.
110 num_q, num_g = distmat.shape
111 dim = q_feats.shape[1]
114 q_feats = q_feats.detach().numpy()
115 g_feats = g_feats.detach().numpy()
118 index = faiss.IndexFlatL2(dim)
121 print(f
'\nnum_q = {num_q}')
122 print(f
'num_g = {num_g}')
123 print(f
'dim = {dim}')
124 print(f
'index = {index}')
125 print(f
'max_rank = {max_rank}')
126 print(f
'q_camids = {q_camids}')
127 print(f
'g_camids = {g_camids}')
132 print(
'Note: number of gallery samples is quite small, got {}'.format(num_g))
135 indices = np.argsort(distmat, axis=1)
137 _, indices = index.search(q_feats, k=num_g)
139 matches = (g_pids[indices] == q_pids[:, np.newaxis]).astype(np.int32)
141 print(f
'matches = {matches}')
149 for q_idx
in range(num_q):
151 q_pid = q_pids[q_idx]
152 q_camid = q_camids[q_idx]
155 order = indices[q_idx]
156 remove = (g_pids[order] == q_pid) & (g_camids[order] == q_camid)
157 keep = np.invert(remove)
158 print(f
'order = {order}')
159 print(f
'remove = {remove}')
160 print(f
'keep = {keep}')
161 print(f
'matches = {matches}')
162 print(f
'matches.shape = {matches.shape}')
165 np.place(keep, keep ==
False,
True)
169 raw_cmc = matches[q_idx][keep]
170 print(f
'raw_cmc = {raw_cmc}')
171 if not np.any(raw_cmc):
175 cmc = raw_cmc.cumsum()
177 pos_idx = np.where(raw_cmc == 1)
178 max_pos_idx = np.max(pos_idx)
179 inp = cmc[max_pos_idx] / (max_pos_idx + 1.0)
184 all_cmc.append(cmc[:max_rank])
189 num_rel = raw_cmc.sum()
190 tmp_cmc = raw_cmc.cumsum()
191 tmp_cmc = [x / (i + 1.)
for i, x
in enumerate(tmp_cmc)]
192 tmp_cmc = np.asarray(tmp_cmc) * raw_cmc
193 AP = tmp_cmc.sum() / num_rel
196 print(f
'num_valid_q = {num_valid_q}')
197 print(f
'all_INP = {all_INP}')
198 print(f
'all_AP = {all_AP}')
200 assert num_valid_q > 0,
'Error: all query identities do not appear in gallery'
202 all_cmc = np.asarray(all_cmc).astype(np.float32)
203 all_cmc = all_cmc.sum(0) / num_valid_q
205 print(f
'all_cmc = {all_cmc}')
207 return all_cmc, all_AP, all_INP
211 distmat, q_feats, g_feats, q_pids, g_pids, q_camids, g_camids, max_rank, use_metric_cuhk03, use_distmat
213 if use_metric_cuhk03:
215 distmat, q_feats, g_feats, g_pids, q_camids, g_camids, max_rank, use_distmat
219 distmat, q_feats, g_feats, q_pids, g_pids, q_camids, g_camids, max_rank, use_distmat
232 use_metric_cuhk03=False,
236 """Evaluates CMC rank.
238 distmat (numpy.ndarray): distance matrix of shape (num_query, num_gallery).
239 q_feats (numpy.ndarray): 2-D array containing query features.
240 g_feats (numpy.ndarray): 2-D array containing gallery features.
241 q_pids (numpy.ndarray): 1-D array containing person identities
242 of each query instance.
243 g_pids (numpy.ndarray): 1-D array containing person identities
244 of each gallery instance.
245 q_camids (numpy.ndarray): 1-D array containing camera views under
246 which each query instance is captured.
247 g_camids (numpy.ndarray): 1-D array containing camera views under
248 which each gallery instance is captured.
249 max_rank (int, optional): maximum CMC rank to be computed. Default is 50.
250 use_metric_cuhk03 (bool, optional): use single-gallery-shot setting for cuhk03.
251 Default is False. This should be enabled when using cuhk03 classic split.
252 use_cython (bool, optional): use cython code for evaluation. Default is True.
253 This is highly recommended as the cython code can speed up the cmc computation
254 by more than 10x. This requires Cython to be installed.
256 if use_cython
and IS_CYTHON_AVAI:
258 distmat, q_feats, g_feats, q_pids, g_pids, q_camids, g_camids, max_rank,
259 use_metric_cuhk03, use_distmat
263 distmat, q_feats, g_feats, q_pids, g_pids, q_camids, g_camids, max_rank,
264 use_metric_cuhk03, use_distmat
evaluate_rank(distmat, q_feats, g_feats, q_pids, g_pids, q_camids, g_camids, max_rank=50, use_metric_cuhk03=False, use_distmat=False, use_cython=True)
evaluate_py(distmat, q_feats, g_feats, q_pids, g_pids, q_camids, g_camids, max_rank, use_metric_cuhk03, use_distmat)
eval_cuhk03(distmat, q_feats, g_feats, q_pids, g_pids, q_camids, g_camids, max_rank, use_distmat)
eval_market1501(distmat, q_feats, g_feats, q_pids, g_pids, q_camids, g_camids, max_rank, use_distmat)