Re-Ranking

Table of Contents

  1. N ( p , k ) N(p, k) N(p,k)
  2. R R R
  3. R ∗ \mathcal{R}^* R
  4. Jaccard距离
  5. V p , g j \mathcal{V}_{p, g_j} Vp,gj
  6. 局部查询扩展

N ( p , k ) N(p, k) N(p,k)

  1. N ( p , k ) = { g 1 0 , g 2 0 , . . . , g k 0 } , ∣ N ( p , k ) ∣ = k N(p, k) = \{g_1^0, g_2^0, ..., g_k^0\}, |N(p, k)| = k N(p,k)={g10,g20,...,gk0},N(p,k)=k
  2. N ( p , k ) N(p, k) N(p,k) 是查询图像 p p p k k k 最近邻图片集合。

R R R

  1. R ( p , k ) = { ( g i ∈ N ( p , k ) ) ∩ ( p ∈ N ( g i , k ) ) } \mathcal{R}(p, k) = \{(g_i \in N(p, k)) \cap (p \in N(g_i, k))\} R(p,k)={(giN(p,k))(pN(gi,k))}
    p p p g i g_i gi 互为 k k k 最近邻
  2. R ( p , k ) \mathcal{R}(p, k) R(p,k) 是以 p p p 作为查询图像,与 p p p 互为 k k k 最近邻的图片集合。

R ∗ \mathcal{R}^* R

  1. 由于照明、姿态、视图、和遮挡的变化,正样本可能不在 N ( p , k ) N(p, k) N(p,k) 中,进而不在 R ( p , k ) \mathcal{R}(p, k) R(p,k) 中。

正样本图像可能被从 k k k -最近邻中排除,并且随后不被包括在 k k k -相互最近邻中。为了解决这个问题,我们根据以下条件将 R ( p , k ) \mathcal{R}(p, k) R(p,k) 中每个候选项的 1 2 k \tfrac{1}{2}k 21k -相互最近邻增量地添加到更鲁棒的集合 R ∗ ( p , k ) \mathcal{R}^*(p, k) R(p,k) 中:

  1. R ∗ ← R ( p , k ) ∪ R ( q , 1 2 k ) \mathcal{R}^* \leftarrow \mathcal{R}(p, k) \cup \mathcal{R}(q, \frac{1}{2}k) RR(p,k)R(q,21k)
  2. s . t .   ∣ R ( p , k ) ∩ R ( q , 1 2 k ) ∣ ≥ 2 3 ∣ R ( q , 1 2 k ) ∣ s.t.\ |\mathcal{R}(p, k) \cap \mathcal{R}(q, \frac{1}{2}k)| \ge \frac{2}{3}|\mathcal{R}(q, \frac{1}{2}k)| s.t. R(p,k)R(q,21k)32R(q,21k)
  3. ∀ q ∈ R ( p , k ) \forall q \in \mathcal{R}(p, k) qR(p,k)

Jaccard距离

  1. p p p g i g_i gi 的相似性度量取决于 p p p g i g_i gi 各自的邻居。
  2. d J ( p , g i ) = 1 − ∣ R ∗ ( p , k ) ∩ R ∗ ( g i , k ) ∣ ∣ R ∗ ( p , k ) ∪ R ∗ ( g i , k ) ∣   ( 5 ) d_J(p, g_i) = 1 - \frac{|\mathcal{R}^*(p, k) \cap \mathcal{R}^*(g_i, k)|}{|\mathcal{R}^*(p, k) \cup \mathcal{R}^*(g_i, k)|}\ (5) dJ(p,gi)=1R(p,k)R(gi,k)R(p,k)R(gi,k) (5)

V p , g j \mathcal{V}_{p, g_j} Vp,gj

  1. V p = [ V p , g 1 , V p , g 2 , . . . , V p , g N ] \mathcal{V}_p = [\mathcal{V}_{p, g_1}, \mathcal{V}_{p, g_2}, ..., \mathcal{V}_{p, g_N}] Vp=[Vp,g1,Vp,g2,...,Vp,gN]

  2. V p , g i = { 1 i f   g i ∈ R ∗ ( p , k ) 0 o t h e r w i s e .   ( 6 ) \mathcal{V}_{p, g_i} = \left\{ \begin{array}{ll} 1 & if \ g_i \in \mathcal{R}^*(p, k) \\ 0 & otherwise. \end{array}\right. \ (6) Vp,gi={10if giR(p,k)otherwise. (6)
    V p , g i = { e − d ( p , g i ) i f   g i ∈ R ∗ ( p , k ) 0 o t h e r w i s e .   ( 7 ) \mathcal{V}_{p, g_i} = \left\{ \begin{array}{ll} e^{-d(p, g_i)} & if \ g_i \in \mathcal{R}^*(p, k) \\ 0 & otherwise. \end{array}\right. \ (7) Vp,gi={ed(p,gi)0if giR(p,k)otherwise. (7)

    1. 如果 V p , g i \mathcal{V}_{p, g_i} Vp,gi 按照公式6中的定义,公式5和公式10是等价的。
    2. 如果 V p , g i \mathcal{V}_{p, g_i} Vp,gi 按照公式7中的定义,公式5和公式10是近似等价的。
  3. g i g_i gi 是图集中的图片, p p p 是查询图像。

  4. ∣ R ∗ ( p , k ) ∩ R ∗ ( g i , k ) ∣ = ∥ min ⁡ ( V p , V g i ) ∥ 1   ( 8 ) |\mathcal{R}^*(p, k) \cap \mathcal{R}^*(g_i, k)| = \|\min(\mathcal{V}_p, \mathcal{V}_{g_i})\|_1 \ (8) R(p,k)R(gi,k)=min(Vp,Vgi)1 (8)

  5. ∣ R ∗ ( p , k ) ∪ R ∗ ( g i , k ) ∣ = ∥ max ⁡ ( V p , V g i ) ∥ 1   ( 9 ) |\mathcal{R}^*(p, k) \cup \mathcal{R}^*(g_i, k) | = \|\max(\mathcal{V}_p, \mathcal{V}_{g_i})\|_1 \ (9) R(p,k)R(gi,k)=max(Vp,Vgi)1 (9)
    L1范数是指向量中各个元素绝对值之和

  6. d J ( p , g i ) = 1 − ∑ j = 1 N min ⁡ ( V p , g j , V g i , g j ) ∑ j = 1 N max ⁡ ( V p , g j , V g i , g j )   ( 10 ) d_J(p_, g_i) = 1 - \frac{\sum_{j=1}^N \min(\mathcal{V}_{p, g_j}, \mathcal{V}_{g_i, g_j})}{\sum_{j=1}^N \max(\mathcal{V}_{p, g_j}, \mathcal{V}_{g_i, g_j})} \ (10) dJ(p,gi)=1j=1Nmax(Vp,gj,Vgi,gj)j=1Nmin(Vp,gj,Vgi,gj) (10)

    如果图像 g j g_j gj 既是 p p p k k k 相互最近邻,又是 g i g_i gi k k k 相互最近邻,
    min ⁡ ( V p , g j , V g i , g j ) = 1 , max ⁡ ( V p , g j , V g i , g j ) = 1 \min(\mathcal{V}_{p, g_j}, \mathcal{V}_{g_i, g_j})=1, \max(\mathcal{V}_{p, g_j}, \mathcal{V}_{g_i, g_j})=1 min(Vp,gj,Vgi,gj)=1,max(Vp,gj,Vgi,gj)=1

局部查询扩展

  1. V p = 1 ∣ N ( p , k ) ∣ ∑ g i ∈ N ( p , k ) V g i   ( 11 ) \mathcal{V}_p = \frac{1}{|N(p, k)|}\sum_{g_i \in N(p, k)}\mathcal{V}_{g_i} \ (11) Vp=N(p,k)1giN(p,k)Vgi (11)
  2. p p p 和其它节点的距离取决于 p p p 的邻居和其它节点的距离。

#!/usr/bin/env python2/python3
# -*- coding: utf-8 -*-
"""
Source: https://github.com/zhunzhong07/person-re-ranking
Created on Mon Jun 26 14:46:56 2017
@author: luohao
Modified by Houjing Huang, 2017-12-22.
- This version accepts distance matrix instead of raw features.
- The difference of `/` division between python 2 and 3 is handled.
- numpy.float16 is replaced by numpy.float32 for numerical precision.
CVPR2017 paper:Zhong Z, Zheng L, Cao D, et al. Re-ranking Person Re-identification with k-reciprocal Encoding[J]. 2017.
url:http://openaccess.thecvf.com/content_cvpr_2017/papers/Zhong_Re-Ranking_Person_Re-Identification_CVPR_2017_paper.pdf
Matlab version: https://github.com/zhunzhong07/person-re-ranking
API
q_g_dist: query-gallery distance matrix, numpy array, shape [num_query, num_gallery]
q_q_dist: query-query distance matrix, numpy array, shape [num_query, num_query]
g_g_dist: gallery-gallery distance matrix, numpy array, shape [num_gallery, num_gallery]
k1, k2, lambda_value: parameters, the original paper is (k1=20, k2=6, lambda_value=0.3)
Returns:
  final_dist: re-ranked distance, numpy array, shape [num_query, num_gallery]
"""
from __future__ import absolute_import
from __future__ import print_function
from __future__ import division

__all__ = ['re_ranking']

import numpy as np
import pudb
from pudb import set_trace


def re_ranking(q_g_dist, q_q_dist, g_g_dist, k1=20, k2=6, lambda_value=0.3):
    original_dist = np.concatenate(
      [np.concatenate([q_q_dist, q_g_dist], axis=1),
       np.concatenate([q_g_dist.T, g_g_dist], axis=1)], axis=0)
    original_dist = np.power(original_dist, 2).astype(np.float32)
    original_dist = np.transpose(1. * original_dist/np.max(original_dist, axis =0))
    v = np.zeros_like(original_dist).astype(np.float32)
    initial_rank = np.argsort(original_dist).astype(np.int32)

    query_num = q_g_dist.shape[0]
    all_num = q_g_dist.shape[0] + q_g_dist.shape[1]

    for i in range(all_num):
        # k-reciprocal neighbors
        # i的前k+1个邻居的索引
        forward_k_neigh_index = initial_rank[i,:k1+1]
        # i的前k+1个邻居的索引的前k+1个邻居的索引
        backward_k_neigh_index = initial_rank[forward_k_neigh_index,:k1+1]
        fi = np.where(backward_k_neigh_index==i)[0]
        k_reciprocal_index = forward_k_neigh_index[fi]
        k_reciprocal_expansion_index = k_reciprocal_index
        for j in range(len(k_reciprocal_index)):
            candidate = k_reciprocal_index[j]
            candidate_forward_k_neigh_index = initial_rank[candidate,:int(np.around(k1/2.))+1]
            candidate_backward_k_neigh_index = initial_rank[candidate_forward_k_neigh_index,:int(np.around(k1/2.))+1]
            fi_candidate = np.where(candidate_backward_k_neigh_index == candidate)[0]
            candidate_k_reciprocal_index = candidate_forward_k_neigh_index[fi_candidate]
            # 对应公式4
            if len(np.intersect1d(candidate_k_reciprocal_index,k_reciprocal_index))> 2./3*len(candidate_k_reciprocal_index):
                k_reciprocal_expansion_index = np.append(k_reciprocal_expansion_index,candidate_k_reciprocal_index)

        # 去除重复的元素
        k_reciprocal_expansion_index = np.unique(k_reciprocal_expansion_index)
        # 对应公式7
        weight = np.exp(-original_dist[i,k_reciprocal_expansion_index])
        # 归一化
        v[i,k_reciprocal_expansion_index] = 1.*weight/np.sum(weight)
        # v[i, j]: 如果i和j是k相互近邻,则v[i, j] = 1, 否则v[i, j] = 0
    original_dist = original_dist[:query_num,]

    if k2 != 1:
        v_q = np.zeros_like(v,dtype=np.float32)
        for i in range(all_num):
            # 对应公式11 多行平均
            v_q[i,:] = np.mean(v[initial_rank[i,:k2],:],axis=0)
            # i和其他节点的距离取决于i的邻居和其它节点的距离
        v = v_q
        del v_q
    del initial_rank

    inv_index = []
    for i in range(all_num):
        # v矩阵中每一列不为0的行索引
        inv_index.append(np.where(v[:,i] != 0)[0])

    jaccard_dist = np.zeros_like(original_dist, dtype=np.float32)

    for i in range(query_num):
        min_dist = np.zeros(shape=[1, all_num], dtype=np.float32)
        # i的前k个相互最近邻
        ind_non_zero = np.where(v[i,:] != 0)[0]
        ind_images = []
        # i的相互最近邻的相互最近邻的行索引
        ind_images = [inv_index[ind] for ind in ind_non_zero]
        for j in range(len(ind_non_zero)):
            # j是i的第j个邻居
            # 计算q_i和g_j的距离
            min_dist[0,ind_images[j]] += np.minimum(
                # 0: 第0维
                v[i, ind_non_zero[j]],
                v[ind_images[j], ind_non_zero[j]])
            # 这里的实现和论文中描述的公式不一致
            # 这里计算的含义是i和3的距离等于j1和3的距离加上j2和3的距离
        # 公式10中计算的是p和g_i的距离,这里计算的是p和前k个相互最近邻的距离
        jaccard_dist[i] = 1-min_dist/(2.-min_dist)

    final_dist = lambda_value* original_dist + (1-lambda_value) * jaccard_dist
    del original_dist
    del v
    del jaccard_dist
    final_dist = final_dist[:query_num,query_num:]
    return final_dist

# 1. 计算的出发点是构建query和gallery的距离。
# v中d(i, j)不等于d(j, i)

# 2. 对v要极其的熟悉
# v[i, j]标志i和j是否是k相互最近邻

# 1. 对np.where()要极其熟悉
# np.where返回的是元组
# np.where(matrix==1)[0] 返回的是矩阵中元素1的行号
# np.where(vector==1)[0] 返回的是向量中元素1的索引


def re_ranking2(q_g_dist, q_q_dist, g_g_dist, k1=20, k2=6, lambda_value=0.3):
    original_dist = np.concatenate(
      [np.concatenate([q_q_dist, q_g_dist], axis=1),
       np.concatenate([q_g_dist.T, g_g_dist], axis=1)], axis=0)
    original_dist = np.power(original_dist, 2).astype(np.float32)
    original_dist = np.transpose(1. * original_dist/np.max(original_dist, axis =0))
    v = np.zeros_like(original_dist).astype(np.float32)
    initial_rank = np.argsort(original_dist).astype(np.int32)

    query_num = q_g_dist.shape[0]
    all_num = q_g_dist.shape[0] + q_g_dist.shape[1]

    for i in range(all_num):
        # k-reciprocal neighbors
        # i的前k+1个邻居的索引
        forward_k_neigh_index = initial_rank[i,:k1+1]
        # i的前k+1个邻居的索引的前k+1个邻居的索引
        backward_k_neigh_index = initial_rank[forward_k_neigh_index,:k1+1]
        fi = np.where(backward_k_neigh_index==i)[0]
        k_reciprocal_index = forward_k_neigh_index[fi]
        k_reciprocal_expansion_index = k_reciprocal_index
        for j in range(len(k_reciprocal_index)):
            candidate = k_reciprocal_index[j]
            candidate_forward_k_neigh_index = initial_rank[candidate,:int(np.around(k1/2.))+1]
            candidate_backward_k_neigh_index = initial_rank[candidate_forward_k_neigh_index,:int(np.around(k1/2.))+1]
            fi_candidate = np.where(candidate_backward_k_neigh_index == candidate)[0]
            candidate_k_reciprocal_index = candidate_forward_k_neigh_index[fi_candidate]
            # 对应公式4
            if len(np.intersect1d(candidate_k_reciprocal_index,k_reciprocal_index))> 2./3*len(candidate_k_reciprocal_index):
                k_reciprocal_expansion_index = np.append(k_reciprocal_expansion_index,candidate_k_reciprocal_index)

        # 去除重复的元素
        k_reciprocal_expansion_index = np.unique(k_reciprocal_expansion_index)
        # 对应公式7
        weight = np.exp(-original_dist[i,k_reciprocal_expansion_index])
        # 归一化
        v[i,k_reciprocal_expansion_index] = 1.*weight/np.sum(weight)
        # v[i, j]: 如果i和j是k相互近邻,则v[i, j] = 1, 否则v[i, j] = 0
    original_dist = original_dist[:query_num,]

    if k2 != 1:
        v_q = np.zeros_like(v,dtype=np.float32)
        for i in range(all_num):
            # 对应公式11 
            v_q[i,:] = np.mean(v[initial_rank[i,:k2],:],axis=0)
            # 多行平均:i和其他节点的距离取决于i的邻居和其它节点的距离
        v = v_q
        del v_q
    del initial_rank

    jaccard_dist = np.zeros_like(original_dist, dtype=np.float32)

    for i in range(query_num):
        min_dist = np.zeros(shape=[1, all_num], dtype=np.float32)
        ind_non_zero = np.where(v[i,:] != 0)[0]
        for j in range(len(ind_non_zero)):
            # 对应公式10
            min_dist[0,j] = np.sum(np.minimum(v[i, :], v[j, :]))
        jaccard_dist[i] = 1-min_dist/(2.-min_dist)

    final_dist = lambda_value* original_dist + (1-lambda_value) * jaccard_dist
    del original_dist
    del v
    del jaccard_dist
    final_dist = final_dist[:query_num,query_num:]
    return final_dist


if __name__ == "__main__":
    q_g_dist = np.random.rand(5, 10)
    q_q_dist = np.random.rand(5, 5)
    g_g_dist = np.random.rand(10, 10)
    f1 = re_ranking(q_g_dist, q_q_dist, g_g_dist, k1=5, k2=3, lambda_value=0.3)
    f2 = re_ranking2(q_g_dist, q_q_dist, g_g_dist, k1=5, k2=3, lambda_value=0.3)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值