我正在尝试在MATLAB中进行实时物体检测和跟踪。但它给了我错误

时间:2014-04-03 15:56:17

标签: computer-vision matlab-cvst video-tracking

function multiObjectTracking()

%创建用于阅读视频,检测移动物体的系统对象, %并显示结果

obj = setupSystemObjects();

tracks = initializeTracks(); % create an empty array of tracks

nextId = 1; % ID of the next track

%检测移动物体,并在视频帧中跟踪它们

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()

%初始化视频I / O. %创建用于从文件中读取视频的对象,绘制跟踪的对象 每帧中有%对象,并播放视频。

        vid = videoinput('winvideo', 1, 'YUY2_320x240');
        src = getselectedsource(vid);

        vid.FramesPerTrigger = 1;

%TriggerRepeat基于零,始终为1 小于触发次数的百分比。

        vid.TriggerRepeat = 899;

        preview(vid);

        start(vid);

        stoppreview(vid);

        savedvideo = getdata(vid);

%创建视频文件阅读器

        obj.reader = vision.VideoFileReader(savedvideo);

%创建两个视频播放器,一个用于显示视频, %和一个显示前景蒙版

        obj.videoPlayer = vision.VideoPlayer('Position', [20, 400, 700, 400]);
        obj.maskPlayer = vision.VideoPlayer('Position', [740, 400, 700, 400]);

        obj.detector = vision.ForegroundDetector('NumGaussians', 3, ...
            'NumTrainingFrames', 40, 'MinimumBackgroundRatio', 0.7);

        obj.blobAnalyser = vision.BlobAnalysis('BoundingBoxOutputPort', true, ...
            'AreaOutputPort', true, 'CentroidOutputPort', true, ...
            'MinimumBlobArea', 400);
    end

    function tracks = initializeTracks()

%创建一个空的曲目数组

        tracks = struct(...
            'id', {}, ...
            'bbox', {}, ...
            'kalmanFilter', {}, ...
            'age', {}, ...
            'totalVisibleCount', {}, ...
            'consecutiveInvisibleCount', {});
    end

%%阅读视频帧 %从视频文件中读取下一个视频帧。

    function frame = readFrame()
        frame = obj.reader.step();
    end


    function [centroids, bboxes, mask] = detectObjects(frame)

%检测前景

        mask = obj.detector.step(frame);

%应用形态学操作去除噪音并填补空洞

        mask = imopen(mask, strel('rectangle', [3,3]));
        mask = imclose(mask, strel('rectangle', [15, 15])); 
        mask = imfill(mask, 'holes');

%执行blob分析以查找连接的组件

        [~, centroids, bboxes] = obj.blobAnalyser.step(mask);
    end

%%预测现有曲目的新位置 %使用卡尔曼滤波器预测每个轨道的质心 %当前帧,并相应地更新其边界框。

    function predictNewLocationsOfTracks()
        for i = 1:length(tracks)
            bbox = tracks(i).bbox;

%预测曲目的当前位置

            predictedCentroid = predict(tracks(i).kalmanFilter);

%移动边界框,使其中心位于 %预测的位置

            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);

%计算为每个轨道分配每个检测的成本

        cost = zeros(nTracks, nDetections);
        for i = 1:nTracks
            cost(i, :) = distance(tracks(i).kalmanFilter, centroids);
        end

%解决分配问题

        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(tracks(trackIdx).kalmanFilter, centroid);

%替换已检测到的预测边界框 %边界框

            tracks(trackIdx).bbox = bbox;

%更新曲目的年龄

            tracks(trackIdx).age = tracks(trackIdx).age + 1;

%更新可见性

            tracks(trackIdx).totalVisibleCount = ...
                tracks(trackIdx).totalVisibleCount + 1;
            tracks(trackIdx).consecutiveInvisibleCount = 0;
        end
    end

%%更新未分配的曲目 %将每个未分配的曲目标记为不可见,并将其年龄增加1。

    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 = 10;
        ageThreshold = 8;

%计算可见的赛道年龄的分数

        ages = [tracks(:).age];
        totalVisibleCounts = [tracks(:).totalVisibleCount];
        visibility = totalVisibleCounts ./ ages;

%找到'丢失的指数'轨道

        lostInds = (ages < ageThreshold & visibility < 0.6) | ...
            [tracks(:).consecutiveInvisibleCount] >= invisibleForTooLong;

%删除丢失的曲目

        tracks = tracks(~lostInds);
    end

    function createNewTracks()
        centroids = centroids(unassignedDetections, :);
        bboxes = bboxes(unassignedDetections, :);

        for i = 1:size(centroids, 1)

            centroid = centroids(i,:);
            bbox = bboxes(i, :);

%创建卡尔曼滤镜对象

            kalmanFilter = configureKalmanFilter('ConstantVelocity', ...
                centroid, [200, 50], [100, 25], 100);

%创建新曲目

            newTrack = struct(...
                'id', nextId, ...
                'bbox', bbox, ...
                'kalmanFilter', kalmanFilter, ...
                'age', 1, ...
                'totalVisibleCount', 1, ...
                'consecutiveInvisibleCount', 0);

%将其添加到曲目数组

            tracks(end + 1) = newTrack;

%递增下一个ID

            nextId = nextId + 1;
        end
    end

    function displayTrackingResults()

%将帧和掩码转换为uint8 RGB

        frame = im2uint8(frame);
        mask = uint8(repmat(mask, [1, 1, 3])) .* 255;

        minVisibleCount = 8;
        if ~isempty(tracks)

%嘈杂的检测往往导致短暂的轨道 %仅显示已显示超过的曲目 %最小帧数。

            reliableTrackInds = ...
                [tracks(:).totalVisibleCount] > minVisibleCount;
            reliableTracks = tracks(reliableTrackInds);

%显示对象。如果未检测到对象 此框架中的%,显示其预测的边界框。

            if ~isempty(reliableTracks)

%获得边界框

                bboxes = cat(1, reliableTracks.bbox);

%get ids

                ids = int32([reliableTracks(:).id]);

%为对象指定标签的标签 我们显示预测而不是实际的百分比 %location

                labels = cellstr(int2str(ids'));
                predictedTrackInds = ...
                    [reliableTracks(:).consecutiveInvisibleCount] > 0;
                isPredicted = cell(size(labels));
                isPredicted(predictedTrackInds) = {' predicted'};
                labels = strcat(labels, isPredicted);

%绘制框架

                frame = insertObjectAnnotation(frame, 'rectangle', ...
                    bboxes, labels);

%在面具上绘制

                mask = insertObjectAnnotation(mask, 'rectangle', ...
                    bboxes, labels);
            end
        end

%显示蒙版和框架

        obj.maskPlayer.step(mask);        
        obj.videoPlayer.step(frame);
    end

displayEndOfDemoMessage(mfilename)
end

2 个答案:

答案 0 :(得分:0)

您的问题是在尝试从相机读取帧时尝试使用vision.VideoFileReadervision.VideoFileReader仅用于阅读视频文件。如果您从相机获取帧,则根本不需要它。您应该将videoinput对象添加到obj结构中,然后尝试在getsnapshot内使用readFrame()

答案 1 :(得分:-1)

我尝试使用MATLAB中的这段代码进行实时对象检测,并做到了。对您来说已经很晚了,但我希望它可以为任何需要的人提供帮助。

 function multiObjectTracking()
  

%创建用于读取视频,检测移动的System对象   对象,并显示结果。

obj = setupSystemObjects();
  tracks = initializeTracks(); % Create an empty array of tracks.
  nextId = 1; % ID of the next track
  

%检测运动物体,并在视频帧中跟踪它们。

for x=1:200
      frame = readFrame();
      [centroids, bboxes, mask] = detectObjects(frame);
      predictNewLocationsOfTracks();
      [assignments, unassignedTracks, unassignedDetections] = ...
          detectionToTrackAssignment();
      updateAssignedTracks();
      updateUnassignedTracks();
      deleteLostTracks();
      createNewTracks();
      displayTrackingResults();
  end
   function obj = setupSystemObjects()
  

%初始化视频I / O             %创建对象以从文件中读取视频,绘制跟踪             每帧中有%个对象,并播放视频。             %创建一个视频文件阅读器。

obj.reader = imaq.VideoDevice('winvideo', 1, 'YUY2_320x240', ...
                         'ReturnedColorSpace', 'rgb');
  

%创建两个视频播放器,一个用于显示视频,             %和一个显示前景遮罩。

obj.videoPlayer = vision.VideoPlayer('Position', [20, 400, 700, 400]);
      obj.maskPlayer = vision.VideoPlayer('Position', [740, 400, 700, 400]);
  

%创建系统对象以进行前景检测和斑点分析             %前景检测器用于分割运动物体             % 的背景。它输出一个二进制掩码,其中像素值             1的%对应于前景,0的值对应             %的背景。

obj.detector = vision.ForegroundDetector('NumGaussians', 3, ...
          'NumTrainingFrames', 40, 'MinimumBackgroundRatio', 0.7);
  

%所连接的前景像素组可能对应于   移动             %个对象。斑点分析系统对象用于查找此类组             %(称为“斑点”或“连接的组件”),并计算其             %特征,例如面积,质心和边界框。

    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 = step(obj.reader);
   end
   function [centroids, bboxes, mask] = detectObjects(frame)
  

%检测前景。

mask = obj.detector.step(frame);
  

%应用形态学操作消除噪声并填充孔。

mask = imopen(mask, strel('rectangle', [3,3]));
      mask = imclose(mask, strel('rectangle', [15, 15]));
      mask = imfill(mask, 'holes');
  

%执行斑点分析以查找连接的组件。

    [~, centroids, bboxes] = obj.blobAnalyser.step(mask);
   end
   function predictNewLocationsOfTracks()
          for i = 1:length(tracks)
              bbox = tracks(i).bbox;
  

%预测轨道的当前位置。

predictedCentroid = predict(tracks(i).kalmanFilter);
  

%移动边界框,使其中心位于                 %的预计位置。

    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);
  

%计算将每个检测分配给每个轨道的成本。

cost = zeros(nTracks, nDetections);
      for i = 1:nTracks
          cost(i, :) = distance(tracks(i).kalmanFilter, centroids);
      end
  

%解决分配问题。

     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(tracks(trackIdx).kalmanFilter, centroid);
  

%用检测到的替换预测的边界框                 %边界框。

tracks(trackIdx).bbox = bbox;
  

%更新曲目的年龄。

tracks(trackIdx).age = tracks(trackIdx).age + 1;
  

%更新可见性。

     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;
  

%计算可见的曲目年龄比例。

ages = [tracks(:).age];
      totalVisibleCounts = [tracks(:).totalVisibleCount];
      visibility = totalVisibleCounts ./ ages;
  

%查找“丢失”曲目的索引。

lostInds = (ages < ageThreshold & visibility < 0.6) | ...
          [tracks(:).consecutiveInvisibleCount] >= invisibleForTooLong;
  

%删除丢失的曲目。

     tracks = tracks(~lostInds);
  end
   function createNewTracks()
          centroids = centroids(unassignedDetections, :);
          bboxes = bboxes(unassignedDetections, :);
          for i = 1:size(centroids, 1)
              centroid = centroids(i,:);
              bbox = bboxes(i, :);
  

%创建一个卡尔曼过滤器对象。

kalmanFilter = configureKalmanFilter('ConstantVelocity', ...
              centroid, [200, 50], [100, 25], 100);
  

%创建一个新曲目。

 newTrack = struct(...
              'id', nextId, ...
              'bbox', bbox, ...
              'kalmanFilter', kalmanFilter, ...
              'age', 1, ...
              'totalVisibleCount', 1, ...
              'consecutiveInvisibleCount', 0);
  

%将其添加到轨道阵列中。

tracks(end + 1) = newTrack;
  

%增加下一个ID。

    nextId = nextId + 1;
          end
   end
   function displayTrackingResults()
  

%将框架和遮罩转换为uint8 RGB。

frame = im2uint8(frame);
      mask = uint8(repmat(mask, [1, 1, 3])) .* 255;
      minVisibleCount = 8;
      if ~isempty(tracks)
  

%噪声检测倾向于导致音轨寿命短。                 %仅显示可见时间超过                 %的最小帧数。

reliableTrackInds = ...
              [tracks(:).totalVisibleCount] > minVisibleCount;
          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);
  

%在框架上绘制对象。

frame = insertObjectAnnotation(frame, 'rectangle', ...
                  bboxes, labels);
  

%在遮罩上绘制对象。

mask = insertObjectAnnotation(mask, 'rectangle', ...
                  bboxes, labels);
          end
      end
  

%显示遮罩和边框。

          obj.maskPlayer.step(mask);
          obj.videoPlayer.step(frame);
   end
  end