使用Kalman滤波器做目标跟踪

2023-11-18

https://www.mathworks.com/help/vision/examples/using-kalman-filter-for-object-tracking.html:由该例整理而来。

1、前言

本文所举例子说明了如何使用vision.KalmanFilter 对象和configureKalmanFilter函数来跟踪目标。示例以函数名形式显示,其函数内容在最后。

function kalmanFilterForTracking

2、介绍

卡尔曼滤波器有很多用处,包括控制,导航,计算机视觉和时间序列计量经济学。这个例子解释了怎样使用卡尔曼滤波器用于目标跟踪,并致力于三个重要的特征:

  • 目标未来位置的预测;
  • 减少不准确检测引入的噪声;
  • 促进多个对象与其轨迹相关联的过程。

3、目标跟踪的挑战

在显示卡尔曼滤波器的使用之前,让我们先看看视频中的跟踪对象。 以下视频显示了一个绿球在地板上从左向右移动。

showDetections();

球上高亮的白色像素是由 vision.ForegroundDetector检测得到的,这个函数可以从背景中分离移动的目标,背景减法因为球和地板的低对比度使得只能检测到球的一部分,不理想并且引入噪声。
把所有帧叠加到单幅图片上,可视化检测到的轨迹如下。

这样的检测结果可以看出两个问题:

  1. 区域中心不同于球的中心,说明检测有误差。
  2. 球被方框遮挡时,检测不到了。

但是,这两个挑战都可以被卡尔曼滤波器解决。

4、使用卡尔曼滤波器跟踪单个目标

使用之前展示的视频,trackSingleObject如下做法:

1. 通过使用configureKalmanFilter创建vision.KalmanFilter。
2. 使用序列中的predict和correct方法消除跟踪系统中存在的噪声。
3. 当球被遮挡时,使用预测方法估计球的位置。

参数选择可以调整,configureKalmanFilter函数可以简化问题,细节性的问题可以看最后的函数内容。
trackSingleObject函数包含了嵌套的辅助函数,下面的全局变量用于在子函数之间传输数据。

frame            = [];  % 视频帧
detectedLocation = [];  % 检测到的位置
trackedLocation  = [];  % 跟踪到的位置
label            = '';  % 球的标签
utilities        = [];  % 处理视频的实例

跟踪单个目标的步骤如下:

function trackSingleObject(param)
  % 创建用于读取视频,检测移动对象和显示结果的实用程序。  utilities = createUtilities(param);

  isTrackInitialized = false;
  while ~isDone(utilities.videoReader)
    frame = readFrame();

    % 检测球
    [detectedLocation, isObjectDetected] = detectObject(frame);

    if ~isTrackInitialized
      if isObjectDetected
        % 当球第一次被检测到时,通过创建一个卡尔曼滤波器初始化一个跟踪器。
        initialLocation = computeInitialLocation(param, detectedLocation);
        kalmanFilter = configureKalmanFilter(param.motionModel, ...
          initialLocation, param.initialEstimateError, ...
          param.motionNoise, param.measurementNoise);

        isTrackInitialized = true;
        trackedLocation = correct(kalmanFilter, detectedLocation);
        label = 'Initial';
     else
        trackedLocation = [];
        label = '';
      end

    else
      % 使用卡尔曼滤波器来跟踪球
      if isObjectDetected % 球被检测到
        % 减少测量噪声通过调用卡尔曼预测和更新
        predict(kalmanFilter);
        trackedLocation = correct(kalmanFilter, detectedLocation);
        label = 'Corrected';
      else % 球丢失了
        % 预测球的位置
        trackedLocation = predict(kalmanFilter);
        label = 'Predicted';
      end
    end

    annotateTrackedObject();
  end % while结束

  showTrajectory();
end

卡尔曼滤波器在解决过程中,分为两种场景:

  1. 当球被检测到时,卡尔曼滤波器首先预测它在当前帧的状态,然后使用最新检测到的目标位置来更新状态。这会产生一个过滤的位置。
  2. 当球看不见时,卡尔曼完全依赖先前的状态预测当前位置。

你可以通过覆盖所有帧来得到球的轨迹。

param = getDefaultParameters();  % 得到卡尔曼参数的配置。

trackSingleObject(param);  % 可视化结果

5、探索卡尔曼滤波器参数配置选项

卡尔曼滤波器的参数配置可谓是颇具挑战性,除了对卡尔曼滤波器的基本理解,更需要的是调参经验。上面定义的 trackSingleObject函数可以帮助你探索不同参数带来的影响。
configureKalmanFilter 返回一个卡尔曼滤波器对象,可以提供5个参数。

kalmanFilter = configureKalmanFilter(MotionModel, InitialLocation,
         InitialEstimateError, MotionNoise, MeasurementNoise)
  • MotionModel设置必须与对象运动的物理特征相对应。 您可以将其设置为恒定速度或恒定加速度模型。 以下示例说明了进行次优选择的后果。
param = getDefaultParameters();         % get parameters that work well
param.motionModel = 'ConstantVelocity'; % switch from ConstantAcceleration
                                        % to ConstantVelocity
% After switching motion models, drop noise specification entries
% corresponding to acceleration.
param.initialEstimateError = param.initialEstimateError(1:2);
param.motionNoise          = param.motionNoise(1:2);

trackSingleObject(param); % visualize the results

请注意,球出现在与预测位置完全不同的位置。 从球被释放的时间起,由于来自地毯的阻力,它经受恒定的减速。 因此,恒定加速模型是更好的选择。 如果保持恒定速度模型,无论您为其他值选择什么,跟踪结果都将是次优的。

  • 通常,您可以将InitialLocation输入设置为首次检测到对象的位置。 您还可以将InitialEstimateError向量设置为较大的值,因为初始状态可能非常嘈杂,因为它是从单个检测派生的。 下图演示了错误配置这些参数的影响。
param = getDefaultParameters();  % get parameters that work well
param.initialLocation = [0, 0];  % location that's not based on an actual detection
param.initialEstimateError = 100*ones(1,3); % use relatively small values

trackSingleObject(param); % visualize the results


使用错误配置的参数,在卡尔曼滤波器返回的位置与对象的实际轨迹对齐之前需要几个步骤。

  • 应根据探测器的精度选择MeasurementNoise的值。 测量噪声设置为较大的值会获得不太精确的检测器。 以下示例说明了错误配置的分段阈值的噪声检测。 增加测量噪声会导致卡尔曼滤波器更多地依赖于其内部状态而不是输入的测量值,从而补偿检测噪声。
param = getDefaultParameters();
param.segmentationThreshold = 0.0005; % smaller value resulting in noisy detections
param.measurementNoise      = 12500;  % increase the value to compensate
                                      % for the increase in measurement noise

trackSingleObject(param); % visualize the results


通常,物体不会以恒定的加速度或恒定的速度移动。 您可以使用MotionNoise指定与理想运动模型的偏差量。 当您增加运动噪声时,卡尔曼滤波器更多地依赖于输入测量而不是内部状态。 尝试使用MotionNoise参数进行试验,以了解有关其效果的更多信息。

现在您已熟悉如何使用卡尔曼滤波器以及如何配置它,下面将帮助您了解如何将其用于多个对象跟踪。

注意:为了简化上述示例中的配置过程,我们使用了configureKalmanFilter函数。 这个函数做了几个假设。 有关详细信息,请参阅功能文档。 如果您需要对配置过程进行更高级别的控制,则可以直接使用vision.KalmanFilter对象。

6、使用卡尔曼滤波器跟踪多目标

多目标跟踪面临寄个额外的挑战:

  • 多个检测器必须联合统一跟踪器
  • 必须处理场景中出现的新对象
  • 当多个目标进入一个检测器时目标的身份必须保持

vision.KalmanFilter该对象结合assignDetectionsToTracks函数可以帮你解决如下问题:

7、本例中使用的函数

参数设置。

function param = getDefaultParameters
  param.motionModel           = 'ConstantAcceleration';
  param.initialLocation       = 'Same as first detection';
  param.initialEstimateError  = 1E5 * ones(1, 3);
  param.motionNoise           = [25, 10, 1];
  param.measurementNoise      = 25;
  param.segmentationThreshold = 0.05;
end

读视频文件下一帧。

function frame = readFrame()
  frame = step(utilities.videoReader);
end

在视频中检测球并标注。

function showDetections()
  param = getDefaultParameters();
  utilities = createUtilities(param);
  trackedLocation = [];

  idx = 0;
  while ~isDone(utilities.videoReader)
    frame = readFrame();
    detectedLocation = detectObject(frame);
    % Show the detection result for the current video frame.
    annotateTrackedObject();

    % To highlight the effects of the measurement noise, show the detection
    % results for the 40th frame in a separate figure.
    idx = idx + 1;
    if idx == 40
      combinedImage = max(repmat(utilities.foregroundMask, [1,1,3]), frame);
      figure, imshow(combinedImage);
    end
  end % while

  % Close the window which was used to show individual video frame.
  uiscopes.close('All');
end

检测当前帧的球。

function [detection, isObjectDetected] = detectObject(frame)
  grayImage = rgb2gray(frame);
  utilities.foregroundMask = step(utilities.foregroundDetector, grayImage);
  detection = step(utilities.blobAnalyzer, utilities.foregroundMask);
  if isempty(detection)
    isObjectDetected = false;
  else
    % To simplify the tracking process, only use the first detected object.
    detection = detection(1, :);
    isObjectDetected = true;
  end
end

显示当前检测与跟踪结果。

function annotateTrackedObject()
  accumulateResults();
  % Combine the foreground mask with the current video frame in order to
  % show the detection result.
  combinedImage = max(repmat(utilities.foregroundMask, [1,1,3]), frame);

  if ~isempty(trackedLocation)
    shape = 'circle';
    region = trackedLocation;
    region(:, 3) = 5;
    combinedImage = insertObjectAnnotation(combinedImage, shape, ...
      region, {label}, 'Color', 'red');
  end
  step(utilities.videoPlayer, combinedImage);
end


function accumulateResults()
  utilities.accumulatedImage      = max(utilities.accumulatedImage, frame);
  utilities.accumulatedDetections ...
    = [utilities.accumulatedDetections; detectedLocation];
  utilities.accumulatedTrackings  ...
    = [utilities.accumulatedTrackings; trackedLocation];
end

显示轨迹。

function showTrajectory
  % Close the window which was used to show individual video frame.
  uiscopes.close('All');

  % Create a figure to show the processing results for all video frames.
  figure; imshow(utilities.accumulatedImage/2+0.5); hold on;
  plot(utilities.accumulatedDetections(:,1), ...
    utilities.accumulatedDetections(:,2), 'k+');

  if ~isempty(utilities.accumulatedTrackings)
    plot(utilities.accumulatedTrackings(:,1), ...
      utilities.accumulatedTrackings(:,2), 'r-o');
    legend('Detection', 'Tracking');
  end
end

选初始位置用在卡尔曼滤波器上。

function loc = computeInitialLocation(param, detectedLocation)
  if strcmp(param.initialLocation, 'Same as first detection')
    loc = detectedLocation;
  else
    loc = param.initialLocation;
  end
end

创建读取视频的实例,检测移动目标,并显示结果。

function utilities = createUtilities(param)
  % Create System objects for reading video, displaying video, extracting
  % foreground, and analyzing connected components.
  utilities.videoReader = vision.VideoFileReader('singleball.mp4');
  utilities.videoPlayer = vision.VideoPlayer('Position', [100,100,500,400]);
  utilities.foregroundDetector = vision.ForegroundDetector(...
    'NumTrainingFrames', 10, 'InitialVariance', param.segmentationThreshold);
  utilities.blobAnalyzer = vision.BlobAnalysis('AreaOutputPort', false, ...
    'MinimumBlobArea', 70, 'CentroidOutputPort', true);

  utilities.accumulatedImage      = 0;
  utilities.accumulatedDetections = zeros(0, 2);
  utilities.accumulatedTrackings  = zeros(0, 2);
end
end
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Kalman滤波器做目标跟踪 的相关文章

  • STM32的CAN标识符过滤器超简单理解

    1 STM32中CAN1与CAN2的过滤器组 103系列14个过滤器组 104 107系列28个过滤器组 CAN FilterInitStructure CAN FilterNumber 0 0 13 2 每组过滤器组有两种工作模式 标识符
  • VC++ FTP文件下传(断点续传)

    include
  • Android OpenCV环境搭建与Demo展示

    title Android OpenCV环境搭建与Demo展示 tags Opencv date 2020 2 02 00 53 00 最终效果 视频展示 https www bilibili com video av86393649 An
  • (一)树莓派Pico用micropython实现LED闪烁

    方法一 这段代码使用MicroPython来控制Pico开发板上的板载led 引脚为25 GPIO 25 来控制LED的闪烁 如果需要控制外接led模块 请确保将LED正确连接到Pico开发板的引脚 并根据需要进行相应的调整 首先 通过 i
  • Docker : docker: Error response from daemon: user specified IP address is supported on user defined

    1 美图 2 背景 想运行docker容器的时候 指定ip 但是发现出问题 base lcc lcc docker run d name es2 ip 172 16 12 12 p 9200 9200
  • 如何将你的iOS应用成功上架App Store(图文详解)

    上架基本需求资料 1 苹果开发者账号 如还没账号先申请 苹果开发者账号申请教程 2 开发好的APP 通过本篇教程 可以学习到ios证书申请和打包ipa上传到appstoreconnect apple com进行TestFlight测试然后提
  • “北漂”小夫妻新婚后的理财计划

    北漂 小夫妻新婚后的理财计划 提要 经过多年的努力打拼 1976 年出生的姜帆终于在京城站稳脚跟 做上了一家大公司的业务主管 今年 十一 国庆节还 和谈了多年马拉松恋爱的女友举行了婚礼 面对婚后新形势下几个令他烦恼的家庭理财目标 他该如何应
  • VNC VIEWER 连接闪退不断重新连接的解决办法

    1 vnc viewer官网下载standalone 2 vnc链接 3 连接后不断闪退 又不断重连 根本无法进行任何操作或操作困难 解决办法 1 2 点击properties 3 点击options general 调低画质
  • C语言好题解析(一)

    目录 选择题1 选择题2 选择题3 选择题4 编程题一 选择题1 执行下面程序 正确的输出是 int x 5 y 7 void swap int z z x x y y z int main int x 3 y 8 swap printf
  • 在Linux上面进行远程git的数据拉取与上传

    1 安装git sudo apt get update sudo apt get install git 2 查看本地git信息 git version 3 在当前路径下创建一个本地git仓库 sudo git init 4 上传当前的文件
  • TIM输出比较

    以下内容均来自 bilibili江协科技 OC输出比较 输出比较可以通过CNT与CCR寄存器值的关系 来对输出电平进行置1 置0或翻转的操作 用于输出一定频率和占空比的PWM波形 每个高级定时器和通用定时器都拥有4个输出比较通道 高级定时器
  • 正负号 substr java_实战LeetCode 系列(一) (题目+解析)

    1 反转字符串 编写一个函数 其作用是将输入的字符串反转过来 示例 1 输入 hello 输出 olleh 示例 2 输入 A man a plan a canal Panama 输出 amanaP lanac a nalp a nam A
  • 8.性能测试流程及策略

    8 性能测试流程及策略 一 准备工作 1 系统基础功能验证 性能测试在什么阶段适合实施 切入点很重要 一般而言 只有在系统基础功能测试验证完成 系统区域稳定的情况下 才会进行性能测试 否则性能测试是无意义的 2 测试团队组建 根据项目的具体
  • 高防cdn有什么优势?

    CDN即内容分发网络 通过在网络上各处放置节点服务器 来协助网站进行缓存 当用户访问网站时 就近分配节点为用户提供服务 从而加快访问速度 提升用户体验 但是普通的cdn并没有防御能力 那么这时就需要用到高防cdn来应对网络上的攻击 下面为大
  • Matlab:从文本文件中读取数值数据到矩阵

    Matlab 从文本文件中读取数值数据到矩阵 在Matlab中 我们常常需要将保存在文本文件中的数值数据读取到程序中 以便进行数据处理和分析 本文将介绍如何使用Matlab将文本文件中的数值数据导入到矩阵中 首先 我们需要创建一个文本文件
  • pandas-新手使用教程

    Pandas 是 Python 语言的一个扩展程序库 用于数据分析 下面将针对该模块进行讲解 一 导入模块 导入pandas模块 import pandas as pd 二 导入数据 常见用法 创建数据框 pd DataFrame 从CSV
  • C# --- Case Study

    C Case Study C Mongo数据库事务的应用 C 如何解析Json文件并注入MongoDB C MongoDB如何安全的替换Collection C netcore MVC项目框架结构 with MongoDB
  • 积分获取方式的两点优化建议

    积分获取是积分体系运营中的一个重要环节 也是针对用户运营的一个开端 如果积分获取做的不到位 那么商家就没法对用户的行为进行引导 也就没法实现商家的预期目标 整个积分体系就相当于白忙活了 这一点商家要特别的注意 在积分体系运营中 商家对于积分

随机推荐

  • 网课-cnn

    图像识别中遇到的问题可能有图片特征的纬度过高 1000 1000像素的图片 特征维度是1000 1000 3 如果你要输入3百万的数据量就意味着特征向量的维度高达三百万 也许有1000个隐藏单元 而所有的权值组成的矩阵W 1 如果使用标准的
  • git第一次配置ssh key,clone代码出错解决方法

    错误 The authenticity of host can t be established ED25519 key fingerprint is SHA256 k4ViHJBFryacGI BqHphyjDBaRLwt5eSGRMJG
  • vue table合并行 动态列名

    需求 1 合并行 相同数据合并 2 根据后端返回数据动态显示列名 我这个业务需求是 每年增加一列 也就是列名不是固定的 后端返回数据每年会多一条数据 根据返回数据显示列名 实现 html
  • 论文阅读 StyleCLIP:《StyleCLIP: Text-Driven Manipulation of StyleGAN Imagery》

    论文地址 https arxiv org pdf 2103 17249 pdf 文章目录 摘要 1 介绍 2 相关工作 2 1 视觉与语言 2 2 潜空间图像处理 3 StyleCLIP文本驱动操作 4 潜在优化 5 潜在映射 6 全局方向
  • 解密蓝牙mesh系列

    转载自 蓝牙技术联盟 蓝牙mesh网络 友谊篇 低功耗蓝牙 Bluetooth Low Energy 是全球最具节能性的短距离无线通信技术之一 其低功耗的特性广受开发者和消费者赞誉 随着蓝牙mesh网络的推出 开发者可能想知道蓝牙mesh网
  • Python3 如何优雅地使用正则表达式(详解五)

    非捕获组命名组 精心设计的正则表达式可能会划分很多组 这些组不仅可以匹配相关的子串 还能够对正则表达式本身进行分组和结构化 在复杂的正则表达式中 由于有太多的组 因此通过组的序号来跟踪和使用会变得困难 有两个新的功能可以帮你解决这个问题 非
  • 线性稳压器基础知识

    1 1 什么是线性稳压器 线性稳压器的工作原理是 采用一个压控电流源以强制在稳压器输出端上产生一个固定 电压 控制电路连续监视 检测 输出电压 并调节电流源 根据负载的需求 以把输 出电压保持在期望的数值 电流源的设计极限限定了稳压器在仍然
  • C++输入输出(一)

    C 并没有专门的输入输出函数 他们都存在于库中 如果要使用cout cin和getline 需要导入iostream库 如果要是用其他的输入输出方式 需要导入cstdio库 一 cout流输出 这个输出方式我们很早就学过了 他的使用方式如下
  • Home Assistant 南方电网 计算电费

    目录 1 China Southern Power Grid Statistics集成 2 获取当月用电情况 3 计算电费然后在UI上显示 3 效果 1 China Southern Power Grid Statistics集成 链接 2
  • ANSYS WORKBENCH 后处理 之 提取截面查看云图

    这是一个结果的云图 现在想要查看管道某横截面的云图 步骤1右键coordinate systems 创建一个坐标系步骤2更改新建坐标轴属性 步骤3新建一个surface 定义中选择刚才创建的坐标系步骤4右键solution 选择刚才创建的面
  • c++的char[]和char*的区别

    大家先来看这道测试题 char str1 abc char str2 abc const char str3 abc const char str4 abc const char str5 abc const char str6 abc c
  • docker命令自动补全

    很多命令都会提供一个bash complete的脚本 在执行该命令时 敲tab可以自动补全参数 会极大提高生产效率 docker亦如此 如 yum install docker后 会有一个文件 usr share bash completi
  • Linux搭建gitlab以及汉化

    注 请使用管理员权限的用户 执行如下操作 文章目录 GitLab搭建 一 安装并配置必要的依赖关系 1 安装ssh 3 启动SSH服务 4 安装防火墙 如果已经安装了防火墙并且已经在运行状态 则可直接进行第6步 5 开启防火墙 6 添加ht
  • 【OpenGL学习】Shader和Shader类的抽象

    Shader 本节学习OpenGL中Shader的使用并将其抽象为类 简要介绍OpenGL所使用的着色器语言GLSL 一 什么是Shader 参考维基百科中对Shader的定义 着色器 维基百科 自由的百科全书 wikipedia org
  • 【终极版】java连接oracle数据库三种方式(上篇)

    很多小伙伴都对java连接oracle数据库的操作弄的稀里糊涂 今天我就贴出终极版 一举解决所有的连接方式 上篇主要是解决利用驱动连接的方式 我是小順 请大家关注我 我会给大家发更多的工具 JAR包 import java sql Conn
  • Mac 电脑python 升级3.7版本

    转自 https www jianshu com p 5f55997ab719 官网下载python3 7 并且安装https www python org downloads mac osx 本人电脑有多个版本的python 为了体验新版
  • ffmpeg推流参考文章

    https www cnblogs com leisure chn p 10623968 html https www bilibili com read cv12294853 基于M3568平台移植nginx https z zlg cn
  • Docker笔记:基本概念、镜像、容器、仓库以及数据卷的使用

    什么是docker docker 是一个开源的应用容器引擎 可以使用docker将应用程序和依赖打包到一个镜像之中 可以非常方便的移植到其他机器上运行 使用docker构建打包我们的应用 build 之后可以像集装箱一样很方便的传输到别的机
  • 【Learning PGM in R】第一章 概率推理

    目录 1 1机器学习 1 1 1监督学习 1 1 2无监督学习和强化学习 1 2概率表示 1 2 1概率计算和随机变量 1 2 2条件概率 联合概率分布和边缘分布 1 3贝叶斯规则 1 4概率图模型基础 1 4 1概率图模型基础理论 1 4
  • 使用Kalman滤波器做目标跟踪

    https www mathworks com help vision examples using kalman filter for object tracking html 由该例整理而来 1 前言 2 介绍 3 目标跟踪的挑战 4