www.gusucode.com > IPCV_Eval_Kit_R2019a_0ce6858工具箱matlab程序源码 > IPCV_Eval_Kit_R2019a_0ce6858/code/demo_files/I4_08_2_myMultiObjectTracking.m

    %% Motion-Based Multiple Object Tracking
%    僩儔僢僉儞僌媄弍丗摦嶌擣幆丄岎捠娔帇丄帺摦幵偺婋尟専抦摍傊偺墳梡
%丂丂Step#1丗奺僼儗乕儉撪偱偺摦偄偰偄傞暔懱偺専弌
%    Step#2丗僼儗乕儉娫偱偺娭楢晅偗
% Kalman僼傿儖僞乕傪巊梡
% 幚峴儃僞儞偱僨儌

clc;close all;imtool close all;clear;

% Stop 儃僞儞昞帵
a=true;
sz = get(0,'ScreenSize');
figure('MenuBar','none','Toolbar','none','Position',[20 sz(4)-100 100 70])
uicontrol('Style', 'pushbutton', 'String', 'Stop',...
        'Position', [20 20 80 40], 'Callback', 'a=false;');
    
%% 奺庬System Objects偺惗惉 %%%%%
% 摦夋撉崬傒偺僆僽僕僃僋僩惗惉
  obj.reader = vision.VideoFileReader('atrium.mp4');
% 摦夋昞帵梡僆僽僕僃僋僩偺惗惉
  obj.videoPlayer = vision.VideoPlayer('Position', [ 20, sz(4)-600, 700, 400]);
  obj.maskPlayer  = vision.VideoPlayer('Position', [740, sz(4)-600, 700, 400]);     
% 摦偄偰偄傞慜宨傪専弌偡傞僆僽僕僃僋僩傪惗惉
  obj.detector = vision.ForegroundDetector('NumGaussians', 3, ...
       'NumTrainingFrames', 40, 'MinimumBackgroundRatio', 0.7);
% 僽儘僽夝愅梡偺僆僽僕僃僋僩偺嶌惉乮拞怱揰丒嫬奅儃僢僋僗乯
  obj.blobAnalyser = vision.BlobAnalysis( 'AreaOutputPort',false, ...
          'CentroidOutputPort', true,  'BoundingBoxOutputPort', true, ...
          'MinimumBlobArea', 400, 'ExcludeBorderBlobs',true);

% 僩儔僢僋乮奺僩儔僢僋偵丄奺摦偄偰偄傞暔懱偺忣曬傪奿擺乯偺弶婜壔
tracks = struct(...
  'id',           {}, ...       % ID斣崋
  'bbox',         {}, ...       %尰僼儗乕儉撪偺嫬奅儃僢僋僗乮昞帵梡乯
  'kalmanFilter', {}, ...       %偙偺暔懱僩儔僢僉儞僌梡偺僇儖儅儞僼傿儖僞乕
  'trails',       [], ...       % 婳愓昞帵梡偵丄夁嫀偺埵抲傪曐懚
  'age',               {}, ...  %嵟弶偵専弌偝傟偰偐傜偺僼儗乕儉悢
  'totalVisibleCount', {}, ...      %専弌偝傟偨慡僼儗乕儉悢           => 偙傟偑鑷抣傪挻偊偨傜昞帵偡傞
  'consecutiveInvisibleCount', {}); %楢懕偟偨旕専弌僼儗乕儉悢         => 偙傟偑鑷抣傪挻偊偨傜偙偺僩儔僢僋傪嶍彍

nextId = 1; % ID of the next track

%% 儊僀儞儖乕僾 %%%%%
while (a && ~isDone(obj.reader))
  frame = step(obj.reader);     % 1僼儗乕儉撉傒崬傒
  
  %% [僼儗乕儉撪偱摦偄偰偄傞慡暔懱偺専弌] %%%%%
  % 僼儗乕儉撪偺暔懱傪専弌丗摦偄偰偄傞暔懱(椞堟)偺専弌丗mask偼1偑慜宨丒0偑攚宨
  mask = step(obj.detector, frame);  % 2抣儅僗僋夋憸丗ForegroundDetector傪巊梡
  % 慜張棟丗嵶偐側僲僀僘偺彍嫀丒寠傪杽傔傞
  mask = imopen(mask, strel('rectangle', [3,3]));      %廂弅->朿挘丗偛傒丒僽儕僢僕彍嫀
  mask = imclose(mask, strel('rectangle', [15, 15]));  %朿挘->廂弅丗寠丒僗儕僢僩杽傔
  mask = imfill(mask, 'holes');
  % 拞怱揰丒嫬奅儃僢僋僗偺専弌
  [centroids, bboxes] = step(obj.blobAnalyser, mask);

  %% [尰僼儗乕儉撪偱偺埵抲傪慜僼儗乕儉偐傜梊應] %%%%%
  % 僇儖儅儞僼傿儖僞傪梡偄偰丄慜僼儗乕儉傑偱偵専弌嵪傒偺奺暔懱(僩儔僢僋)偺埵抲梊應
  for i = 1:length(tracks)
    bbox = tracks(i).bbox;    % 慜僼儗乕儉偱偺嫬奅儃僢僋僗
    % 尰僼儗乕儉偱偺埵抲偺梊應
    predictedPosition = int32(predict(tracks(i).kalmanFilter));
    % 嫬奅儃僢僋僗偺拞怱傪丄梊應廳怱埵抲傊挷惍
    tracks(i).bbox = [predictedPosition - bbox(3:4)/2, bbox(3:4)];
  end
  
  %% 婛専弌暔懱(僩儔僢僋)偵丄専弌偝傟偨暔懱傪懳墳晅偗 %%%%%
  % 僐僗僩偺寁嶼丗婛専弌暔懱偺梊應埵抲偲奺専弌暔懱偺嫍棧
  cost = zeros(length(tracks), size(centroids, 1));         % 僩儔僢僋悢 x 専弌悢
  for i = 1:length(tracks)
      cost(i, :) = distance(tracks(i).kalmanFilter, centroids);
  end
  
  % 奺僩儔僢僋偵専弌偝傟偨暔懱傪妱摉 (僴儞僈儕傾儞傾儖僑儕僘儉丗僐僗僩偺崌寁偑嵟彫偵側傞傛偆偵乯
  % assignment:僩儔僢僋斣崋偲専弌斣崋偺慻偑戙擖偝傟傞
  costOfNonAssignment = 20;     %彫偝偄偲婛懚僩儔僢僋偵傾僒僀儞偝傟側偄傕偺憹偊傞=>怴偟偄僩儔僢僋偑懡偔惗惉偝傟傞
  [assignments, unassignedTracks, unassignedDetections] = ...
              assignDetectionsToTracks(cost, costOfNonAssignment);

  %% 懳墳偡傞暔懱偑尒偮偐偭偨僩儔僢僋偺忣曬峏怴 %%%%%
  for i = 1:size(assignments, 1)
      trackIdx = assignments(i, 1);           %僩儔僢僋偺斣崋
      detectionIdx = assignments(i, 2);       %専弌暔懱偺斣崋
      centroid = centroids(detectionIdx, :);  %偦偺専弌偝傟偨暔懱i偺拞怱揰傪拪弌乮obj.blobAnalyser.step(mask)偺寢壥傪巊梡乯
      bbox = bboxes(detectionIdx, :);         %偦偺専弌偝傟偨暔懱偺嫬奅儃僢僋僗傪拪弌乮obj.blobAnalyser.step(mask)偺寢壥傪巊梡)

      % 専弌偝傟偨埵抲偲梊應抣傪梡偄偰丄尰嵼埵抲傪悇掕
      c2 = correct(tracks(trackIdx).kalmanFilter, centroid);

      % 奺僩儔僢僋忣曬傪峏怴丗嫬奅儃僢僋僗丄age丄totalVisibleCount丄consecutiveInvisibleCount
      tracks(trackIdx).bbox = bbox;
      tracks(trackIdx).trails{end+1} = c2;
      tracks(trackIdx).age = tracks(trackIdx).age + 1;
      tracks(trackIdx).totalVisibleCount = ...
          tracks(trackIdx).totalVisibleCount + 1;
      tracks(trackIdx).consecutiveInvisibleCount = 0;
  end
    
  %% 懳墳偡傞暔懱偑尒偮偐傜側偐偭偨僩儔僢僋偺忣曬峏怴 %%%%%
  %           age丄consecutiveInvisibleCount
  for i = 1:length(unassignedTracks)
    ind = unassignedTracks(i);
    %tracks(ind).trails{end+1} = predict(tracks(ind).kalmanFilter);    % 梊應埵抲婳愓偺昞帵
    tracks(ind).age = tracks(ind).age + 1;
    tracks(ind).consecutiveInvisibleCount = ...
                  tracks(ind).consecutiveInvisibleCount + 1;
  end
  

  %% 尒幐偭偨僩儔僢僋傪徚嫀 %%%%%
  % 楢懕20僼儗乕儉埲忋晄娤應偱僩儔僢僋偐傜徚嫀
  if ~isempty(tracks)
    % compute the fraction of the track's age for which it was visible
    ages = [tracks(:).age];
    totalVisibleCounts = [tracks(:).totalVisibleCount];
    visibility = totalVisibleCounts ./ ages;     % 慡age拞偱娤應偝傟偨僼儗乕儉偺妱崌
      
    % find the indices of 'lost' tracks
    lostInds = (ages < 8 & visibility < 0.6) | ...
               ([tracks(:).consecutiveInvisibleCount] >= 20);   %20僼儗乕儉埲忋楢懕晄娤應偱徚嫀

    tracks = tracks(~lostInds);   %尒幐偭偨僩儔僢僋偺徚嫀
  end

  %% 怴偨偵尒偮偐偭偨暔懱偵懳偟丄怴偟偄僩儔僢僋傪惗惉 %%%%%
  %      (偙偙偱偼傾僒僀儞偝傟側偐偭偨僩儔僢僋傪丄怴偟偄僩儔僢僋偲偡傞)
        centroids1 = centroids(unassignedDetections, :);           % Nx2 double
        bboxes = bboxes(unassignedDetections, :);                 % Nx4 int32
        
        for i = 1:size(centroids1, 1)
            
            centroid = centroids1(i,:);
            bbox = bboxes(i, :);
            
            % 偁偨傜偟偄暔懱堦偮偵懳偟偰丄僇儖儅儞僼傿儖僞乕傪1偮惗惉
            % http://www.mathworks.com/videos/introduction-to-kalman-filters-for-object-tracking-79674.html
            kalmanFilter = configureKalmanFilter('ConstantVelocity', ...
                centroid, ...     % 弶婜嵗昗
                [200, 50], ...    % InitialEstimateError ? Initial estimate uncertainty variance [埵抲梡 懍搙梡]   懍搙丒壛懍搙偼弶婜抣0
                [100, 25], ...    % MotionNoise ? Deviation of selected and actual model
                100);             % MeasurementNoise ? Variance inaccuracy of detected location  憹傗偡偲MotionModel桪愭

            
            % 怴偟偄僩儔僢僋偺惗惉
            newTrack = struct(...
                'id', nextId, ...
                'bbox', bbox, ...
                'kalmanFilter', kalmanFilter, ...
                'trails',{{}},...
                'age', 1, ...
                'totalVisibleCount', 1, ...
                'consecutiveInvisibleCount', 0);
            newTrack.trails{1} = centroid;
            
            % 惗惉偟偨怴偟偄僩儔僢僋傪丄僩儔僢僋偺攝楍偺嵟屻偵捛壛
            tracks(end + 1) = newTrack;
            
            % nextId傪1偮憹傗偡
            nextId = nextId + 1;
        end

    
%% [寢壥偺昞帵] %%%%%
        frame = im2uint8(frame);
        mask = uint8(repmat(mask, [1, 1, 3])) .* 255;  %uint8 RGB傊曄姺

        if ~isempty(tracks)

            reliableTrackInds = ...
                [tracks(:).totalVisibleCount] > 8;         % 専弌夞悢<8夞偺傕偺偼丄傑偩昞帵偟側偄
            reliableTracks = tracks(reliableTrackInds);
            
            if ~isempty(reliableTracks)
                % 嫬奅偺巐妏榞偺嵗昗偺拪弌
                bboxes = cat(1, reliableTracks.bbox);
                
                % ID斣崋偺庢摼
                ids = int32([reliableTracks(:).id]);
                
                labels = cellstr(int2str(ids'));
                predictedTrackInds = ...
                    [reliableTracks(:).consecutiveInvisibleCount] > 0;
                isPredicted = cell(size(labels));
                isPredicted(predictedTrackInds) = {' predicted'};    % 悇掕偟偨応強偺応崌
                labels = strcat(labels, isPredicted);
                
                % RGB偺僼儗乕儉偺拞偵丄巐妏榞傪昤夋
                frame = insertObjectAnnotation(frame, 'rectangle', ...
                    bboxes, labels);
                
                % RGB偺僼儗乕儉撪偵丄婳愓傪昞帵
                for i = 1:length(tracks)
                  p = cat(1,tracks(i).trails{:});                % 僩儔僢僋枅偵丄婳愓偺嵗昗 Nx2 傪庢摼
%                  frame = insertMarker(frame, p, 'o', 'color', 'red', 'size', 3);    % 婳愓傪o偱昞帵
                  if size(p,1) > 2                              % 婳愓傪慄偱昞帵
                    frame = insertShape(frame, 'Line', reshape(p',1,[]), 'color', 'red', 'SmoothEdges',false);
                  end
                end
                
                % 儅僗僋夋憸撪偵丄巐妏榞傪昤夋
                mask = insertObjectAnnotation(mask, 'rectangle', ...
                    bboxes, labels);
                % 儅僗僋夋憸撪偵丄centroids傪亄偱昞帵
                mask = insertMarker(mask, centroids, 'plus');     % 椢怓 (専弌偝傟偨慡暔懱偺拞怱揰)
            end
        end
        
        % 昞帵
        obj.videoPlayer.step(frame);          % RGB僼儗乕儉偺昞帵
        obj.maskPlayer.step(mask);           % 儅僗僋偺昞帵
        
  drawnow;             % 僾僢僔儏儃僞儞偺僀儀儞僩偺妋擣
end


% Copyright 2014 The MathWorks, Inc.

release(obj.reader);
release(obj.videoPlayer);
release(obj.maskPlayer);
release(obj.detector);