人體姿態估計-評價指標
看了幾篇人體姿態估計的經典論文之後,突然發現其實自己對於人體姿態估計這個方向的評價指標並沒有進行深入的研究和理解,所以看論文有時候看得不明不白,所以決定先對於這個任務最為基礎的一部分——評價指標,先進行一個閱讀和理解。
人體姿態估計實際上可以細分乘四個任務:單人姿態估計,多人姿態估計,人體姿態跟蹤和3D人體姿態估計。因為人體姿態跟蹤和3D人體姿態估計作者還沒有進行了解,所以相應的評價指標就在本篇文章先不進行探討,等之後瞭解深入之後再回來補充。
所以本文的針對目標就是
單人姿態估計
任務和
多人姿態估計
任務中分別對應的評價指標。
單人姿態估計
首先單人姿態估計如其名,就是針對圖片中的單個人(圖片中可能有多個人,但只有某一個人遮擋最少或者大小最大,總而言之就是最好識別)進行識別。實際上這類任務針對的並不是原圖,而是識別並切割出來單個人物,針對於這個人,找出其身體的關節點。使用的方法是自頂向下(top-down)的(CPM, Hourglass)。這類任務的方法基本都是先檢測出人的bounding box,在使用single-stage的方法檢測關節點。
使用的資料集:
LSP
地址:
http://
sam。johnson。io/research
/lsp。htm
樣本數:2K
關節點個數:14
全身,單人
FLIC
地址:
https://
bensapp。github。io/flic-
dataset。html
樣本數:2W
關節點個數:9
全身,單人
MPII
地址:
http://
human-pose。mpi-inf。mpg。de
/
樣本數:25K
關節點個數:16
全身,單人/多人,40K people,410 human activities
使用的指標:
PCK
Percentage of Correct Keypoints (PCK),reports the percentage of keypoint detection falling within a normalized distance of the ground truth。
計算檢測的關鍵點與其對應的groundtruth間的歸一化距離小於設定閾值的比例。
FLIC 中是以軀幹直徑(torso size) 作為歸一化參考。
MPII 中是以頭部長度(head length) 作為歸一化參考,即
PCKh
。
正確估計出的關鍵點比例。這是比較老的人體姿態估計指標,在17年比較廣泛使用,現在基本不再使用。
其中
表示id為
的關鍵點
表示第k個閾值
表示第p個行人
表示第
個人中id為
的關鍵點的預測值和groundtruth的歐式距離
表示第
個人的尺度因子,這個因子不同公開資料集使用的計算方法不同,就是上文提到的FLIC和MPII資料集的差別。
表示人工設定的閾值,
表示
閾值下id為i的關鍵點的PCK指標
表示
閾值下的演算法PCK指標
def compute_pck_pckh(dt_kpts,gt_kpts,refer_kpts):
“”“
pck指標計算
:param dt_kpts:演算法檢測輸出的估計結果,shape=[n,h,w]=[行人數,2,關鍵點個數]
:param gt_kpts: groundtruth人工標記結果,shape=[n,h,w]
:param refer_kpts: 尺度因子,用於預測點與groundtruth的歐式距離的scale。
pck指標:軀幹直徑,左肩點-右臀點的歐式距離;
pckh指標:頭部長度,頭部rect的對角線歐式距離;
:return: 相關指標
”“”
dt=np。array(dt_kpts)
gt=np。array(gt_kpts)
assert(len(refer_kpts)==2)
assert(dt。shape[0]==gt。shape[0])
ranges=np。arange(0。0,0。1,0。01)
kpts_num=gt。shape[2]
ped_num=gt。shape[0]
#compute dist
scale=np。sqrt(np。sum(np。square(gt[:,:,refer_kpts[0]]-gt[:,:,refer_kpts[1]]),1))
dist=np。sqrt(np。sum(np。square(dt-gt),1))/np。tile(scale,(gt。shape[2],1))。T
#compute pck
pck = np。zeros([ranges。shape[0], gt。shape[2]+1])
for idh,trh in enumerate(list(ranges)):
for kpt_idx in range(kpts_num):
pck[idh,kpt_idx] = 100*np。mean(dist[:,kpt_idx] <= trh)
# compute average pck
pck[idh,-1] = 100*np。mean(dist <= trh)
return pck
OKS
OKS
(object keypoint similarity),關鍵點相似度,在人體關鍵點評價任務中,對於網路得到的關鍵點好壞,並不是僅僅透過簡單的歐氏距離來計算的,而是有一定的尺度加入,來計算兩點之間的相似度。這個指標主要是用在多人姿態估計任務當中。
其中:
表示在groundtruth中某個人
表示表示某個人的關鍵點
表示當前檢測的一組關鍵點中id為i的關鍵點與groundtruth裡行人p的關鍵點中id為
的關鍵點的歐式距離
,
為當前的關鍵點檢測結果,
是groundtruth裡行人p的關鍵點id為i的關鍵點。
表示這個關鍵點的可見性為1,即關鍵點無遮擋並且已標註。
表示關鍵點有遮擋但已標註。
表示groundtruth行人中id為p的人的尺度因子,其值為行人檢測框面積的平方根:
,
為檢測框的寬和高,這裡的檢測框就是bounding box。
表示id為i i
i
型別的關鍵點歸一化因子,這個因子是透過對所有的樣本集中的groundtruth關鍵點由人工標註與真實值存在的標準差,
越大表示此型別的關鍵點越難標註。對
coco
資料集中的
5000
個樣本統計出
17
類關鍵點的歸一化因子,
的取值可以為:
{鼻子:0.026,眼睛:0.025,耳朵:0.035,肩膀:0.079,手肘:0.072,手腕:0.062,臀部:0.107,膝蓋:0.087,腳踝:0.089}
,因此此值可以當作常數看待,但是使用的型別僅限這個裡面。如果使用的關鍵點型別不在此當中,可以使用另外一種統計方法計算此值,詳細見下文
表示如果條件*成立,那麼
,否則
,在此處的含義是:僅計算groundtruth中已標註的關鍵點。
oks = [0。5, 0。55, 0。6, 0。65, 0。7, 0。75, 0。8, 0。85, 0。9, 0。95]
sigmas = np。array([。26, 。25, 。25, 。35, 。35, 。79, 。79, 。72, 。72, 。62,。62, 1。07, 1。07, 。87, 。87, 。89, 。89])/10。0
variances = (sigmas * 2)**2
def compute_kpts_oks(dt_kpts, gt_kpts, area):
“”“
this function only works for computing oks with keypoints,
:param dt_kpts: 模型輸出的一組關鍵點檢測結果dt_kpts。shape=[3,14],dt_kpts[0]表示14個橫座標值,dt_kpts[1]表示14個縱座標值,dt_kpts[3]表示14個可見性,
:param gt_kpts:groundtruth的一組關鍵點標記結果gt_kpts。shape=[3,14],gt_kpts[0]表示14個橫座標值,gt_kpts[1]表示14個縱座標值,gt_kpts[3]表示14個可見性,
:param area:groundtruth中當前一組關鍵點所在人檢測框的面積
:return:兩組關鍵點的相似度oks
”“”
g = np。array(gt_kpts)
xg = g[0::3]
yg = g[1::3]
vg = g[2::3]
assert(np。count_nonzero(vg > 0) > 0)
d = np。array(dt_kpts)
xd = d[0::3]
yd = d[1::3]
dx = xd - xg
dy = yd - yg
e = (dx**2 + dy**2) /variances/ (area+np。spacing(1)) / 2#加入np。spacing()防止面積為零
e=e[vg > 0]
return np。sum(np。exp(-e)) / e。shape[0]
針對於
的取值,如果增加了新的關鍵點型別或者用於其它物體的關鍵點檢測,也可以根據自己的樣本集進行設定,具體為方法為:
AP(Average Precision)平均準確率
還有一個指標是作為COCO資料集的指標,既可以用在單人姿態估計,也可以用在多人姿態估計,他針對的是計算測試集精度百分比,這就是平均準確率(AP)。
相信瞭解目標檢測的朋友應該對這個指標並不陌生,但是人體姿態估計裡面的AP計算方法和目標檢測裡的有所不同。
單人姿態估計AP:
計算出groundtruth與檢測得到的關鍵點的相似度
oks
為一個標量,然後人為的給定一個閾值
T
,然後可以透過所有圖片的
oks
計算
AP
:
多人姿態估計AP:
如果採用的檢測方法是自頂向下,先把所有的人找出來再檢測關鍵點,那麼其
AP
計算方法如同
單人姿態估計AP
如果採用的檢測方法是自底向上,先把所有的關鍵點找出來然後再組成人。假設一張圖片中有M個人,預測出N個人,由於不知道預測出的
N
個人與groundtruth中的
M
個人的一一對應關係,因此需要計算groundtruth中每一個人與預測的
N
個人的
oks
,那麼可以獲得一個大小為
M
×
N
的矩陣,矩陣的每一行為groundtruth中的一個人與預測結果的
N
個人的
oks
,然後找出每一行中
oks
最大的值作為當前
GT
的
oks
。最後每一個
GT
行人都有一個標量
oks
,然後人為的給定一個閾值
T
,然後可以透過所有圖片中的所有行人計算
AP
:
def compute_oks(dts, gts):
if len(dts) * len(gts) == 0:
return np。array([])
oks_mat = np。zeros((len(dts), len(gts)))
# 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((len(sigmas)))
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) / variances / (gt[‘area’]+np。spacing(1)) / 2
if k1 > 0:
e=e[vg > 0]
oks_mat[i, j] = np。sum(np。exp(-e)) / e。shape[0]
return oks_mat
mAP(mean Average Precision)
mAP是常用檢測指標,具體就是給
AP
指標中的人工閾值
T
設定不同的值,然後會獲得多個
AP
指標,最後再對多個
AP
指標求平均,最終獲得mAP。
Reference: