提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
命题背景
2022年韩国首尔发生了一起踩踏事故。至今仍让人记忆深刻,那就是10·29韩国首尔踩踏事故。
10月29日晚,韩国首尔龙山区梨泰院举行万圣节派对,附近聚集人数据推测约10万人,发生踩踏事故的小巷是一个宽约3.2米,长约45米左右的斜坡,事故发生时,整条小巷都挤满了人。发生踩踏事故的地点是其中大约长5.7米的一段,警方称当时这一段约18平方米的空间里约有300多人,本次事故死伤者基本处在这一空间中。
预防人员踩踏的一个重要指标就是人群密度。本次黑客松,以人群密度估计为开放选题。参与赛道三的比赛。
人群计数,又叫人群密度估计,是一种通过计算机计算或估计图像中人数的技术。通过对人群聚集的分析,可以帮助城市管理者、大型活动组织方实时了解人群拥挤情况,以利于早期防范群体事件、人群踩踏等,在视频监控、公共安全方面的应用广泛。
一、前期准备
数据集
人群计数是计算机视觉领域的一个重要研究方向,常用的数据集有以下这些:
- ShanghaiTech Part A/B: 这个数据集包含482张图片,其中训练集300张,测试集182张。图片的平均分辨率为589 x 868,标签格式为.mat。
- NWPU-Crowd: 这个数据集包含1,000张图片,全部用于训练。图片分辨率分别为576 x 768和768 x 1024,标签格式为.mat。
- JHU-CROWD++: 这个数据集包含1,200张图片,全部用于训练。图片分辨率最高达到2,048 x 2,048,标签格式为.mat。
- UCF-QNRF: 这个数据集包含1,535张图片,其中训练集1,201张,测试集334张。图片的平均分辨率为4,000 x 3,000,标签格式为.mat。
- SCUTFIR行人检测数据集: 这是一个大型远红外行人检测数据集。
- AudioVisual人群计数数据集: 这是一个用于人群计数的新数据集,包含大约2,000个带注释的图像令牌,每个图像对应一个1秒的音频剪辑和一个密度图。
- UCF-CC-50数据集: 这个数据集包含极其密集人群的图像。
- CIHP人体解析数据集: 这个数据集包含38,280张多人图像,这些图像具有精细的注释、高外观可变性和复杂性。
这次我们选择使用UCF数据集,下载已经标注好的测试集和训练集。
典型算法介绍
人群计数算法主要分为三大类:detection-based,regression-based,density estimation
- detection-based早期的方法是基于人的检测,然后在检测框的基础上得到人群数目,这类方法无法处理遮挡严重的场景
- regression-based从图像特征直接映射到人的数目,这类方法无法得到人群分布这一重要特征
- density estimation输入图像,输出一张与输入一样大小的人群密度图,通过对密度图进行积分得到人群的数目,这类方法无法给出准确的人的位置信息
工具集介绍
Intel® Extension for PyTorch*是英特尔发起的一个开源扩展项目,它基于PyTorch的扩展机制实现,通过提供额外的软件优化极致地发挥硬件特性,帮助用户在原生PyTorch的基础上更最大限度地提升英特尔 CPU 上的深度学习推理计算和训练性能。这个扩展项目针对命令模式(imperative mode)和图模式进行了优化,并针对PyTorch的三个关键模块进行了优化:运算符、图和运行时。优化的运算符和内核通过PyTorch调度机制完成调用。这个扩展项目不仅可以直接用于提升PyTorch在英特尔CPU上的性能,还可以为英特尔的硬件提供更好的支持,使得PyTorch用户能够更加及时地受益于英特尔硬件的最新功能,并在第一时间体验软件优化带来的最佳性能和部署便利。除了CPU,这个扩展项目还将在不久的将来为英特尔GPU带来支持和优化
评测指标
MAE(Mean Absolute Error)和MSE(Mean Squared Error)是常见的两个评测指标,用于评估预测结果和真实值之间的差异。
MAE是指预测值和真实值之间绝对值的平均差,它可以衡量预测值和真实值之间的绝对误差大小。MAE的计算公式为:
MAE = (|预测值-真实值|)/n
其中,n为样本数量。
MSE是指预测值和真实值之间平方差的平均数,它可以衡量预测值和真实值之间的误差大小,并且考虑了误差的正负。MSE的计算公式为:
MSE = ((预测值-真实值)^2)/n
其中,n为样本数量。
在人群计数任务中,MAE和MSE可以用来评估模型预测结果和真实值之间的差异。MAE可以衡量模型预测的绝对误差大小,MSE可以衡量模型预测的误差大小,并且考虑了误差的正负。通过比较MAE和MSE的值,可以评估模型的性能好坏。
二、设计思路
1.模型定义
定义一个 U-Net 模型,或者修改VGG 15 模型去适应密度估计任务
import torch
import torch.nn as nn
class UNet(nn.Module):
def __init__(self, in_channels, out_channels):
super(UNet, self).__init__()
self.encoder = nn.Sequential(
nn.Conv2d(in_channels, 64, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2)
)
self.middle = nn.Sequential(
nn.Conv2d(64, 128, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=3, padding=1),
nn.ReLU(inplace=True)
)
self.decoder = nn.Sequential(
nn.Conv2d(128, 64, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, kernel_size=3, padding=1),
nn.ReLU(inplace=True),
nn.ConvTranspose2d(64, out_channels, kernel_size=2, stride=2)
)
def forward(self, x):
x1 = self.encoder(x)
x2 = self.middle(x1)
x3 = self.decoder(x2)
return x3
2.使用模型进行人群密度估计
启用 Intel® Extension for PyTorch
import intel_pytorch_extension as ipex
torch.backends.quantized.engine = "qnnpack"
加载预训练的 U-Net 模型
model = UNet(in_channels=3, out_channels=1)
model.load_state_dict(torch.load("unet_weights.pth"))
model = model.to(ipex.DEVICE)
使用 U-Net 模型进行人群密度估计
def crowd_density_estimate(image_path):
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
img = Image.open(image_path)
img_t = transform(img)
batch_t = torch.unsqueeze(img_t, 0).to(ipex.DEVICE)
人群密度的密度图,求和获得人群估计
model.eval()
with torch.no_grad():
output = model(batch_t)
density_map = output.squeeze().cpu().numpy()
crowd_estimate = density_map.sum()
return crowd_estimate
效果展示及总结
测试过程只需要将图片输入到网络中进行前向运算,然后对输出的密度图进行积分(就是对整张密度图的所有像素进行求和)得到的结果就是当前图片中所含人数的估计值,比如简单的 np.sum (Diest)(D_{i}^{e s t})(D_{i}^{e s t}) 。np.sum输出为189.收敛的效果还是不错的。
同时,我们比较了是否使用Intel 拓展推理。结果是使用intel拓展时推理速度有明显提升。