leoshine/Spherical_Regression

Incorrect matrix norm in geodesic_dist function

Closed this issue · 0 comments

In function geodesic_dist:

def geodesic_dist(R, R_gt):  # _geo_err
    R, R_gt = map(np.matrix, [R, R_gt])
    # With out disp annoying error
    _logRR, errest = logm(R.transpose()*R_gt, disp=False)
    R_angle  = norm(_logRR, 2) / sqrt(2)
    return R_angle

The matrix 2-norm is incorrectly used, as the defenition of geodesic distance is in Frobenius norm.

This initial implementation geodesic_dist(R, R_gt) was simply trying to replicate the matlab evaluation code from RenderForCNN (ICCV 2015):
R_angle = norm(logm(R_pred'*R_label)) / sqrt(2);

However, we find it uses an incorrect matrix norm. Thanks @Davmo049 for discovering the issue.

The default mode of matrix norm function in matlab and python are different.
(In matlab, the default is 2 norm. In python, the default is Frobenius norm.)
So the above matlab code is indeed using default 2-norm of matrix, and thus so do my implementation in geodesic_dist(R, R_gt).

The later implementation geodesic_dist_new(R, R_gt) only borrows the idea from “3D Pose Regression using Convolutional Neural Networks” to accelerate computation, while ensures the same result is returned as geodesic_dist(R, R_gt).

The correct implementation would be:

def geodesic_dist(R, R_gt): 
    R, R_gt = map(np.matrix, [R, R_gt])
    _logRR, errest = logm(R.transpose()*R_gt, disp=False)
    R_angle  = norm(_logRR, 'fro') / sqrt(2)
    return R_angle
 
 
 
def geodesic_dist_new(R, R_gt):
    R, R_gt = map(np.matrix, [R, R_gt])
    # Do clipping to [-1,1].
    # For a few cases, (tr(R)-1)/2 can be a little bit less/greater than -1/1.
    logR_F = np.clip( (np.trace(R.transpose()*R_gt)-1.)/2., -1, 1)
    R_angle = np.arccos( logR_F )
    return R_angle