본문 바로가기
AI & CS 지식/인공지능 Q&A

[AI Q&A] OKS(Object Keypoint Similarity)란?

by rahites 2024. 11. 22.

여러 Human Pose Estimation 논문을 읽다보면 대다수의 논문들이 평가지표로 OKS(Object Keypoint Similarity)라는 계산식을 사용하는 것을 알 수 있다. 물론 나도 이미 여러번 보았으며 무엇인지 이해했었지만, 너무나도 많이 나오는 내용이다 보니 논문을 리뷰하는데에도 매번 작성할 수 없어, 한번 제대로 이해하기 쉽게 정리한 후 앞으로 나올 논문 리뷰들에 태그를 달아두려 한다.


OKS(Object Keypoint Simiarity)HPE(Human Pose Estimation) Task에서 예측된 Keypoint와 실제 Ground Truth Keypoint가 얼마나 유사한지를 측정하는 지표이다. OD(Object Detection)에서 주로 사용하는 평가지표인 IoU(Intersection over Union)과 비슷한 역할을 한다고 생각하면 되는데, HPE에서도 OD와 비슷하게 OKS의 Threshold를 기준으로 Keypoint를 잘 예측하였는지를 판단하고 이에 대한 Precision과 Recall을 구하는 방식으로 평가가 이루어진다.

 

OKS를 계산하는 수식은 다음와 같다.

$$ OKS = \frac{\sum_i \exp(-d_i^2/2s^2k_i^2)\delta(v_i>0)}{\sum_i \delta(v_i>0)} $$

  • $d_i$ : i번째 Keypoint의 예측값과 실제값 사이의 Euclidean 거리
  • $s$ : Object Scale(일반적으로는 Bounding box 면적의 제곱근)
  • $k_i$ : 각 Keypoint 유형 별 상수(ex. 정확해야 하는 눈은 작은 값, 엉덩이는 상대적으로 큰 값)
  • $v_i$ : Keypoint의 Visibility Flag
    (COCO의 경우 v=0 : not visible / v=1 : visible but occluded / v=2 : visible)
  • $\sigma$ : visibility가 0보다 큰 값만을 평가지표에 사용하려는 지시함수(v>0이면 1, v=0이면 0)

 

※ COCO Format Keypoint 유형 별 상수(가중치)

# COCO keypoint sigmas
self.kpt_oks_sigmas = np.array([.26, .25, .25, .35, .35, .79, .79, .72, .72, .62,.62, 1.07, 1.07, .87, .87, .89, .89])/10.0

 

전체적인 식을 살펴보면 가우시안 분포와 매우 닮아 있는 것을 확인할 수 있다. 또한 지시함수 $\sigma$를 사용하여 Ground Truth에 라벨링이 되어있지 않는다면 OKS 계산에 사용되지 않는다는 점도 알 수 있다.

 

위의 수식을 가지고 평가가 이뤄지는 과정은 아래와 같이 정리할 수 있다.

 

  1. 모델이 예측한 Keypoint와 Ground Truth Keypoint간의 거리 $d_i$를 계산
  2. i번째 관절 별 계산된 $d_i$를 Object Scale $s$와 Keypoint 별 가중치 $k_i$를 적용하여 정규화를 진행
  3. visibility를 활용하여 OKS 점수를 계산. 이 때 분모에 visibility가 0인 값들의 총 개수로 나누어주어 전체 keypoint에 대해 계산한 값의 평균 값을 OKS로 출력

출력된 OKS는 [0,1]의 값을 가지며 1로 갈수록 예측된 Keypoint와 Ground Truth Keypoint가 유사하다는 것을 의미한다.

 

이렇게 계산된 OKS를 가지고 아래의 과정을 통해 mAP(mean Average Precision)를 계산한다.

 

  1. 다양한 OKS Threshold(0.5, 0.55, .., 0.95)를 가지고 Precision-Recall Curve를 계산한다.
  2. 모든 이미지에 대해 계산된 OKS를 가지고 Threshold 값에 대한 AP를 계산한다.
  3. 모든 Threshold에 대해 AP 평균을 계산하여 mAP를 계산한다.

결국 이러한 수식과 평가 과정을 통해 OKS는 예측한 Keypoint가 Ground Truth Keypoint 위치에 맞게 잘 예측되었는지를 판단한다.


실제 COCO API 코드 상에서 OKS를 구하는 부분은 다음과 같다.

def computeOks(self, imgId, catId):
    p = self.params
    # dimention here should be Nxm
    gts = self._gts[imgId, catId]
    dts = self._dts[imgId, catId]
    inds = np.argsort([-d['score'] for d in dts], kind='mergesort')
    dts = [dts[i] for i in inds]
    if len(dts) > p.maxDets[-1]:
        dts = dts[0:p.maxDets[-1]]
    # if len(gts) == 0 and len(dts) == 0:
    if len(gts) == 0 or len(dts) == 0:
        return []
    ious = np.zeros((len(dts), len(gts)))
    sigmas = p.kpt_oks_sigmas
    vars = (sigmas * 2)**2
    k = len(sigmas)
    # compute oks between each detection and ground truth object
    for j, gt in enumerate(gts):
        # create bounds for ignore regions(double the gt bbox)
        g = np.array(gt['keypoints'])
        xg = g[0::3]; yg = g[1::3]; vg = g[2::3]
        k1 = np.count_nonzero(vg > 0)
        bb = gt['bbox']
        x0 = bb[0] - bb[2]; x1 = bb[0] + bb[2] * 2
        y0 = bb[1] - bb[3]; y1 = bb[1] + bb[3] * 2
        for i, dt in enumerate(dts):
            d = np.array(dt['keypoints'])
            xd = d[0::3]; yd = d[1::3]
            if k1>0:
                # measure the per-keypoint distance if keypoints visible
                dx = xd - xg
                dy = yd - yg
            else:
                # measure minimum distance to keypoints in (x0,y0) & (x1,y1)
                z = np.zeros((k))
                dx = np.max((z, x0-xd),axis=0)+np.max((z, xd-x1),axis=0)
                dy = np.max((z, y0-yd),axis=0)+np.max((z, yd-y1),axis=0)
            e = (dx**2 + dy**2) / vars / (gt['area']+np.spacing(1)) / 2
            if k1 > 0:
                e=e[vg > 0]
            ious[i, j] = np.sum(np.exp(-e)) / e.shape[0]
    return ious
  • p.kpt_oks_sigmas를 x, y에 모두 적용하기 위해 2를 곱하고 거듭제곱해준다는 점
  • k1>0을 통해 visibility가 있는 keypoint만 선택하여 oks에 반영한다는 점
  • np.spacing(1)을 사용하여 0으로 나누는 것을 방지했다는 점(machine epsilon과 동일)

위의 특징들을 주의깊게 보면서 코드와 수식을 살펴보면 어떤식으로 계산이 이루어지는 지 알 수 있을 것이다.

 

 

참고자료

https://github.com/cocodataset/cocoapi

 

GitHub - cocodataset/cocoapi: COCO API - Dataset @ http://cocodataset.org/

COCO API - Dataset @ http://cocodataset.org/ . Contribute to cocodataset/cocoapi development by creating an account on GitHub.

github.com

 

댓글