基于运动的多目标跟踪Matlab示例,记录每个时间点的每个对象质心并计算各自的速度

基于运动的多目标跟踪Matlab示例,记录每个时间点的每个对象质心并计算各自的速度,matlab,feature-detection,matlab-cvst,centroid,Matlab,Feature Detection,Matlab Cvst,Centroid,我正在尝试开发一个对象跟踪脚本,在每个时间点找到对象的所有质心,这样我就可以根据每帧之间的时间计算它们的速度。我正在使用教程中的基于运动的多对象跟踪,并且已经成功地将其用于视频,但现在我正在尝试找出如何提取每个对象的质心数据,然后计算速度!如果您有任何建议,请告诉我 最好的,本 function multiObjectTracking() % Create System objects used for reading video, detecting moving objects,

我正在尝试开发一个对象跟踪脚本,在每个时间点找到对象的所有质心,这样我就可以根据每帧之间的时间计算它们的速度。我正在使用教程中的基于运动的多对象跟踪,并且已经成功地将其用于视频,但现在我正在尝试找出如何提取每个对象的质心数据,然后计算速度!如果您有任何建议,请告诉我

最好的,本

  function multiObjectTracking()
  % Create System objects used for reading video, detecting moving objects,
  % and displaying the results.
  obj = setupSystemObjects();
  tracks = initializeTracks(); % Create an empty array of tracks.
  nextId = 1; % ID of the next track
  % Detect moving objects, and track them across video frames.
  while ~isDone(obj.reader)
      frame = readFrame();
      [centroids, bboxes, mask] = detectObjects(frame);
      predictNewLocationsOfTracks();
      [assignments, unassignedTracks, unassignedDetections] = ...
          detectionToTrackAssignment();
      updateAssignedTracks();
      updateUnassignedTracks();
      deleteLostTracks();
      createNewTracks();
      displayTrackingResults();
  end
   function obj = setupSystemObjects()
          % Initialize Video I/O
          % Create objects for reading a video from a file, drawing the tracked
          % objects in each frame, and playing the video.
          % Create a video file reader.
          obj.reader = vision.VideoFileReader('Beads.wmv');
          % Create two video players, one to display the video,
          % and one to display the foreground mask.
          obj.videoPlayer = vision.VideoPlayer('Position', [20, 400, 700, 400]);
          obj.maskPlayer = vision.VideoPlayer('Position', [740, 400, 700, 400]);
          % Create System objects for foreground detection and blob analysis
          % The foreground detector is used to segment moving objects from
          % the background. It outputs a binary mask, where the pixel value
          % of 1 corresponds to the foreground and the value of 0 corresponds
          % to the background.
          obj.detector = vision.ForegroundDetector('NumGaussians', 3, ...
              'NumTrainingFrames', 40, 'MinimumBackgroundRatio', 0.7);
          % Connected groups of foreground pixels are likely to correspond to moving
          % objects.  The blob analysis System object is used to find such groups
          % (called 'blobs' or 'connected components'), and compute their
          % characteristics, such as area, centroid, and the bounding box.
          obj.blobAnalyser = vision.BlobAnalysis('BoundingBoxOutputPort', true, ...
              'AreaOutputPort', true, 'CentroidOutputPort', true, ...
              'MinimumBlobArea', 400);
   end
   function tracks = initializeTracks()
          % create an empty array of tracks
          tracks = struct(...
              'id', {}, ...
              'bbox', {}, ...
              'kalmanFilter', {}, ...
              'age', {}, ...
              'totalVisibleCount', {}, ...
              'consecutiveInvisibleCount', {});
   end
   function frame = readFrame()
          frame = obj.reader.step();
   end
   function [centroids, bboxes, mask] = detectObjects(frame)
          % Detect foreground.
          mask = obj.detector.step(frame);
          % Apply morphological operations to remove noise and fill in holes.
          mask = imopen(mask, strel('rectangle', [3,3]));
          mask = imclose(mask, strel('rectangle', [15, 15]));
          mask = imfill(mask, 'holes');
          % Perform blob analysis to find connected components.
          [~, centroids, bboxes] = obj.blobAnalyser.step(mask);
   end
   function predictNewLocationsOfTracks()
          for i = 1:length(tracks)
              bbox = tracks(i).bbox;
              % Predict the current location of the track.
              predictedCentroid = predict(tracks(i).kalmanFilter);
              % Shift the bounding box so that its center is at
              % the predicted location.
              predictedCentroid = int32(predictedCentroid) - bbox(3:4) / 2;
              tracks(i).bbox = [predictedCentroid, bbox(3:4)];
          end
   end
   function [assignments, unassignedTracks, unassignedDetections] = ...
              detectionToTrackAssignment()
          nTracks = length(tracks);
          nDetections = size(centroids, 1);
          % Compute the cost of assigning each detection to each track.
          cost = zeros(nTracks, nDetections);
          for i = 1:nTracks
              cost(i, :) = distance(tracks(i).kalmanFilter, centroids);
          end
          % Solve the assignment problem.
          costOfNonAssignment = 20;
          [assignments, unassignedTracks, unassignedDetections] = ...
              assignDetectionsToTracks(cost, costOfNonAssignment);
   end
  function updateAssignedTracks()
          numAssignedTracks = size(assignments, 1);
          for i = 1:numAssignedTracks
              trackIdx = assignments(i, 1);
              detectionIdx = assignments(i, 2);
              centroid = centroids(detectionIdx, :);
              bbox = bboxes(detectionIdx, :);
              % Correct the estimate of the object's location
              % using the new detection.
              correct(tracks(trackIdx).kalmanFilter, centroid);
              % Replace predicted bounding box with detected
              % bounding box.
              tracks(trackIdx).bbox = bbox;
              % Update track's age.
              tracks(trackIdx).age = tracks(trackIdx).age + 1;
              % Update visibility.
              tracks(trackIdx).totalVisibleCount = ...
                  tracks(trackIdx).totalVisibleCount + 1;
              tracks(trackIdx).consecutiveInvisibleCount = 0;
          end
  end
   function updateUnassignedTracks()
          for i = 1:length(unassignedTracks)
              ind = unassignedTracks(i);
              tracks(ind).age = tracks(ind).age + 1;
              tracks(ind).consecutiveInvisibleCount = ...
                  tracks(ind).consecutiveInvisibleCount + 1;
          end
   end
  function deleteLostTracks()
          if isempty(tracks)
              return;
          end
          invisibleForTooLong = 20;
          ageThreshold = 8;
          % Compute the fraction of the track's age for which it was visible.
          ages = [tracks(:).age];
          totalVisibleCounts = [tracks(:).totalVisibleCount];
          visibility = totalVisibleCounts ./ ages;
          % Find the indices of 'lost' tracks.
          lostInds = (ages < ageThreshold & visibility < 0.6) | ...
              [tracks(:).consecutiveInvisibleCount] >= invisibleForTooLong;
          % Delete lost tracks.
          tracks = tracks(~lostInds);
  end
   function createNewTracks()
          centroids = centroids(unassignedDetections, :);
          bboxes = bboxes(unassignedDetections, :);
          for i = 1:size(centroids, 1)
              centroid = centroids(i,:);
              bbox = bboxes(i, :);
              % Create a Kalman filter object.
              kalmanFilter = configureKalmanFilter('ConstantVelocity', ...
                  centroid, [200, 50], [100, 25], 100);
              % Create a new track.
              newTrack = struct(...
                  'id', nextId, ...
                  'bbox', bbox, ...
                  'kalmanFilter', kalmanFilter, ...
                  'age', 1, ...
                  'totalVisibleCount', 1, ...
                  'consecutiveInvisibleCount', 0);
              % Add it to the array of tracks.
              tracks(end + 1) = newTrack;
              % Increment the next id.
              nextId = nextId + 1;
          end
   end
   function displayTrackingResults()
          % Convert the frame and the mask to uint8 RGB.
          frame = im2uint8(frame);
          mask = uint8(repmat(mask, [1, 1, 3])) .* 255;
          minVisibleCount = 8;
          if ~isempty(tracks)
              % Noisy detections tend to result in short-lived tracks.
              % Only display tracks that have been visible for more than
              % a minimum number of frames.
              reliableTrackInds = ...
                  [tracks(:).totalVisibleCount] > minVisibleCount;
              reliableTracks = tracks(reliableTrackInds);
              % Display the objects. If an object has not been detected
              % in this frame, display its predicted bounding box.
              if ~isempty(reliableTracks)
                  % Get bounding boxes.
                  bboxes = cat(1, reliableTracks.bbox);
                  % Get ids.
                  ids = int32([reliableTracks(:).id]);
                  % Create labels for objects indicating the ones for
                  % which we display the predicted rather than the actual
                  % location.
                  labels = cellstr(int2str(ids'));
                  predictedTrackInds = ...
                      [reliableTracks(:).consecutiveInvisibleCount] > 0;
                  isPredicted = cell(size(labels));
                  isPredicted(predictedTrackInds) = {' predicted'};
                  labels = strcat(labels, isPredicted);
                  % Draw the objects on the frame.
                  frame = insertObjectAnnotation(frame, 'rectangle', ...
                      bboxes, labels);
                  % Draw the objects on the mask.
                  mask = insertObjectAnnotation(mask, 'rectangle', ...
                      bboxes, labels);
              end
          end
          % Display the mask and the frame.
          obj.maskPlayer.step(mask);
          obj.videoPlayer.step(frame);
   end
  end
函数multiObjectTracking()
%创建用于读取视频、检测移动对象的系统对象,
%并显示结果。
obj=setupSystemObjects();
tracks=初始化tracks();%创建一个空的轨迹数组。
nextId=1;%下一首曲目的ID
%检测移动对象,并跨视频帧跟踪它们。
而~isDone(obj.reader)
frame=readFrame();
[质心、B盒、遮罩]=检测对象(帧);
predictNewLocationsOfTracks();
[assignments,UnassignedTrack,unassignedDetections]=。。。
detectionToTrackAssignment();
updateAssignedTracks();
updateUnassignedTracks();
deleteLostTracks();
createNewTracks();
displayTrackingResults();
结束
函数obj=setupSystemObjects()
%初始化视频I/O
%创建用于从文件中读取视频的对象,绘制跟踪对象
%对象,并播放视频。
%创建一个视频文件读取器。
obj.reader=vision.VideoFileReader('Beads.wmv');
%创建两个视频播放器,一个用于显示视频,
%一个用于显示前景遮罩。
obj.videoPlayer=vision.videoPlayer('Position',[20400700400]);
obj.maskPlayer=vision.VideoPlayer('Position',[740400700400]);
%创建用于前景检测和blob分析的系统对象
%前景检测器用于从图像中分割运动对象
%背景。它输出一个二进制掩码,其中像素值
%值1对应于前景,值0对应于
%背景。
obj.detector=vision.ForegroundDetector('NumGaussians',3。。。
“NumTrainingFrames”,40,“MinimumBackgroundRatio”,0.7);
%连接的前景像素组可能对应于移动的像素
%对象。blob分析系统对象用于查找此类组
%(称为“blob”或“connected components”),并计算它们的
%特征,例如面积、质心和边界框。
obj.blobAnalyser=vision.BlobAnalysis('BoundingBoxOutputPort',true。。。
“AreaOutputPort”,true,“CentroidOutputPort”,true。。。
“最小面积”,400);
结束
函数跟踪=initializeTracks()
%创建一个空的轨迹数组
轨道=结构(。。。
'id',{}。。。
'bbox',{}。。。
“kalmanFilter”,{}。。。
'年龄',{}。。。
'totalVisibleCount',{}。。。
'连续可视计数',{});
结束
函数帧=readFrame()
frame=obj.reader.step();
结束
函数[质心、B盒、遮罩]=检测对象(帧)
%检测前景。
掩模=目标探测器步进(帧);
%应用形态学操作以消除噪声并填充孔。
mask=imopen(mask,strel(‘矩形’,[3,3]);
mask=imclose(mask,strel('rectangle',[15,15]);
遮罩=填充(遮罩“孔”);
%执行blob分析以查找连接的组件。
[~,质心,B盒]=obj.blobAnalyser.step(遮罩);
结束
函数predictNewLocationsOfTracks()
对于i=1:长度(轨道)
bbox=轨道(i)。bbox;
%预测轨道的当前位置。
预测质心=预测(轨迹(i).Kalman滤波器);
%移动边界框,使其中心位于
%预测的位置。
预测质心=int32(预测质心)-bbox(3:4)/2;
轨迹(i).bbox=[预测质心,bbox(3:4)];
结束
结束
函数[assignments,unassignedTracks,unassignedDetections]=。。。
detectionToTrackAssignment()
nTracks=长度(轨道);
n检测=尺寸(质心,1);
%计算将每个检测分配给每个轨迹的成本。
成本=零(nTrack,nDetection);
对于i=1:nTracks
成本(i,:)=距离(轨迹(i).卡尔曼滤波器,质心);
结束
%解决分配问题。
不分配成本=20;
[assignments,UnassignedTrack,unassignedDetections]=。。。
分配检测跟踪(成本、不分配成本);
结束
函数updateAssignedTracks()
numAssignedTracks=大小(分配,1);
对于i=1:numassignedtrack
trackIdx=分配(i,1);
检测dx=分配(i,2);
质心=质心(检测dx,:);
bbox=bboxes(检测dx,:);
%更正对对象位置的估计
%使用新的检测方法。
正确(轨迹(trackIdx).kalmanFilter,形心);
%将预测的边界框替换为检测到的边界框
%边界框。
轨道(trackIdx).bbox=bbox;
%更新曲目的年龄。
轨道(trackIdx)。年龄=轨道(trackIdx)。年龄+1;
%更新可见性。
曲目(trackIdx).totalVisibleCount=。。。
轨道(trackIdx)。总可视计数+1;
轨迹(轨迹IDX)。连续可视计数=0;
结束