import numpy as np import torch import torch.nn as nn from torch.autograd import Variable import scipy.io def extract_feature(model, dataloaders, device, ms=[1]): features = torch.FloatTensor() model = model.to(device) for data in dataloaders: img, label = data n, c, h, w = img.size() ff = torch.FloatTensor(n, 2048).zero_().to(device) for i in range(2): if i == 1: img = fliplr(img) input_img = Variable(img.to(device)) for scale in ms: if scale != 1: # bicubic is only available in pytorch>= 1.1 input_img = nn.functional.interpolate(input_img, scale_factor=scale, mode='bicubic', align_corners=False) _, outputs = model(input_img) ff += outputs # # norm feature fnorm = torch.norm(ff, p=2, dim=1, keepdim=True) ff = ff.div(fnorm.expand_as(ff)) features = torch.cat((features, ff.data.cpu()), 0) return features def test_evaluate(path, dataset, device): result = scipy.io.loadmat(path) query_feature = torch.FloatTensor(result['query_f']) query_cam = result['query_cam'][0] query_label = result['query_label'][0] gallery_feature = torch.FloatTensor(result['gallery_f']) gallery_cam = result['gallery_cam'][0] gallery_label = result['gallery_label'][0] query_feature = query_feature.to(device) gallery_feature = gallery_feature.to(device) CMC = torch.IntTensor(len(gallery_label)).zero_() ap = 0.0 for i in range(len(query_label)): ap_tmp, CMC_tmp = evaluate(query_feature[i], query_label[i], query_cam[i], gallery_feature, gallery_label, gallery_cam) if CMC_tmp[0] == -1: continue CMC = CMC + CMC_tmp ap += ap_tmp CMC = CMC.float() CMC = CMC / len(query_label) # average CMC return CMC[0], CMC[4], CMC[9], ap / len(query_label) def evaluate(qf, ql, qc, gf, gl, gc): query = qf.view(-1, 1) 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] # good index query_index = np.argwhere(gl == ql) camera_index = np.argwhere(gc == qc) good_index = np.setdiff1d(query_index, camera_index, assume_unique=True) junk_index1 = np.argwhere(gl == -1) junk_index2 = np.intersect1d(query_index, camera_index) junk_index = np.append(junk_index2, junk_index1) # .flatten()) CMC_tmp = compute_mAP(index, good_index, junk_index) return CMC_tmp def compute_mAP(index, good_index, junk_index): ap = 0 cmc = torch.IntTensor(len(index)).zero_() if good_index.size == 0: # if empty cmc[0] = -1 return ap, cmc # remove junk_index mask = np.in1d(index, junk_index, invert=True) index = index[mask] # find good_index index ngood = len(good_index) mask = np.in1d(index, good_index) rows_good = np.argwhere(mask == True) rows_good = rows_good.flatten() cmc[rows_good[0]:] = 1 for i in range(ngood): d_recall = 1.0 / ngood precision = (i + 1) * 1.0 / (rows_good[i] + 1) if rows_good[i] != 0: old_precision = i * 1.0 / rows_good[i] else: old_precision = 1.0 ap = ap + d_recall * (old_precision + precision) / 2 return ap, cmc def fliplr(img): inv_idx = torch.arange(img.size(3) - 1, -1, -1).long() # N x C x H x W img_flip = img.index_select(3, inv_idx) return img_flip