关键点检测的指标主要是 OKS 和 PCK。其中 OKS 是现在的常用指标,PCK 主要用在 MPII 等较老的数据集上,从 OKS 还衍生出 AP 和 AR 两个指标。
OKS (Object Keypoint Similarity)
表示 person id
表示 keypoint id
表示预测的关节点和标注的关节点的欧氏距离
表示尺度缩放因子,
表示第 个骨骼点的归一化因子,对数据集中所有 groundtruth 计算的标准差而得到的,反映出当前骨骼点标注时候的标准差, 越大则越难标注
表示关节点是否可见
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
| def compute_oks(dts, gts): if len(dts) * len(gts) == 0: return np.array([]) oks_mat = np.zeros((len(dts), len(gts)))
for j, gt in enumerate(gts): 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: dx = xd - xg dy = yd - yg else: 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
|
OKS 矩阵
对于多人姿态估计,若 gt 中 M 个人,预测了 N 个人,计算两两之间的 OKS 构成 矩阵,最后选择每个 gt 的人中最大的 OKS 值作为结果。
PCK (Percentage of Correct Keypoints)
表示 person id
表示 keypoint id
表示预测的关节点和标注的关节点的欧氏距离
表示尺度缩放因子,对于 FLIC 使用的是躯干直径(左肩到左臀或右肩到左臀),对于 MPII 用的是头部对角线的长度(PCKh)
表示第 个骨骼点的阈值
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
| 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] 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 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)
pck[idh,-1] = 100*np.mean(dist <= trh) return pck
|
PCK 现在用的不多,主要用的是 OKS
AP(Average Precision)& AR(Average Recall)
AP 和 AR 都是针对整个数据集而言的。在算 Precision 或者 Recall 之前,必然先要对关键点检测结果进行排序,很多文章都没有明确这里排序的依据是什么。从实现上来看,是根据人检测框的置信度高低进行排序的。
在计算 AP 和 AR 之前,先要画出 下的 PR 曲线。先对每个检测结果排序,然后计算从头到第 k 个结果时的 Precision 和 Recall,就能画出 PR 曲线了,算出曲线下面积,在 COCO 中用的是 11 点采样法。Precision 和 Recall 的计算方式如下所示:
对于多人关键点检测的任务,首先要做的是将检测到的结果 dt
和 gt
做匹配( 则为一对匹配,每个 dt
会和 OKS
最大的相匹配),那么就可能会出现有的 dt
没有与之相匹配的 gt
。从代码中可知,COCO 中将 TP 定义为有匹配并且匹配到的不是 ignore
的 gt
,FP 的定义为没有匹配的 gt
, 其实就是所有的 gt
个数(比如标注了 100 个 instance,那么 )。
下, 就是此时采样后的 Precision 均值。, 同理。
关于 COCO 上各个指标的具体定义可以参考下图:
人体姿态估计-评价指标(一)_ZXF_1991 的博客 - CSDN 博客
目标检测中的 mAP 是什么含义? - 知乎
mAP for Object Detection