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

news2024/11/24 23:06:25

一些前提

先思考下面几个问题;

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.5
    y_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 + start
    d2 = (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的值,只取1
    
    return 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 / stride

    limb_vec = centerB - centerA  # 求出两个点的向量
    norm = np.linalg.norm(limb_vec)  # 是需要求单位向量,所以先计算范数,也就是向量模长
    if (norm == 0.0):  # 这里表示两个点基本重合了
        # print 'limb is too short, ignore it...'
        return accumulate_vec_map, count
    limb_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向量都不为0
    mask = 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  # 该区域计算次数都+1

    mask = count == 0

    count[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程序的调用;

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/876651.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【枚举倍数+容斥】CF803 F

Problem - F - Codeforces 题意&#xff1a; 思路&#xff1a; 正难则反&#xff0c;考虑容斥 即考虑gcd ! 1的所有子序列个数 因为子序列内部无序&#xff0c;因此不算真正的子序列&#xff0c;考虑枚举倍数 根据经典套路&#xff0c;我们去枚举 gcd&#xff0c;然后去枚…

【枚举gcd】CF803 C

Problem - C - Codeforces 题意&#xff1a; 思路&#xff1a; 要使所有数的 gcd 尽可能大 设 gcd k 那么就是 k1 * k&#xff0c;k2 * k&#xff0c;k3 * k&#xff0c;.... 它们的和是n 那么(k1 k2 k3 ....) * k n 根据惯用套路&#xff0c;我们去枚举 n 的因子即…

Vue3 setup tsx 子组件向父组件传值 emit

需求&#xff1a;Vue3 setup 父组件向子组件传值&#xff0c;子组件接收父组件传入的值&#xff1b;子组件向父组件传值&#xff0c;父组件接收的子组件传递的值。 父组件&#xff1a;parent.tsx&#xff1a; import { defineComponent, ref, reactive } from vue; import To…

使用GUI Guider工具开发嵌入式GUI应用 (3) - 使用label组件

使用GUI Guider工具开发嵌入式GUI应用 (3) - 使用label组件 文章目录 使用GUI Guider工具开发嵌入式GUI应用 (3) - 使用label组件引言在GUI Guider工程中创建label组件编译MCU工程并下载到开发板 引言 本节讲述在GUI Guider中&#xff0c;应用各种UI的基本元素&#xff0c;并顺…

信创领航,合作共赢 | GBASE南大通用广州天河产业信创联盟协会交流分享会

参与本次会议的成员有&#xff1a; 广州天河信创产业联盟秘书长林坚武、广州天河科技园信息产业联合会秘书长王飞、北明软件事业部总经理周丽娟、盛祺信息副总经理闫建、天亿马营销中心总经理梁志杰、观必达总经理缪明宝、省信息工程资源部总监周燕莉、高科信息生态总监王晖、…

Dubbo基于springboot学习笔记

本文参考&#xff1a;【优极限】最透彻的Dubbo教程&#xff08;dubbo经典之作完整版&#xff09;&#xff0c;阿里分布式框架dubbo零基础实战教学_手把手地啊你读懂底层源码【完整版】_哔哩哔哩_bilibili 1、 互联网架构演变 &#xff08;1&#xff09;单一应用架构 把系统中…

CentOS 8 非编译方式 yum 安装 FFmpeg

FFmpeg 是一套免费的开源计算机程序&#xff0c;它提供了录制、转换以及流化音视频的完整解决方案。FFmpeg 在 Linux 平台下开发&#xff0c;但它同样也可以在其它操作系统环境中编译运行&#xff0c;包括 Windows、Mac OS X 等。大多数文章都是说的ubuntu上如何安装&#xff0…

测试架构师如何落地性能测试方案(一)

背景描述&#xff1a; 最近刚接手一个新项目&#xff0c;在最开始的时候要求对这个项目做性能测试&#xff0c;产品经理也给不出性能需求&#xff0c;只因为这个项目是电商项目&#xff0c;可能会有高并发&#xff0c;秒杀的场景&#xff0c;所以产品经理要求我们对这个项目必…

亿发创新中医药信息化解决方案,自动化煎煮+调剂,打造智能中药房

传统中医药行业逐步复兴&#xff0c;同时互联网科技和人工智能等信息科技助力中医药行业逐步实现数字化转型。利用互联网、物联网、大数据等科技&#xff0c;实现现代科学与传统中医药的结合&#xff0c;提供智能配方颗粒调配系统、中药自动化调剂系统、中药煎配智能管理系统、…

前后端分离------后端创建笔记(05)用户列表查询接口(下)

本文章转载于【SpringBootVue】全网最简单但实用的前后端分离项目实战笔记 - 前端_大菜007的博客-CSDN博客 仅用于学习和讨论&#xff0c;如有侵权请联系 源码&#xff1a;https://gitee.com/green_vegetables/x-admin-project.git 素材&#xff1a;https://pan.baidu.com/s/…

2023年国赛数学建模思路 - 案例:感知机原理剖析及实现

文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法&#xff0c;其…

类对象数组抽取对象指定属性重新组成新的类对象数组

原本后台返回数据是这样&#xff1a; 我只想要每条数据对象的jianyanneirong和jianyannneirong1两个属性的信息&#xff1a; 1.使用map方法 //contentList是原本类对象数组let a contentList.map((val)>{return {jianyanneirong: val.jianyanneirong,jianyanneirong1: val.…

【EI/SCOPUS检索】第三届计算机视觉、应用与算法国际学术会议(CVAA 2023)

第三届计算机视觉、应用与算法国际学术会议&#xff08;CVAA 2023) The 3rd International Conference on Computer Vision, Application and Algorithm 2023年第三届计算机视觉、应用与算法国际学术会议&#xff08;CVAA 2023&#xff09;主要围绕计算机视觉、计算机应用、计…

展会邀请 | 虹科诚邀您参加8月16日深圳视觉系统设计技术会议

VisionCon视觉系统设计技术会议 将于8月16日在深圳深铁皇冠假日酒店隆重举行&#xff01; 人力成本的提高、国际关系的不确定性等众多因素&#xff0c;都在促使中国制造业采用更先进的自动化及智能化技术&#xff0c;同时也在加速核心技术的国产化。作为智能制造不可或缺的关…

机器学习笔记 - 在 Vision Transformer 中可视化注意力

2022 年,视觉变换器(ViT) 成为卷积神经网络(CNN) 的有力竞争对手,后者现已成为计算机视觉领域的最先进技术,并广泛应用于许多图像识别应用中。在计算效率和准确性方面,ViT 模型超过了当前最先进的 (CNN) 几乎四倍。 一、视觉转换器 (ViT) 如何工作? 视觉转换器模型的性能…

VictoriaMetrics部署及vmalert集成钉钉告警

1、部署VictoriaMetrics cd /usr/local wget https://github.com/VictoriaMetrics/VictoriaMetrics/releases/download/v1.65.0/victoria-metrics-amd64-v1.65.0.tar.gz mkdir victoria-metrics && tar -xvzf victoria-metrics-amd64-v1.65.0.tar.gz && \ mv …

python_PyQt5运行股票研究python方法工具V1.1_增加表格展示控件

承接 【python_PyQt5运行股票研究python方法工具V1.0】 地址 python_PyQt5运行股票研究python方法工具V1.0_程序猿与金融与科技的博客-CSDN博客 目录 结果展示&#xff1a; 代码&#xff1a; 示例py文件代码&#xff08;计算股票日横截面数据&#xff09; 参数json文件 表…

Java SPI机制

Java SPI机制 java的spi就是一种服务提供发现机制&#xff0c;在一方制定好接口规范后&#xff0c;通过spi的机制可以它的子实现类进行服务发现&#xff0c;以及加载它的子实现类&#xff0c;通过这种机制&#xff0c;让我们在引入第三方库时&#xff0c;不用讲第三方库中的类…

Dubbo 核心概念和架构

以上是 Dubbo 的工作原理图&#xff0c;从抽象架构上分为两层&#xff1a;服务治理抽象控制面 和 Dubbo 数据面 。 服务治理控制面。服务治理控制面不是特指如注册中心类的单个具体组件&#xff0c;而是对 Dubbo 治理体系的抽象表达。控制面包含协调服务发现的注册中心、流量管…

如何批量上传截图

转载&#xff1a;如何批量上传截图 目前用的截图是把iphone上的宣传图改大了分辨率而已&#xff0c;并不是真正ipad上的效果&#xff0c;举例&#xff0c;假设目前在做一个项目是 uniapp开发的&#xff0c;可以通过浏览器运行&#xff0c;运行的分辨率改成ipad截图就可以了&a…