復現過程:
首先當然是准備數據集,我沒有用論文作者的shanghaitech數據集,准備了malldataset數據集,反正都是大同小異啦。這篇文章的label有一點區別的就是它不是像很多分類的問題一樣是0 1 啥的,而是整張圖像,這還是我第一次遇到這樣的問題,還是蠻新鮮的。
然后參見人群密度估計之MCNN密度圖的生成,在MATLAB上寫了程序:
clear;
load('perspective_roi.mat');
load('mall_gt.mat');
m=480;n=640;
m=m/4;
n=n/4;
mask = imresize(roi.mask,0.25); %圖像縮小4倍
for i=1:2000 %2000幅圖像
gt = frame{i}.loc; %第一個frame結構體的loc字段
gt = gt/4;
d_map = zeros(m,n);
for j=1:size(gt,1)
ksize = ceil(25/sqrt(pMapN(floor(gt(j,2)),1)));
ksize = max(ksize,7);
ksize = min(ksize,25);
radius = ceil(ksize/2);
sigma = ksize/2.5;
h = fspecial('gaussian',ksize,sigma);
x_ = max(1,floor(gt(j,1)));
y_ = max(1,floor(gt(j,2)));
if (x_-radius+1<1)
for ra = 0:radius-x_-1
h(:,end-ra) = h(:,end-ra)+h(:,1);
h(:,1)=[];
end
end
if (y_-radius+1<1)
for ra = 0:radius-y_-1
h(end-ra,:) = h(end-ra,:)+h(1,:);
h(1,:)=[];
end
end
if (y_-radius+1<1)
for ra = 0:radius-y_-1
h(end-ra,:) = h(end-ra,:)+h(1,:);
h(1,:)=[];
end
end
if (x_+ksize-radius>n)
for ra = 0:x_+ksize-radius-n-1
h (:,1+ra) = h(:,1+ra)+h(:,end);
h(:,end) = [];
end
end
if(y_+ksize-radius>m)
for ra = 0:y_+ksize-radius-m-1
h (1+ra,:) = h(1+ra,:)+h(end,:);
h(end,:) = [];
end
end
d_map(max(y_-radius+1,1):min(y_+ksize-radius,m),max(x_-radius+1,1):min(x_+ksize-radius,n))...
= d_map(max(y_-radius+1,1):min(y_+ksize-radius,m),max(x_-radius+1,1):min(x_+ksize-radius,n))...
+ h;
end
map0_255 = Normalize(d_map)
% %方法1,保存為圖片,再轉為LMDB
% %把數組A中的數轉換成字符串表示形式
str=num2str(i,'./density/seq_%06d.jpg');
%imwrite(d_map,str);
imshow( map0_255);
%方法2,直接轉為HDF5
% trainLabels=permute(d_map,[2 1]);
% str=num2str(i,'./density_map/seq_%06d.h5');
% h5create(str,'/label',size(trainLabels),'Datatype','double');
% h5write(str,'/label',trainLabels);
end
最后得到的圖像規到0-255后輸出為:
而d_map中的數據大致是,d_map是0-1之間的數值 
對d_map中的數值分析可以得知,就算歸到0-255,數值依然很小,所以,成黑白狀態。
說明:在pMapN中存的是透視變化的加權值,Roi表示在圖像中定義的ROI區域,mask掩碼可以實現只對ROI區域操作。
我用的深度學習框架是caffe。提取label是整個實驗完成的第一關,前面說了,這個實驗比較特殊,label是整張圖像。一開始考慮用hdf5傳輸數據,然而事實證明速度太慢,所以就考慮用兩個lmdb,一個裝數據,另一個裝label,只需要模仿着tools/convert_imageset.cpp 寫一個data和label分開存放到兩個LMDB里的代碼,訓練的時候用兩個data layer讀兩個LMDB。
這里為了加速模型的收斂,我進行了減均值和歸一化操作。由於數據集只有2000,並不像imagenet那樣的大數據,為了提高泛化能力,適應不同的數據集,我這里的均值沒有取2000個圖片的均值,而是直接設置為127.5,歸一化則除以128。
最終的測試程序如下:
- clear;clc;
- addpath('/home/caffe/matlab');
- caffe.reset_all();
- caffe.set_device(0);
- caffe.set_mode_gpu();
- model = 'deploy.prototxt';
- weights = 'network.caffemodel';
- net = caffe.Net(model, weights, 'test');
- cropImg=imread('IMG_12.jpg'); //cropImg是圖像裁剪
- cropImg = cropImg(:, :, [3, 2, 1]);
- cropImg = permute(cropImg, [2, 1, 3]); //permute(多維數組,[維數的組合])
- cropImg = single(cropImg);
- cropImg=imresize(cropImg,[480 640]);
- cropImg=(cropImg-127.5)/128;
- res = net.forward({cropImg});
- figure,imshow(cropImg,[]);
- figure,imagesc(res{1,1});
- count = sum(sum(res{1,1}))
- caffe.reset_all();
貼幾個效果圖:
