C3F:首个开源人群计数算法框架
导读:52CV曾经报道多篇拥挤人群计数相关的技术,比如最近的:
CVPR 2019 | 西北工业大学开源拥挤人群数据集生成工具,大幅提升算法精度
视频监控的普及,需求推动技术的快速进步。
本文为首个PyTorch人群计数框架C3F开发者投稿,详细介绍了该框架的方方面面,欢迎大家参考。
开源地址:
https://github.com/gjy3035/C-3-Framework
近两年,有关人群计数的文章呈现出爆炸式增长。然而,人群计数不像其他任务(目标检测、语义分割等)有着简洁/易开发的开源代码框架,大大降低了我们对于idea的验证效率。
因此在2018年12月份,我萌生了自己搭一个人群计数框架的想法,尽可能兼顾当前主流数据集和主流算法。并于2019年3月底基本完成了主体框架。
代码发布之后,由于缺少对于代码细节的文档介绍,issues和emails让人应接不暇。所以,在这里对该项目做一个代码层面上的介绍,并辅之以一些实验分析来帮助大家有效提高网络性能。
更重要地,希望能够抛砖引玉,让大家利用C3F,更高效地研究出性能更好的人群计数网络,推动该领域的发展。
本文主要内容包括:
- 数据处理:不同数据集的处理过程。
- 模型:基于ImageNet分类模型设计的人群计数器以及我们复现的一些主流网络。
- 训练技巧:一些常见的网络训练技巧。
- 实验结果:在Shanghai Tech Part B数据集上的实验结果及分析。
- 总结
- 致谢
- Q&A:一些常见问题的解答。
1. 数据处理
我们提供了常见的六个主流数据库的预处理代码,处理好的数据集以及PyTorch下的data loader,包括:
UCF_CC_50[[1]](UCF50),
Shanghai Tech Part A/B[[2]](SHT A/B),
WorldExpo'10[[3]](WE),
UCF-QNRF[[4]](QNRF),
GCC[[5]]。
后期还会提供UCSD[[11]]和MALL[[12]]数据集的相关内容。
1.1 生成密度图-处理参数
注:
1. 为了能够使得输入图像兼容更多的网络,预处理时对图像的高和宽进行了限制,使其能够被16整除。确保网络中一些含有降采样操作的层(conv with stride2 或者池化)能够正确输出。在人群计数领域中,常见encoder中一般输出为1/8原图尺寸,因此被16整除完全满足需求。
2. 为节约显存,对QNRF和GCC的图像进行了保持长宽比的降采样操作。
1.2 多Batch-size训练
由于UCF50、SHT A、QNRF所包含的图像尺寸不一,为了实现多batch size的训练,我们重写了`collate_fn`函数。该函数在随机拿到N张图像和GT后,选择最小的高h_min和最小的宽w_min对所有图像进行crop,拼成Tensor送入到网络中进行训练。
根据经验,如果是from scratch training,对于这几个数据集建议采用多batch size训练或者采用GCC-SFCN中加padding的方案,对于有预训练参数的模型(AlexNet,VGG,ResNet等),建议采用单一batch size进行训练。
1.3 Label Transform
代码中我们提供了两种对密度图进行transform的操作。一种参考了CSRNet源码[[6]]中对密度图进行降采样的操作(`GTScaleDown`),一种是对密度图点乘一个放大因子(`LabelNormalize`)。
1.3.1 GTScaleDown
由于CSRNet中,网络回归的密度图为原图的1/8,因此作者对密度图进行了降采样,并点乘64以保证密度图之和依然约等于总人数。该操作会带来一个问题:会影响PSNR和SSIM的值。因此我们不建议使用该操作。在我们实现其他网络过程中,也会出现网络输出为1/4,1/8等尺寸,为避免该问题,在网络内部增加上采样层实现与原图大小的密度图。
1.3.2 LabelNormalize
这算是一个训练的trick,我们通过实验发现,对于密度图乘以一个较大的放大因子,可以使网络更快的收敛,甚至取得更低的估计误差。
1.4 数据增强
2 模型
这一部分,我们介绍几种常见分类网络(AlexNet,VGG,ResNet等)“魔改”为人群计数的网络。
2.1 Baseline模型
2.1.1 AlexNet
对于AlexNet网络[[7]],我们小幅修改了conv1和conv2层的padding,以保证其对于feature map的大小能够正常整除。同时,截取conv5之前的网络,作为人群计数的encoder,其大小为原始输入的1/16。decoder的设计依然遵循简约的原则,用“两层卷积+上采样”直接回归到1-channel的密度图。
2.1.2 VGG系列:VGG和VGG+decoder
对于VGG网络[[8]]的两个变体,我们完全采用了VGG-16模型的前10个卷积层。其中,VGG采用了最为简单的decoder,而VGG+decoder则是简单设计了一个含有三个反卷积的模块。下表展示了二者在SHT上的实验结果。
VGG系列性能对比:
VGG系列可视化对比:
VGG结果
VGG+decoder结果
通过在SHT B上实验结果来看,两者的模型性能(MAE,MSE)差不多,但VGG+decoder有着更为精细的密度图。二者的性能非常接近CSRNet(同样的backbone)的结果。
2.1.3 ResNet系列:Res50和Res101
对于ResNet[[9]],为了保证密度图的大小不至于过小(不小于原图尺寸的1/8),我们修改了res.layer3中第一层stride的大小(将原本的2改为1),以此当做encoder。本着简单的原则,decoder由两层卷积构成。从实验结果来看,ResNet展现除了强大的特征提取能力,在SHT B上直接达到了现有SOTA的水平。据我们所知,截止目前(2019.4),已发表/录用文章中最好的是PACNN+[[10]],其MAE/MSE为:7.6/11.8。我们的模型在SHT B数据集上具体表现如下:
2.2 C3F框架下复现模型比较
除了上述基于ImageNet分类模型设计的Baselines以外,我们也尝试在C3F下复现了以下几个主流算法的结果,包括MCNN[[2]],CMTL[[13]],CSRNet[[6]]以及SANet[[14]]。我们复现的模型在SHT B数据集上具体表现如下:
注:
1. 在MCNN复现过程中,与原网络结构唯一不同在于,我们的MCNN处理的是RGB图像。
2. 原始的CMTL在训练前,通过随机裁剪生成好了训练集。我们采用在线裁剪的方法可以使训练覆盖更多的裁剪区域。此外,由于选择了在线裁剪,CMTL中的分类任务的标签页适应性地改成了在线计算与分配。
3. 据我们所知,SANet复现结果,是当前所有复现中最接近论文结果的,虽然这一结果与论文结果依然相差甚远。
3 训练技巧
3.1 LabelNormalize的调参
在C3F已公布的实验结果中,均对密度图进行了点乘100的操作。实验过程中,我们也发现,设置一个合适的放大因子,对于网络的有效训练非常有益。这一节,我们简要说一下为什么这样一个简单的操作会有效的原因。
一个初始化好的计数网络来说,自身参数符合一定的分布,如果目标分布和初始化分布相差过大的话,网络会陷入一个比较差的局部解,难以训练出好的结果。该特性在使用预训练分类模型的计数网络时,显得更为重要。
这一节,我们选择Res50网络,分别测试在对密度图分别乘以[1,10,100,1000,2000,4000]时,网络的计数性能差异。下表展示了不同放大因子下在SHT B上的实验结果。
我们发现,当采用原始密度图时,网络并不能正确收敛。观察结果发现,网络一直输出一张全0的密度图。陷入到一个局部解无法进一步优化。当放大因子为1000时,网络达到了最优性能。之后,随着放大因子的增加,网络的计数性能又逐步降低。
下图展示了在六组不同的放大因子下,MAE和MSE在验证集上随时间的变化曲线。橙色曲线表示对密度图不进行放大情况下,网络性能的表现。我们发现,网络陷入到一个局部解难以跳出。
不同放大因子的实验对比:
由于橙色曲线会干扰我们对其他参数曲线的对比,因此,下图展示了移除掉橙色曲线后,即放大因子为[10,100,1000,2000,4000]的曲线对比。从图中可以看出,除了放大因子取10时,效果较差,其他几种曲线重合度非常高。
不同放大因子的实验对比:
综上,我们设定一个较大的放大因子,不仅可以促使模型快速收敛,也可以帮助模型取得一个更优的性能。
3.2 特征图大小对比:1/8 size v.s 1/16 size
过小的特征图尺寸会对计数的性能产生非常大的影响。这里,我们进行两组对比试验:
1) ResNet-50中res.layer3以前的层原封不动当做backbone,最终输出密度图作16x的上采样;
2) C3F最终采用的方案,输出密度图作8x的上采样。
从实验结果可以看出,在将stride改为1后,模型输出了分辨率更高的密度图,同时在计数误差上取得了更好的效果。同时,我们也对比一下两者在训练过程中,测试集上MAE和MSE的表现,如下图所示。其中蓝色部分为stride=2的结果,橙色为stride=1的结果。能够很直观的看出,平滑后的曲线图,橙色曲线整体要低于蓝色曲线。(注:实验中,其他参数均与`results_reports/Res50/SHHB`中的设置保持一致。)
不同特征图大小的实验对比:
3.3 数据归一化中,均值和标准差对实验结果的影响
C3F中,在`misc`中我们提供了`cal_mean.py`来计算数据集中的训练数据中均值和标准差。大多数人会使用ImageNet的均值和标准差(也就是`mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]`),经过实测,该参数对最终的性能影响有限。我们继续使用Res50和MCNN网络进行试验,用两种均值、标准差进行归一化,比较最终的计数误差,结果见下表。(注:Res50实验中,其他参数均与`results_reports/Res50/SHHB`中的设置保持一致。MCNN实验则是与`results_reports/MCNN/SHHB`中的设置保持一致)
从表格中,我们可以看出,使用了自身数据集的均值和标准差,性能要略微优于使用ImageNet上的均值和标准差所得到的的结果。下图展示了训练过程中验证集上MAE和MSE的变化曲线,其中橙色代表采用了SHT B的均值和标准差的实验,蓝色则为采用了ImageNet的结果。从图中可以看出,二者的重合度非常高。
Res50:不同均值标准差的实验对比:
MCNN:不同均值标准差的实验对比
由于人群图像和ImageNet数据均属于自然图像,计算出的均值和标准差也比较类似。因此,改值对实验结果的影响并不是很大。当然,影响程度也与数据集有关,如果数据具有很强的偏置,最好还是采用数据对应的均值和标准差。总的来说,我们还是建议使用训练数据的均值和标准差,以取得更好的计数性能。
4 实验结果
本节,我们将复现的所有算法在SHT B上的性能展示出来,方便大家做最终的对比。我们发现,得益于ResNet-101强大的学习能力,以其为Backbone的人群计数器在MAE和MSE指标上超越了其他所有算法。此外,我们还发现,对于有预训练参数的网络,甚至可以不需要对网络进行过多的设计,例如Dilated Conv、Multi-column Conv、Scale Aggregation等,就可以达到一个较好的结果。
5 总结展望
本项目旨在提供一个简单、高效、易用、灵活的人群计数框架,方便新手快速上手入门、资深研究者高效实现idea以及最大化模型性能。
本技术报告则是对该项目的一个简单介绍,使大家能够对我们的项目有一个更深的理解,这样用起来也会更加顺手,最大化框架的使用度。
同时,我们英文Technical Report(为本文的精简内容)也将在arxiv上预印。如果大家有任何问题、建议,欢迎大家在仓库中提issue和PR,让C3F变得更好!
6 致谢
在整个项目推进的过程中,得到了很多人的大力支持。
特别地,感谢@wwwzxoe303com对关键代码的检查和测试,感谢@PetitBai对项目Readme.md的校对,感谢Google Colab提供免费实验资源。
此外,我们的部分代码、设计逻辑参考或直接借用了以下作者的仓库/项目/代码,在此一并表示感谢!正是有了以下几个出色的开源代码,我们才得以完成C3F项目。
py-faster-rcnn:
https://github.com/rbgirshick/py-faster-rcnn)
pytorch-semantic-segmentation:
https://github.com/zijundeng/pytorch-semantic-segmentation
CSRNet-pytorch:
https://github.com/leeyeehoo/CSRNet-pytorch
SANet_implementation:
https://github.com/BIGKnight/SANet_implementation
enet.pytorch:
https://github.com/gjy3035/enet.pytorch
GCC-SFCN:
https://github.com/gjy3035/GCC-SFCN
PCC-Net:
https://github.com/gjy3035/PCC-Net(论文尚未发表,因此暂未公开源码)
7 Q&A
1. Q:能否提供Python3环境下的代码?
A:会,但现在时机不成熟。原因是Tensorboard暂时还不支持Python3.7,加之人手不足,暂无开发计划。
2. Q:为什么在SHT B上做实验?以后会不会对其他数据集进行验证?
A:因为图像尺寸相同,便于多batch-size的训练和测试,能够最大化利用显卡,节省显卡资源和训练时间。对于其他数据集,由于自己的时间有限,也没有足够的显卡资源,暂时不会做其他数据集实验。
3. Q:语义分割和人群计数非常类似,能不能直接用一些分割网络呢?
A:二者同属于逐像素任务,前者为逐像素分类,后者为逐像素回归。根据我的实验,某些分割网络直接修改最后一层为回归层后,其效果与backbone相比,提升非常有限。甚至性能会有所下降。深层问题暂时还没有仔细思考。不过据我所知,有人对此问题已经做了研究,大家耐心等待即可。
4. Q:正确的训练、验证、测试流程应该是怎样的?
A:严格意义上,所有数据集应该都包含以上三种数据(如果没有验证集,则应该从训练集中随机选择一部分)。在本项目中,为了能够确保所有实验结果可以复现,我们直接将测试集当做验证集来监控训练过程。
5. Q:部分模型会在PyTorch1.0下报上采样函数`F.upsample`的警告信息。
A:该警告不影响训练。为了兼容0.4版本,我们依然采用`F.upsample`方法来对Tensor进行放大尺寸的操作。
参考文献
[1] H. Idrees, I. Saleemi, C. Seibert, and M. Shah. Multi-source multi-scale counting in extremely dense crowd images. In CVPR, 2013.
[2] Y. Zhang, D. Zhou, S. Chen, S. Gao, and Y. Ma. Single image crowd counting via multi-column convolutional neural network. In CVPR, 2016.
[3] C. Zhang, K. Kang, H. Li, X. Wang, R. Xie, and X. Yang. Data-driven crowd understanding: a baseline for a largescale crowd dataset. IEEE T-MM, 2016.
[4] H. Idrees, M. Tayyab, K. Athrey, D. Zhang, S. Al-Maadeed, N. Rajpoot, and M. Shah. Composition loss for counting, density map estimation and localization in dense crowds. In ECCV, 2018.
[5] Q. Wang, J. Gao, W. Lin, and Y. Yuan. Learning from synthetic data for crowd counting in the wild. In CVPR, 2019.
[6] Y. Li, X. Zhang, and D. Chen. Csrnet: Dilated convolutional neural networks for understanding the highly congested scenes. In CVPR, 2018.
[7] A. Krizhevsky, I. Sutskever, and G. Hinton. Imagenet classification with deep convolutional neural networks. In NIPS, 2012.
[8] K. Simonyan and A. Zisserman. Very deep convolutional networks for large-scale image recognition. In ICLR, 2015.
[9] K. He, X. Zhang, S. Ren, and J. Sun. Deep residual learning for image recognition. In CVPR, 2016.
[10] M. Shi, Z. Yang, C. Xu, and Q. Chen. Revisiting Perspective Information for Efficient Crowd Counting. In CVPR, 2019.
[11] A. B. Chan, Z.-S. J. Liang, and N. Vasconcelos. Privacy preserving crowd monitoring: Counting people without people models or tracking. In CVPR, 2008.
[12] K. Chen, C. C. Loy, S. Gong, and T. Xiang. Feature mining for localised crowd counting. In BMVC, 2012.
[13] V. A. Sindagi and V. M. Patel. Cnn-based cascaded multitask learning of high-level prior and density estimation for crowd counting. In AVSS, 2017.
[14] X. Cao, Z. Wang, Y. Zhao, and F. Su. Scale aggregation network for accurate and efficient crowd counting. In ECCV, 2018.
开源地址:
https://github.com/gjy3035/C-3-Framework
加群交流