人群計數的方法分為傳統的視頻和圖像人群計數算法以及基於深度學習的人群計數算法,深度學習方法由於能夠方便高效地提取高層特征而獲得優越的性能是傳統方法無法比擬的。本文簡單了秒速了近幾年,基於單張圖像利用CNN估計人群密度圖和計數的方法。
-
傳統的人群計數方法
傳統的人群計數方法可以分為兩類,基於檢測的方法和基於回歸的方法。-
基於檢測的方法
早期的計數方法主要是基於檢測的方法,使用一個滑動窗口來檢測場景中的人群,並統計人數。 基於檢測的方法可以分為兩類:- 基於整體的檢測,訓練一個分類器,利用從行人全身提取到的小波,HOG,邊緣等特征檢測行人。 學習的方法有SVM,boosting和隨機森林等。 基於整體的方法主要適用於稀疏人群,隨着人群密度的提升,人與人之間的遮擋越來越嚴重,這種方法就不再適用。
- 基於部分的身體的檢測。 為了處理人與人的遮擋問題,主要通過檢測身體的部分結構,例如頭,肩膀等去統計人群的數量。這種方法比之基於整體的檢測,在效果上有略微的提升。
-
基於回歸的方法
論何種基於檢測的方法,都很難處理人群之間嚴重的遮擋問題。所以,基於回歸的方法逐漸被用來解決人群計數的問題。 基於回歸的方法,主要思想是學習一種特征到人群數量的映射。該類方法主要分為兩步:1. 提取場景的低級特征,例如例如前景特征,邊緣特征,紋理和梯度特征;2. 學習一個回歸模型,例如線性回歸,嶺回歸或者高斯過程回歸,學習一個低級特征到人群數的映射關系。 -
基於密度圖的方法
基於回歸的方法雖然能在一定程度上解決遮擋的問題,但是由於是使用整幅圖像的特征進行回歸技術,從而忽略了圖像的空間信息。在2010年的Visual Geometry Group University of Oxford提出了:學習圖像的局部特征和其相應的密度圖之間的映射,從而在計數的過程中加入圖像的空間信息。 論文地址:Learning To Count Objects in Images . 該論文最早提出使用密度圖來進行計數的方法,后來很多的圖像計數多數基於此方法。
-
-
基於深度學習的方法
深度學習在計算機的視覺的識別,分割,檢測相比傳統的方法都取得了很大的進步,人群計數也不例外,近年來的方法多數是使用深度學習的方法,利用深度學習的學歷能力得到圖像到其相應的人群密度圖或者數量。
傳統的方法通常都是輸入圖像的一個patch,並且通常分為兩個步驟:特征的提取,回歸或者分類,而基於CNN的方法則輸入是一種完整的圖片,並且進行end-to-end的訓練。無論是使用回歸或者密度圖,CNN的方法都能取得較好的結果。
本文主要總結下,近幾年關於使用CNN基於單幅人群圖像生成密度圖的方法。
MCNN (cvpr2016)
zhang等人提出了 Multi-column Convolutional Neural Network (MCNN)網絡來預測人群的密度圖。MCNN中有三大創新:
- 提出了MCNN網絡,能夠處理任意大小的圖像,並且使利用3個具有不同卷積核大小的網絡來分別提取人群圖像的特征,來適應人群頭部大小的變化。
- 提出一種根據人頭標記生成人群密度圖的方法
- 構建了一個新的數據集 Shanghaitech ,包含1198張圖像約有330000個人頭標記數據。
作者認為,人群計數存在着以下的困難:
- 前景的分割,現有的計數方法通常需要前景分割,而前景分割是很困難的。使用MCNN網絡則不需要進行前景分割,輸入任意的人群圖像,通過CNN網絡直接估計其密度圖。
- 密集人群存在嚴重的遮擋
- 人群圖像中人的尺度存在着較大的差異就需要融合多種圖像的特征來估計人群的數量,這些特征人工則很難設計。
為了應對以上問題,作者提出了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}\)是生成的低分辨率的密度圖。
對於生成高分辨率的分支HR-CNN,其輸入則是\(X_i,\hat{Z_i}\),其表示如下
其損失函數為
使用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這樣的從低分辨率密度圖細化到高分辨率的密度圖。