【问题标题】:I'm trying to do real time object detection and tracking in MATLAB. But it's giving me error我正在尝试在 MATLAB 中进行实时对象检测和跟踪。但它给了我错误
【发布时间】:2014-04-03 15:56:16
【问题描述】:
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 从零开始,始终为一 比触发器的数量少 %。

        vid.TriggerRepeat = 899;

        preview(vid);

        start(vid);

        stoppreview(vid);

        savedvideo = getdata(vid);

% 创建视频文件阅读器

        obj.reader = vision.VideoFileReader(savedvideo);

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

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

% 获取 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

displayEndOfDemoMessage(mfilename)
end

【问题讨论】:

  • 顺便说一下,这里没有光流。您可能需要编辑您的问题以避免混淆。

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


【解决方案1】:

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

【讨论】:

  • 请告诉我如何在这段代码中添加我的实时视频..?
  • 我已经做到了。您可以拨打getsnapshot(vid)获取每个视频帧。
猜你喜欢
  • 1970-01-01
  • 2021-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多