当前位置: 首页 > news >正文

实战——OPenPose讲解及代码实现

一些前提

先思考下面几个问题;

1、什么是姿态估计?

参考:Point Detect任务,识别人体指定部分的关键点;

2、姿态估计中的难点是什么?

从干扰的角度,人体被遮挡对检测的影响很大;

如何对检测的点进行匹配拼接,并且是顺序拼接,而且确保是同一个人;

怎么提升性能,算法能够实时推理;

3、COCO数据集的关键点有几个,分别是?

在这里插入图片描述

数据集中是17个点,实际上训练时候还要加上一个脖子的点,通过两个肩膀的点计算;

4、应用领域有哪些?

  • 运动领域:例如健身动作识别;
  • 安全领域:路面防摔跤、游泳池溺水;
  • 特殊需求:比如是否佩戴某件物品,可以根据关键点和物体的定位;

5、姿态估计方法分为几个大类?

  • Top-down(自顶向下):先检测所有的人,再对每个框的人进行姿态估计输出结果

    优点:准确率高,点的回归率高;

    缺点:算法性能依赖检测效果,复杂度较高,实时性比较差;

    主要用于一些离线的项目,对实时性没要求!!!

  • bottom-up(自底向上):先检测所有关键点,再进行匹配连接

    优点:计算量较小,可以达到实时性的效果;

    缺点:精度较差,匹配策略比较复杂;

论文解读

论文地址:https://arxiv.org/pdf/1611.08050.pdf

参考文章:https://zhuanlan.zhihu.com/p/514078285

首先看一下整体的流程图:

在这里插入图片描述

首先输入一张W * H的图像进入网络,网络会有两个分支:

一是关键点检测,会生成一个热力图,检测出J个标签部位的点;

二是得到关键点的方向关系,也被称为PAF,对于每一个关键点都有其亲和域的方向;

最终结合二者,将所有关键点连接起来,输出一个完整的人体骨架;

算法流程

重点的关注点:

1、关键点的heatmap标注生成,采用高斯函数;

2、PAF:部分亲和域,文章提出的重要方法;

3、匹配策略:匈牙利匹配;

1、数据制作

采用的数据集为COCO数据集,其中人体骨骼点的标注信息为【x,y,label】,这里的label取值为0、1、2,分别表示不存在、遮挡、正常,其中不存在的关键点是需要去除的;

关键点高斯热力图实现:

def putGaussianMaps(center, accumulate_confid_map, sigma, grid_y, grid_x, stride):start = stride / 2.0 - 0.5y_range = [i for i in range(int(grid_y))]x_range = [i for i in range(int(grid_x))]xx, yy = np.meshgrid(x_range, y_range)      # 构建棋盘xx = xx * stride + start                    # 每个点在原始图像上的位置yy = yy * stride + startd2 = (xx - center[0]) ** 2 + (yy - center[1]) ** 2  # 计算每个点和GT点的距离exponent = d2 / 2.0 / sigma / sigma                 # 这里在做一个高斯计算mask = exponent <= 4.6052                           # 将在这个阈值范围内的点用True记录cofid_map = np.exp(-exponent)                       # 这里做一个标准化cofid_map = np.multiply(mask, cofid_map)            # 取出对应关系为True的点accumulate_confid_map += cofid_map                  # 将每个点计算的结果都累加到上一次的特征中accumulate_confid_map[accumulate_confid_map > 1.0] = 1.0      # 对结果大于1的值,只取1return accumulate_confid_map    # 返回热力图(heatmap)

PAF数据计算的实现:

def putVecMaps(centerA, centerB, accumulate_vec_map, count, grid_y, grid_x, stride):centerA = centerA.astype(float)centerB = centerB.astype(float)thre = 1  # 表示宽度,也就是一个设定好的参数centerB = centerB / stride  # 缩放比例特定到特征图中centerA = centerA / stridelimb_vec = centerB - centerA  # 求出两个点的向量norm = np.linalg.norm(limb_vec)  # 是需要求单位向量,所以先计算范数,也就是向量模长if (norm == 0.0):  # 这里表示两个点基本重合了# print 'limb is too short, ignore it...'return accumulate_vec_map, countlimb_vec_unit = limb_vec / norm  # 向量除以模长,得到单位向量# print 'limb unit vector: {}'.format(limb_vec_unit)# To make sure not beyond the border of this two points# 得到所有可能存在方向的区域(这里就用到了之前的超参数阈值)min_x = max(int(round(min(centerA[0], centerB[0]) - thre)), 0)max_x = min(int(round(max(centerA[0], centerB[0]) + thre)), grid_x)min_y = max(int(round(min(centerA[1], centerB[1]) - thre)), 0)max_y = min(int(round(max(centerA[1], centerB[1]) + thre)), grid_y)# 得到一个可能存在向量的矩形框range_x = list(range(int(min_x), int(max_x), 1))range_y = list(range(int(min_y), int(max_y), 1))xx, yy = np.meshgrid(range_x, range_y)  # 制作一个网格ba_x = xx - centerA[0]  # the vector from (x,y) to centerA 根据位置判断是否在该区域上(分别得到X和Y方向的)ba_y = yy - centerA[1]# 向量叉乘根据阈值选择赋值区域,任何向量与单位向量的叉乘即为四边形的面积# 这里是重点步骤,也就是论文中的公式,表示计算出两个向量组成四边形的面积limb_width = np.abs(ba_x * limb_vec_unit[1] - ba_y * limb_vec_unit[0])mask = limb_width < thre  # mask is 2D (小于阈值的表示在该区域上)vec_map = np.copy(accumulate_vec_map) * 0.0  # 构建一个全为0的矩阵# 这行代码主要作用是将mask扩展一个维度并且赋值给vec_map数组vec_map[yy, xx] = np.repeat(mask[:, :, np.newaxis], 2, axis=2)# 在该区域上的都用对应的方向向量表示(根据mask结果表示是否在,通过乘法的方式)vec_map[yy, xx] *= limb_vec_unit[np.newaxis, np.newaxis, :]# #在特征图中(46*46)中 哪些区域是该躯干所在区域,判断x或者y向量都不为0mask = np.logical_or.reduce((np.abs(vec_map[:, :, 0]) > 0, np.abs(vec_map[:, :, 1]) > 0))# 每次返回的accumulate_vec_map都是平均值,现在还原成实际值accumulate_vec_map = np.multiply(accumulate_vec_map, count[:, :, np.newaxis])accumulate_vec_map += vec_map  # 加上当前关键点位置形成的向量count[mask == True] += 1  # 该区域计算次数都+1mask = count == 0count[mask == True] = 1  # 没有被计算过的地方就等于自身(因为一会要除法)accumulate_vec_map = np.divide(accumulate_vec_map, count[:, :, np.newaxis])  # 算平均向量count[mask == True] = 0  # 还原回去return accumulate_vec_map, count

这两个函数是最重要的两个部分,也就是对训练数据的处理,生成出需要的训练数据,其中遍历原始数据的代码并没有展示,详细可以看看源代码中的data.py文件;

2、模型搭建

下面看一下总的网络架构:

在这里插入图片描述

模型的backbone可以选择比较多,这里选择VGG19,在Stage1之前得到一个46x46大小的特征图;

接下来通过几个stage不断地·扩大感受野,提升模型的效果,每次上面结构输出关键点的热力图(维度为19),下面结果输出关键点的PAF方向信息(维度为38),计算损失保存,接下来将两个维度的特征进行拼接,再传入接下来的stage中,通过不断的堆叠提升整个算法的精度;

3、预测推理

预测模型这里,在官方源码中是将paf的处理封装在一个cpp库中,通过编译得到静态库,代码中可以调用;

这里PAF的处理主要是采用积分计算的方式,也就是对于连线的点的方向选择,采用积分的方式计算最佳连线策略;

运行picture_demo.py得到最终的结果,如下图所示:

模型结果及推理耗时:

可以看出模型的结构为Vgg19,这是可以替换的,并且特征图的输出维度为38和19,这也符合定义的骨骼点分类和连接方式;

总结

一些细节例如匈牙利匹配算法、PAF权值计算、模型结构改进等在这里并没有过多介绍;

并且对于现在OPenpoe的使用,主要是将其编译成一个库,作为Python程序的调用;

并且相比于本次的代码,其实时性很好,符合大部分落地场景的需求;

如果有想要本次项目源码的,可以在评论区留下邮箱,也欢迎大家一起讨论,后续也会探讨更多最新的技术;

相关文章:

实战——OPenPose讲解及代码实现

一些前提 先思考下面几个问题&#xff1b; 1、什么是姿态估计&#xff1f; 参考&#xff1a;Point Detect任务&#xff0c;识别人体指定部分的关键点&#xff1b; 2、姿态估计中的难点是什么&#xff1f; 从干扰的角度&#xff0c;人体被遮挡对检测的影响很大&#xff1b;…...

专注于创意设计,为您的小程序和网站建设带来更多的可能性

随着移动互联网的快速发展&#xff0c;越来越多的企业开始关注小程序和网站建设&#xff0c;以此来拓展业务和提升品牌形象。 在这个领域中&#xff0c;创意设计扮演着关键的角色。它不仅可以帮助企业打造独特的形象和品牌&#xff0c;还能够提高用户体验和购买决策的效率。 因…...

ATF(TF-A)安全通告 TFV-6 (CVE-2017-5753, CVE-2017-5715, CVE-2017-5754)

ATF(TF-A)安全通告汇总 目录 一、ATF(TF-A)安全通告 TFV-6 (CVE-2017-5753, CVE-2017-5715, CVE-2017-5754) 二、Variant 1 (CVE-2017-5753) 三、Variant 2 (CVE-2017-5715) 四、Variant 3 (CVE-2017-5754) 一、ATF(TF-A)安全通告 TFV-6 (CVE-2017-5753, CVE-2017-5715, C…...

vue3 基础语法 02

你好&#xff0c;今天过的怎么样呀&#xff0c;嘿嘿&#xff0c;加油夏 &#x1f495; 文章目录 一、模板语法 一、模板语法 React的开发模式&#xff1a; React 使用的 jsx&#xff0c;对应的代码编写的类似于js的一种语法&#xff1b;通过 Babel 将 jsx &#xff0c; 编译成…...

版本控制工具——git

版本控制是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理&#xff0c;是软件配置管理的核心思想之一。 版本控制最主要的功能就是追踪文件的变更。它将什么时候、什么人更改了文件的什么内容等信息忠实地了记录下来。每一次文件的改变&#xff0c;文件的…...

超详细,自动化测试实战-获取配置文件信息(实例源码)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 配置文件的类型 …...

spring 2.7.14 cors 设置 allowedOrigins(“*“)通配符 失效怎么解决

失效代码&#xff1a; package com.yukuanyan.searcher_web.config;import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebM…...

一、Go的前景与优势、基础语法

Go简介 Go的公司、场景应用 公司占比&#xff1a; 字节跳动领先&#xff0c;公司内部有上万个微服务使用go来编写&#xff0c;不久前也开源了GO RPC框架KiteX。 同时&#xff0c;腾讯、百度、美团、滴滴、深信服、平安、OPPO、知乎、去哪儿、360、金山、微博、哩哔哩、七牛、…...

shell脚本循环语句

shell脚本循环语句 一.echo命令二.查看当前系统的时间--date命令三.循环语句for四.while循环语句结构五.while循环语句结构&#xff08;迭代&#xff09;六.continue和break 一.echo命令 echo -n 表示不换行输出 echo -e输出转义符&#xff0c;将转义后的内容输出到屏幕上 常…...

二叉树题目:二叉树的直径

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;二叉树的直径 出处&#xff1a;543. 二叉树的直径 难度 3 级 题目描述 要求 给定二叉树的根结点 root \texttt{root} root&#xff0c;返回其直径…...

嵌入式:C高级 Day4

一、整理思维导图 二、写一个函数&#xff0c;获取用户的uid和gid并使用变量接收 三、整理冒泡排序、简单选择排序和快速排序的代码 冒泡排序 #include <myhead.h>void output(int arr[], int len); void bubble_sort(int arr[], int len);int main(int argc, const ch…...

cmake常用命令(1)——函数相关

一、function/endfunction cmake中的函数与其他语言相似&#xff0c;表示一个命令集&#xff0c;可以被重复调用。形式如下&#xff1a; function(<name> [<arg1> ...])<commands> endfunction() function&#xff1a;表示函数开始 <name>&#xf…...

阿里三年功能测试的一些感悟

一、前言 功能测试是测试工程师的基础功&#xff0c;很多人功能测试还做不好&#xff0c;就想去做性能测试、自动化测试。很多人对功能测试的理解就是点点点&#xff0c;如何自己不用心去悟&#xff0c;去研究&#xff0c;那么你的职业生涯也就停留在点点点上了。在这里&#…...

React源码解析18(4)------ completeWork的工作流程【mount】

摘要 经过上一章&#xff0c;我们得到的FilberNode已经具有了child和return属性。一颗Filber树的结构已经展现出来了。 那我们最终是想在页面渲染真实的DOM。所以我们现在要在completeWork里&#xff0c;构建出一颗离屏的DOM树。 之前在说FilberNode的属性时&#xff0c;我们…...

Kafka: 详解、使用教程和示例

Kafka: 详细介绍、使用教程和示例 什么是 Kafka&#xff1f; Kafka 是一个分布式的流处理平台&#xff0c;最初由 LinkedIn 开发&#xff0c;现已成为 Apache 基金会的顶级项目。它以高吞吐量、可靠性和可扩展性而闻名&#xff0c;被广泛应用于实时数据传输、日志收集、事件处…...

【LeetCode周赛】LeetCode第358场周赛

LeetCode第358场周赛 数组中的最大数对和翻倍以链表形式表示的数字限制条件下元素之间的最小绝对差 数组中的最大数对和 给你一个下标从0开始的整数数组nums。请你从nums中找出和最大的一对数&#xff0c;且这两个数数位上最大的数字相等。 返回最大和&#xff0c;如果不存在满…...

Node.js学习笔记-04

这第九章也是个大重点 九、玩转进程 Node在选型时决定在V8引擎之上构建&#xff0c;也就意味着它的模型与浏览器类似。 本章关于进程的介绍和讨论将会解决如下两个问题&#xff1a; 单进程单线程并非完美&#xff0c;如今CPU基本均是多核的&#xff0c;真正的服务器&#xf…...

基于dbn+svr的交通流量预测,dbn详细原理

目录 背影 DBN神经网络的原理 DBN神经网络的定义 受限玻尔兹曼机(RBM) DBN+SVR的交通流量预测 基本结构 主要参数 数据 MATALB代码 结果图 展望 背影 DBN是一种深度学习神经网络,拥有提取特征,非监督学习的能力,是一种非常好的分类算法,本文将DBN+SVR用于交通流量预测…...

【第一阶段】kotlin中反引号中的函数名特点

在kotlin中可以直接中文定义函数&#xff0c;使用反引号进行调用 eg: fun main() {2023年8月9日定义的函数(5) }private fun 2023年8月9日定义的函数(num:Int){println("反引号的用法$num") }执行结果 在Java中is,in可以定义方法&#xff0c;但是在kotlin中is,in是…...

数据分析-python学习 (1)numpy相关

内容为&#xff1a;https://juejin.cn/book/7240731597035864121的学习笔记 导包 import numpy as np numpy数组创建 创建全0数组&#xff0c;正态分布、随机数组等就不说了&#xff0c;提供了相应的方法通过已有数据创建有两种 arr1np.array([1,2,3,4,5]) 或者datanp.loadt…...

<6>-MySQL表的增删查改

目录 一&#xff0c;create&#xff08;创建表&#xff09; 二&#xff0c;retrieve&#xff08;查询表&#xff09; 1&#xff0c;select列 2&#xff0c;where条件 三&#xff0c;update&#xff08;更新表&#xff09; 四&#xff0c;delete&#xff08;删除表&#xf…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统

目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索&#xff08;基于物理空间 广播范围&#xff09;2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

elementUI点击浏览table所选行数据查看文档

项目场景&#xff1a; table按照要求特定的数据变成按钮可以点击 解决方案&#xff1a; <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么&#xff1f;它的作用是什么&#xff1f; Spring框架的核心容器是IoC&#xff08;控制反转&#xff09;容器。它的主要作用是管理对…...