[开源]基于姿态估计的运动计数APP开发(一)

前言:

    看着自己日渐发福的身材,回想当年的英姿煞爽,感慨颇多。作为一个有羞耻心的程序猿,我决定开始减肥。考察了数十项减肥项目,我选择了仰卧起坐。因为它场地限制小,时间限制短,不剧烈,不伤身,最关键的是能够一边看综艺,一边锻炼,简直妙不可言!试行了几天之后发现有一个比较棘手的问题,做着做着,就忘了做了多少个,一脸懵逼,万般无奈,于是便有了这个运动计数APP的灵感。不用太花哨的功能,最最简单的一点,能够对我的仰卧起坐进行计数,并显示在APP的界面上,到了10,20这种(%10==0)的关键节点上面会有林志玲小姐姐的加油鼓励!其实界面的编码并不难,难的是算法的开发。。。

总体思路:

    计算机视觉中有一个应用分支叫做姿态估计,能够以关键点的方式来估计出一个/多个人的姿态信息。如下图所示:

为了算法开发减低难度,这个APP只需要进行单人的姿态检测即可。如果姿态检测的效果好,那么理论上就能完成仰卧起坐的计数。计数规则很简单:通过观察仰卧起坐的姿势,只要代表头部的关键点与代表膝盖的关键点之间的欧氏距离出现周期性的变化,即可认为是在做仰卧起坐,并且可以方便的统计出频率与周期,从而进行计数。所以剩下的问题就是如何选择设计一个模型,能够又快又好的进行姿态检测了。毕竟要在手机上实现,没有速度,一切都是扯淡!

拍拍脑门的第一个方案:

    由于我之前做的比较多的是目标检测,没有做过姿态估计,对该领域不太了解,但是直觉却告诉我这很简单。因为做的是单人的姿态检测,并且假设我需要预测13个关键点。如下图所示:

扫描二维码关注公众号,回复: 15625717 查看本文章

那么理论上我只要回归13*2的坐标即可。一个很自然的思路就是用轻量级的分类网络,将最后的分类向量修改为坐标回归向量即可。有了这个一拍脑门的想法之后,分分钟就改好了shufflenetV2的网络,如下图所示:

此时,离真正的训练还有一步之遥,那就是训练数据。由于姿态估计是一个比较大众的领域,已经有很多开源的数据集,恰好我的笔记本上有COCO数据集,里面有人体姿态估计的标签,于是就选择了COCO作为训练集。由于COCO的姿态检测包含多人,我修改的网络只针对一个人。于是我把COCO中有姿态估计的图片进行了过滤,只保留了单人的姿态估计图片。大概有2万多张,还好,数目不算少。

准备好网络与数据集之后,启动了我可怜的笔记本,那风扇的轰鸣声让我觉得异常踏实。经过3天2夜的鏖战,竟然发现loss无法下降!此时直觉告诉我用Global Pooling的方式数据损失太大,用于分类还可以,用于回归可能不行。于是我将最后的GlobalingPooling去掉,直接使用两个FC层进行预测。如下图所示:

又经过三天两夜的咆哮,loss还算比较正正常。当我满心欢喜的准备做测试的时候,发现效果苦不堪言。基本无法使用。。。。看来姿态估计没有我想的那么简单,需要从长计议。

第二个方案:

经过狂补各种姿态估计的知识后,发现直接回归坐标确实已经很少使用。取而代之的是使用heatmap来输出关键点的位置。这和anchor free的目标检测中的centness之类的做法差不多,即通过查找heatmap中响应值最大的点来确定关键点的坐标。如下图所示(只显示部分heatmap):

思考了一下原因,直接回归坐标,通常会将最后的featuremap下采样到很小,这样才能够实现全局的回归,但是关键点预测这种任务对位置信息非常敏感,过小的特征会极大的丢失空间信息,因而导致预测位置非常不准。而heatmap方式一般要求最后的特征图比较大,通常是输入图片的1/2或者1/4,那么就非常适合做一些空间相关的任务。其实如果人为的将特征图压缩的很小,heatmap的方式也一样不太准。有了上面的思考,便有了第二个方案,就是将shufflenet最终输出的7*7的特征图进行上采样到13*56*56大小(考虑到最终的应用以及场景,56*56足够实现仰卧起坐动作的识别),13表示的是13个关键点。然后输出的特征经过sigmoid激活之后便得到了13*56*56的heatmaps。这里多提两点,就是heatmap标签的设计和loss的平衡问题。先说说标签的设计,如果只是简单的将标签转化成一个one_hot的heatmap,效果不会太好。因为标签点附件的点实际上对于网络来说提取的特征是类似的,那么如果强行把不是标签附近的点设置为0,表现不会很好,一般会用高斯分布来制作标签heatmap,如下图所示:

另外要说的就是loss的平衡了,上面的标签heatmap大家也看到了,无论是one-hot的heatmap还是高斯分布的heatmap,大部分的点都是负样本点,直接使用MSE而不加以区分,网络基本上会训练出一个输出全是0的heatmap。主要原因就是训练的梯度被负样本压制,正样本的梯度实在太小。因此需要做一个分区。我这里把正负样本的比重设置为10:1

又开始3天2夜的咆哮,网络总算能够work了,对于coco上训练过的数据,效果不错。如下图所示:

但是对于从百度拉下来的仰卧起坐图片,效果有点欠缺,分析了一下原因,COCO的单人姿态图片中,都是一些很生活化的场景,很少有人躺在地上的情形。因此需要对数据做一些增强或者增加一些特别的仰卧起坐的图片。

总结:

目前的网络只是能够work,距离真正的落地还有一段距离。主要表现在对仰卧起坐的泛化性上比较差。后期的计划主要包括两方面:一方面是基于数据。例如增加一些姿态估计的数据集,MPII等,或者是自己收集一些仰卧起坐的视频,人工标注,另外还可以对数据增强进行完善。另外一方面是考虑网络的设计以及loss的求解上面。网络是否可以增加一些shortcut,是否可以接借鉴一些成熟的姿态检测网络,以及对于最终的heatmap是否可以使用softargmax转换成坐标回归等。这些都留在下一期的内容中。

@end

猜你喜欢

转载自blog.csdn.net/cjnewstar111/article/details/115445478