文章目录
Introduction
深度学习算法需要适当的评估指标才能在训练过程中很好地学习分布,并在推理过程中表现良好。评估指标取决于手头的任务。
在本节中,我们将简要讨论 HPE 所需的四个评估指标。
Percentage of Correct Parts (PCP)
PCP 用于测量肢体的正确检测。如果两个预测关节位置与真实肢体关节位置之间的距离几乎小于肢体长度的一半,则认为肢体被检测到。然而,有时它会惩罚较短的肢体,例如下臂。
Percentage of Detected Joints (PDJ)
为了解决 PCP 提出的问题,提出了一个新的度量标准。它在躯干直径的一定比例内测量预测关节与真实关节之间的距离,称为检测关节百分比 (PDJ)。
PDJ 有助于实现定位精度,这缓解了 PCP 的缺点,因为所有关节的检测标准都基于相同的距离阈值。
Percentage of Correct Key-points (PCK)
PCK 被用作衡量预测关键点和真实关节是否在某个距离阈值内的准确度指标。PCK 通常是相对于被包围在边界框内的对象的比例来设置的。
阈值可以是:
- PCKh@0.5 是当阈值 = 头骨链接的 50% 时
- PCK@0.2 = 预测关节与真实关节之间的距离 < 0.2 * 躯干直径
- 有时将 150 毫米作为阈值。
- 它缓解了肢体较短的问题,因为较短的肢体具有较小的躯干和头骨链接。
- PCK 用于 2D 和 3D (PCK3D)
Object Keypoint Similarity (OKS) based mAP
OKS 在 COCO 关键点挑战中通常用作评估指标。它被定义为:
其中,
- di 是地面实况和预测关键点之间的欧式距离
- s 是对象段面积的平方根
- k 是控制衰减的每个关键点常数。
- vi 被认为是一个可见性标志,可以是 0、1 或 2,分别表示未标记、已标记但不可见和可见且已标记。
- i表示某个关键点的下标
- Ki表示id为i ii类型的关键点归一化因子,这个因子是通过对所有的样本集中的groundtruth关键点由人工标注与真实值存在的标准差, 越大表示此类型的关键点越难标注。对coco数据集中的5000个样本统计出17类关键点的归一化因子, 的取值可以为:{鼻子:0.026,眼睛:0.025,耳朵:0.035,肩膀:0.079,手肘:0.072,手腕:0.062,臀部:0.107,膝盖:0.087,脚踝:0.089},因此此值可以当作常数看待,但是使用的类型仅限这个里面。
关键点归一化因子可由下图理解:
PS:自己的数据集没法确定这个值,这个值是多人标注时,在归一化后,统计的不同人标注的同一点的标准差,用来表征这个关键点的检测难度。
因为 OKS 用于计算距离 (0-1),所以它显示了预测关键点与真实关键点的接近程度。
import numpy as np
import glob
import os
import cv2
oks = [0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95]
sigmas = np.array([0.75, 0.75])/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).reshape(3, -1)
xg = g[0::3]
yg = g[1::3]
vg = g[2::3]
assert(np.count_nonzero(vg > 0) > 0)
d = np.array(dt_kpts).reshape(3, -1)
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]