栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

PifPaf: Composite Fields for Human Pose Estimation

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

PifPaf: Composite Fields for Human Pose Estimation

发表于arxiv, 一个bottom-up的方法, 用来预测单张图片中多个人体的关节点位置, 已开源

arxiv地址: https://arxiv.org/abs/1903.06593
github地址: https://github.com/vita-epfl/openpifpaf
2021年新出的3D姿态估计paper:https://arxiv.org/pdf/2103.02440.pdf
github地址:https://github.com/openpifpaf/openpifpaf

文章比较难懂的原因是,这篇文章是多篇文章思想的集合,追根溯源,必须要去看这篇文章引用的文章,你才会看得懂:

《Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields》
《Towards Accurate Multi-person Pose Estimation in the Wild》
《PersonLab: Person Pose Estimation and Instance Segmentation with a Bottom-Up, Part-based, Geometric Embedding Model》
《Rethinking the Heatmap Regression for Bottom-up Human Pose Estimation》

带着问题看论文

1.不同类(头、身体,不同通道的)怎么连接的?

可以参考openpose文章去理解:《Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields》输出特征图的维度是[b, 17, 7,h, w],17个关节的预测在不同channel,但是大小是一样,可以拼到一张图上,因为我们知道,脚和膝盖、膝盖和腰是连接,那先把所有检测出来的脚和所有的膝盖连接起来,之后再做NMS或其他后处理方法去掉不对的连接。

PIF的offset图为什么渐进的?而不是指向Ground True的方向?

文章是在《Towards Accurate Multi-person Pose Estimation in the Wild》文章的基础上,添加 p b i , j p_b^{i,j} pbi,j​和 p σ i , j p_sigma^{i,j} pσi,j​,公式也改了,但是含义没变

PAF怎么产生的,怎么遍历成一个人的?

借鉴文章《PersonLab: Person Pose Estimation and Instance Segmentation with a Bottom-Up, Part-based, Geometric Embedding Model》的贪心法

所以,这篇文章就是拼接的

一. 解决问题和贡献 1.1. 解决问题

bottom-up方案(OpenPose)在地低分辨率上表现差,文章在《Towards Accurate Multi-person Pose Estimation in the Wild》文章的基础上,添加 p b i , j p_b^{i,j} pbi,j​和 p σ i , j p_sigma^{i,j} pσi,j​,将特征图的定位转换到原图上做处理up-bottom(Mask RCNN)方案在多人有遮挡的场景上表现差,以及错检

红圈中是错检测,黑框中的是漏检的


Mask RCNN在拥挤的场景漏检

1.2. 贡献

bottom-up, box-free, end-to-end cnn architecture提出Part Intensity Field (PIF) 用来定位人体关节点位置提出Part Association Field (PAF)用来确定关节点之间的连接 1.3. 整体结构

二. 关节点定义

过早时期,谷歌提出直接对关键点做回归,通过多次迭代校准关键点的定位(x,y),这样定位还是不是很准确,后来的方法都是基于关键点热力图,将一个关键点Ground True坐标周围半径R内区域都设为1,之外的区域设为0,转化为分类问题。

三. PIF(Part Intensity Fields)

PIF label是confidence map和regression map的结合

PIF输出的是[b, 17, 5,h, w]纬度

b:batch17:代表预测的关键点个数h,w:特征图的长宽5:表示{ p c i , j p_c^{i,j} pci,j​, p x i , j p_x^{i,j} pxi,j​, p y i , j p_y^{i,j} pyi,j​, p b i , j p_b^{i,j} pbi,j​, p σ i , j p_sigma^{i,j} pσi,j​}

(i,j)是输出特征图上的坐标, p c i , j p_c^{i,j} pci,j​表示输出的(x,y)表示(i,j)指向周围关键点真值的方向向量 p c i , j : p_c^{i,j}: pci,j​:是经过PIF的特征图上(i,j)位置的confidence预测值 p x i , j p_x^{i,j} pxi,j​、 p y i , j p_y^{i,j} pyi,j​:是经过PIF的特征图上(i,j)位置的(x,y)方向上offset(偏置)向量 p b i , j p_b^{i,j} pbi,j​:是Laplace Loss上的系数,控制关键点热力图的大小 p σ i , j p_sigma^{i,j} pσi,j​:不是高斯的 σ sigma σ,是用来将特征图还原到原图的比例 3.1. p c i , j p_c^{i,j} pci,j​的作用

p c i , j p_c^{i,j} pci,j​在PIF中代表点(i,j)是否是关键点的置信度,用来判断关键点,在PAF里面用来衡量两点的关联性大小

3.2. p x i , j p_x^{i,j} pxi,j​、 p y i , j p_y^{i,j} pyi,j​的作用

有个这个PIF label,就可以根据 p c i , j p_c^{i,j} pci,j​, p x i , j p_x^{i,j} pxi,j​, p y i , j p_y^{i,j} pyi,j​得到位置精度更高的confidence map,公式如下:

公式展开就是 ∑ i , j e − ( x − p x i , j ) 2 + ( y − p y i , j ) 2 2 ∗ ( p σ i , j ) 2 displaystylesum_{i,j}e^{-frac{(x-p_x^{i,j})^2+(y-p_y^{i,j})^2}{2*(p_sigma^{i,j})^2}} i,j∑​e−2∗(pσi,j​)2(x−pxi,j​)2+(y−pyi,j​)2​

在理解这个公式之前,先看一下《Towards Accurate Multi-person Pose Estimation in the Wild》文章的公式:


h k ( x j ) h_k(x_j) hk​(xj​):表示 h k ( x i ) h_k(x_i) hk​(xi​)热力图(半径R区域)内的其他关键点的热力图
l k l_k lk​:表示第k个关键点
x i x_i xi​:表示当前点
x j x_j xj​:表示和 x i x_i xi​离 l k l_k lk​等距的所有点
G ( x j + F k ( x j ) − x i ) = G ( x j + l k − x j − x i ) = G ( l k − x i ) G(x_j + F_k(x_j)-x_i) = G(x_j + l_k - x_j - x_i) = G(l_k - x_i) G(xj​+Fk​(xj​)−xi​)=G(xj​+lk​−xj​−xi​)=G(lk​−xi​) :表示 h k ( x j ) h_k(x_j) hk​(xj​)的系数,是固定值,也就是离 l k l_k lk​等距的热力图的权重一样
这个公式离说明,特征图上的点 x i x_i xi​离关键点真值 l k l_k lk​越近, l k − x j − x i l_k - x_j - x_i lk​−xj​−xi​越小,因为是高斯函数,所以计算得到的权重G就越大,说明对计算的 f k ( x i ) f_k(x_i) fk​(xi​)的贡献越大,这也符合逻辑

同样的,本篇论文的公式也是表示越近的点权重越大,只不过距离是offset与(x,y)的距离。所以这就是为什么相近的offset(图像种的箭头)方向很接近,远的相差远,呈现渐变的感觉:

图(a)是PIFlabel里的 p c i , j p_c^{i,j} pci,j​图(b)是PIF预测的结果offset: p x i , j p_x^{i,j} pxi,j​, p y i , j p_y^{i,j} pyi,j​ ,放大后可以看出方向是渐变的,相近的向量方向相近,不仔细分析注意不到这点图©是三者融合之后的结果. 可以看出来点的位置更精确, 中心处的响应值更强, 边缘处更弱 3.3. p b i , j p_b^{i,j} pbi,j​的作用

用来控制同一张图片上不同大小的目标物的关键点热力图(Heatmap)大小(大的物体,关键点热力图区域就应该大),文章中半径为 3 σ 3sigma 3σ,loss函数如下:

| x − μ ∣ / b |x - mu|/b |x−μ∣/b作为指数函数的幂次,就是 e − ( x − μ ) 2 ∗ ( b σ ) 2 e^{-frac{(x-mu)}{2*(bsigma)^2}} e−2∗(bσ)2(x−μ)​,所以 p b i , j p_b^{i,j} pbi,j​相当于是对 σ sigma σ值加权

拓展: 《Rethinking the Heatmap Regression for Bottom-up Human Pose Estimation》论文中也考虑了不同Scale目标应该有不同大小热力图的问题

区别是,文章Scale-Adaptive Heatmap Regression采用增加一个分支去计算Scale maps,得到不同Scale的目标应该有的热力图大小,对预测的Heatmaps重加权;因为Scale maps会导致到特征图出现形变,所以在Loss里面加了正则项:

Scale-Adaptive Heatmap Regression会导致背景数量减少,前景和背景样本不均衡,所以加了Weight-Adaptive HeatmapRegression:

就是借鉴Focal Loss处理类别不均衡和难易样本不均衡问题
想了解详细,可以去知乎看作者的讲解:CVPR 2021 论文解读Vol.7 | “自底向上”人体姿态估计的尺度自适应方法

3.4. p σ i , j p_sigma^{i,j} pσi,j​的作用

p σ i , j p_sigma^{i,j} pσi,j​:不是高斯的 σ sigma σ,是用来将特征图还原到原图进行处理的比例系数,论文里没有详细说明,但是代码(openpifpaf-main/src/openpifpaf/csrc/src/cif_hr.cpp)中可以看出:

void CifHr::accumulate(const torch::Tensor& cif_field, int64_t stride, double min_scale, double factor) {
    if (ablation_skip) return;

    auto cif_field_a = cif_field.accessor();
    float min_scale_f = min_scale / stride;

    float v, x, y, scale, sigma;
    for (int64_t f=0; f < cif_field_a.size(0); f++) {
        for (int64_t j=0; j < cif_field_a.size(2); j++) {
            for (int64_t i=0; i < cif_field_a.size(3); i++) {
                v = cif_field_a[f][1][j][i];
                if (v < threshold) continue;

                scale = cif_field_a[f][4][j][i]; // 每个点(j,i)的scale不一样,相当于权重
                if (scale < min_scale_f) continue;

                x = cif_field_a[f][2][j][i] * stride;
                y = cif_field_a[f][3][j][i] * stride;
                sigma = fmaxf(1.0, 0.5 * scale * stride);   // 通过stride还原到原图尺寸,scale可以学习的参数

                // Occupancy covers 2sigma.
                // Restrict this accumulation to 1sigma so that seeds for the same joint
                // are properly suppressed.
                add_gauss(f, v / neighbors * factor, x, y, sigma, 1.0);
            }
        }
    }
}


void CifHr::add_gauss(int64_t f, float v, float x, float y, float sigma, float truncate) {
    auto accumulated_a = accumulated.accessor();

    auto minx = std::clamp(int64_t(x - truncate * sigma), int64_t(0), accumulated_a.size(2) - 1); //x < truncate * sigma,等于0
    auto miny = std::clamp(int64_t(y - truncate * sigma), int64_t(0), accumulated_a.size(1) - 1);
    // -siga < x < sigma -> minx=0 -> x + sigma + 1 > 0 + 1 -> maxx = x + sigma + 1  (0, x + sigma + 1)
    //  x < -sigma -> minx=0 -> x + sigma + 1 < 0 + 1 -> maxx = min + 1 = 1 (0, 1)
    // x > sigma -> minx= x - sigma  -> x + sigma + 1 > x - sigma + 1 -> maxx = x + sigma + 1  (x - sigma, x + sigma + 1 || accumulated_a.size(1) - 1)
    auto maxx = std::clamp(int64_t(x + truncate * sigma + 1), minx + 1, accumulated_a.size(2));  
    auto maxy = std::clamp(int64_t(y + truncate * sigma + 1), miny + 1, accumulated_a.size(1));

    float sigma2 = sigma * sigma;
    float truncate2_sigma2 = truncate * truncate * sigma2;
    float deltax2, deltay2;
    float vv;
    for (int64_t xx=minx; xx < maxx; xx++) {
        // x < -sigma -> xx = x = 0  -> deltax2 = 0
        deltax2 = (xx - x) * (xx - x);     
                                            
        for (int64_t yy=miny; yy < maxy; yy++) {
            deltay2 = (yy - y) * (yy - y);

            if (deltax2 + deltay2 > truncate2_sigma2) continue;

            if (deltax2 < 0.25 && deltay2 < 0.25) {
                // this is the closest pixel
                vv = v;
            } else {
                vv = v * approx_exp(-0.5 * (deltax2 + deltay2) / sigma2);
            }

            auto& entry = accumulated_a[f][yy][xx];
            entry = fmaxf(entry, revision) + vv;
            entry = fminf(entry, revision + 1.0);
        }
    }
}

cif_field_a[f][1][j][i] : p c i , j p_c^{i,j} pci,j​cif_field_a[f][2][j][i] 、cif_field_a[f][3][j][i]: p x i , j p_x^{i,j} pxi,j​, p y i , j p_y^{i,j} pyi,j​cif_field_a[f][4][j][i]: p σ i , j p_sigma^{i,j} pσi,j​ 四. PAF (Part Association Fields)

PAF label的输出是[b, 17, 7,h, w]纬度

7:表示{ a c i , j a_c^{i,j} aci,j​, a x 1 i , j a_{x1}^{i,j} ax1i,j​, a y 1 i , j a_{y1}^{i,j} ay1i,j​, p b 1 i , j p_{b1}^{i,j} pb1i,j​, a x 2 i , j a_{x2}^{i,j} ax2i,j​, a y 2 i , j a_{y2}^{i,j} ay2i,j​, p b 2 i , j p_{b2}^{i,j} pb2i,j​}

$a_c^{i,j}:代表(i,j)的confidence{ a y 1 i , j a_{y1}^{i,j} ay1i,j​, p b 1 i , j p_{b1}^{i,j} pb1i,j​}和{ a x 2 i , j a_{x2}^{i,j} ax2i,j​, a y 2 i , j a_{y2}^{i,j} ay2i,j​}:分别代表(i,j)该点到真正的两个ground truth 关键点的(x_offset, y_offset) p b 1 i , j p_{b1}^{i,j} pb1i,j​、 p b 2 i , j p_{b2}^{i,j} pb2i,j​:是相对应的两个用来计算loss的系数

理解PAF流程之前,先看看OpenPose的流程:

17个关节点分别用17个channel的特征图去预测
(a)根据先验知识:右腰和右肩有连接,左腰和左肩有连接,将左腰channel上通过PIF检测出来的所有关键点,和左肩channel上通过PIF检测出来的所有关键点连接,不需要考虑对不对
(b)通过连接线的中点是否落在向量空间来决定连接线是否正确:



公式中的limb c:代表手臂(手和手肘的连接线),
公式中k:代表地个人
公式中 σ sigma σ:学习得到
图中j1、j2代表ground point,第j1、j2个关键点
图中P点:就是我们要判断的预测连接线中点
图中v:代表j1到j2的单位向量
即P点落在limb c与垂直方向的单位向量v组成的向量区域内,那就是预测正确,否则连接线错误,即这两个预测的关键点之间没有关联,不属于同一个人
还是不懂的可以去B站看这个视频:B站:第3课 人体骨骼点检测:自底向上
(c)通过(b)后只剩下有连线中点有交叉的部分,都在向量区域,满足条件的错误连线。通过大小是超参数的区域做NMS(非极大抑制)或者匈牙利算法,抑制掉有交叉的(计算得到的)低关联度连接线,得到(c)图

不同的是,不是直接连线预测的关键点作为连接线,而是通过:对特征图中所有(i,j)点,首先找到离它最近的预测的关键点,如图(b)的短箭头:

然后通过先验知识知道第一个关键点和其他channel的关键点有连接关系,获取第二个关键点,通过如下关系计算得到通过(i,j)连接的两个预测的关键点之间的关联度PAF:

x:(i,j)到关键点1的连线 a c a_c ac​:PAF输出的confidence a c i , j a_c^{i,j} aci,j​a1:PAF输出的 a x 1 i , j a_{x1}^{i,j} ax1i,j​, a y 1 i , j a_{y1}^{i,j} ay1i,j​ b 1 b_1 b1​:代表 p b 1 i , j p_{b1}^{i,j} pb1i,j​ f 2 ( a x 2 , a y 2 ) f_2(a_{x2},a_{y2}) f2​(ax2​,ay2​):利用PIF的公式更新得到的关键点2的新confidence
五. 解码后处理(Greedy Decoding)

得到PIF和PAF后,为了确保根据PAF找到的两个点确实是应该连到一起的, 程序会执行reverse操作, 即如果通过point a找到了point b, 那么就会从point b找到point c, 如果point a和point c之间的距离小于设定好的阈值, 那么就说明这两个点应该被连在一起. 计算出来哪些点需要连在一起之后, 然后通过NMS方式将多连接的线去除掉,直到完整的pose被找到。

六.其他

文章对Smooth L1和Laplace Loss做了对比实验,Laplace Loss加上尺度因子b效果更好

参考文章:
【1】CSDN:PifPaf: Composite Fields for Human Pose Estimation

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/753958.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号