File size: 5,186 Bytes
a80d6bb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import numpy as np
import sys
import os
ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, ROOT_DIR)

from utils import evaluation_utils,metrics,fm_utils
import cv2

class auc_eval:
    def __init__(self,config):
        self.config=config
        self.err_r,self.err_t,self.err=[],[],[]
        self.ms=[]
        self.precision=[]

    def run(self,info):
        E,r_gt,t_gt=info['e'],info['r_gt'],info['t_gt']
        K1,K2,img1,img2=info['K1'],info['K2'],info['img1'],info['img2']
        corr1,corr2=info['corr1'],info['corr2']
        corr1,corr2=evaluation_utils.normalize_intrinsic(corr1,K1),evaluation_utils.normalize_intrinsic(corr2,K2)
        size1,size2=max(img1.shape),max(img2.shape)
        scale1,scale2=self.config['rescale']/size1,self.config['rescale']/size2
        #ransac
        ransac_th=4./((K1[0,0]+K1[1,1])*scale1+(K2[0,0]+K2[1,1])*scale2)
        R_hat,t_hat,E_hat=self.estimate(corr1,corr2,ransac_th)
        #get pose error
        err_r, err_t=metrics.evaluate_R_t(r_gt,t_gt,R_hat,t_hat)
        err=max(err_r,err_t)
        
        if len(corr1)>1:
            inlier_mask=metrics.compute_epi_inlier(corr1,corr2,E,self.config['inlier_th'])
            precision=inlier_mask.mean()
            ms=inlier_mask.sum()/len(info['x1'])
        else:
            ms=precision=0
        
        return {'err_r':err_r,'err_t':err_t,'err':err,'ms':ms,'precision':precision}

    def res_inqueue(self,res):
        self.err_r.append(res['err_r']),self.err_t.append(res['err_t']),self.err.append(res['err'])
        self.ms.append(res['ms']),self.precision.append(res['precision'])

    def estimate(self,corr1,corr2,th):
        num_inlier = -1
        if corr1.shape[0] >= 5:
            E, mask_new = cv2.findEssentialMat(corr1, corr2,method=cv2.RANSAC, threshold=th,prob=1-1e-5)
            if E is None:
                E=[np.eye(3)]
            for _E in np.split(E, len(E) / 3):
                _num_inlier, _R, _t, _ = cv2.recoverPose(_E, corr1, corr2,np.eye(3), 1e9,mask=mask_new)
                if _num_inlier > num_inlier:
                    num_inlier = _num_inlier
                    R = _R
                    t = _t
                    E = _E
        else:
            E,R,t=np.eye(3),np.eye(3),np.zeros(3)
        return R,t,E

    def parse(self):
        ths = np.arange(7) * 5
        approx_auc=metrics.approx_pose_auc(self.err,ths)
        exact_auc=metrics.pose_auc(self.err,ths)
        mean_pre,mean_ms=np.mean(np.asarray(self.precision)),np.mean(np.asarray(self.ms))
        
        print('auc th: ',ths[1:])
        print('approx auc: ',approx_auc)
        print('exact auc: ', exact_auc)
        print('mean match score: ',mean_ms*100)
        print('mean precision: ',mean_pre*100)

        

class FMbench_eval:

    def __init__(self,config):
        self.config=config
        self.pre,self.pre_post,self.sgd=[],[],[]
        self.num_corr,self.num_corr_post=[],[]

    def run(self,info):
        corr1,corr2=info['corr1'],info['corr2']
        F=info['f']
        img1,img2=info['img1'],info['img2']

        if len(corr1)>1:
            pre_bf=fm_utils.compute_inlier_rate(corr1,corr2,np.flip(img1.shape[:2]),np.flip(img2.shape[:2]),F,th=self.config['inlier_th']).mean()
            F_hat,mask_F=cv2.findFundamentalMat(corr1,corr2,method=cv2.FM_RANSAC,ransacReprojThreshold=1,confidence=1-1e-5)
            if F_hat is None:
                F_hat=np.ones([3,3])
                mask_F=np.ones([len(corr1)]).astype(bool)
            else:
                mask_F=mask_F.squeeze().astype(bool)
            F_hat=F_hat[:3]
            pre_af=fm_utils.compute_inlier_rate(corr1[mask_F],corr2[mask_F],np.flip(img1.shape[:2]),np.flip(img2.shape[:2]),F,th=self.config['inlier_th']).mean()
            num_corr_af=mask_F.sum()
            num_corr=len(corr1)
            sgd=fm_utils.compute_SGD(F,F_hat,np.flip(img1.shape[:2]),np.flip(img2.shape[:2]))
        else:
            pre_bf,pre_af,sgd=0,0,1e8
            num_corr,num_corr_af=0,0
        return {'pre':pre_bf,'pre_post':pre_af,'sgd':sgd,'num_corr':num_corr,'num_corr_post':num_corr_af}


    def res_inqueue(self,res):
        self.pre.append(res['pre']),self.pre_post.append(res['pre_post']),self.sgd.append(res['sgd'])
        self.num_corr.append(res['num_corr']),self.num_corr_post.append(res['num_corr_post'])

    def parse(self):
        for seq_index in range(len(self.config['seq'])):
            seq=self.config['seq'][seq_index]
            offset=seq_index*1000
            pre=np.asarray(self.pre)[offset:offset+1000].mean()
            pre_post=np.asarray(self.pre_post)[offset:offset+1000].mean()
            num_corr=np.asarray(self.num_corr)[offset:offset+1000].mean()
            num_corr_post=np.asarray(self.num_corr_post)[offset:offset+1000].mean()
            f_recall=(np.asarray(self.sgd)[offset:offset+1000]<self.config['sgd_inlier_th']).mean()

            print(seq,'results:')
            print('F_recall: ',f_recall)
            print('precision: ',pre)
            print('precision_post: ',pre_post)
            print('num_corr: ',num_corr)
            print('num_corr_post: ',num_corr_post,'\n')