关键点检测(姿态估计)任务
1. 任务调研
1.1 任务定义
关键点检测任务目标是标出物体的关键部位,姿态估计任务目标是对物体(通常是人和动物)的姿态(即关键点和关键点之间的连接关系)进行估计。关键点检测和姿态估计通常合在一起讨论,原因是对于人体和动物等其身体部位之间的连接关系是固定的,得到了人体关键点的检测结果,就可以得到姿态估计的结果(是否有姿态估计取决于是否有关键点之间的连接关系)。
1.2 评价指标
评价指标一般采用COCO格式的mAP。mAP的计算方式与COCO目标检测中的mAP计算方式类似,对于关键点检测方法检测出的所有物体以及物体中的关键点,首先使用关键点中的OKS度量指标对所有检测出的物体进行分类,分为TP、FP、FN几类,划分完之后,通过改变score的阈值计算P-R曲线,P-R曲线下的面积即为AP的值。
与目标检测mAP计算方式最大的不同在于,目标检测中衡量实例之间的相似度时使用的是检测框之间的IOU,而在关键点检测中,衡量实例相似度使用的是物体关键点之间的OKS距离,OKS的计算方式如下:
OKS代表的是一个物体其所有关键点检测结果(prediction)和真实标注(ground truth)之间的相似度,di代表第i个检测出的关键点和真实标注的欧氏距离,s是物体的像素面积,k代表第i种关键点(例如鼻子)的归一化因子,是对已有数据集中所有物体的同种关键点(例如数据集种所有人的鼻子关键点)计算得到的,值越大,代表数据集中这个关键点标注越差即这个关键点越难检测,值越小代表这个关键点标注越好,即这个关键点检测难度较小。有了OKS距离之后,可以计算得到不同OKS阈值下的AP指标。COCO的关键点检测指标如下图所示,与目标检测类似定义:
1.3 主流数据集调研
根据目标类型的不同,姿态估计(关键点检测)数据集的标注形式也不同。姿态估计(关键点检测)数据集根据目标类型可以分为以下几类:
目标类型 | 任务类型 | 代表数据集 |
---|---|---|
人体 | 人体姿态估计/关键点检测 (human body keypoint) | COCO, MPII, MPII-TRB, AI Challenger, CrowdPose, OCHuman, MHP |
人体(全身) | 人体(全身)姿态估计/关键点检测 (human wholebody keypoint) | COCO WholeBody, Halpe |
人脸 | 人脸关键点检测 (face keypoint) | 300W, WFLW, AFLW, COFW, COCO-WholeBody-Face |
手 | 手部关键点检测 (hand keypoint) | OneHand-10K, FreiHand, CMU Panoptic HandDB, InterHand2.6M, RHD, COCO-WholeBody-Hand |
衣物 | 衣物关键点检测 (fashion lanmark) | DeepFashion |
动物 | 动物姿态估计/关键点检测 (animal keypoint) | Animal-Pose, AP-10K, Horse-10, MacaquePose, Vinegar Fly, Desert Locust, Grévy’s Zebra, ATRW |
我们调研了10个主流姿态估计/关键点检测数据集,涵盖了所有以上不同类型的数据集。完整的字段调研结果如下表所示:
姿态估计/关键点检测数据集 | image_id | height | width | instance_id | category_id | is_crowd | area | num_keypoints | bbox | segmentation | keypoints | visible | center | categories | super_categories | keypoint_names | skeleton | other |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
COCO | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | ||
MPII | Y | Y | Y | Y | scale, person, torsoangle | |||||||||||||
AIC | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | |||
CrowdPose | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | crowd index | ||
COCO-WholeBody | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | face valid/kpts/bbox, right hand valid/kpts/bbox, left hand valid/kpts/bbox, foot valid/kpts | ||
Halpe | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Hoi | ||||||
300W | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | ||||
OneHand10K | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y | |||
DeepFashion | Y | Y | Y | Y | Y | Y | Y | variation | ||||||||||
AnimalPose | Y | Y | Y | Y | Y | Y | Y | Y | Y | Y |
经过整理,关键点检测/姿态估计任务的字段可以分为两种:一种是不同数据集共有的共享字段,一种是不同数据集不同的独立字段。关键点检测/姿态估计任务的共享字段和独立字段如下表所示:
字段类型 | 字段名称 | 含义 |
---|---|---|
共享字段 | image_id | 定位到唯一图片,比如用图片名或者图片路径表示 |
keypoints | 单个目标的关键点标注,包含了一系列坐标点,坐标点用[x, y]或者[x,y,vis]表示(vis代表这个关键点是否可见) | |
visible | 表示某个关键点是否可见,使用整数来标识 | |
独立字段 | height/width | 图像的原始尺寸(长和宽) |
instance_id | 这个目标的id,定位到某个具体的目标 | |
category_id | 类别id,表示这个目标属于哪个类别 | |
is_crowd | 标注的是一个对象还是一组对象,使用0或者1来标识,如果是一组对象为1,否则为0, | |
area | 这个目标所占的面积,通常使用所占像素个数来表示 | |
num_keypoints | 关键点个数 | |
bbox | 目标的矩形框标注,通常使用[x,y,w,h]来表示 | |
segmentation | 目标的像素级分割标注,通常使用一组[x,y]坐标来表示 | |
center | 目标的中心点坐标,使用[x,y]来表示,通常代表的是目标矩形框的中心点坐标 | |
categories | 表示数据集中所包含的类别以及类别编号 | |
super_categories | 数据集中类别的父类 | |
keypoint_names | 关键点的名称 | |
skeleton | 关键点之间的连接关系 | |
scale | MPII中字段,表示目标框的缩放比例,MPII中由于目标框是正方形,scale*200px可以还原得到目标框的边长 | |
person | MPII中字段,代表图片中人的个数 | |
torsoangle | MPII中字段,代表人体躯干的偏转角度 | |
face/hand/foot valid | COCO-WholeBody中字段,代表是否有脸/手/脚的标注,值为0或者1 | |
face/hand/foot kpts | COCO-WholeBody中字段,表示脸/手/脚的关键点标注,为一组坐标点 | |
face/hand bbox | COCO-WholeBody中字段,表示脸/手的矩形框标注,表示为矩形框[x,y,h,w] | |
Hoi | Halpe中字段,使用整型表示,代表的是人体和其他物体发生交互的种类(例如0代表拿起,1代表坐,等等) | |
Variation | DeepFashion中字段,使用整型表示,代表的是任务的姿态 |
综上所述,需要描述一个关键点检测数据集,最基础的字段包括image_id, keypoints, visible这三个字段,数据集独立字段用户自行添加修改。
2. 模板展示
根据上述的调研结果,我们知道对于关键点检测/姿态估计任务,一个样本最重要的属性是图片的id(或路径)、每个目标的关键点标注,以及关键点是否可见这个属性,考虑到每张图片可能包含多个物体,可能有多个关键点标注,我们定义了一个嵌套结构体KeyPointLocalObject,用来表述单个目标的关键点标注的信息(即类别和关键点)。在关键点检测/姿态估计任务结构体的$fields 属性中定义了image和annotations两个字段,其中annotations字段则为多个KeyPointLocalObject结构体构成的列表(列表为空表示图片中没有关键点标注的物体)。最后,考虑到模板需要具有的代表性和可扩展性,在所有的属性中,有一些属性是必须的,其他一些特定数据集中的独立字段是可选的。基于上述考虑,我们制定了关键点检测/姿态估计任务的模板,如下所示:
KeypointClassDom:
$def: class_domain
classes:
- person
-
- ...
KeypointDescDom:
$def: class_domain
classes:
- "left eye"
-
- ...
skeleton:
- [14, 16]
- [5, 6]
- [10, 12]
- ...
-
定义了目标类别的KeypointClassDom。KeypointClassDom定义了目标的类别域,即这个目标属于哪些类别,比如person等。
-
定义了目标关键点名称以及连接关系的KeypointDescDom。KeypointDescDom定义了关键点的检测任务中一些事先定义好的域,包括关键点名称和关键点之间的连接关系skeleton。
KeyPointLocalObject:
$def: struct
$params: ['cdom1', 'cdom2']
$fields:
keypoint: Keypoint[dom=$cdom2]
label: Label[dom=$cdom1]
$optional: ["label"]
KeyPointSample:
$def: struct
$params: ['cdom1', 'cdom2']
$fields:
image: Image
annotations: List[etype=LocalObjectEntry[cdom1=$cdom1, cdom2=$cdom2]]
data:
sample-type: ObjectKeypointSample[cdom1=KeypointClassDom, cdom2=KeypointDescDom]
其次是定义了关键点检测sample的yaml文件。包括以下几个部分:
-
KeyPointSample。KeyPointSample定义了关键点检测中的一个sample对象,包括图像路径image以及标注了的目标列表annotations。
-
KeyPointLocalObject。KeyPointLocalObject定义了一个目标的标注,标注里包括:
-
目标的类别label,注意这个label所属的域是KeypointClassDom,即目标所属的类别。
-
关键点标注keypoint,即目标的关键点标注,Keypoint标注使用列表[x1,y1,v1,x2,y2,v2,.....]来表示,x1,y1表示关键点的坐标,v1表示这个关键点的可见性(关键点的可见性标注方面,不设定统一的标准,和原始数据集格式保持一致,认为<=0的值即代表不可见且无标注,>1代表有标注)。keypoint所属的域是KeypointDescDom即描述关键点的domain。
-
3. 使用方法
下面介绍怎么使用上面定义的模板来描述一个数据集,以COCOKeypoint2017为例,描述了sample的yaml文件keypoint-coco2017.yaml如下:
$dsdl-version: "0.5.0"
KeyPointLocalObject:
$def: struct
$params: ["cdom0", "cdom1"]
$fields:
iscrowd: Int
area: Num
category: Label[dom=$cdom0]
bbox: BBox
polygon: Polygon
num_keypoints: Int
ann_id: Int
keypoints: Keypoint[dom=$cdom1]
KeyPointSample:
$def: struct
$params: ["cdom0", "cdom1"]
$fields:
media: Image
height: Int
width: Int
image_id: Int
annotations: List[etype=KeyPointLocalObject[cdom0=$cdom0, cdom1=$cdom1]]
可以看出,COCO2017Keypoints数据集的模板除了关键点检测任务模板中的必须字段外(keypoints, visible, 以及image_id),还有许多数据集特有的独立字段
在检测模板中的一些字段含义如下: - $dsdl-version: 描述了该文件对应的dsdl版本。
-
ObjectKeypointEntry: 定义了关键点标注的描述方式的嵌套结构体,包含四个字段:
-
$def: struct, 表示这是一个结构体类型。
-
$params: 定义了形参,在这里即class domain。
-
$fields: 结构体类所包含的属性,具体包括:
- is_crowd: 是对一个物体的标注还是多个物体的标注。
- area: 目标实例的像素面积。
- category: 物体所属的类别。
- bbox: 目标的目标框标注,类型为BBox。
- polygon: 目标的实例分割标注,类型为Polygon。
- num_keypoints: 代表这个对象关键点的个数。
- ann_id: 实例标注在整个数据集中的编号。
- keypoints: 关键点标注的列表,其中每一个元素是一个[x,y,z]的三维坐标,x和y表示关键点位置,z表示这个关键点的可见情况。
-
-
KeypointDetectionSample: 定义了关键点检测/姿态估计任务sample的结构体,包含四个字段:
-
$def: struct, 表示这是一个结构体类型。
-
$params: 定义了形参,在这里即class domain。
-
$fields: 结构体类所包含的属性,具体包括:
- media 图片的路径。
- height: 图像的高。
- width: 图像的宽。
- image_id: 图像在数据集中的编号。
- annotations 标注信息,关键点检测/姿态估计任务中,为前面的ObjectKeypointEntry构成的一个列表。
-
描述了关键点检测任务的class-dom.yaml文件如下所示:
$dsdl-version: "0.5.0"
COCO2017KeypointsClassDom:
$def: class_domain
classes:
- person
COCO2017KeypointsDescDom[COCO2017KeypointsClassDom]:
$def: class_domain
classes:
- nose[person]
- left_eye[person]
- right_eye[person]
- ...
skeleton:
- [16, 14]
- [14, 12]
- [17, 15]
- ...
上面的文件中给出了关键点检测任务重类别域的定义,具体包含下列字段:
- COCO2017KeypointsClassDom:COCO2017Keypoint关键点检测的类别域,只包含了人这一个类别 。
- COCO2017KeypointsDescDom:COCO2017Keypoint关键点检测的数据集描述信息域,继承了COCO2017KeypointsClassDom,包含了数据集中对person的描述信息,包括关键点名称以及关键点之间的连接关系。