主要内容

使用卡尔曼滤波进行目标跟踪

这个例子展示了如何使用愿景。KalmanFilter对象和configurekalmanfilter.函数来跟踪对象。

这个例子是一个函数,它的主体位于顶部,助手例程以嵌套函数的形式出现。

函数Kalmanfilterfortracking.

介绍

卡尔曼滤波器有许多用途,包括在控制、导航、计算机视觉和时间序列计量经济学的应用。这个例子说明了如何使用卡尔曼滤波器跟踪目标,并重点介绍了三个重要的特性:

  • 预测对象的未来位置

  • 通过不准确的检测引入的噪声减少

  • 便于将多个对象关联到它们的轨迹的过程

目标跟踪的挑战

在展示卡尔曼滤波器的使用之前,让我们先看看跟踪视频中的目标所面临的挑战。下面的视频显示了一个绿色的球在地板上从左到右移动。

showdetections();

球上的白色区域突出显示使用的像素愿景。ForegroundDetector,它将移动的物体从背景中分离出来。背景减法只能找到球的一部分,因为球和地面之间的对比度很低。换句话说,检测过程不理想,引入了噪声。

要轻松可视化整个对象轨迹,我们将所有视频帧覆盖到单个图像上。“+”标记表示使用BLOB分析计算的质心。

showTrajectory ();

可以观察到两个问题:

  1. 该地区的中心通常与球中心不同。换句话说,球的位置存在错误。

  2. 当球被盒子遮挡时,球的位置是不可用的,即测量丢失。

通过使用卡尔曼滤波器可以解决这些挑战。

使用Kalman滤波器跟踪单个对象

利用之前看到的视频trackSingleObject函数向您展示如何:

  • 创建愿景。KalmanFilter通过使用configurekalmanfilter.

  • 使用预测正确的方法以消除跟踪系统中存在的噪声

  • 使用预测方法自身估计球的位置,盒子被盒子封闭

卡尔曼滤波器参数的选择可能是具有挑战性的。的configurekalmanfilter.函数有助于简化这个问题。更多的细节可以在示例中找到。

trackSingleObject函数包含嵌套的帮助函数。下面的顶级变量用于在嵌套函数之间传输数据。

帧= [];%视频帧detectedLocation = [];%检测到的位置trackedLocation = [];%跟踪位置标签=''球的%标签实用程序= [];%实用程序用于处理视频

跟踪单个对象的过程如下所示。

函数tracksingleobject(param)%创建用于读取视频,检测移动对象,%并显示结果。公用事业= createUtilities(参数);isTrackInitialized = false;hasFrame(utilities.videoReader) frame = readFrame(utilities.videoReader);发现球。[detectedLocation, isObjectDetected] = detectObject(帧);如果~ isTrackInitialized如果IsobjectDetected.初始化轨道通过创建一个卡尔曼过滤器当球%首次检测。InitialLocation = CompututeInitialLocation(Param,DetectedLocation);kalmanfilter = configurekalmanfilter(param.motionmodel,...initialLocation param.initialEstimateError,...参数。motionNoise param.measurementNoise);isTrackInitialized = true;trackkedlocation = correct(kalmanFilter, detectedLocation);标签='最初的'别的trackedLocation = [];标签=''结尾别的%使用卡尔曼滤波来跟踪球。如果IsobjectDetected.球被检测到。%通过调用predict来减少测量噪音%正确。预测(kalmanFilter);trackkedlocation = correct(kalmanFilter, detectedLocation);标签='纠正'别的球丢了。预测球的位置。trackedLocation =预测(kalmanFilter);标签=“预测”结尾结尾AnnotateTrackedObject();结尾%,而showTrajectory ();结尾

卡尔曼滤波解决了两种截然不同的情况:

  • 当检测到球时,卡尔曼滤波首先预测其在当前视频帧中的状态,然后利用新检测到的目标位置对其状态进行校正。这将生成一个过滤过的位置。

  • 当球丢失时,卡尔曼滤波器仅依靠它的先前状态来预测球的当前位置。

通过覆盖所有视频帧,您可以看到球的轨迹。

param = getDefaultParameters();%得到工作良好的卡尔曼配置%在本例中trackSingleObject(参数);%可视化结果

探索卡尔曼滤波配置选项

配置卡尔曼滤波器可能非常具有挑战性。除了对卡尔曼滤波器的基本理解外,它通常需要实验,以便提出一组合适的配置参数。的trackSingleObject方法提供的各种配置选项configurekalmanfilter.功能。

configurekalmanfilter.函数返回一个卡尔曼滤波器对象。您必须提供5个输入参数。

配置kalmanFilter (MotionModel, InitialLocation, InitialEstimateError, MotionNoise, MeasurementNoise)

MotionModel设置必须与物体运动的物理特性相对应。你可以将它设置为匀速或匀速加速度模型。下面的例子说明了做出次优选择的后果。

param = getDefaultParameters();%获得良好的参数参数。motionModel =“ConstantVelocity”%从常量加速开关%到ConstantVelocity.切换运动模型后%,放弃噪声规格条目%对应于加速度。参数。initialEstimateError = param.initialEstimateError (1:2);参数。motionNoise = param.motionNoise (1:2);trackSingleObject(参数);%可视化结果

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

通常,你会设置InitialLocation输入对象第一次被检测到的位置。你也可以设置InitialEstimateError矢量到大的值,因为初始状态可能是非常嘈杂的,因为它是由一个单一的检测。下图展示了错误配置这些参数的影响。

param = getDefaultParameters();%获得良好的参数参数。初始分配= [0,0];%不是基于实际检测的位置参数。initialEstimateError = 100 * 1(1、3);%使用相对较小的值trackSingleObject(参数);%可视化结果

在参数配置错误的情况下,在卡尔曼滤波返回的位置与目标的实际轨迹对齐之前,需要进行几个步骤。

的值MeasurementNoise应根据探测器的精度来选择。将测量噪声设置为更大的值为一个不太精确的探测器。下面的例子说明了错误配置的分割阈值的噪声检测。增加测量噪声会导致卡尔曼滤波器更多地依赖其内部状态而不是传入的测量值,从而补偿检测噪声。

param = getDefaultParameters();Param.SegimationThreshold = 0.0005;%较小的值导致噪声检测参数。measurementNoise = 12500;%增加值以补偿增加测量噪声的百分比trackSingleObject(参数);%可视化结果

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

现在您熟悉如何使用Kalman过滤器以及如何配置它,下一节将帮助您了解它如何用于多个对象跟踪。

注意:为了简化上述示例中的配置过程,我们使用了configurekalmanfilter.功能。此功能产生了几个假设。有关详细信息,请参阅功能的文档。如果您需要更大级别的配置过程,可以使用愿景。KalmanFilter直接对象。

利用卡尔曼滤波跟踪多目标

跟踪多个目标会带来一些额外的挑战:

  • 多重检测必须与正确的轨道相关联

  • 你必须处理场景中出现的新对象

  • 当多个对象合并为一个检测时,必须维护对象标识

愿景。KalmanFilter对象与assignDetectionsToTracks功能可以帮助解决问题

  • 为跟踪分配检测

  • 确定一个检测是否对应一个新对象,换句话说,跟踪创建

  • 正如在遮挡单个对象的情况下,可以使用预测来帮助单独彼此接近的物体

要了解更多关于使用卡尔曼滤波器跟踪多个目标的信息,请参阅标题中的示例基于运动的多目标跟踪

示例中使用的实用程序函数

实用程序函数用于检测对象并显示结果。本节示出了示例如何实现这些功能。

获取创建Kalman过滤器的默认参数,并用于分割球。

函数param = getDefaultParameters。motionModel =“ConstantAcceleration”;参数。initialLocation =“和第一次发现一样”;参数。initialEstimateError = 1E5 * ones(1,3);参数。motionNoise = [25,10,1];参数。measurementNoise = 25;参数。segmentationThreshold = 0.05;结尾

检测和注释视频中的球。

函数showdetections()param = getDefaultParameters();公用事业= createUtilities(参数);trackedLocation = [];Idx = 0;hasFrame(utilities.videoReader) frame = readFrame(utilities.videoReader);detectedLocation = detectObject(框架);%显示当前视频帧的检测结果。AnnotateTrackedObject();%要突出显示测量噪声的影响,显示检测在单独的数字中的第40帧的%结果。Idx = Idx + 1;如果idx == 40 combinedImage = max(repmat(utilities. exe))foregroundMask, (1, 1, 3)), im2single(帧));图中,imshow (combinedImage);结尾结尾%,而%关闭用于显示单个视频帧的窗口。uiscopes.close ('全部');结尾

在当前视频帧中检测球。

函数[检测,IsObjectDetected] =探测器(帧)灰度率= RGB2GRAY(IM2Single(帧));实用程序.Foregroundmask =步骤(实用程序.ForegroundDetector,灰度);检测=步骤(Utilities.Blobanalyzer,Utilities.ForegroundMask);如果isempty(检测)isObjectDetected = false;别的%为了简化跟踪过程,只使用第一个检测到的对象。检测=检测(1,:);IsObjectDetected = True;结尾结尾

显示当前的检测和跟踪结果。

函数AnnotatEtrackedObject()累积();%将前景掩模与当前视频帧组合起来,以便%表示检测结果。combinedImage = max (repmat(公用事业。foregroundMask, (1, 1, 3)), im2single(帧));如果〜isempty(trackedlocation)shape ='圆圈';区域= TrackedLocation;地区(:,3)= 5;组合= InsertObjectAnnotation(组合模拟,形状,...区域,{标签},“颜色”“红色”);结尾步骤(实用程序。放像机、combinedImage);结尾

通过叠加所有视频帧来显示球的轨迹。

函数showTrajectory%关闭用于显示单个视频帧的窗口。uiscopes.close ('全部');%创建一个图形来显示所有视频帧的处理结果。图;imshow (utilities.accumulatedImage / 2 + 0.5);持有;情节(utilities.accumulatedDetections (: 1),...utilities.accumulatedDetections (:, 2),k +的);如果〜isempty(实用程序。...utilities.accumulatedTrackings (:, 2),'r-o');传奇(“检测”“跟踪”);结尾结尾

累积视频帧、检测到的位置和跟踪到的位置来显示球的轨迹。

函数accumulateResults()公用事业。accumulatedImage = max(实用程序。accumulatedImage,框架);utilities.accumulatedDetections...= [utilities.accumulatedDetections;detectedLocation];utilities.accumulatedTrackings...= [实用程序。追踪者;结尾

出于说明目的,选择卡尔曼滤波器使用的初始位置。

函数loc = computeInitialLocation(param, detectedLocation)如果比较字符串(param.initialLocation“和第一次发现一样”)LOC =检测到位置;别的loc = param.initialLocation;结尾结尾

创建用于读取视频、检测移动对象和显示结果的工具。

函数实用程序=创造率(Param)%创建系统对象用于读取视频,显示视频,提取视频%前景,并分析连接组件。实用工具。videoReader = videoReader (“singleball.mp4”);实用程序.videoplayer = Vision.videoplayer(“位置”[100100500400]);实用工具。foregroundDetector =愿景。ForegroundDetector (...'numtringframes'10'InitialVariance',param.segimationThreshold);实用程序.Blobanalyzer = Vision.BlobanAlysis(“AreaOutputPort”, 错误的,...“MinimumBlobArea”, 70,'centroidoutputport', 真的);实用程序.AccumuldedImage = 0;实用程序。accumulatedDetections =零(0,2);实用程序.AccumulatedTrackings =零(0,2);结尾
结尾