naver/r2d2

About matching score

reacher-l opened this issue · 2 comments

Hello, your work is excellent. I would like to follow your work, Can you open your test code about matching score?

same interest here, I cannot reproduce the results stated in the paper

-- coding: utf-8 --

"""
Spyder Editor

This is a temporary script file.
"""

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import os
import torch
from scipy.io import loadmat
from tqdm import tqdm_notebook as tqdm
#%matplotlib inline

use_cuda = torch.cuda.is_available()
device = torch.device('cuda:0' if use_cuda else 'cpu')
top_k = None

n_i = 52
n_v = 56

#dataset_path = 'hpatches-sequences-release'
dataset_path = '/hpatch/hpatches_sequences/hpatches-sequences-release'

lim = [1, 15]
rng = np.arange(lim[0], lim[1] + 1)

def mnn_matcher(descriptors_a, descriptors_b):
device = descriptors_a.device
sim = descriptors_a @ descriptors_b.t()
nn12 = torch.max(sim, dim=1)[1]
nn21 = torch.max(sim, dim=0)[1]
ids1 = torch.arange(0, sim.shape[0], device=device)
# mask = (ids1 == nn21[nn12])
# matches = torch.stack([ids1[mask], nn12[mask]])
matches = torch.stack([ids1, nn12])
return matches.t().data.cpu().numpy()

import pdb

def benchmark_features(read_feats):
seq_names = sorted(os.listdir(dataset_path))

n_feats = []
n_matches = []
match_score = 0
match_score_count = 0

for seq_idx, seq_name in tqdm(enumerate(seq_names), total=len(seq_names)):
    keypoints_a, descriptors_a = read_feats(seq_name, 1)
    n_feats.append(keypoints_a.shape[0])

    for im_idx in range(2, 7):
        keypoints_b, descriptors_b = read_feats(seq_name, im_idx)
        # pdb.set_trace()
        n_feats.append(keypoints_b.shape[0])

        matches = mnn_matcher(
            torch.from_numpy(descriptors_a).to(device=device), 
            torch.from_numpy(descriptors_b).to(device=device)
        )
        # pdb.set_trace()
        homography = np.loadtxt(os.path.join(dataset_path, seq_name, "H_1_" + str(im_idx)))
        
        pos_a = keypoints_a[matches[:, 0], : 2] 
        pos_a_h = np.concatenate([pos_a, np.ones([matches.shape[0], 1])], axis=1)
        pos_b_proj_h = np.transpose(np.dot(homography, np.transpose(pos_a_h)))
        pos_b_proj = pos_b_proj_h[:, : 2] / pos_b_proj_h[:, 2 :]

        pos_b = keypoints_b[matches[:, 1], : 2]

        dist = np.sqrt(np.sum((pos_b - pos_b_proj) ** 2, axis=1)) #2713

        n_matches.append(matches.shape[0])#2713, 2
        # pdb.set_trace()
        match_score += sum(dist<=5)/dist.shape[0]
        match_score_count+=1

return match_score, match_score_count

def summary(stats):
seq_type, n_feats, n_matches = stats
print('# Features: {:f} - [{:d}, {:d}]'.format(np.mean(n_feats), np.min(n_feats), np.max(n_feats)))
print('# Matches: Overall {:f}, Illumination {:f}, Viewpoint {:f}'.format(
np.sum(n_matches) / ((n_i + n_v) * 5),
np.sum(n_matches[seq_type == 'i']) / (n_i * 5),
np.sum(n_matches[seq_type == 'v']) / (n_v * 5))
)

def generate_read_function(method, extension='ppm'):
def read_function(seq_name, im_idx):
aux = np.load(os.path.join(dataset_path, seq_name, '%d.%s.%s' % (im_idx, extension, method)))
if top_k is None:
return aux['keypoints'], aux['descriptors']
else:
assert('scores' in aux)
ids = np.argsort(aux['scores'])[-top_k :]
return aux['keypoints'][ids, :], aux['descriptors'][ids, :]
return read_function

errors = {}
method = 'r2d2_fuxian'
read_function = generate_read_function(method)
match_score,match_score_count = benchmark_features(read_function)
print(match_score/match_score_count)

I used the code above to get a similar matching score!