Body estimation 学习之:(1)生成关节 heatmap 全网最详细操作教程

import numpy as np
import cv2
import matplotlib.pyplot as plt
from matplotlib import cm as c
import os
import math

os.chdir("../")

points = [[367,  81,  2],
          [378, 118,   2],
          [358, 129,   2],
          [341, 159,   2],
          [309, 178,   2],
          [399, 108,   2],
          [433, 142,   2],
          [449, 165,   2],
          [393, 214,   2],
          [367, 273,   2],
          [396, 341,   2],
          [424, 203,   2],
          [429, 294,  2],
          [466, 362,   2],
          [360,  75,   2],
          [374,  73,   2],
          [356,  81,   2],
          [386,  78,   2]]
bgr_image = cv2.imread("./datasets/val2017/000000000785.jpg")
rgb_image = cv2.cvtColor(bgr_image, cv2.COLOR_BGR2RGB)
plt.imshow(rgb_image)

在这里插入图片描述

生成 heatmap 代码总览

th = 4.6052
delta = math.sqrt(th*2)
# sigma = 30 
delta

import math
import numpy as np
import cv2
import matplotlib.pyplot as plt
from matplotlib import cm as c

points = [[367,  81,  2],
          [378, 118,   2],
          [358, 129,   2],
          [341, 159,   2],
          [309, 178,   2],
          [399, 108,   2],
          [433, 142,   2],
          [449, 165,   2],
          [393, 214,   2],
          [367, 273,   2],
          [396, 341,   2],
          [424, 203,   2],
          [429, 294,  2],
          [466, 362,   2],
          [360,  75,   2],
          [374,  73,   2],
          [356,  81,   2],
          [386,  78,   2]]
bgr_image = cv2.imread("./datasets/val2017/000000000785.jpg")

def put_heatmap(shape, center, sigma):
    center_x, center_y, _ = center
    heatmap = np.zeros((shape[0], shape[1]))
    height, width, _ = shape
    th = 4.6052
    delta = math.sqrt(th * 2)   # 3.0348640826238
    
    x0 = int(max(0, center_x - delta * sigma))
    y0 = int(max(0, center_y - delta * sigma))

    x1 = int(min(width, center_x + delta * sigma))
    y1 = int(min(height, center_y + delta * sigma))

    for y in range(y0, y1):
        for x in range(x0, x1):
            d = (x - center_x) ** 2 + (y - center_y) ** 2  # 高斯!
            exp = d / 2.0 / sigma / sigma  # 高斯!
            if exp > th:
                continue
            heatmap[y][x] = max(heatmap[y][x], math.exp(-exp))
            heatmap[y][x] = min(heatmap[y][x], 1.0)
    return heatmap
    
for point in points:
    guss_heatmap = put_heatmap(rgb_image.shape, point, sigma = 7)
    fg, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(40, 8))

    ax1.imshow(rgb_image)
    ax2.imshow(guss_heatmap, cmap=c.jet)
    guss_heatmap = np.array(guss_heatmap)
    
    guss_heatmap[guss_heatmap < 0] = 0
    guss_heatmap = cv2.normalize(guss_heatmap, guss_heatmap, 0, 255, cv2.NORM_MINMAX)
    guss_heatmap = np.uint8(guss_heatmap)
    jetmap = cv2.applyColorMap(255-guss_heatmap, cv2.COLORMAP_JET)
    alpha = 0.5
    out = cv2.addWeighted(rgb_image, alpha, jetmap, 1 - alpha, 0, jetmap)
    ax3.imshow(out, cmap=c.jet)

代码解读

  • 拿 points 中的一个点做例子
point = np.array([358, 129, 2])
img_shape = rgb_image.shape
center_x, center_y, _ = point
# 产生一张空白的图,准备往里填数据
heatmap = np.zeros((img_shape[0],img_shape[1]))
plt.imshow(heatmap)

在这里插入图片描述

height, width, _ = img_shape
th = 4.6052
delta = math.sqrt(th * 2)   # 3.0348640826238
sigma = 20

通过加减 σ ∗ δ \sigma * \delta σδ 得到实施高斯计算的范围

这么写保证 c e n t e r _ x , c e n t e r _ y center\_x, center\_y center_x,center_y 减去 Font metrics not found for font: . 之后不会超过 heatmap 的边框范围

x0 = int(max(0, center_x - delta * sigma))
y0 = int(max(0, center_y - delta * sigma))

这么写保证 c e n t e r _ x , c e n t e r _ y center\_x, center\_y center_x,center_y 加上 Font metrics not found for font: . 之后不会超过 heatmap 的边框范围

x1 = int(min(width, center_x + delta * sigma))
y1 = int(min(height, center_y + delta * sigma))
plt.scatter(x=x0,y=y0,color="red")
plt.scatter(x=x1,y=y1,color="green")
plt.scatter(x=center_x,y=center_y,color="blue")
plt.xlim((0,img_shape[1]))
plt.ylim((img_shape[0],0))
(425.0, 0.0)

在这里插入图片描述

  • 通过上面的步骤可以看见,其实通过对角线限制出了一个区域,这个区域是正方形的,红色点和绿色点分别是对角线的边界,我们对这个区域中的所有点进行遍历并通过下面公式,算出各个像素点在满足高斯分布的情况下的像素值

f ( x , y ) = 2 π σ 2 e − 1 2 [ ( x − u 1 ) 2 + ( y − u 2 ) 2 ] σ 2 f(x,y)=2\pi \sigma^2 e^{-\frac{1}{2}\frac{[(x-u_1)^2+(y-u_2)^2]}{\sigma^2}} f(x,y)=2πσ2e21σ2[(xu1)2+(yu2)2]

按照公式求算所有像素点

for y in range(y0, y1):
    for x in range(x0, x1):
        '''
        高斯!这里直接取得 $2πsigma^2$ 后面的部分
        '''
        d = (x - center_x) ** 2 + (y - center_y) ** 2  
        exp = d / 2.0 / sigma / sigma  # 高斯!
        if exp > th:
            continue
        # 将 heatmap 的像素值限制在 0,1 之间
        heatmap[y][x] = max(heatmap[y][x], math.exp(-exp))
        heatmap[y][x] = min(heatmap[y][x], 1)
plt.imshow(heatmap)
plt.scatter(x=x0,y=y0,color="red")
plt.scatter(x=x1,y=y1,color="green")
plt.scatter(x=center_x,y=center_y,color="blue")
plt.xlim((0,img_shape[1]))
plt.ylim((img_shape[0],0))
(425.0, 0.0)

在这里插入图片描述

fg, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(40, 8))
ax1.imshow(rgb_image)
# 对高斯 heatmap 图进行上色,按照 c.jet 的上色风格来可视化
ax2.imshow(heatmap, cmap=c.jet)
guss_heatmap = np.array(heatmap)

在这里插入图片描述

对 heatmap 进行规范化

  • 线性放缩到 0-255 像素值之间
guss_heatmap = cv2.normalize(guss_heatmap, guss_heatmap, 0, 255, cv2.NORM_MINMAX)
plt.imshow(guss_heatmap,cmap=c.jet)

在这里插入图片描述

guss_heatmap = np.uint8(guss_heatmap)  # 转换图的数值类型
jetmap = cv2.applyColorMap(guss_heatmap, cv2.COLORMAP_JET)
jetmap_ = cv2.applyColorMap(255-guss_heatmap, cv2.COLORMAP_JET)

将 heatmap 转换成 jetmap 进行 weighted 叠加

  • heatmap 是数组,不符合 c v 2. a d d W e i g h t e d cv2.addWeighted cv2.addWeighted 的格式,因此要转成 jetmap
  • 如果转jetmap 的过程中不用 255 − h e a t m a p 255-heatmap 255heatmap 就会出现下述情况
plt.imshow(jetmap)

在这里插入图片描述

plt.imshow(jetmap_)

在这里插入图片描述

alpha = 0.5
out_ = cv2.addWeighted(rgb_image, alpha, jetmap, 1 - alpha,0,jetmap)
plt.imshow(out_, cmap=c.jet)
# ax3.imshow(out, cmap=c.jet)

在这里插入图片描述

alpha = 0.5
out = cv2.addWeighted(rgb_image, alpha, jetmap_, 1 - alpha,0,jetmap_)
plt.imshow(out, cmap=c.jet)
# ax3.imshow(out, cmap=c.jet)

在这里插入图片描述

升级方法:使用矩阵代替循环

def generate_gaussian_heatmap(shape, joint, sigma):
    x, y,_ = joint 
    grid_x = np.tile(np.arange(shape[1]), (shape[0], 1))
    grid_y = np.tile(np.arange(shape[0]), (shape[1], 1)).transpose()
    grid_distance = (grid_x - x) ** 2 + (grid_y - y) ** 2
    gaussian_heatmap = np.exp(-0.5 * grid_distance / sigma ** 2)
    # 产生的就是一整张图的gaussian分布,只不过里中心点远的点非常非常小
    return gaussian_heatmap
for point in points:
    guss_heatmap = generate_gaussian_heatmap(rgb_image.shape, point, sigma = 7)
    fg, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(40, 8))

    ax1.imshow(rgb_image)
    ax2.imshow(guss_heatmap, cmap=c.jet)

    guss_heatmap[guss_heatmap < 0] = 0
    guss_heatmap = cv2.normalize(guss_heatmap, guss_heatmap, 0, 255, cv2.NORM_MINMAX)
    guss_heatmap = np.uint8(guss_heatmap)
    jetmap = cv2.applyColorMap(255-guss_heatmap, cv2.COLORMAP_JET)
    alpha = 0.5
    out = cv2.addWeighted(rgb_image, alpha, jetmap, 1 - alpha, 0, jetmap)
    ax3.imshow(out, cmap=c.jet)
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

暖仔会飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值