openpose中PAF的实现原理

以人体右下胳膊为例,假设A,B两点分别是右手肘和右手腕,我们现在要以此来实现右胳膊中的PAF。

def putVecMaps(centerA, centerB, accumulate_vec_map, count, grid_y, grid_x, stride):
    centerA = centerA.astype(float)
    centerB = centerB.astype(float)

首先假定人体的胳膊宽度为1(即thre=1),然后将坐标除以stride值,即将坐标映射到特征图中。得到AB向量后将其单位华得到单位向量。

thre = 1  # limb width
    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)

然后我们要判断,特征图上哪些点是属于该合理区域的,该部分较难理解。根据A和B的坐标,首先得到一个矩形,即代码中的range部分,那模型如何判断特征图中的点哪些在range中哪些不在range中?

# 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)

根据上述代码可以得到一个矩形,如图:
在这里插入图片描述
我们针对特征图中的点做向量,以A为例,假设特征图中的点为C,那么用向量AC与AB的单位向量做叉乘,可以得到以两个向量为边的平行四边形的面积,以面积作为划分标准。
具体对比如图所示:
在这里插入图片描述

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 # 小于阈值的表示在该区域上

对每个点都要进行如上计算,全部算完以后可以得到一个mask矩阵, 里面是true or false,true代表该点在矩阵内,false则不在。

vec_map = np.copy(accumulate_vec_map) * 0.0 #本次计算

    vec_map[yy, xx] = np.repeat(mask[:, :, np.newaxis], 2, axis=2)
    vec_map[yy, xx] *= limb_vec_unit[np.newaxis, np.newaxis, :] #在该区域上的都用对应的方向向量表示(根据mask结果表示是否在)

在这里插入图片描述
该段代码描述的是,每个在区域内的点,最后都会被画成AB的单位向量,false=0,true=1,然后用bool矩阵去乘单位向量。
效果图如下:
在这里插入图片描述

mask = np.logical_or.reduce(
        (np.abs(vec_map[:, :, 0]) > 0, np.abs(vec_map[:, :, 1]) > 0)) #在特征图中(46*46)中 哪些区域是该躯干所在区域

判断是否为躯干,再次得到一个bool矩阵。

accumulate_vec_map = np.multiply(
        accumulate_vec_map, count[:, :, np.newaxis]) #每次返回的accumulate_vec_map都是平均值,现在还原成实际值
    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

最后就是计算,当有重叠部分时,算法是如何处理的。其中最重要的是计算平均的处理,是先将原平均值还原,再将新的特征图加进去算,除以总数n+1即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值