人群计数的方法分为传统的视频和图像人群计数算法以及基于深度学习的人群计数算法,深度学习方法由于能够方便高效地提取高层特征而获得优越的性能是传统方法无法比拟的。本文简单了秒速了近几年,基于单张图像利用CNN估计人群密度图和计数的方法。

  1. 传统的人群计数方法

    传统的人群计数方法可以分为两类,基于检测的方法和基于回归的方法。

    • 基于检测的方法

      早期的计数方法主要是基于检测的方法,使用一个滑动窗口来检测场景中的人群,并统计人数。 基于检测的方法可以分为两类:

      • 基于整体的检测,训练一个分类器,利用从行人全身提取到的小波,HOG,边缘等特征检测行人。 学习的方法有SVM,boosting和随机森林等。 基于整体的方法主要适用于稀疏人群,随着人群密度的提升,人与人之间的遮挡越来越严重,这种方法就不再适用。
      • 基于部分的身体的检测。 为了处理人与人的遮挡问题,主要通过检测身体的部分结构,例如头,肩膀等去统计人群的数量。这种方法比之基于整体的检测,在效果上有略微的提升。
    • 基于回归的方法

      论何种基于检测的方法,都很难处理人群之间严重的遮挡问题。所以,基于回归的方法逐渐被用来解决人群计数的问题。 基于回归的方法,主要思想是学习一种特征到人群数量的映射。该类方法主要分为两步:1. 提取场景的低级特征,例如例如前景特征,边缘特征,纹理和梯度特征;2. 学习一个回归模型,例如线性回归,岭回归或者高斯过程回归,学习一个低级特征到人群数的映射关系。

    • 基于密度图的方法

      基于回归的方法虽然能在一定程度上解决遮挡的问题,但是由于是使用整幅图像的特征进行回归技术,从而忽略了图像的空间信息。在2010年的Visual Geometry Group University of Oxford提出了:学习图像的局部特征和其相应的密度图之间的映射,从而在计数的过程中加入图像的空间信息。 论文地址:Learning To Count Objects in Images . 该论文最早提出使用密度图来进行计数的方法,后来很多的图像计数多数基于此方法。

  2. 基于深度学习的方法

深度学习在计算机的视觉的识别,分割,检测相比传统的方法都取得了很大的进步,人群计数也不例外,近年来的方法多数是使用深度学习的方法,利用深度学习的学历能力得到图像到其相应的人群密度图或者数量。

传统的方法通常都是输入图像的一个patch,并且通常分为两个步骤:特征的提取,回归或者分类,而基于CNN的方法则输入是一种完整的图片,并且进行end-to-end的训练。无论是使用回归或者密度图,CNN的方法都能取得较好的结果。

本文主要总结下,近几年关于使用CNN基于单幅人群图像生成密度图的方法。

MCNN (cvpr2016)

zhang等人提出了 Multi-column Convolutional Neural Network (MCNN)网络来预测人群的密度图。MCNN中有三大创新:

  • 提出了MCNN网络,能够处理任意大小的图像,并且使利用3个具有不同卷积核大小的网络来分别提取人群图像的特征,来适应人群头部大小的变化。
  • 提出一种根据人头标记生成人群密度图的方法
  • 构建了一个新的数据集 Shanghaitech ,包含1198张图像约有330000个人头标记数据。

作者认为,人群计数存在着以下的困难:

  1. 前景的分割,现有的计数方法通常需要前景分割,而前景分割是很困难的。使用MCNN网络则不需要进行前景分割,输入任意的人群图像,通过CNN网络直接估计其密度图。
  2. 密集人群存在严重的遮挡
  3. 人群图像中人的尺度存在着较大的差异就需要融合多种图像的特征来估计人群的数量,这些特征人工则很难设计。

为了应对以上问题,作者提出了MCNN网络,使用3个不同尺度的卷积网络提取图像的多尺度特征,并使用\(1 \times 1\)的卷积核将多尺度的特征融合到一起。 其网络结构如下:

这类利用多个网络的模型具有较多的参数,计算量大,无法进行实时的人群计数预测。而且多阵列的网络并不能如所描述的一般,提取不同的尺度的人头特征。

密度图的生成

人群计数的数据集,通常是标记了人头的位置,就需要根据人头位置的数据来生成相应的人群密度图。 MCNN种提出了一种自适应卷积核的方法,来生成相应的密度图。

在由标记生成密度图的过程,首先将每个人头对应的位置设置为1,然后对该图像进行高斯卷积。

代码如下:

img = cv2.imread(path)
density = np.zeros((img.shape[0],img.shape[1])) for i inr range(0,len(gt)):
if int(gt[i][1]) < img.shape[0] and int(gt[i][0]) < img.shape[1]:
density[int(gt[i][1]),int(gt[i][0])] = 1
density = cv2.GaussianBlur(density,(5,5))

这种构建的密度图是假设人头相对于图像平面是独立存在的,事实上,由于透视畸变的村子,不同位置人头对应着不同大小的像素区域。 因此,要想生成精确的人群密度图像,就要考虑单应性引起的畸变,但是畸变参数是不容易得到的。故,作者假设每个头部周围的人群分布比较均匀,那么头部与其最近的k个邻居之间的平均距离,给出了一个合理的几何失真估计(由透视效果引起)。而且作者在拥挤的场景中,头部的大小通常与相邻两个人中心的距离有关。 作为一种折衷,对于那些拥挤场景的密度图,建议根据每个人与其邻居的平均距离来自适应地确定每个人的扩展参数,也就是高斯卷积核的方差。

也是就,其为每个人头位置根据其与周围相邻的人头的距离来构建卷积的方差,然后将所有人头点卷积后的结果累加到一起,就是最终生成的密度图。具体代码如下:

    gt_count = np.count_nonzero(gt)
if gt_count == 0:
return density # FInd out the K nearest neighbours using a KDTree
pts = np.array(list(zip(np.nonzero(gt)[1].ravel(), np.nonzero(gt)[0].ravel())))
leafsize = 2048 # build kdtree
tree = scipy.spatial.KDTree(pts.copy(), leafsize=leafsize) # query kdtree
distances, locations = tree.query(pts, k=4) for i, pt in enumerate(pts):
pt2d = np.zeros(gt.shape, dtype=np.float32)
pt2d[pt[1],pt[0]] = 1.
if gt_count > 1:
sigma = (distances[i][1]+distances[i][2]+distances[i][3])*0.1
else:
sigma = np.average(np.array(gt.shape))/2./2. #case: 1 point #Convolve with the gaussian filter
density += scipy.ndimage.filters.gaussian_filter(pt2d, sigma, mode='constant')

CP-CNN (cvpr 2017)

CP-CNN( Generating High-Quality Crowd Density Maps using Contextual Pyramid CNNs) 使用图像的全局和局部特征信息生成估计人群图像的密度图。

其网络结构如下:

绿色子网络表示对整张输入图像做特征提取并分类(类别为作者分好的密度等级,即当前输入图像属于哪个密度等级),并将分类结果张成一个与密度特征具有相同高和宽的图像(全局上下文);蓝色子网络对原图中割出的patch做同样的操作,得到局部上下文。最终将全局和局部上下文特征与原图产生的密度图(黄色部分)在通道维度拼接(concate)。该方法的初衷是为了考虑一幅图像中人群的全局密度和局部密度信息,最后对整个特征做约束,使得网络对任何一张图像都自适应的学到相应密度等级的特征。

CSRNet (cvpr 2018)

CSRnet网络模型主要分为前端和后端网络,采用剔除了全连接层的VGG-16作为CSRnet的前端网络,提取图像的特征,输出密度图的大小为原始输入图像的1/8。采用空洞卷积神经网络作为后端网络,在保持分辨率的同时扩大感知域, 生成高质量的人群分布密度图。

采用剔除了全连接层的VGG-16网络,并且采用3×3的卷积核。研究表明,对于相同大小的感知域,卷积核越小,卷积层数越多的模型要优于那些有着更大卷积核且卷积层数较少的模型。为了平衡准确性和资源开销,这里的VGG-16网络采用10层卷积层和3层池化层的组合。后端网络采用六层空洞卷积层,空洞率相同。最后采用一层1×1的普通卷积层输出结果,其网络结构如下:

CSRNet的主要思路是,使用预训练的VGG进行特征提取,后面再使用空洞卷积,在扩大感受野的同时,生成人群的密度图。

ic-CNN (ECCV 2018)

Iterative Crowd Counting,其采取的思路是首先生成低分辨率的密度图,然后进一步的细化来生成高分辨率的密度图。该网络结构由两个CNN分支组成,一个分支用来生成低分辨率的密度图,另一个使用生成的低分辨率的密度图以及提取的特征图的基础上,生成高分辨率的密度图。其网络结构如下:

该网络的输入是一个三元组\(\mathcal{D}=\left\{\left(X_{1}, Y_{1}, Z_{1}\right), \ldots,\left(X_{n}, Y_{n}, Z_{n}\right)\right\}\),其中\(X_i\)是输入的图像,\(Y_i\)是和原图像相同分辨率的密度图,\(Z_i\)则是低分辨率的密度图。

对于生成低分辨率密度图的分支LR-CNN,其输入是\(X_i\),则可以用如下公式表示

\[\hat{Z}_{i}=f_{l}\left(X_{i} ; \theta_{l}\right)
\]

其中,\(\hat{Z}_{i}\)是生成的低分辨率的密度图。

对于生成高分辨率的分支HR-CNN,其输入则是\(X_i,\hat{Z_i}\),其表示如下

\[\hat{Y}_{i}=f_{h}\left(X_{i}, \hat{Z}_{i} ; \theta_{l}, \theta_{h}\right)
\]

其损失函数为

\[\mathcal{L}\left(\theta_{l}, \theta_{h}\right)=\frac{1}{n} \sum_{i=1}^{n}\left(\lambda_{l} L\left(\hat{Z}_{i}, Z_{i}\right)+\lambda_{h} L\left(\hat{Y}_{i}, Y_{i}\right)\right)
\]

使用HR-CNN输出的高分辨率的密度图作为最终的输出结果。其表现如下

SANet(ECCV 2018)

Scale Aggregation Network for Accurate and Efficient Crowd Counting,该方法同样考虑要提取每个图像的多个尺度的人头信息,但并不采取类似MCNN的多阵列网络结构,其使用了类似于Inception架构的模块,在每个卷积层都同时使用不同大小的卷积核,最后通过反卷积得到最终的密度图。

简单来说,就是使用一系列的Inception结构提取不同尺度的特征,再使用反卷积(Transposed CONV)生成高分辨率的密度图,其网络结构如下:

Summary

简单的梳理了下2016年到2018年出现的一些基于CNN生成人群密度图的方法。 可以看出,生成人群密度图的难点仍然是:人头的重叠以及人头尺度的变化。 这两个困难有时候有可以看作是一个:人头尺度变小了,其看着就重叠到了一起。 所以目前主流的方法,仍然是提取多尺度的人头特征信息,当然也有ic-CNN这样的从低分辨率密度图细化到高分辨率的密度图。

基于CNN的人群密度图估计方法简述的更多相关文章

  1. 利用opencv作透明重叠人群密度热度图

    在作热度图的时候我们经常需要将热度图调整透明度后叠加在原图上达到更好的展示效果.比如检测人气密度的热度图: (来自sensetime) 一般作图的时候会第一时间想到matplotlib,因为可以很方便 ...

  2. 人群密度检测MCNN+CSRnet

    MCNN(简单理解): 三列卷积神经网络,分别为大中小三种不同尺度的卷积核,表示为L列(使用大尺度卷积核: 9*9, 7*7, 7*7,7*7), M(使用中等尺度卷积核: 7*7, 5*5, 5*5 ...

  3. 第六篇:R语言数据可视化之数据分布图(直方图、密度曲线、箱线图、等高线、2D密度图)

    数据分布图简介 中医上讲看病四诊法为:望闻问切.而数据分析师分析数据的过程也有点相似,我们需要望:看看数据长什么样:闻:仔细分析数据是否合理:问:针对前两步工作搜集到的问题与业务方交流:切:结合业务方 ...

  4. cvpr2017:branchout——基于CNN的在线集成跟踪

    1.引言 2017年CVPR上有不少关于跟踪的paper.CF方面最引人瞩目的应该是ECO了,CNN方面也有一些新的进展.Branchout是一个基于CNN用bagging集成的在线跟踪方法. con ...

  5. LSF-SCNN:一种基于 CNN 的短文本表达模型及相似度计算的全新优化模型

    欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 本篇文章是我在读期间,对自然语言处理中的文本相似度问题研究取得的一点小成果.如果你对自然语言处理 (natural language proc ...

  6. Deep Snake : 基于轮廓调整的SOTA实例分割方法,速度32.3fps | CVPR 2020

    论文提出基于轮廓的实例分割方法Deep snake,轮廓调整是个很不错的方向,引入循环卷积,不仅提升了性能还减少了计算量,保持了实时性,但是Deep snake的大体结构不够优雅,应该还有一些工作可以 ...

  7. 基于ros2 dashing的建图导航探索

    基于ros2 dashing的建图导航探索 1. 环境准备 安装ros2 dashing, 参考链接: https://index.ros.org/doc/ros2/Installation/Dash ...

  8. 基于Delphi的三层数据库系统的实现方法

    基于Delphi的三层数据库系统的实现方法   1  引言 当前的数据库应用系统中,按其结构划分为两类,一类是两层结构的数据库应系统,另一类是多层结构的数据库应用系统. 两层结构的数据库应用系统包括客 ...

  9. Pathchirp—有效的带宽估计方法(二)

    上一个blog介绍了有效带宽估计方法:pathload.http://blog.csdn.net/ice110956/article/details/11126491. 做一个小小的总结:pathlo ...

随机推荐

  1. SpringMVC+GSON 对象序列化--日期格式的处理

    Gson异常强大因此使用它代替了Jackson作为SpringMVC消息转换器. 在自己的项目中,发现对象在序列化后,日期格式出现了问题. 先看问题 在员工表中有一列是生日,字段类型为Date,也就是 ...

  2. jq slideToggle()坑

    jQuery slideToggle() 方法 jQuery slideToggle() 方法可以在 slideDown() 与 slideUp() 方法之间进行切换. 如果元素向下滑动,则 slid ...

  3. RedHat Linux下iptables防火墙设置

    一般情况下iptables已经包含在Linux发行版中.运行 # iptables --version 来查看系统是否安装iptables 启动iptables:# service iptables ...

  4. 剑指Offer_编程题之二维数组中的查找

    题目描述 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数.

  5. jQuery-01:on live bind delegate

    摘自:https://www.cnblogs.com/moonreplace/archive/2012/10/09/2717136.html moonreplace这位大牛的 当我们试图绑定一些事件到 ...

  6. golang自定义路由控制实现(二)-流式注册接口以及支持RESTFUL

        先简单回顾一下在上一篇的文章中,上一篇我主要是结合了数组和Map完成路由映射,数组的大小为8,下标为0的代表Get方法,以此类推,而数组的值则是Map,键为URL,值则是我们编写对应的接口.但 ...

  7. Idea 的两个快捷键不能用的解决过程

    早上来重启电脑后,Idea 的Ctrl+Alt+V还能用,但中间不知道那个时间点开始就不好用了(中间有启动有道词典查词) 度娘上没找到答案,hot key这种软件被win10提示有病毒,没敢用 然后尝 ...

  8. OAthe2 Login use OkHttpClient and OAuth2RestTemplate

    http://samchu.logdown.com/posts/1437422-oathe2-login-use-okhttpclient-and-oauth2resttemplate?utm_sou ...

  9. 查找linux设备的uuid

    [root@ ~]# blkid /dev/vdc /dev/vdc: UUID="bxxxx-xxx-41b9-8146-7da8bd645b92" TYPE="ext ...

  10. Selenium 指定浏览器位置

    在脚本开头要指定浏览器位置. public static void main(String[] args) throws InterruptedException, IOException { Sys ...