본문 바로가기
Terminology

[평가 지표] ATE(Absolute Trajectory Error), RPE(Relative Pose Error)

by xoft 2023. 5. 18.

Predicted된 Camera Pose가 GT(Ground Truth)와 얼마나 가까운지를 어떻게 정량적으로 측정할까요?

이번에는 Camera Pose를 Estimation하는 논문에서 사용되는 평가지표에 대해 알아보겠습니다. SLAM, Image Matching, NeRF 분야에서 주로 쓰입니다.

 

크게 Camera가 어디에 위치해 있는지(Camera Position), 어디를 바라보고 있는지(Camera Rotation)를 평가하게 됩니다.

 

 

ATE(Absolute Trajectory Error)

아주 간단합니다. x,y,z로 구성된 Camera Position 차이에 대한 평균 값만 계산합니다. MSE(Mean Square Error)에 루트를 씌워준 RMSE를 사용해서 너무 Gap이 큰 이상치에 대해 고려해줍니다. (수식 출처: link)

 

 

RPE(Relative Pose Error)

수식으로는 아래와 같이 표현되어 있습니다(수식 link). 아래 수식으로는 복잡해 보여서 설명하지 않겠습니다. 대신 천천히 기본 개념과 함께 코드로 설명하고 다시 언급하겠습니다.

 

ATE는 너무 쉬웠지만, RPE는 생각하기 좀 까다롭습니다. 전제는 GT와 Predicted된 Camera Pose가 Trajectory로 구성되어야 합니다. 설명하기 앞서 Rotation Matrix과 Transformation Matrix의 개념과 특성을 먼저 보겠습니다. 이미 아시는 분은 바로 아래 언급된 소스코드 보셔도 됩니다. 

 

R이라는 Rotation Matrix는 원점을 기준으로, 좌표 A를 좌표 B로 회전 할 수 있습니다. camera parameter글 의 Transformation Matrix부분을 참조 바랍니다. R의 역함수는 좌표B를 좌표A로 회전 할 수 있습니다. 'R'과 'R의 역함수'를 행렬곱하게 되면 1이 되어, 좌표A에 'R'와 'R의 역함수'를 곱하면,  좌표 A->좌표B->좌표A로 변환이되면서 원점으로 돌아오게 됩니다. SO(3) Group에 속합니다. (SO(3) 세부개념 link 참조)

Rotation Matrix로부터 회전과 함께 좌표 이동 t (x,y,z)까지 고려된 Matrix를 Transformation Matrix라고 합니다. 위 GT와 pred는 Transformation Matrix형태로 구성되어 있습니다.

이 Transformation Matrix도 아래 성질을 갖습니다.

'T'와 'T의 역함수'를 행렬곱하게 되면 1이 되어, 좌표A에 'T'와 'T의 역함수'를 곱하면, 좌표A->좌표B->좌표A로 변환되어 똑같이 되돌아오게 됩니다. SE(3) Group에 속합니다. (SE(3) 세부개념 link 참조)

 

Transformation Matrix성질에 대해 좀 더 설명하자면, Transformation Matrix 1와 Transformation Matrix 2를 곱하게되면, 새로운 Transformation Matrix가 만들어지며, 특정 point에 대한 회전/이동변환이 두 번 적용된 Transformation Matirx를 구할 수 있습니다.

수식을 그림으로 도식화하면 아래와 같습니다. (그림 출처 : link)

Transformation Matrix P1 , P2가 있을 때, 둘에 대한 행렬 곱은 P1을 한번 적용하고, 그 후에 P2를 적용하게 됩니다.

 

 

이제 RPE를 설명하기 위해, 구현 코드를 보겠습니다. 다음 코드를 참조하였습니다. ->  코드 바로가기

def rotation_error(pose_error):
    a = pose_error[0, 0]
    b = pose_error[1, 1]
    c = pose_error[2, 2]
    d = 0.5*(a+b+c-1.0)
    rot_error = np.arccos(max(min(d, 1.0), -1.0))
    return rot_error

def translation_error(pose_error):
    dx = pose_error[0, 3]
    dy = pose_error[1, 3]
    dz = pose_error[2, 3]
    trans_error = np.sqrt(dx**2+dy**2+dz**2)
    return trans_error

def compute_rpe(gt, pred):
    trans_errors = []
    rot_errors = []
    for i in range(len(gt)-1):
        gt1 = gt[i]
        gt2 = gt[i+1]
        gt_rel = np.linalg.inv(gt1) @ gt2

        pred1 = pred[i]
        pred2 = pred[i+1]
        pred_rel = np.linalg.inv(pred1) @ pred2
        rel_err = np.linalg.inv(gt_rel) @ pred_rel
        
        trans_errors.append(translation_error(rel_err))
        rot_errors.append(rotation_error(rel_err))
    rpe_trans = np.mean(np.asarray(trans_errors))
    rpe_rot = np.mean(np.asarray(rot_errors))
    return rpe_trans, rpe_rot

np.linalg.inv()는 역행렬 함수이고,  @는 행렬곱을 의미합니다. 

 

gt_rel은, trajectory 내 'i번째 GT pose의 역함수'와 'i+1번째 GT Pose'가 행렬곱을 하게 됩니다. i번째와 i+1번째의 pose가 동일하다면, 원점으로 돌아오게 됩니다. gt_rel은 현재 gt pose과 다음 gt pose간의 변화량을 Transformation Matrix로 구성하게 됩니다. 변화량이 두개 pose의 차이 입니다.

 

pred_rel도, 비슷한 형태로 구성되어 있습니다.  'i번째 pred pose의 역함수'와 'i+1번째 pred Pose'가 행렬곱을 하게 됩니다.  pred_rel는 현재 pred pose와 다음 pred pose간의 변화량을 Transformation Matrix로 구성하게 됩니다.

 

rel_err를 보겠습니다. 'gt_rel의 역함수'와 'pred_rel의 곱'으로 되어 있습니다. 이 또한 변화량을 계산하게 됩니다. 결과적으로 GT와 predicted 각각 trajectory의 상대적인 transformation의 변화량을 계산 해주고, 그 둘간의 변화량을 다시 계산해주게 됩니다.

 

RPEt를 계산하는 translation_error 함수는 직관적으로 squared error를 계산 한 후, 함수 밖에서 평균을 내고 있습니다.

RPEr을 계산하는 rotation_error 함수는 대각성분으로만 식이 구성되어 있는데, Rotation Matrix의 아래 공식(출처 : link)을 이용해서, 각도 Θ를 계산 할 수 있기 때문입니다. 아래 수식과 코드를 비교해 보시길 바랍니다.

tr(R)은 R행렬의 대각행렬의 합입니다. R행렬에 대한 trace를 계산한다고 표현합니다. 각도 Θ는 평균값으로 계산합니다.

 

이제 처음에 언급한 수식을 해석 할 수 있을 겁니다. ref는 GT, est는 estimation된 결과입니다. P는 Transformation Matrix입니다. δ는 변화량을 나타내는 기호입니다. 

 

마지막으로 다시 한 번 정리해보겠습니다.

 

RPEt는 GT와 Predicted 결과 각각에 대해 현재 camera pose 다음 camera pose와 상대적인 position 변화량을 계산하고, 그 상대적인 변화량간의 변화량을 계산합니다. 그리고 평균을 냅니다.

 

RPEr는 GT와 Predicted 결과 각각에 대해 현재 camera pose 다음 camera pose와 상대적인 rotation 변화량을 rotation matirx를 통해 계산하고, 그 상대적인 변화량간의 변화량을 rotation matrix로 계산한 후에, 각도로 변환하여 평균값을 사용합니다.

 

 

댓글