人群计数:CSRNet-Dilated Convolutional Neural Networks for Understanding the Highly Congested Scenes

(鉴于有朋友提到模型去哪里下载的问题,这里多加一句)
CSRNet 官方GitHub地址:https://github.com/leeyeehoo/CSRNet-pytorch

这里面包括代码和训练好的模型。

模型再给一个链接吧:

链接:https://pan.baidu.com/s/1f3xo63KL__3QEF2H0XElUg
提取码:8159

分割线

从广义上讲,目前有四种方法来计算人群中的人数:

1.基于检测的方法
在这里,即使用移动的窗口式探测器来识别图像中的人并计算其中的人数。用于检测的方法需要经过良好训练的分类器,其可以提取低级特征。尽管这些方法适用于检测面部,但它们在拥挤的图像上表现不佳,因为大多数目标对象不清晰可见。

2.基于回归的方法
我们无法使用上述方法提取低级功能,所以基于回归的方法在这方面就胜出了。我们首先从图像中裁剪补丁,然后为每个补丁提取低级特征。

3.基于密度估计的方法
我们首先为对象创建密度图。然后,该算法学习提取的特征与其对象密度图之间的线性映射。我们还可以使用随机森林回归等机器学习算法来学习输入输出之间的非线性映射关系。

4.基于CNN的方法
我们不是查看图像的补丁,而是使用CNN构建端到端的回归方法。这将整个图像作为输入并直接进行人群计数。 CNN在回归或分类任务方面运作良好,并且它们也证明了它们在生成密度图方面的价值。

CSRNet是我们将在本文中实现的一个模型,它可以部署更深入的CNN,用于捕获高级特征并生成高质量的密度图,而不会扩展网络复杂性。在深入代码部分之前,让我们先了解CSRNet。

论文中先提出了一些针对MCNN的实验,发现 MCNN 中过多的参数用于对输入图片的进行密度水平分类,然后通过实验中证明了MCNN中不同的通道收集到的特征差距不大,从而验证了MCNN中冗杂的网络结构是没有必要的。

论证图如下:
在这里插入图片描述

关于密度图的生成问题,采用了与MCNN中相同的策略,论文中直接用了MCNN里边生成.mat文件的方法,然后再生成.h5文件用于产生真值,此处有一个我认为比较好的关于生成过程的相关讲解:

高斯模糊算法:https://blog.csdn.net/farmwang/article/details/74452750

论文中采用的数据增强方式为:
将一张图片裁剪为9个部分,每个部分占1/4,前4个部分互相之间不重叠,后面5个随机。最后将这9张图片再镜像对称一下。但是我看了源码后发现作者并没有严格按照这个方法来做。这一点上可以随意发挥。

论文做了ablation study:即模型简化测试。
看看取消掉一些模块后性能有没有影响。 根据奥卡姆剃刀法则,简单和复杂的方法能达到一样的效果,那么简单的方法更可靠。
实际上ablation study就是为了研究模型中所提出的一些结构是否有效而设计的实验。 比如你提出了某某结构,但是要想确定这个结构是否有利于最终的效果,那就要将去掉该结构的网络与加上该结构的网络所得到的结果进行对比,这就是ablation study。

**

CSRNet的网络架构:

**

在这里插入图片描述

CSRNet使用已训练好的VGG-16的前13层网络作为前端,其中包括了10个卷积层和3个池化层(max-pooling)。因为有3个filter=2 x 2、stride=2的池化层,且卷积都是使用了padding=1、stride=1、filter=3 x 3的卷积层,所以 VGG-16的输出大小是原始输入大小的1/64, 比如原来是64 x 64, 输出就变成了8 x 8,同时,去掉了全连接层以适应输入图片尺寸的变化。

CSRNet在后端使用了空洞卷积层(或者叫膨胀卷积层),这个要说的话篇幅就太长了,它的作用就是不通过pooling也能有较大的感受野,相比于传统的先池化再卷积再上采样的操作,这样做避免了由于池化产生的精度上的损失。原文说的是:deploy dilated convolutional layers as the back-end for extracting deeper information of saliency as well as maintaining the output resolution

参考下面的图像:

  1. 空洞卷积在这里插入图片描述

  2. 空洞卷积与传统操作的优劣(通过他们提取的特征图的细节比较):
    在这里插入图片描述

**

接下来就是把模型跑起来:

**
我们将在ShanghaiTech数据集上训练CSRNet。 这包含1198个注释图像,总共330,165人。

使用以下代码块克隆CSRNet-pytorch的官方存储库。 这包含用于创建数据集,训练模型和验证结果的完整代码:

git clone https://github.com/leeyeehoo/CSRNet-pytorch.git

请在继续操作之前按照官方github上的配置安装CUDA和PyTorch等。

现在,将数据集移动到上面克隆的存储库中并解压缩。

文件里边的 make_dataset.ipynb 用来创建基本真值(ground_truth)。

是先用MCNN里边的生成真值的文件来生成.mat(Matlab文件格式)文件,然后再是用这个来生

成.h5文件。

你需要改一下文件的路径(换成自己的路径),如下所示:

在这里插入图片描述

为每个图像生成密度图是一个耗时的步骤。 因此,在代码运行时,冲泡一杯咖啡。

到目前为止,我们已经为part_A_final中的图像生成了基本真值。 接下来请自行为part_B_final 图像训练集执行相同的操作。

让我们看一个示例图像并计算其ground truth:

在这里插入图片描述
260就是该图的实际人数。

**

训练模型开始了

**

现在,我们有图像以及相应的真值(ground_truth)。 是时候训练我们的模型!

我们将使用克隆目录中提供的.json文件。 我们只需要更改json文件中图像的位置。 为此,请打开.json文件,并将当前位置替换为图像所在的位置(建议用linux下的libreoffice 批量操作)。

请注意,所有这些代码都是用Python 2.7编写的。如果您正在使用Python 3 版本,请进行以下更改:

在model.py中,将第18行中的xrange更改为range

更改model.py中的第19行:list(self.frontend.state_dict().items())[i][1].data[:] = list(mod.state_dict().items())[i][1].data[:]

在image.py中,将第11行的ground_true替换为ground_truth

把 image.py 中倒数第二行 cv2.resize(target,(target.shape[1]/8,target.shape[0]/8)。。。单除号‘ / ’换成’’ // ‘’.因为要进行取整操作。
与此类似的还有该文件下的crop_size = (img.size[0]/2,img.size[1]/2) 。 将单除号改为双除号。

现在,进入 你放置 CSRNet-pytorch库的文件夹位置,然后在这里打开终端
执行以下命令:

在这里,说两句
1、 源码里边默认是不开启随机裁剪以增强数据的,只是简单地把图片重复了4遍。数据增强开启方法就是去改一下源码,在 image.py 里边有一个 if False : 把False 改为True 后再对应改一下对应的表示概率的数字就OK了。

如图(CV2那里忘记加除号了):

在这里插入图片描述

2、 下面这行代码,part_A_train.json是训练集,part_A_val.json是验证集,官方写的是:
Try python train.py train.json val.json 0 0 to start training process.,是要我们写出自己的验证集和训练集,打开该文件,批量将路径修改,然后可以自己改一下训练集和测试集的数量。

python3 train.py part_A_train.json part_A_val.json 0 0

再次,请坐下来,因为这需要很多时间。 您可以通过减少 train.py 文件中的纪元数(epoch)以加速该过程。 如果您不想等待,可以选择下载预先训练好的模型(该项目的github 上有,就是下载CSRNet的地方,不过要翻墙)。

最后,让我们检查模型的实际表现。 我们将使用val.ipynb文件来验证结果。

进入val.ipynb,然后添加部分代码,位置以及代码如图(记得修改路径):

mae = 0
for i in range(len(img_paths)):
    img = transform(Image.open(img_paths[i]).convert('RGB')).cuda()
    gt_file = h5py.File(img_paths[i].replace('.jpg','.h5').replace('images','ground_truth'),'r')
    groundtruth = np.asarray(gt_file['density'])
    output = model(img.unsqueeze(0))
    mae += abs(output.detach().cpu().sum().numpy()-np.sum(groundtruth))
print (mae/len(img_paths))

以及:

from matplotlib import cm as c
path = '/home/ao_han/文档/program/CSRNet/Shanghai/part_A_final/test_data/images_train/1.jpg'
img = transform(Image.open(path).convert('RGB')).cuda()

output = model(img.unsqueeze(0))
print("Predicted Count : ",int(output.detach().cpu().sum().numpy()))
temp = np.asarray(output.detach().cpu().reshape(output.detach().cpu().shape[2],output.detach().cpu().shape[3]))
plt.imshow(temp,cmap = c.jet)
plt.show()
temp = h5py.File('/home/ao_han/文档/program/CSRNet/Shanghai/part_A_final/test_data/ground_truth/IMG_100.h5', 'r')
temp_1 = np.asarray(temp['density'])
plt.imshow(temp_1,cmap = c.jet)
print("Original Count : ",int(np.sum(temp_1)) + 1)
plt.show()
print("Original Image")
plt.imshow(plt.imread(path))
plt.show()

位置如下图所示:

在这里插入图片描述

此时的MAE值为65.966,这已经非常好了。作者原文里给出的是68.

这是它生成的预测图和真值图的区别:

在这里插入图片描述

其实,,,这是从它github上下载下来的它的模型(即已经跑好了的模型)(手动狗头保命)

下面,看看我自己跑的(2080ti 跑了15个小时左右,这个是最初跑的,数据增强没有开启。跑的A训练集):

在这里插入图片描述
这是测试的结果(B数据集的,A的模型貌似被我弄丢了,B跑了300个epoch):

在这里插入图片描述

这个MAE是10.5, 作者在论文中给出的是10.6。

在这里插入图片描述

现在让我们检查单个图像上的预测:

在这里插入图片描述

作者给的模型跑出来的MAE、MSE 比论文中给出的最优值还要低一些,我猜想的原因是,论文投出去比较早,作者提交代码是之后是事,所以产生了这个差距。

到此,模型已经建立完毕。

大家可以关注我一下(狗头保命),我会一直跟进人群技术这方面的最新进展.

不对的地方烦请大佬们指正Orz.

本文基于该博客改进:https://blog.csdn.net/weixin_41697507/article/details/89436973

  • 23
    点赞
  • 99
    收藏
    觉得还不错? 一键收藏
  • 60
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 60
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值