赞
踩
以下贴上原论文摘要翻译:
我们介绍了一种新的无热图联合检测方法YOLO-pose,以及基于流行的YOLO目标检测框架的图像中的二维多人姿态估计。现有的基于热图的两阶段方法是次优的,因为它们不是端到端可训练的,而且训练依赖于替代L1损失,这并不等同于最大化评价指标,即对象关键点相似度(OKS)。我们的框架允许我们端到端训练模型,并优化OKS度量本身。该模型在一次前进中学习联合检测多人的边界盒及其相应的2D姿态,从而引入了自顶向下和自底向上方法的最佳效果。该方法不需要自底向上方法的后处理,将检测到的关键点分组成骨架,因为每个边界框都有一个相关的姿态,从而实现了关键点的固有分组。与自顶向下方法不同的是,由于所有人的位置和姿态都在一个推论中,因此不需要多次向前传递。YOLO-pose在COCO验证(90.2% AP50)和测试开发集(90.3% AP50)上实现了最新的最先进的结果,超越了所有现有的无翻转测试、多尺度测试或任何其他测试时间增加的单一前向通过方法。本文报告的所有实验和结果都没有增加任何测试时间,不像传统的方法使用翻转测试和多尺度测试来提高性能。
我们可知,Yolo-pose不像传统的姿态识别器那样生成关键点满足高斯分布的热力图方式去估计关键点,而是直接通过回归的方式计算出关键点位置。
贡献:
1、提出解决多人姿态估计与目标检测。因为姿态估计和目标检测的主要挑战,如规模变化和遮挡是共同的。因此,迈出了统一这两个领域的第一步。我们的方法将直接受益于物体检测领域的任何进步。
2、我们的无热图方法使用标准的OD后处理,而不是涉及像素级NMS、调整、细化、线积分和各种分组算法的复杂后处理。由于没有独立的后处理,该方法具有端到端训练的鲁棒性。
3、将目标检测的IOU损失扩展到关键点。对象关键点相似度(OKS)不仅用于评估,而且是训练的损失。OKS损失是尺度不变的,本质上对不同的关键点给予不同的权重我们实现了SOTA AP50,计算量少了~4倍。例如,在coco test-dev2017上,Yolov5m6-pose在66.3 GMACS时实现了89.8的AP50,而SOTA DEKR[30]在283.0 GMACS时实现了89.4的AP50。
4、提出了一种联合检测和姿态估计框架。通过OD网络,姿态估计几乎没有开销。
5、我们提出了低复杂度的模型变体,其性能显著优于像EfficientHRNet这样的实时聚焦模型。
直接贴论文里的图
该模块位于yolo.py中,基于yolo修改的下游任务一般修改该模块。
由网络框架我们可知,yolo-pose有四个head,分别对应四个不同尺度的特征图,分别是8080,4040,2020,1010。
在yolo中有预设anchor的操作,一般对对一个grid预设3个,yolo-pose也不例外,因此需要将head输出tensor转为:
1:
a = self.m[i](x[i]) b = self.m_kpt[i](x[i]) x[i] = torch.cat((self.m[i](x[i]), self.m_kpt[i](x[i])), axis=1) self.m = nn.ModuleList(nn.Conv2d(x, self.no_det * self.na, 1) for x in ch) # output conv if self.nkpt is not None: if self.dw_conv_kpt: #keypoint head is slightly more complex self.m_kpt = nn.ModuleList( nn.Sequential(DWConv(x, x, k=3), Conv(x,x), DWConv(x, x, k=3), Conv(x, x), DWConv(x, x, k=3), Conv(x,x), DWConv(x, x, k=3), Conv(x, x), DWConv(x, x, k=3), Conv(x, x), DWConv(x, x, k=3), nn.Conv2d(x, self.no_kpt * self.na, 1)) for x in ch) else: #keypoint head is a single convolution self.m_kpt = nn.ModuleList(nn.Conv2d(x, self.no_kpt * self.na, 1) for x in ch)
为什么是18:
18 = 3 * 6
3:anchor数量
6 = x,y,w,h,conf,cls
为什么是51:
51 = 17 * 3
13:coco数据集关键点数量
3 = x,y,conf
self.m[i]使用1*1卷积,输出通道为18,输出通道为153,用于坐标的预测:
self.m_kpt[i]的操作就可多了,用于关键点的预测:
Sequential( (0): Conv( (conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=128) (act): SiLU(inplace=True) ) (1): Conv( (conv): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1)) (act): SiLU(inplace=True) ) (2): Conv( (conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=128) (act): SiLU(inplace=True) ) (3): Conv( (conv): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1)) (act): SiLU(inplace=True) ) (4): Conv( (conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=128) (act): SiLU(inplace=True) ) (5): Conv( (conv): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1)) (act): SiLU(inplace=True) ) (6): Conv( (conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=128) (act): SiLU(inplace=True) ) (7): Conv( (conv): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1)) (act): SiLU(inplace=True) ) (8): Conv( (conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=128) (act): SiLU(inplace=True) ) (9): Conv( (conv): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1)) (act): SiLU(inplace=True) ) (10): Conv( (conv): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), groups=128) (act): SiLU(inplace=True) ) (11): Conv2d(128, 153, kernel_size=(1, 1), stride=(1, 1)) )
2:
3:
4:
将4个不同尺度的预测结果合并:
5:
对合并完结果做nms
pred = non_max_suppression(pred, opt.conf_thres, opt.iou_thres, classes=opt.classes, agnostic=opt.agnostic_nms, kpt_label=kpt_label)
将预测出的边框信息和关键点信息转成实际尺寸大小:
scale_coords(img.shape[2:], det[:, :4], im0.shape, kpt_label=False)
scale_coords(img.shape[2:], det[:, 6:], im0.shape, kpt_label=kpt_label, step=3)
画图:
plot_one_box(xyxy, im0, label=label, color=colors(c, True), line_thickness=opt.line_thickness, kpt_label=kpt_label, kpts=kpts, steps=3, orig_shape=im0.shape[:2])
(end,记一次debug detect模块的个人理解,帮助学习,水平有限~~)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。