python并列密度图_人群密度图生成-Python实现

最近在做人群密度估计,是一种以密度图的形式表示人群密集程度的方法,大概如下图

左图是某公共场所的人群图,右图是人群密度图,也就是用来训练生成人群密度图网络的标签。首先要将原图中左右人头的坐标标定出来,然后生成密度图像。

原理

如果一个标注点的位置为

,我们可以将它表示为

,因此有

个人头的标签可以表示为:

我们可以使用高斯核

对这个函数卷积得到密度函数

。然而这是假设每个

在样本空间中是独立的。实际上,每个

是3D场景中的人群密度样本,由于透视失真,像素与周边样本在不同场景区域尺度不一致。

因此为了精确估计群体密度

需要考虑透视变换,我们需要考虑真实和图像的失真。通常我们不能确定场景的几乎形状。但是,如果我们每个头部周围的人群是均匀分布的,那么头部与最近k个邻居之间的图像中的平均距离可以给出几何失真的合理估计。

因此,我们应该根据图像中每个人头部大小来确定参数

,但是在实际情况下,由于遮挡,不可能准确的获得头部的尺寸,而且很难找到头部尺寸和密度图之间的关系。我们发现头部大小通常与拥挤场景中两个头部中心距离有关,所以我们使用相邻头部的平均距离作为参数。

对于每个人头

,给出

个近邻头部距离

的平均值

,

相关的像素对应场景中地面上的一个区域,这个区域的半径与

成正比。因此,为了估计像素

周围的人群密度,我们需要用一个自适应的高斯核与

卷积,这个高斯核的方差

可变且与

成比例。

这里

代码

import numpy as np

import os

import matplotlib.image as mpimg

import scipy.io as sio

from scipy.ndimage import filters

import matplotlib.pyplot as plt

from sklearn.neighbors import NearestNeighbors

from PIL import Image

import math

def gaussian_filter_density(gt):

pts = np.array(list(zip(np.nonzero(gt)[1], np.nonzero(gt)[0])))

neighbors = NearestNeighbors(n_neighbors=4, algorithm='kd_tree', leaf_size=1200)

neighbors.fit(pts.copy())

distances, _ = neighbors.kneighbors()

density = np.zeros(gt.shape, dtype=np.float32)

type(distances)

sigmas = distances.sum(axis=1) * 0.075

for i in range(len(pts)):

pt = pts[i]

pt2d = np.zeros(shape=gt.shape, dtype=np.float32)

pt2d[pt[1]][pt[0]] = 1

# starttime = datetime.datetime.now()

density += filters.gaussian_filter(pt2d, sigmas[i], mode='constant')

# endtime = datetime.datetime.now()

#

# interval = (endtime - starttime)

# print(interval)

return density

def create_density(gts, d_map_h, d_map_w):

res = np.zeros(shape=[d_map_h, d_map_w])

bool_res = (gts[:, 0] < d_map_w) & (gts[:, 1] < d_map_h)

for k in range(len(gts)):

gt = gts[k]

if (bool_res[k] == True):

res[int(gt[1])][int(gt[0])] = 1

pts = np.array(list(zip(np.nonzero(res)[1], np.nonzero(res)[0])))

neighbors = NearestNeighbors(n_neighbors=4, algorithm='kd_tree', leaf_size=1200)

neighbors.fit(pts.copy())

distances, _ = neighbors.kneighbors()

map_shape = [d_map_h, d_map_w]

density = np.zeros(shape=map_shape, dtype=np.float32)

sigmas = distances.sum(axis=1) * 0.075

for i in range(len(pts)):

pt = pts[i]

pt2d = np.zeros(shape=map_shape, dtype=np.float32)

pt2d[pt[1]][pt[0]] = 1

# starttime = datetime.datetime.now()

density += filters.gaussian_filter(pt2d, sigmas[i], mode='constant')

return density

if __name__ == '__main__':

train_img = './ShanghaiTech_Crowd_Counting_Dataset/part_A_final/train_data/images'

train_gt = './ShanghaiTech_Crowd_Counting_Dataset/part_A_final/train_data/ground_truth'

out_path = './ShanghaiTech_Crowd_Counting_Dataset/true_crowd_counting/'

validation_num = 15

img_names = os.listdir(train_img)

num = len(img_names)

num_list = np.arange(1, num + 1)

# random.shuffle(num_list)

global_step = 1

for i in num_list:

full_img = train_img + '/IMG_' + str(i) + '.jpg'

full_gt = train_gt + '/GT_IMG_' + str(i) + '.mat'

img = mpimg.imread(full_img)

data = sio.loadmat(full_gt)

gts = data['image_info'][0][0][0][0][0] # shape like (num_count, 2)

count = 1

# fig1 = plt.figure('fig1')

# plt.imshow(img)

shape = img.shape

if (len(shape) < 3):

img = img.reshape([shape[0], shape[1], 1])

d_map_h = math.floor(math.floor(float(img.shape[0]) / 2.0) / 2.0)

d_map_w = math.floor(math.floor(float(img.shape[1]) / 2.0) / 2.0)

# starttime = datetime.datetime.now()

# den_map = gaussian_filter_density(res)

if (global_step == 4):

print(1)

den_map = create_density(gts / 4, d_map_h, d_map_w)

# endtime = datetime.datetime.now()

# interval = (endtime - starttime).seconds

# print(interval)

p_h = math.floor(float(img.shape[0]) / 3.0)

p_w = math.floor(float(img.shape[1]) / 3.0)

d_map_ph = math.floor(math.floor(p_h / 2.0) / 2.0)

d_map_pw = math.floor(math.floor(p_w / 2.0) / 2.0)

if (global_step < validation_num):

mode = 'val'

else:

mode = 'train'

py = 1

py2 = 1

for j in range(1, 4):

px = 1

px2 = 1

for k in range(1, 4):

print('global' + str(global_step))

# print('j' + str(j))

# print('k' +str(k))

print('----------')

if (global_step == 4 & j == 3 & k == 4):

print('global' + str(global_step))

final_image = img[py - 1: py + p_h - 1, px - 1: px + p_w - 1, :]

final_gt = den_map[py2 - 1: py2 + d_map_ph - 1, px2 - 1: px2 + d_map_pw - 1]

px = px + p_w

px2 = px2 + d_map_pw

if final_image.shape[2] < 3:

final_image = np.tile(final_image, [1, 1, 3])

image_final_name = out_path + mode + '_img/' 'IMG_' + str(i) + '_' + str(count) + '.jpg'

gt_final_name = out_path + mode + '_gt/' + 'GT_IMG_' + str(i) + '_' + str(count)

Image.fromarray(final_image).convert('RGB').save(image_final_name)

np.save(gt_final_name, final_gt)

count = count + 1

py = py + p_h

py2 = py2 + d_map_ph

global_step = global_step + 1

# fig2 = plt.figure('fig2')

# plt.imshow(den_map)

# plt.show()

这里是以ShanghaiTech_Crowd_Counting_Dataset为例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值