# Copyright 2021 Huawei Technologies Co., Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ============================================================================ """Numpy version of euclidean distance, etc.""" import numpy as np from utils.metric import cmc, mean_ap def normalize(nparray, order=2, axis=0): """Normalize a N-D numpy array along the specified axis.""" norm = np.linalg.norm(nparray, ord=order, axis=axis, keepdims=True) return nparray / (norm + np.finfo(np.float32).eps) def compute_dist(array1, array2, dis_type='euclidean'): """Compute the euclidean or cosine distance of all pairs. Args: array1: numpy array with shape [m1, n] array2: numpy array with shape [m2, n] type: one of ['cosine', 'euclidean'] Returns: numpy array with shape [m1, m2] """ assert dis_type in ['cosine', 'euclidean'] if dis_type == 'cosine': array1 = normalize(array1, axis=1) array2 = normalize(array2, axis=1) dist = np.matmul(array1, array2.T) return -1*dist # shape [m1, 1] square1 = np.sum(np.square(array1), axis=1)[..., np.newaxis] # shape [1, m2] square2 = np.sum(np.square(array2), axis=1)[np.newaxis, ...] squared_dist = - 2 * np.matmul(array1, array2.T) + square1 + square2 squared_dist[squared_dist < 0] = 0 dist = np.sqrt(squared_dist) return dist def compute_score(dist_mat, query_ids, gallery_ids): mAP = mean_ap(distmat=dist_mat, query_ids=query_ids, gallery_ids=gallery_ids) cmc_scores, _ = cmc(distmat=dist_mat, query_ids=query_ids, gallery_ids=gallery_ids, topk=10) return mAP, cmc_scores