# Mask R-CNN in Detectron2 for Key Point Detect
# 1.COCO数据集中定义的人体关键点检测任务
人体关键点检测常用于人体姿态估计,不仅需要找到人的bounding box
,还需要找出其中关键点的位置。coco
中human
这个类别每个对象定义了17种关键点,依次是['nose', 'left_eye', 'right_eye', 'left_ear', 'right_ear', 'left_shoulder', 'right_shoulder', 'left_elbow', 'right_elbow', 'left_wrist', 'right_wrist', 'left_hip', 'right_hip', 'left_knee', 'right_knee', 'left_ankle', 'right_ankle']
,此外还有skeleton
骨架字段,表示各个种类关键点之间的连接信息,如[6, 7]
表示left_shoulder
与left_elbow
相连。具体的关系如下:
{
1: {
'supercategory': 'person',
'id': 1,
'name': 'person',
'keypoints': ['nose', 'left_eye', 'right_eye', 'left_ear', 'right_ear', 'left_shoulder', 'right_shoulder', 'left_elbow', 'right_elbow', 'left_wrist', 'right_wrist', 'left_hip', 'right_hip', 'left_knee', 'right_knee', 'left_ankle', 'right_ankle'],
'skeleton': [
[16, 14],
[14, 12],
[17, 15],
[15, 13],
[12, 13],
[6, 12],
[7, 13],
[6, 7],
[6, 8],
[7, 9],
[8, 10],
[9, 11],
[2, 3],
[1, 2],
[1, 3],
[2, 4],
[3, 5],
[4, 6],
[5, 7]
]
}
}
在coco
的标注文件中,keypoints
检测数据集的标注信息类别如以上介绍的17种,另外在annotation
中增加了num_keypoints
和keypoints
字段,分别表示当前实例中包含了几个关键点和关键点的具体位置信息。keypoints
是长度为3k
的数组,其中k
是关键点的类别数目,coco
中k=17
,3
表示的是关键点的(x,y,v)
,x,y
是关键点在原图上的坐标,v
取0,1,2
,定义的是关键点是否可见,其中v=0
表示关键点没有标注,表示为(x=0,y=0,v=0)
,v=1
表示标注但被遮挡,v=2
表示标注且可见。
coco
中只标注了图像中非拥挤场景中级以上大小的human
的keypoints
,训练/验证/测试数据包括超过200000
张图像,250000
个人体图像标注了关键点,训练/验证数据中有超过150000
个人体图像,标注了超过1 700 000
个关键点,keypoints
标注文件的字段如下 (opens new window):
annotations[{
"id": int,
"image_id": int,
"category_id": int,
"segmentation": RLE or [polygon],
"area": float,
"bbox": [x,y,width,height],
"iscrowd": 0 or 1,
"keypoints": [x1,y1,v1,...],
"num_keypoints": int
}]
categories[{
"id": int,
"name": str,
"supercategory": str,
"keypoints": [str],
"skeleton": [edge],
}]
# 2.Detectron2中实现的Mask R-CNN用于Keypoints关键点检测
前面介绍了RPN
和RoI Pooler
,通过RPN
(opens new window)网络可以找到可能包含物体的proposal bounding boxes
,RoI Pooler
(opens new window)可以对proposal bounding boxes
的选定区域进行特征提取,以这两个技术为基础,Mask R-CNN
可用来实例分割和关键点检测。
Mask R-CNN
中实现的key points
检测如上图所示,使用的是heatmap
概率图的方式,keypoint_head
是roi_head
中的一个分支,其输入的features
是对backbone
提取的图像特征features
做RoI Pooler
后得到的, 输入keypoint_head
中的proposals
已经没有了层级信息,在做RoI Pooler
时有一个assign_boxes_to_levels
的过程,其原理参考FPN
(opens new window)论文中的方程1。 keypoint_head
的结构如上图,由8
个CNN
组成,后跟1
个Transposed CNN
和1
个向上2x
的interpolation
操作,用来输出key points heatmap prediction
。若输入keypoint_head
的feature shape
为NxCxHxW
,则输出feature shape
为NxKx(4*H)x(4*W)
,其中K
表示的是实例中定义的key point
总的类别,N
表示的是batch
中所有的instance
个数,其和图片的对应关系,保存在keypoint_head
的另一个输入instances
中。
keypoint_head
的最终预测输出kp_heatmap pred
是NxKx(4*H)x(4*W)
的特征图,在训练时,根据gt_keypoints
将其先转到(4*H)x(4*W)
尺度上得坐标(x,y)
,再取y*kp_heatmap pred.cols+x
作为此点的目标值,在K
个通道取有效点与kp_heatmap pred
上对应valid
通道的(4*H)x(4*W)
概率图计算交叉熵损失函数cross_entropy
。其原理是对每个(4*H)x(4*W)
的概率图上的元素做分类,target
就是当前类别keypoint
在heatmap
尺度上的位置。推理时,对每个instance
的K
通道(4*H)x(4*W)
的heatmaps
,在每个通道heatmap
上做softmax
,求得概率最大的元素位置,即对应通道上keypoint
的位置和评分,如此得到N
个实例在K
种关键点上预测的结果,NxKx(x,y,score)
。最后,可以根据score
的大小过滤掉K
个通道上评分比较低的点。