当前位置: 首页 > 编程日记 > 正文

Openpose+Tensorflow 这样实现人体姿态估计 | 代码干货


作者 | 李秋键

出品 | AI科技大本营(ID:rgznai100)

人体姿态估计指从单个 RGB 图像中精确地估计出人体的位置以及检测骨骼关键点的位置。人体姿态估计是计算机视觉领域的研究热点,是诸多计算机视觉任务的基础,如动作分类、异常行为检测、自动驾驶等。

Openpose 项目库运用流行的深度学习算法,能快速地识别图像中单人及多人的二维姿态,通过学习检测图像中人物的关键点位置,从而不依赖于图像中的局部特征完成人物目标检测,即使在图像噪声较大下,可准确提取人物的关键点,然后使用建模重构的方式对学习检测到的像中人物关键点位置进行姿态特征的提取,能更有效地保证精度及连续性。

本项目通过使用 Tensorflow 搭建 Openpose 环境实现对人体18个骨骼点的实时监测。其最终实现的效果如下图可见:

基本介绍

姿态估计分为单人姿态估计和多人姿态估计两大类,前者根据给定边界框的裁剪图像预测一个目标的所有人体关键点,后者需要进一步估计一幅图像中所有人的姿态。其中姿态识别的发展历程如下图可见:

Openpose 作为多人姿态估计算法比单人姿态估计更加复杂,不仅要扫描整个图像以寻找可能的人体关节候选区域,还要生成关节热图来进一步预测对应关键点的真实位置。同时还要根据当前身体关节和相邻层中每个身体部位之间的置信度,来确定哪些关节与当前关节属于同一个人。

1.1 环境要求

平台:Python3.6.5+Windows

主要用的库:opencv-python模块、Numpy模块、TensorFlow模块。

1.2 应用领域

人体姿态估计在人机交互、智能监控、虚拟现实以及运动分析等领域有着广阔的应用前景。

人机交互:基于姿态估计的人机交互可应用于日常生活中,例如,在我们日常使用的快手、抖音和微视等视频软件中,一些动作特效就是由姿态估计技术完成的,体感游戏也依赖于姿态估计技术。

智能监控:人体姿态估计目前最为广泛的应用是在智能监控中。随着人们安防意识的提升以及监控技术的日益成熟,智能监控系统的应用领域在不断扩大。智能监控与普通监控的区别主要在于其将人体姿态估计技术嵌入视频服务器中,运用算法估计、判断监控画面场景中的人体姿态,提取其中的关键信息,当出现异常行为时及时向用户发出警报。

其他应用:除了人机交互和智能监控,姿态估计还可应用于体育项目、队列评分、智能驾驶、零售等。例如在体育领域,人工智能教练系统来帮助运动员调整专业动作,为运动员提供个性化的运动训练体验

算法流程

Openpose算法姿态提取算法的流程如下图所示,可概括为以下几步:

(a)输入一个w×h的彩色人物图像;

(b)前馈网络对检测目标的关键点位置进行预测,并得到其二维置信度映射S以及一组2D矢量向量场L;

(c)用S和L来编码检测目标各部间的关联向量场;

(d)通过置信度分析检测目标的亲和向量场,最终标示出所有检测目标的2D关键点。

2.1 Openpose网络

Openpose的整体网络结构采用VGG网络作为骨架进行预训练处理。该网络分为两个部分,两部分能同时对提取到的关键点进行预测置信图、编码相邻关键点间的关联向量场并分别回归S和L。

图中上半部分即第一分支用以预测置信图,下半部分即第二分支用以预测关联向量场。每回归一次S和L即为完成一轮迭代预测,通过连续的t∈(1,⋯,T)轮迭代,就能形成整个预测网络体系结构。

每一阶段统计一次反馈损失函数,并把S、L及F即原始输入连接起来,进而得到下一阶段预测训练的输入。在进行了n轮迭代之后,S能起到一定程度的区分预测网络体系左右结构的作用,迭代次数越多其区分程度越显著。

其中网络模型代码如下:

def setup(self):min_depth = 8depth = lambda d: max(int(d *self.conv_width), min_depth)depth2 = lambda d: max(int(d *self.conv_width2), min_depth)with tf.variable_scope(None,'MobilenetV1'):(self.feed('image').convb(3, 3, depth(32), 2,name='Conv2d_0').separable_conv(3, 3, depth(64),1, name='Conv2d_1').separable_conv(3, 3, depth(128),2, name='Conv2d_2').separable_conv(3, 3, depth(128),1, name='Conv2d_3').separable_conv(3, 3, depth(256),2, name='Conv2d_4').separable_conv(3, 3, depth(256),1, name='Conv2d_5').separable_conv(3, 3, depth(512),1, name='Conv2d_6').separable_conv(3, 3, depth(512),1, name='Conv2d_7').separable_conv(3, 3, depth(512),1, name='Conv2d_8')# .separable_conv(3, 3, depth(512),1, name='Conv2d_9')# .separable_conv(3, 3,depth(512), 1, name='Conv2d_10')# .separable_conv(3, 3,depth(512), 1, name='Conv2d_11')# .separable_conv(3, 3,depth(1024), 2, name='Conv2d_12')# .separable_conv(3, 3,depth(1024), 1, name='Conv2d_13'))(self.feed('Conv2d_1').max_pool(2, 2,2, 2, name='Conv2d_1_pool'))(self.feed('Conv2d_7').upsample(2,name='Conv2d_7_upsample'))(self.feed('Conv2d_1_pool', 'Conv2d_3','Conv2d_7_upsample').concat(3, name='feat_concat'))feature_lv = 'feat_concat'with tf.variable_scope(None,'Openpose'):prefix = 'MConv_Stage1'(self.feed(feature_lv).separable_conv(3, 3, depth2(128),1, name=prefix + '_L1_1').separable_conv(3, 3, depth2(128),1, name=prefix + '_L1_2').separable_conv(3, 3, depth2(128),1, name=prefix + '_L1_3').separable_conv(1, 1, depth2(512),1, name=prefix + '_L1_4').separable_conv(1, 1, 38, 1,relu=False, name=prefix + '_L1_5'))(self.feed(feature_lv).separable_conv(3, 3, depth2(128),1, name=prefix + '_L2_1').separable_conv(3, 3, depth2(128),1, name=prefix + '_L2_2').separable_conv(3, 3, depth2(128),1, name=prefix + '_L2_3').separable_conv(1, 1, depth2(512),1, name=prefix + '_L2_4').separable_conv(1, 1, 19, 1,relu=False, name=prefix + '_L2_5'))for stage_id inrange(self.num_refine):prefix_prev = 'MConv_Stage%d' %(stage_id + 1)prefix = 'MConv_Stage%d' %(stage_id + 2)(self.feed(prefix_prev +'_L1_5',prefix_prev +'_L2_5',feature_lv).concat(3, name=prefix +'_concat').separable_conv(7, 7,depth2(128), 1, name=prefix + '_L1_1').separable_conv(7, 7,depth2(128), 1, name=prefix + '_L1_2').separable_conv(7, 7,depth2(128), 1, name=prefix + '_L1_3').separable_conv(1, 1,depth2(128), 1, name=prefix + '_L1_4').separable_conv(1, 1, 38, 1, relu=False,name=prefix + '_L1_5'))(self.feed(prefix + '_concat').separable_conv(7, 7,depth2(128), 1, name=prefix + '_L2_1').separable_conv(7, 7,depth2(128), 1, name=prefix + '_L2_2').separable_conv(7, 7,depth2(128), 1, name=prefix + '_L2_3').separable_conv(1, 1,depth2(128), 1, name=prefix + '_L2_4').separable_conv(1, 1, 19, 1,relu=False, name=prefix + '_L2_5'))# final result(self.feed('MConv_Stage%d_L2_5' %self.get_refine_num(),'MConv_Stage%d_L1_5' %self.get_refine_num()).concat(3, name='concat_stage7'))

2.2 模型训练

通过 TensorFlow 对姿态训练,官方提供了三个模型,分别为:

Cmu:基于模型的VGG预训练网络。其中使用TensorFlow将Caffe格式的Weights转换为tensorflow格式。

Dsconv:与cmu版本相同的架构,除了移动网络的深度可分离卷积。使用“迁移学习”来训练它,但它提供的速度和准确性都相对较差。

Mobilenet:在mobilenet模型的基础上,使用12个卷积层作为特征提取层。为了对小人物进行改进,对体系结构进行了微小的修改。根据网络规模参数学习三种模型。

算法测试

3.1 人体关键点:

Openpose算法针对已有"bottom-up"方法缺点:

(1)未利用全局上下文先验信息,也即图片中其他人的身体关键点信息;(2)将关键点对应到不同的人物个体,算法复杂度太高。提出了“Part Affinity Fields (PAFs)”方法,即每个像素是2D的向量,用于表征位置和方向信息。基于检测出的关节点和关节联通区域,使用greedy inference算法,可以将这些关节点快速对应到不同人物个体。

其中18个关键点对应位置分别如下:

3.2 算法测试:

其中image参数为所需要测试的图片路径;model为使用的测试模型,默认为cmu模型;通过直接运行提供的源码中的test.py即可得到运行效果。

parser =argparse.ArgumentParser(description='tf-pose-estimation run')
parser.add_argument('--image', type=str, default='./images/p2.jpg')
parser.add_argument('--model', type=str, default='cmu',help='cmu / mobilenet_thin/ mobilenet_v2_large / mobilenet_v2_small')
parser.add_argument('--resize', type=str, default='0x0',help='if provided, resizeimages before they are processed. ''default=0x0,Recommends : 432x368 or 656x368 or 1312x736 ')
parser.add_argument('--resize-out-ratio', type=float, default=4.0,help='if provided, resizeheatmaps before they are post-processed. default=1.0')
args = parser.parse_args()
w, h = model_wh(args.resize)
if w == 0 or h == 0:e =TfPoseEstimator(get_graph_path(args.model), target_size=(432, 368))
else:e =TfPoseEstimator(get_graph_path(args.model), target_size=(w, h))
# estimate human posesfrom a single image !
image =common.read_imgfile(args.image, None, None)
image=cv2.resize(image,(600,400))
cv2.imshow("2",image)
if image is None:logger.error('Image can not beread, path=%s' % args.image)sys.exit(-1)
t = time.time()
humans = e.inference(image, resize_to_default=(w > 0 and h > 0), upsample_size=args.resize_out_ratio)
elapsed = time.time() - t
logger.info('inference image: %sin %.4f seconds.' % (args.image, elapsed))
image = TfPoseEstimator.draw_humans(image, humans, imgcopy=False)
cv2.imshow("1",image)
cv2.waitKey(0)

代码:https://pan.baidu.com/s/1vkc1EQuaAUMqoaegkdZ_pA

提取码:i46w

作者简介:李秋键,CSDN博客专家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap竞赛获奖等。

在评论区留言你对Openpose、Tensorflow的学习心得

AI科技大本营将选出三名优质留言

携手【北京大学出版社】送出

《TensorFlow深度学习实战大全》一本

截至7月13日14:00点

更多精彩推荐
Windows 11 上手机!小米 8、一加 6T、微软 Lumia 950 XL 都可以运行深度学习教你重建赵丽颖的三维人脸Arm收购进展、元宇宙、GPU涨价……听听黄仁勋怎么说点分享点收藏点点赞点在看

相关文章:

主动防病毒内容篇

为何需要主动防病毒 近年来,对于防病毒软件效用的争论有愈演愈烈之势。我们知道,目前几乎所有的主流防病毒产品都是以分析病毒特征码为基础,通过升级安装在用户端的病毒特征码数据库实现对病毒的辨识。只有发现和确认了病毒之后,才…

icinga服务器系统监控软件的安装

系统环境rhel和Centos都可以安装这里我们所使用的安装包为中文版的icinga-cn-1.9.3.tar.bz2(1)安装icinga软件所支持的组件包(我们这里采用yum源的方式)组件:libdbi-dbd-mysql-0.8.3-5.1.el6.x86_64.rpmgd-devel-2.0.3…

size_t与ssize_t

size_t与ssize_t 为了增强程序的可移植性,便有了size_t,它是为了方便系统之间的移植而定义的,不同的系统上,定义size_t可能不一样。 l 在32位系统上定义为unsigned int ,也就是说在32位系统上是32位无符号整形…

自动驾驶中实时车道检测和警报

作者 | 小白 来源 | 小白学视觉未来十年,自动驾驶将彻底改变人们的出行方式。目前,自动驾驶应用程序目前正在测试各种案例,包括客车、机器人出租车自、动商业运输卡车、智能叉车以及用于农业的自动拖拉机。自动驾驶需要计算机视觉感知模块来…

OSS.Core基于Dapper封装(表达式解析+Emit)仓储层的构思及实现

最近趁着不忙,在构思一个搭建一个开源的完整项目,至于原因以及整个项目框架后边文章我再说明。既然要起一个完整的项目,那么数据仓储访问就必不可少,这篇文章我主要介绍这个新项目(OSS.Core)中我对仓储层的…

GNU Make chapter 2 —— Makefile 介绍

Makefile是由一系列的rule规则组成,这些rule都遵循以下形式: target ... : prerequisites ...command...... target(目标) 一般来说是需要生成的程序(模块)的名字,也可以是要执行的动作的名字,这…

C#编写的生成缩略图程序

if(fileupload.PostedFile!null) { //addto为要添加的属性,aboutfile为文件说明 string nam fileupload.PostedFile.FileName ; //取得文件名(抱括路径)里最后一个"."的索引 int i nam.LastIndexOf("."); /…

深度盘点Python11个主流框架:Pandas、Django、Matplotlib、Numpy、PyTorch......

六月份TIOBE编程语言排行榜,位居第二名的Python与第一名C语言之间的差距正在逐渐缩小。Python如此受欢迎一方面得益于它崇尚简洁的编程哲学,另一方面是因为强大的第三方库生态。要说杀手级的库,很难排出个先后顺序,因为python的明…

多表查询 外连接

关于外连接查询:链接查询的时候经常直接使用连接语句,可是如果只有主键没有写其他属性的时候,直接用连接查询得到的记录数是不完整的。 所以应该使用外连接查询:left join on 或者right join on. 例如在工单管理部分绑定到gridvie…

C#生成Excel文件的方法

一个示例&#xff1a; class AppTest { private Excel.ApplicationClass _x; public static void Main0() { AppTest a new AppTest(); a._x new Excel.ApplicationClass(); a._x.UserControl false; for (int i 0 ;i < 4; i) { a.SaveToXls("D://test//" i…

太酷了,Python 制作足球可视化图表 | 代码干货

作者 | 小F来源 | 法纳斯特大家好&#xff0c;我是小F。最近不少小伙伴都会熬夜看欧洲杯。今年的欧洲杯相比起往年的欧洲杯来说&#xff0c;可谓是冷门频出&#xff0c;出乎意料。真的不知道&#xff0c;第一会花落谁家&#xff5e;本期小F就和大家分享一下&#xff0c;用Pytho…

便捷,轻巧的Groovy数据库操作

本文主要介绍Groovy对数据的CRUD操作&#xff0c;熟悉groovy.sql包&#xff0c;测试使用的数据库是H2。1.数据库连接配置//数据库连接配置 def db [url:jdbc:h2:mem:groovy,user:root,password:root,driver:org.h2.Driver ];2.创建数据库连接&#xff0c;这里使用到Groovy的Sq…

Linux查看CPU和内存使用情况详解

在系统维护的过程中&#xff0c;随时可能有需要查看 CPU 使用率&#xff0c;并根据相应信息分析系统状况的需要。在 CentOS 中&#xff0c; 可以通过 top 命令来查看 CPU 使用状况。运行 top 命令后&#xff0c;CPU 使用状态会以全屏的方式显示&#xff0c;并且会处在对话的 模…

Fatal Error: Out of memory php内存溢出处理三种方法

有时候我们在运行php程序的时候会发现 Fatal Error: Out of memory 这样的提示&#xff0c;这有可能是程序中用到了大量了变量和对象&#xff0c;导致分配的内存不够用。 修改php.ini文件里的memory_limit参数 方法一&#xff1a;修改php.ini文件里的memory_limit默认参数128M&…

腾讯联合国家天文台启动探星计划,优图AI可提升120倍数据处理效率

7月9日&#xff0c;2021世界人工智能大会腾讯论坛在上海举办&#xff0c;腾讯云副总裁、腾讯优图实验室总经理吴运声发表了“人工智能的可持续发展之道”主题演讲&#xff0c;宣布全新推出腾讯云TI ONE、TI Matrix、TI DataTruth三大AI底层平台&#xff0c;可以提供包括算法开发…

C++:STL标准入门汇总

学无止境&#xff01;&#xff01;&#xff01; 第一部分&#xff1a;&#xff08;参考百度百科&#xff09; 一、STL简介 STL&#xff08;Standard Template Library&#xff0c;标准模板库)是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R…

C#精髓【月儿原创】第三讲 C#泛型有什么好处

说明&#xff1a;准备出一个系列&#xff0c;所谓精髓讲C#语言要点。这个系列没有先后顺序&#xff0c;不过尽量做到精。可能会不断增删整理&#xff0c;本系列最原始出处是csdn博客,谢谢关注。 C#精髓 第三讲 C#泛型有什么好处 作者&#xff1a;清清月儿 主页&#xff1a…

腾讯汤道生:人工智能最大的价值是“服务于人”

7月9日&#xff0c;2021世界人工智能大会腾讯论坛在上海拉开帷幕&#xff0c;腾讯高级执行副总裁、云与智慧产业事业群CEO汤道生开场致辞。汤道生表示&#xff0c;人工智能的最大价值是“服务于人”&#xff0c;让衣食住行实现“以消费者为中心”的智慧化供给&#xff0c;让生产…

[转]在Eclipse中使用JUnit4进行单元测试(中级篇)

我们继续对初级篇中的例子进行分析。初级篇中我们使用Eclipse自动生成了一个测试框架&#xff0c;在这篇文章中&#xff0c;我们来仔细分析一下这个测试框架中的每一个细节&#xff0c;知其然更要知其所以然&#xff0c;才能更加熟练地应用JUnit4。 一、 包含必要地Package…

linux下磁盘镜像软件DRBD的使用

一、 什么是DRBD DRBD的全称为&#xff1a;Distributed Replicated Block Device (DRBD)分布式块设备复制,DRBD是由内核模块和相关脚本而构成&#xff0c;用以构建高可用性的集群。其实现方式是通过网络来镜像整个设备。它允许用户在远程机器上建立一个本地块设备的实时镜像。与…

ASP.NET2.0轻松搞定统计图表【月儿原创】

ASP.NET2.0轻松搞定统计图表 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.3.27 本文讲述如何绘制条形图&#xff0c;折线图&#xff0c;柱形图&#xff0c;面积图等常见图形。 效果图&#xff1a; 手把手…

基于 Python 的 8 种常用抽样方法

抽样是统计学、机器学习中非常重要&#xff0c;也是经常用到的方法&#xff0c;因为大多时候使用全量数据是不现实的&#xff0c;或者根本无法取到。所以我们需要抽样&#xff0c;比如在推断性统计中&#xff0c;我们会经常通过采样的样本数据来推断估计总体的样本。上面所说的…

RegularExpressions(4) RegularExpressions 成员(一)

为什么80%的码农都做不了架构师&#xff1f;>>> 主要成员有: IRegex、ICapture、IMatch、IMatchCollection、IGroup、IGroupCollection 先看: ICapture; 常用的 IMatch、IGroup 都是从它继承而来; 作为一个底层接口一般不会被直接使用. 它为 IMatch、IGroup 提供了…

公有云环境下应用程序的自动化部署与水平扩展问题

先介绍了一下公有云计算环境下的一些特点&#xff0c;再根据这些特点探讨一下作为云计算用户而言&#xff0c;如何对应用程序做好自动化部署和水平扩展&#xff08;弹性计算&#xff09;的问题。阅读本文需要有一定的云计算知识、开发运维知识。 公有云环境的优势及其特点 公有…

另辟蹊径创建移动应用:iOS和Android代码共享

2019独角兽企业重金招聘Python工程师标准>>> 过去几年&#xff0c;移动应用席卷了整个世界&#xff0c;在工作和生活的方方面面改变着我们使用互联网的方式。创建移动应用的各种技术也随之兴起&#xff0c;各种开发流程也 将移动应用视为一等公民&#xff0c;开始考…

从0开始,基于Python探究深度学习神经网络

来源 | Data Science from Scratch&#xff0c; Second Edition作者 | Joel Grus全文共6778字&#xff0c;预计阅读时间50分钟。深度学习1. 张量2. 层&#xff08;Layer&#xff09;的抽象3. 线性层4. 神经网络作为一个层的序列5. 损失和优化6. 示例&#xff1a;XOR 重新…

ASP.NET2.0雷霆之怒盗链者的祝福【月儿原创】

ASP.NET2.0雷霆之怒盗链者的祝福 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.3.28 所谓盗链就是指其他网站把我们站点的文件链接帖到他们站上&#xff0c;这样白白占用我们的带宽。访问对于网站盗链行为&am…

数通手稿留档——BGP

本文转自Grodd51CTO博客&#xff0c;原文链接&#xff1a;http://blog.51cto.com/juispan/1954062&#xff0c;如需转载请自行联系原作者

ASP.NET2.0打通文件图片处理任督二脉【月儿原创】

ASP.NET2.0打通文件图片处理任督二脉 作者&#xff1a;清清月儿 主页&#xff1a;http://blog.csdn.net/21aspnet/ 时间&#xff1a;2007.4.1 1.最简单的单文件上传(没花头)2.多文件上传3.客户端检查上传文件类型(以上传图片为例)4.服务器端检查上传文件类型(以上…

PaaS变厚了

通过与包括东方通等在内的众多厂商的合作&#xff0c;华云数据的运营型PaaS变得越来越厚实。借助PaaS Plus的推出&#xff0c;华云数据要把云化的工作前移&#xff0c;在产品开发和测试阶段就开始云化&#xff0c;这会让传统企业的云化取得更好的效果。“PaaS是个筐&#xff0c…