文章目录
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πσ2e−21σ2[(x−u1)2+(y−u2)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 255−heatmap 就会出现下述情况
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)