首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >基于matlab多运动目标跟踪监测算法实现

基于matlab多运动目标跟踪监测算法实现

作者头像
裴来凡
发布2026-04-02 14:39:19
发布2026-04-02 14:39:19
1190
举报

步骤1:创建系统对象

创建用于读取视频帧、检测前景对象和显示结果的系统对象。

代码语言:javascript
复制
function obj = setupSystemObjects()
        % 读取视频文件
        obj.reader = VideoReader('atrium.mp4');
        % 创建两个视频播放器,一个用于显示视频,一个用于显示前景蒙版
        obj.maskPlayer = vision.VideoPlayer('Position', [740, 400, 700, 400]);
        obj.videoPlayer = vision.VideoPlayer('Position', [20, 400, 700, 400]);
        % 创建用于前景检测和blob分析的系统对象
        obj.detector = vision.ForegroundDetector('NumGaussians', 3, ...
            'NumTrainingFrames', 40, 'MinimumBackgroundRatio', 0.7);
        obj.blobAnalyser = vision.BlobAnalysis('BoundingBoxOutputPort', true, ...
            'AreaOutputPort', true, 'CentroidOutputPort', true, ...
            'MinimumBlobArea', 400);
    end

步骤2:初始化轨迹

代码语言:javascript
复制
function tracks = initializeTracks()
        % 创建一个空的轨迹数组
        tracks = struct(...
            'id', {}, ...
            'bbox', {}, ...
            'kalmanFilter', {}, ...
            'age', {}, ...
            'totalVisibleCount', {}, ...
            'consecutiveInvisibleCount', {});
    end

步骤3:检测对象

代码语言:javascript
复制
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

步骤4:预测现有轨迹的新位置

使用卡尔曼滤波预测当前帧中每个轨迹的质心,并相应地更新其边界框。

代码语言:javascript
复制
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

步骤5:将检测分配给轨迹

代码语言:javascript
复制
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

步骤6:更新分配的轨迹

代码语言:javascript
复制
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;
            % 更新age
            tracks(trackIdx).age = tracks(trackIdx).age + 1;
            % 更新visibility
            tracks(trackIdx).totalVisibleCount = ...
                tracks(trackIdx).totalVisibleCount + 1;
            tracks(trackIdx).consecutiveInvisibleCount = 0;
        end
    end

步骤7:更新未分配的轨迹

代码语言:javascript
复制
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

步骤8:删除丢失的轨迹

代码语言:javascript
复制
function deleteLostTracks()
        if isempty(tracks)
            return;
        end
        invisibleForTooLong = 20;
        ageThreshold = 8;
        % 计算轨迹visibility的age分数
        ages = [tracks(:).age];
        totalVisibleCounts = [tracks(:).totalVisibleCount];
        visibility = totalVisibleCounts ./ ages;
        % 查找“丢失”轨迹的索引
        lostInds = (ages < ageThreshold & visibility < 0.6) | ...
            [tracks(:).consecutiveInvisibleCount] >= invisibleForTooLong;
        % 删除丢失的轨迹
        tracks = tracks(~lostInds);
    end

步骤9:创建新轨迹

为从未分配的检测结果创建新的轨迹。

代码语言:javascript
复制
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

步骤10:显示跟踪结果

代码语言:javascript
复制
function displayTrackingResults()
        % 将帧和mask转换为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上绘制对象
                frame = insertObjectAnnotation(frame, 'rectangle', ...
                    bboxes, labels);
                % 在mask上绘制对象
                mask = insertObjectAnnotation(mask, 'rectangle', ...
                    bboxes, labels);
            end
        end
        % 显示mask和frame
        obj.maskPlayer.step(mask);
        obj.videoPlayer.step(frame);
    end

链接:https://ww2.mathworks.cn/help/vision/ug/motion-based-multiple-object-tracking.html?s_tid=srchtitle_site_search_1_Motion-Based+Multiple+Object+Tracking

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-04-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 图像处理与模式识别研究所 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档