密集人群计数离散密度图生成

#生成离散密度图 ,其实就是一个二维数组
def gen_discrete_map(im_height, im_width, points):
    """
        func: generate the discrete map.
        points: [num_gt, 2], for each row: [width, height]
        """
    discrete_map = np.zeros([im_height, im_width], dtype=np.float32) # 首先初始化一下,高、宽和image一样 这里假设为400 * 300 里面4个人
    h, w = discrete_map.shape[:2] # 表示从序列的开始提取直到索引 2 的元素(不包括索引 2) shape返回元组(400,300)就是h=400 宽 = 300
    num_gt = points.shape[0] # shape返回元组(4,2) 取第一个索引 也就是4
    if num_gt == 0:
        return discrete_map #没有人头直接返回初始化的图 也就是全0的二维矩阵
    
    # fast create discrete map
    #  将点坐标四舍五入变整数 np.array将points变成numpy数组(这一步多余了)以为points本来就是numoy数组 .round()对每一个数字四舍五入 .astype将float变int
    points_np = np.array(points).round().astype(int)
    #这两个p_h 、p_w 是为了调整x和y,保证x和y不会超过边界
    #points_np[:, 1]对取整后的二维矩阵 选取所有行(:表示选取所有行),仅选择每行的第一个元素(1表示选取第一个元素)即y 比如[20 30 100 200]
    # np.array([2]*3) 意味着生成[2 2 2]
    # np.minimum 比较两个数组,选择每个位置的最小值
    p_h = np.minimum(points_np[:, 1], np.array([h-1]*num_gt).astype(int))
    #oints_np[:, 0]提取所有x 就是那四个人头的x坐标 比如[2 4 6 10]
    p_w = np.minimum(points_np[:, 0], np.array([w-1]*num_gt).astype(int))
    # 将二维坐标映射的一维数组 用y*宽度+x 作为一维的索引 并转换为张量
    p_index = torch.from_numpy(p_h* im_width + p_w).to(torch.int64)
    # 创建一维0张量,索引处点1,.view(im_height, im_width) 将一维张量重新构形成原始的二维图像尺寸,再变成numpy数组
    discrete_map = torch.zeros(im_width * im_height).scatter_add_(0, index=p_index, src=torch.ones(im_width*im_height)).view(im_height, im_width).numpy()

    ''' slow method
    for p in points:
        p = np.round(p).astype(int)
        p[0], p[1] = min(h - 1, p[1]), min(w - 1, p[0])
        discrete_map[p[0], p[1]] += 1
    '''
    #这个断言是一个安全检查,确保没有点丢失或多计算。如果断言失败(即,如果离散图的总和与点的数量不相符),Python 将抛出一个 AssertionError,这有助于调试和确保函数的正确性。
    assert np.sum(discrete_map) == num_gt
    return discrete_map

以上为作者源码

自我复现一遍,以自己标记的数据为例

import os
import torch
os.environ['KMP_DUPLICATE_LIB_OK']='True'
from datasets.crowd  import random_crop,gen_discrete_map
from PIL import Image
import scipy.io
import numpy as np
import matplotlib.pyplot as plt

image_path = r'F:\crowd_data_self\img_1.jpg'
image = Image.open(image_path)
im_width, im_height = image.size
print(f'im_w:{im_width},im_h:{im_height}')

mat_file_path = r'F:\CCTrans-main\img_1.mat'
mat = scipy.io.loadmat(mat_file_path)

points = mat['image_info'][0][0][0]
print(points)
print(points.shape)
print(type(points))
discrete_map = np.zeros([im_height, im_width], dtype=np.float32)
points_round = np.array(points).round().astype(int)
y = points_round[:, 1]
x = points_round[:,0]
num = points.shape[0]
print(f'x坐标为:{x}')
print(f'y坐标为:{y}')
y_l = np.minimum(y,[im_height-1]*num)
x_l = np.minimum(x,[im_width-1]*num)
print(f'y坐标为:{y_l}')
print(f'x坐标为:{x_l}')

p_index = torch.from_numpy(y_l * im_width + x_l).to(torch.int64)
print(f'坐标点转换为一维索引:{p_index}')

discrete_map = torch.zeros(im_width*im_height).scatter_add_(0,index=p_index,src=torch.ones(im_width*im_height)).view(im_height,im_width).numpy()
print(discrete_map)

首先,提取到image_info,形如:

然后用切片操作拿到x和y坐标,并处理一下(四舍五入、不超过边界)、再转换为一维索引

最后创建一个height*weight的空tensor,索引处标1,再转换成二维数组,得到离散密度图

重点学习到的操作

1、.shape[:2]切片操作 

因为.shape会返回 行*列的元组,比如(400,300) 再提取该元组从0-2(不包括2)的元素,就可以得到height和width

h,w = discrete_map.shape[:2] 

这里也是同理 拿到shape的第一个元素,即行 

目的是拿到总人头数:

 num_gt = points.shape[0] # shape返回元组(4,2) 取第一个索引 也就是4

2、.round()对每一个元素四舍五入 astype转换类型

points_np = np.array(points).round().astype(int)

3、拿到所有x坐标和y坐标,也是用切片操作

points_np是二维数组,:表示选取所有行,1表示拿第一个元素(从0开始,这里就是y)

points_np[:, 1]
print(points_np) #会得到所有y,如下

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值