目录

1.算法概述

2.图像形态学处理原理

3.GRNN网络原理

4.基于形态学处理和GRNN网络的人员密度检测方法

5.部分源码


       基于形态学处理和 GRNN 网络的人员密度检测是一种结合了数学形态学图像处理技术和广义回归神经网络(GRNN)的方法,旨在准确地从图像或视频中估计人员密度。

1.算法概述

       人群密度情况分为三个等级,(1)稀少和不拥挤情况下为绿色提醒。(2)比较拥挤情况下,黄色预警。(3)非常拥挤情况下,红色报警。 不同人群密度情况通过相应的报警级别在界面上实时显示出来

人群密度分类两种思路:

(1)估计在景人数,根据人数多少,判断人群密度情形。

(2)提取分析人群的整体特征,训练样本,利用分类器学习分类。

2.图像形态学处理原理

       图像预处理:形态学处理可以用于对输入的人群图像进行预处理。例如,通过开运算可以去除图像中的小噪声块,这些噪声块可能是由于图像采集过程中的干扰或者背景中的一些小物体导致的。通过闭运算可以填充人群区域内的一些小空洞,使得人群区域更加完整。例如,在一些人群图像中,由于人群的分布不均匀,可能会出现一些小的空隙,闭运算可以将这些空隙填充,从而更准确地表示人群的实际分布区域。

       特征提取:形态学处理还可以用于提取人群图像的一些特征。例如,通过形态学骨架提取算法,可以提取出人群区域的骨架,骨架可以反映人群的大致形状和结构信息。另外,通过计算形态学的一些参数,如面积、周长、离心率等,可以作为人群密度检测的辅助特征。例如,人群密度较高时,人群区域的面积通常会较大,周长也会相应较长。

3.GRNN网络原理

       广义回归神经网络(Generalized regression neural network, GRNN)是一种建立在非参数核回归基础之上的神经网络,通过观测样本计算自变量和因变量之间的概率密度函数。GRNN结构如图1所示,整个网络包括四层神经元:输入层、模式层、求和层与输出层。

       GRNN神经网络的性能,主要通过对其隐回归单元的核函数的光滑因子来设置的,不同的光滑因子可获得不同的网络性能。输入层的神经元数目与学习样本中输入向量的维数m相等。每个神经元都分别对应一个不同的学习样本,模式层中第i个神经元的传递函数为:

 

       由此可以看出,当选择出学习样本之后,GRNN网络的结构与权值都是完全确定的,因而训练GRNN网络要比训练BP网络和RBF网络便捷得多。根据上述GRNN网络的各个层的输出计算公式,整个GRNN网络的输出可用如的式子表示:

4.基于形态学处理和GRNN网络的人员密度检测方法

       首先对输入的人群图像进行形态学处理,如前面所述,通过开运算、闭运算等操作对图像进行预处理,去除噪声和填充空洞。

       然后提取图像的特征,除了形态学特征(如面积、周长、骨架等)外,还可以结合其他图像特征提取方法,如灰度共生矩阵(GLCM)来提取纹理特征。灰度共生矩阵是一种广泛使用的纹理分析工具,可用于提取图像的纹理信息,如能量、对比度、熵和均匀性等,这些纹理特征与人群密度有一定的相关性。例如,人群密度较高时,图像的纹理通常会更加复杂,对比度和熵的值可能会较大。

       此外,还可以提取一些基于统计的特征,如平均灰度值、灰度方差等。平均灰度值可以反映图像的整体亮度情况,灰度方差可以反映图像中灰度值的离散程度,在一定程度上也与人群密度有关。

       将提取到的特征作为GRNN网络的输入,将对应的实际人员密度值作为输出,组成训练样本集。

       使用训练样本集对GRNN网络进行训练,通过调整光滑因子σ等参数,使得GRNN网络的输出能够尽可能准确地拟合实际的人员密度值。可以采用一些优化算法来寻找最优的光滑因子σ,如交叉验证法等。交叉验证法是将训练样本集分成若干个子集,依次使用其中一个子集作为验证集,其他子集作为训练集,通过比较不同光滑因子σ下验证集的预测误差,选择预测误差最小的光滑因子σ作为最优参数。

       训练好GRNN模型后,对于新的待检测人群图像,同样提取相应的特征,然后将特征输入到训练好的GRNN模型中,模型会输出预测的人员密度值。

5.部分源码


for tt = frameNum_Originals
    disp('当前帧数');
    tt
    indxx            = indxx + 1; 
    pixel_original   = read(Obj,tt);
    pixel_original2  = imresize(pixel_original,[RR,CC]);
 
    
 
    Temp = zeros(RR,CC,CRGB,'uint8');

    Temp = pixel_original2;
    Temp = reshape(Temp,size(Temp,1)*size(Temp,2),size(Temp,3));  

    image = Temp;
    for kk = 1:K   
        Datac         = double(Temp)-reshape(Mus(:,kk,:),D,CRGB);
        Squared(:,kk) = sum((Datac.^ 2)./reshape(Sigmas(:,kk,:),D,CRGB),2); 
    end
    [junk,index] = min(Squared,[],2); 
    Gaussian                                                = zeros(size(Squared));
    Gaussian(sub2ind(size(Squared),1:length(index),index')) = ones(D,1);
    Gaussian                                                = Gaussian&(Squared<Deviation_sq);
    %参数更新
    Weights = (1-Alpha).*Weights+Alpha.*Gaussian;
    for kk = 1:K
        pixel_matched   = repmat(Gaussian(:,kk),1,CRGB);
        pixel_unmatched = abs(pixel_matched-1);
        Mu_kk           = reshape(Mus(:,kk,:),D,CRGB);
        Sigma_kk        = reshape(Sigmas(:,kk,:),D,CRGB);
        Mus(:,kk,:)     = pixel_unmatched.*Mu_kk+pixel_matched.*(((1-Rho).*Mu_kk)+(Rho.*double(image)));
        Mu_kk           = reshape(Mus(:,kk,:),D,CRGB); 
        Sigmas(:,kk,:)  = pixel_unmatched.*Sigma_kk+pixel_matched.*(((1-Rho).*Sigma_kk)+repmat((Rho.* sum((double(image)-Mu_kk).^2,2)),1,CRGB));       
    end
    replaced_gaussian   = zeros(D,K); 
    mismatched          = find(sum(Gaussian,2)==0);       
    for ii = 1:length(mismatched)
        [junk,index]                            = min(Weights(mismatched(ii),:)./sqrt(Sigmas(mismatched(ii),:,1)));
        replaced_gaussian(mismatched(ii),index) = 1;
        Mus(mismatched(ii),index,:)             = image(mismatched(ii),:);
        Sigmas(mismatched(ii),index,:)          = ones(1,CRGB)*Variance;
        Weights(mismatched(ii),index)           = Props;  
    end
    Weights         = Weights./repmat(sum(Weights,2),1,K);
    active_gaussian = Gaussian+replaced_gaussian;
    %背景分割 
    [junk,index]    = sort(Weights./sqrt(Sigmas(:,:,1)),2,'descend');
    bg_gauss_good   = index(:,1);
    linear_index    = (index-1)*D+repmat([1:D]',1,K);
    weights_ordered = Weights(linear_index);
    for kk = 1:K
        Weight(:,kk)= sum(weights_ordered(:,1:kk),2);
    end
    bg_gauss(:,2:K) = Weight(:,1:(K-1)) < Back_Thresh;
    bg_gauss(:,1)   = 1;           
    bg_gauss(linear_index)     = bg_gauss;
    active_background_gaussian = active_gaussian & bg_gauss;
    foreground_pixels          = abs(sum(active_background_gaussian,2)-1);
    foreground_map             = reshape(sum(foreground_pixels,2),RR,CC);
    Images1                    = foreground_map;   
    objects_map                = zeros(size(foreground_map),'int32');
    object_sizes               = [];
    Obj_pos                    = [];
    new_label                  = 1;
    %计算连通区域
    [label_map,num_labels]     = bwlabel(foreground_map,8);

    for label = 1:num_labels 
       object      = (label_map == label);
       object_size = sum(sum(object));
       if(object_size >= Comp_Thresh)
          objects_map             = objects_map + int32(object * new_label);
          object_sizes(new_label) = object_size;
          [X,Y]                   = meshgrid(1:CC,1:RR);    
          object_x                = X.*object;
          object_y                = Y.*object;
          Obj_pos(:,new_label)    = [sum(sum(object_x)) / object_size;
                                     sum(sum(object_y)) / object_size];
          new_label               = new_label + 1;
       end
    end
    num_objects = new_label - 1;
    %去除阴影
    index                       = sub2ind(size(Mus),reshape(repmat([1:D],CRGB,1),D*CRGB,1),reshape(repmat(bg_gauss_good',CRGB,1),D*CRGB,1),repmat([1:CRGB]',D,1));
    background                  = reshape(Mus(index),CRGB,D);
    background                  = reshape(background',RR,CC,CRGB); 
    background                  = uint8(background);
    if  indxx <= 500;
        background_Update           = background;
    else
        background_Update           = background_Update;
    end
        
    
    
    background_hsv              = rgb2hsv(background);
    image_hsv                   = rgb2hsv(pixel_original2);
    for i = 1:RR
        for j = 1:CC      
            if (objects_map(i,j))&&...
               (abs(image_hsv(i,j,1)-background_hsv(i,j,1))<SHADOWS(1))&&...
               (image_hsv(i,j,2)-background_hsv(i,j,2)<SHADOWS(2))&&...
               (SHADOWS(3)<=image_hsv(i,j,3)/background_hsv(i,j,3)<=SHADOWS(4))
               Shadows(i,j) = 1;  
            else
               Shadows(i,j) = 0;  
            end               
        end    
    end
    Images0           = objects_map;
    objecs_adjust_map = Shadows;
    Images2           = objecs_adjust_map;    
    
    
    
    
    %%
    %根据像素所在区域大小比例以及纹理特征分析获得人密度
    %腐蚀处理
    se        = strel('ball',6,6);
    Images2BW = floor(abs(imdilate(Images2,se)-5));
    Images3BW = zeros(size(Images2BW));
    X1 = round(168/2);
    X2 = round(363/2);
    Y1 = round(204/2);
    Y2 = round(339/2);
    if indxx > 80;
       %计算区域内像素值
       S1           = sum(sum(Images2BW(Y1:Y2,X1:X2)));
       S2(indxx-80) = S1/((X2-X1)*(Y2-Y1)); 
    end
    Images3BW(Y1:Y2,X1:X2)   = Images2BW(Y1:Y2,X1:X2);
    Images3Brgb              = pixel_original2(Y1:Y2,X1:X2,:);
    %纹理检测
    %计算纹理
    [A,B]     = func_wenli(rgb2gray(Images3Brgb));
    %选择能量 熵作为判断依据
    if indxx > 80;
       F1(indxx-80) = A(1);
       F2(indxx-80) = A(2);
       F3(indxx-80) = A(3);
    end
    if indxx > 80;
        load train_model.mat
        P     = [S2(indxx-80);F2(indxx-80)];
        y     = round(NET(P));


        if y == 1
           set(handles.text2,'String','低密度'); 
           set(handles.text2,'ForegroundColor',[0 1 0]) ;
        end
        if y == 2
           set(handles.text2,'String','中密度');  
           set(handles.text2,'ForegroundColor',[1 1 0]) ;
        end    
        if y == 3
           set(handles.text2,'String','高密度');   
           set(handles.text2,'ForegroundColor',[1 0 0]) ;
        end    
    end
    
    
    
    
    axes(handles.axes1)
    imshow(pixel_original2);
%     title('定位检测区域');
    hold on
    line([X1,X2],[Y1,Y1],'LineWidth',1,'Color',[0 1 0]);
    hold on
    line([X2,X2],[Y1,Y2],'LineWidth',1,'Color',[0 1 0]);
    hold on
    line([X2,X1],[Y2,Y2],'LineWidth',1,'Color',[0 1 0]);    
    hold on
    line([X1,X1],[Y2,Y1],'LineWidth',1,'Color',[0 1 0]); 
    
    
    axes(handles.axes2)
    imshow(uint8(background_Update));
%     title('背景获得');
    
 
    axes(handles.axes3)
    imshow(Images0,[]);
%     title('动态背景提取');    
    axes(handles.axes4)
    imshow(Images3BW,[]);
%     title('动态背景提取(检测区域内)');       
    
    
    pause(0.0000001);
end

测试结果如下:

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐