卡尔曼滤波的运动目标检测算法

基于卡尔曼滤波的运动目标检测算法

卡尔曼滤波是一种高效的递归算法,特别适用于运动目标检测和跟踪。

卡尔曼滤波原理

卡尔曼滤波通过预测-校正两个阶段估计系统状态:

  1. 预测阶段:根据系统模型预测下一时刻状态

    \[\hat{x}_k^- = A\hat{x}_{k-1} + Bu_k \]

    \[P_k^- = AP_{k-1}A^T + Q \]

  2. 校正阶段:利用观测值更新预测

    \[K_k = P_k^-H^T(HP_k^-H^T + R)^{-1} \]

    \[\hat{x}_k = \hat{x}_k^- + K_k(z_k - H\hat{x}_k^-) \]

    \[P_k = (I - K_kH)P_k^- \]

MATLAB实现代码

%% 基于卡尔曼滤波的运动目标检测
clc; clear; close all;

% 设置随机种子保证结果可复现
rng(42);

%% 参数设置
sim_time = 10;          % 仿真时间(秒)
dt = 0.1;               % 时间步长(秒)
num_steps = sim_time/dt;% 总步数

% 目标初始状态 [x, y, vx, vy]
initial_state = [0; 0; 2; 1]; 

% 卡尔曼滤波器参数
A = [1 0 dt 0;          % 状态转移矩阵
     0 1 0 dt;
     0 0 1 0;
     0 0 0 1];
 
H = [1 0 0 0;           % 观测矩阵
     0 1 0 0];
 
Q = diag([0.1, 0.1, 0.5, 0.5]); % 过程噪声协方差
R = diag([1, 1]);        % 观测噪声协方差

% 创建视频对象用于记录结果
video_output = VideoWriter('kalman_tracking.avi');
video_output.FrameRate = 10;
open(video_output);

%% 初始化目标真实轨迹和观测数据
true_states = zeros(4, num_steps);
measurements = zeros(2, num_steps);

% 生成真实轨迹 (正弦运动)
for k = 1:num_steps
    t = k*dt;
    true_states(1,k) = 10*sin(0.5*t); % x位置
    true_states(2,k) = 5*cos(0.8*t);  % y位置
    true_states(3,k) = 5*cos(0.5*t);  % x速度
    true_states(4,k) = -4*sin(0.8*t); % y速度
    
    % 添加观测噪声
    measurements(:,k) = H * true_states(:,k) + sqrt(R)*randn(2,1);
end

%% 卡尔曼滤波初始化
x_est = [measurements(1,1); measurements(2,1); 0; 0]; % 初始状态估计
P_est = diag([10, 10, 5, 5]); % 初始估计协方差

% 存储估计结果
estimated_states = zeros(4, num_steps);
estimated_states(:,1) = x_est;

%% 卡尔曼滤波主循环
for k = 2:num_steps
    % --- 预测阶段 ---
    x_pred = A * x_est;         % 状态预测
    P_pred = A * P_est * A' + Q; % 协方差预测
    
    % --- 更新阶段 ---
    K = P_pred * H' / (H * P_pred * H' + R); % 卡尔曼增益计算
    x_est = x_pred + K * (measurements(:,k) - H * x_pred); % 状态更新
    P_est = (eye(4) - K * H) * P_pred; % 协方差更新
    
    % 存储估计结果
    estimated_states(:,k) = x_est;
    
    % --- 可视化 ---
    figure(1); clf;
    hold on; grid on; box on;
    
    % 绘制轨迹
    plot(true_states(1,1:k), true_states(2,1:k), 'b-', 'LineWidth', 1.5, 'DisplayName', '真实轨迹');
    plot(measurements(1,1:k), measurements(2,1:k), 'ro', 'MarkerSize', 4, 'DisplayName', '观测点');
    plot(estimated_states(1,1:k), estimated_states(2,1:k), 'g--', 'LineWidth', 1.5, 'DisplayName', '卡尔曼估计');
    
    % 当前时刻标记
    plot(true_states(1,k), true_states(2,k), 'bo', 'MarkerSize', 10, 'MarkerFaceColor', 'b');
    plot(measurements(1,k), measurements(2,k), 'ro', 'MarkerSize', 8, 'MarkerFaceColor', 'r');
    plot(estimated_states(1,k), estimated_states(2,k), 'go', 'MarkerSize', 12, 'MarkerFaceColor', 'g');
    
    % 添加卡尔曼增益指示器
    plot([true_states(1,k), measurements(1,k)], [true_states(2,k), measurements(2,k)], 'r:', 'LineWidth', 0.5);
    plot([true_states(1,k), estimated_states(1,k)], [true_states(2,k), estimated_states(2,k)], 'g-', 'LineWidth', 1.5);
    
    % 设置图形属性
    title(sprintf('卡尔曼滤波目标跟踪 (时间: %.1f秒)', k*dt));
    xlabel('X位置 (m)'); ylabel('Y位置 (m)');
    legend('Location', 'best');
    axis equal;
    axis([-15 15 -8 8]);
    
    % 添加协方差椭圆
    position_cov = P_est(1:2,1:2);
    error_ellipse(position_cov, [x_est(1), x_est(2)], 'conf', 0.95, 'style', 'g-');
    
    % 记录帧
    frame = getframe(gcf);
    writeVideo(video_output, frame);
    
    pause(0.01); % 控制显示速度
end

% 关闭视频文件
close(video_output);

%% 结果分析
figure(2);
subplot(2,1,1);
hold on; grid on;
plot(dt:dt:sim_time, true_states(1,:), 'b-', 'LineWidth', 1.5, 'DisplayName', '真实X位置');
plot(dt:dt:sim_time, measurements(1,:), 'ro', 'MarkerSize', 4, 'DisplayName', '观测X位置');
plot(dt:dt:sim_time, estimated_states(1,:), 'g--', 'LineWidth', 1.5, 'DisplayName', '估计X位置');
title('X方向位置跟踪');
xlabel('时间 (秒)'); ylabel('位置 (m)');
legend;

subplot(2,1,2);
hold on; grid on;
plot(dt:dt:sim_time, true_states(2,:), 'b-', 'LineWidth', 1.5, 'DisplayName', '真实Y位置');
plot(dt:dt:sim_time, measurements(2,:), 'ro', 'MarkerSize', 4, 'DisplayName', '观测Y位置');
plot(dt:dt:sim_time, estimated_states(2,:), 'g--', 'LineWidth', 1.5, 'DisplayName', '估计Y位置');
title('Y方向位置跟踪');
xlabel('时间 (秒)'); ylabel('位置 (m)');
legend;

%% 计算跟踪误差
position_error = sqrt((true_states(1,:) - estimated_states(1,:)).^2 + ...
                 (true_states(2,:) - estimated_states(2,:)).^2);
velocity_error = sqrt((true_states(3,:) - estimated_states(3,:)).^2 + ...
                 (true_states(4,:) - estimated_states(4,:)).^2);

figure(3);
subplot(2,1,1);
plot(dt:dt:sim_time, position_error, 'b-', 'LineWidth', 1.5);
title('位置跟踪误差');
xlabel('时间 (秒)'); ylabel('误差 (m)'); grid on;

subplot(2,1,2);
plot(dt:dt:sim_time, velocity_error, 'r-', 'LineWidth', 1.5);
title('速度跟踪误差');
xlabel('时间 (秒)'); ylabel('误差 (m/s)'); grid on;

fprintf('平均位置误差: %.4f m\n', mean(position_error));
fprintf('最大位置误差: %.4f m\n', max(position_error));
fprintf('平均速度误差: %.4f m/s\n', mean(velocity_error));

%% 辅助函数:绘制协方差椭圆
function error_ellipse(covariance, center, varargin)
    % 解析可选参数
    p = inputParser;
    addParameter(p, 'conf', 0.95, @(x) x>0 && x<1);
    addParameter(p, 'style', 'r-', @ischar);
    parse(p, varargin{:});
    
    conf = p.Results.conf;
    style = p.Results.style;
    
    % 计算椭圆参数
    [V, D] = eig(covariance);
    [D, order] = sort(diag(D), 'descend');
    V = V(:, order);
    
    % 计算卡方分布的临界值
    chi2_val = sqrt(chi2inv(conf, 2));
    
    % 椭圆参数
    theta = linspace(0, 2*pi, 100);
    a = chi2_val * sqrt(D(1));
    b = chi2_val * sqrt(D(2));
    
    % 椭圆点
    ellipse = [a*cos(theta); b*sin(theta)];
    ellipse = V * ellipse;
    
    % 绘制椭圆
    plot(center(1) + ellipse(1,:), center(2) + ellipse(2,:), style, 'LineWidth', 1.5);
end

代码功能详解

1. 参数设置

  • 仿真时间:10秒
  • 时间步长:0.1秒
  • 目标初始状态:[x, y, vx, vy]
  • 卡尔曼滤波器参数:
    • 状态转移矩阵A
    • 观测矩阵H
    • 过程噪声协方差Q
    • 观测噪声协方差R

2. 目标轨迹生成

  • 生成正弦运动轨迹:x = 10*sin(0.5t), y = 5*cos(0.8t)
  • 添加高斯观测噪声模拟实际传感器测量

3. 卡尔曼滤波实现

  1. 初始化

    • 初始状态估计:使用第一次观测值
    • 初始协方差矩阵:设置为对角阵
  2. 预测阶段

    x_pred = A * x_est;
    P_pred = A * P_est * A' + Q;
    
  3. 更新阶段

    K = P_pred * H' / (H * P_pred * H' + R);
    x_est = x_pred + K * (measurements(:,k) - H * x_pred);
    P_est = (eye(4) - K * H) * P_pred;
    

参考代码 基于卡尔曼滤波算法的运动目标检测 youwenfan.com/contentac/45685.html,做视频车道线检测,动态车辆识别,行人检测的朋友可以参考一下

此实现完整展示了卡尔曼滤波在运动目标检测中的应用,通过调整模型参数和噪声协方差矩阵,可以适应不同的应用场景和目标运动特性。

posted @ 2025-08-01 11:01  令小飞  阅读(138)  评论(0)    收藏  举报