Mean Shift目标跟踪算法MATLAB实现

Mean Shift算法是一种基于密度梯度的非参数化目标跟踪方法,特别适合实时视频跟踪。

matlab 复制代码
function mean_shift_tracking_demo()
    % 主函数:Mean Shift目标跟踪演示
    clear; clc; close all;
    
    % 参数设置
    video_source = 'camera';  % 可选 'video' 或 'camera'
    roi_size = [64, 64];      % 初始目标区域大小
    num_bins = 16;            % 颜色直方图bin数量
    stop_threshold = 0.1;     % 停止迭代阈值
    max_iterations = 20;      % 最大迭代次数
    
    % 加载视频源
    if strcmp(video_source, 'video')
        vid_reader = VideoReader('walking.mp4'); % 替换为你的视频文件
    else
        vid_reader = webcam(); % 使用摄像头
    end
    
    % 读取第一帧并选择目标区域
    frame = readFrame(vid_reader);
    if size(frame, 3) == 1
        frame = repmat(frame, [1, 1, 3]); % 转为RGB
    end
    
    figure('Name', '目标选择', 'NumberTitle', 'off');
    imshow(frame);
    title('请用鼠标选择目标区域');
    roi = round(getPosition(imrect));
    close;
    
    % 提取目标区域
    target_region = imcrop(frame, roi);
    [center_y, center_x] = deal(roi(2)+roi(4)/2, roi(1)+roi(3)/2);
    position = [center_x, center_y, roi(3), roi(4)];
    
    % 计算目标模型(颜色直方图)
    target_model = compute_histogram(target_region, num_bins);
    
    % 创建结果显示窗口
    fig_handle = figure('Name', 'Mean Shift目标跟踪', 'NumberTitle', 'off', ...
                        'Position', [100, 100, 1200, 500]);
    
    % 主循环
    while hasFrame(vid_reader)
        % 读取新帧
        frame = readFrame(vid_reader);
        if isempty(frame), break; end
        if size(frame, 3) == 1
            frame = repmat(frame, [1, 1, 3]); % 转为RGB
        end
        
        % 执行Mean Shift跟踪
        [position, weights] = mean_shift_track(frame, target_model, position, ...
                                               num_bins, stop_threshold, max_iterations);
        
        % 可视化结果
        visualize_results(fig_handle, frame, position, target_region, weights);
        
        % 更新目标模型(可选,使跟踪更适应目标变化)
        if mod(floor(vid_reader.CurrentTime*10), 5) == 0
            new_target = imcrop(frame, [position(1)-position(3)/2, position(2)-position(4)/2, position(3), position(4)]);
            target_model = 0.9*target_model + 0.1*compute_histogram(new_target, num_bins);
        end
        
        % 控制播放速度
        pause(0.05);
    end
    
    % 释放资源
    if strcmp(video_source, 'camera')
        clear vid_reader;
    else
        release(vid_reader);
    end
end

function model = compute_histogram(region, num_bins)
    % 计算图像区域的颜色直方图
    region = im2double(region);
    
    % 转换到HSV空间(对光照变化更鲁棒)
    hsv_region = rgb2hsv(region);
    hue = hsv_region(:,:,1);  % 色调分量
    
    % 将色调值映射到0-1范围
    hue = hue * 360; % 转换为角度
    hue(hue > 360) = hue(hue > 360) - 360;
    hue = hue / 360;  % 归一化到[0,1)
    
    % 计算直方图(使用Epanechnikov核加权)
    [rows, cols] = size(hue);
    center_row = ceil(rows/2);
    center_col = ceil(cols/2);
    
    hist_vals = zeros(1, num_bins);
    bin_width = 1/num_bins;
    
    for i = 1:rows
        for j = 1:cols
            % 计算到中心的距离(Epanechnikov核)
            dist = sqrt((i-center_row)^2 + (j-center_col)^2);
            kernel_val = max(0, 1 - (dist/(min(rows,cols)/2))^2);
            
            % 确定bin索引
            bin_idx = floor(hue(i,j) / bin_width) + 1;
            if bin_idx > num_bins, bin_idx = 1; end % 处理边界
            
            hist_vals(bin_idx) = hist_vals(bin_idx) + kernel_val;
        end
    end
    
    % 归一化直方图
    model = hist_vals / sum(hist_vals);
end

function [new_pos, weights] = mean_shift_track(frame, target_model, init_pos, num_bins, threshold, max_iter)
    % Mean Shift跟踪核心算法
    pos = init_pos;
    [height, width, ~] = size(frame);
    
    for iter = 1:max_iter
        % 提取当前搜索窗口
        x = round(pos(1));
        y = round(pos(2));
        w = round(pos(3));
        h = round(pos(4));
        
        % 确保窗口在图像范围内
        x1 = max(1, x - w/2);
        y1 = max(1, y - h/2);
        x2 = min(width, x + w/2);
        y2 = min(height, y + h/2);
        
        if x2 <= x1 || y2 <= y1
            break;
        end
        
        candidate = imcrop(frame, [x1, y1, x2-x1, y2-y1]);
        [cand_h, cand_w, ~] = size(candidate);
        
        % 计算候选区域直方图
        cand_model = compute_histogram(candidate, num_bins);
        
        % 计算相似度(Bhattacharyya系数)
        rho = sum(sqrt(target_model .* cand_model));
        
        % 计算权重图
        weights_map = zeros(cand_h, cand_w);
        hsv_cand = rgb2hsv(im2double(candidate));
        hue = hsv_cand(:,:,1) * 360 / 360; % 归一化色调
        
        for i = 1:cand_h
            for j = 1:cand_w
                bin_idx = floor(hue(i,j) * num_bins) + 1;
                if bin_idx > num_bins, bin_idx = 1; end
                
                % 计算权重 (Epanechnikov核)
                dist_x = (j - cand_w/2) / (cand_w/2);
                dist_y = (i - cand_h/2) / (cand_h/2);
                dist = sqrt(dist_x^2 + dist_y^2);
                kernel_val = max(0, 1 - dist^2);
                
                weights_map(i,j) = kernel_val * sqrt(target_model(bin_idx) / (cand_model(bin_idx) + eps));
            end
        end
        
        % 计算加权均值(Mean Shift向量)
        total_weight = sum(weights_map(:));
        if total_weight < eps
            break;
        end
        
        dx = sum(sum(weights_map .* (1:cand_w))) / total_weight - (cand_w+1)/2;
        dy = sum(sum(weights_map .* (1:cand_h)')) / total_weight - (cand_h+1)/2;
        
        % 更新位置
        new_x = x + dx;
        new_y = y + dy;
        
        % 检查收敛条件
        shift = sqrt(dx^2 + dy^2);
        if shift < threshold
            break;
        end
        
        pos(1) = new_x;
        pos(2) = new_y;
    end
    
    new_pos = pos;
    weights = weights_map;
end

function visualize_results(fig, frame, pos, target, weights)
    % 可视化跟踪结果
    figure(fig);
    clf;
    
    % 显示当前帧
    subplot(1,3,1);
    imshow(frame);
    hold on;
    rectangle('Position', [pos(1)-pos(3)/2, pos(2)-pos(4)/2, pos(3), pos(4)], ...
              'EdgeColor', 'r', 'LineWidth', 2);
    title('当前帧跟踪结果');
    hold off;
    
    % 显示目标模板
    subplot(1,3,2);
    imshow(target);
    title('目标模板');
    
    % 显示权重图
    subplot(1,3,3);
    imagesc(weights);
    axis image; colorbar;
    title('Mean Shift权重分布');
    
    drawnow;
end

算法原理详解

Mean Shift跟踪算法的核心思想是通过迭代寻找目标区域在特征空间中的概率密度峰值:

  1. 特征表示:使用颜色直方图(通常是HSV空间的色调分量)表示目标外观

  2. 相似性度量:使用Bhattacharyya系数衡量目标模型和候选区域的相似度

  3. Mean Shift向量:计算加权质心偏移,作为新的搜索中心

  4. 迭代优化:重复计算直到收敛到局部最大值

数学表达

给定目标模型 qqq和候选模型 p(y)p(y)p(y),Bhattacharyya系数:

Mean Shift向量:

其中

,g(x)是核函数的轮廓函数

算法特点

  1. 优势

    • 不需要预训练模型

    • 对部分遮挡鲁棒

    • 计算效率高,适合实时应用

    • 自动确定目标尺度(本实现中固定了尺度)

  2. 局限性

  • 对快速运动目标可能丢失

  • 对相似颜色干扰敏感

  • 需要手动初始化第一帧

参数调优指南

  1. 颜色空间

    • HSV/HSL比RGB对光照变化更鲁棒

    • 可尝试Lab空间处理阴影

  2. 核函数选择

    • Epanechnikov核:计算高效

    • 高斯核:更平滑但计算量大

  3. 直方图bin数量

    • 太少:区分度不足

    • 太多:统计不可靠

    • 推荐:8-32个bin

  4. 停止条件

  • 位移阈值:0.1-1.0像素

  • 最大迭代:10-20次

参考代码 matlab语言实现的经典Mean shift 目标跟踪算法 www.youwenfan.com/contentcss/122380.html

扩展改进方向

  1. 多特征融合

    matlab 复制代码
    % 结合颜色和纹理特征
    function combined_model = combine_features(color_hist, texture_hist, alpha)
        combined_model = alpha * color_hist + (1-alpha) * texture_hist;
    end
  2. 尺度自适应

    matlab 复制代码
    % 在每次迭代中调整窗口大小
    scale_factor = 1 + 0.1 * (current_similarity - previous_similarity);
    new_size = old_size * scale_factor;
  3. 运动预测

    matlab 复制代码
    % 使用Kalman滤波预测目标位置
    predicted_pos = kalman_filter(last_pos, velocity);
  4. 背景抑制

    matlab 复制代码
    % 使用空间掩码减少背景影响
    mask = fspecial('gaussian', [size(region,1), size(region,2)], sigma);
    weighted_hist = hist_vals .* mask;
相关推荐
励志的小陈2 小时前
复杂度算法题——旋转数组(三种思路)
c语言·数据结构·算法
tankeven2 小时前
HJ151 模意义下最大子序列和(Easy Version)
c++·算法
不光头强2 小时前
力扣78子集题解
算法·leetcode·深度优先
独断万古他化2 小时前
【算法通关】二叉树中的深搜:DFS 递归解题套路
算法·二叉树·深度优先·dfs·递归
㓗冽2 小时前
2026.03.27(第三天)
数据结构·c++·算法
sali-tec2 小时前
C# 基于OpenCv的视觉工作流-章44-直线卡尺
图像处理·人工智能·opencv·算法·计算机视觉
Magic--2 小时前
经典概率题:飞机座位分配问题(LeetCode 1227)超详细解析
算法·leetcode·职场和发展
urkay-3 小时前
Android 图片轮廓提取与重叠轮廓合并处理
android·算法·iphone
七七肆十九3 小时前
PTA 7-38 数列求和-加强版
数据结构·算法