主要内容

使用卡尔曼滤波跟踪对象

这个例子展示了如何使用vision.KalmanFilter对象和configureKalmanFilter函数跟踪对象。

这个例子是一个函数的主体顶部和辅助例程的形式嵌套函数。

函数kalmanFilterForTracking

介绍

卡尔曼滤波器有许多用途,包括应用程序控制、导航、计算机视觉和时间序列计量经济学。这个例子演示了如何使用卡尔曼滤波跟踪对象和主要集中在“新居”的三个重要特征:

  • 预测对象未来的位置

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

  • 促进协会的多个对象的过程

挑战的对象跟踪

使用卡尔曼滤波之前,让我们先检查跟踪对象在一个视频里的挑战。下面的视频展示了一个绿色的球在地板上从左向右移动。

showDetections ();

白色区域的球突出了像素检测使用vision.ForegroundDetector,它将移动物体与背景。背景减法只发现球的一部分,因为低对比度和球之间的地板上。换句话说,检测过程不理想,介绍了噪声。

很容易想象整个对象轨迹,我们覆盖所有视频帧到一个图像。“+”标志表明使用blob的质心计算分析。

showTrajectory ();

可以观察到两个问题:

  1. 该地区的中心通常是不同于球的中心。换句话说,有一个错误的测量球的位置。

  2. 球的位置不可用盒子阻挡时,即测量失踪。

这些挑战可以通过使用卡尔曼滤波处理。

使用卡尔曼滤波跟踪单个对象

使用视频见过,trackSingleObject功能向您展示如何:

  • 创建vision.KalmanFilter通过使用configureKalmanFilter

  • 使用预测正确的方法在序列消除噪声出现在跟踪系统

  • 使用预测方法本身估计球的位置时,闭塞的盒子

卡尔曼滤波器参数的选择可以是一个挑战。的configureKalmanFilter函数可以简化这个问题。更多细节关于这个可以找到进一步的例子。

trackSingleObject功能包括嵌套的辅助函数。下面的顶级变量用于嵌套函数之间传输数据。

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

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

函数trackSingleObject(参数)%创建实用工具用于阅读视频,检测运动物体,%和显示结果。公用事业= createUtilities(参数);isTrackInitialized = false;hasFrame (utilities.videoReader)帧= readFrame (utilities.videoReader);%检测球。[detectedLocation, isObjectDetected] = detectObject(框架);如果~ isTrackInitialized如果isObjectDetected%初始化跟踪通过创建一个球时,卡尔曼滤波器%首次发现。detectedLocation initialLocation = computeInitialLocation(参数);kalmanFilter = configureKalmanFilter (param.motionModel,initialLocation param.initialEstimateError,参数。motionNoise param.measurementNoise);isTrackInitialized = true;trackedLocation =正确(kalmanFilter detectedLocation);标签=“初始”;其他的trackedLocation = [];标签=;结束其他的%使用卡尔曼滤波跟踪球。如果isObjectDetected%球被检测到。%降低测量噪声通过调用预测紧随其后%正确。预测(kalmanFilter);trackedLocation =正确(kalmanFilter detectedLocation);标签=“纠正”;其他的%球不见了。%预测球的位置。trackedLocation =预测(kalmanFilter);标签=“预测”;结束结束annotateTrackedObject ();结束%,而showTrajectory ();结束

有两种截然不同的场景,卡尔曼滤波器地址:

  • 首先检测到球时,卡尔曼滤波器预测其状态在当前视频帧,然后使用最新发现的对象位置正确的状态。这产生一个过滤的位置。

  • 球不见了时,卡尔曼滤波器只依赖于其之前的状态预测球的当前位置。

你可以看到球的轨迹覆盖所有视频帧。

param = getDefaultParameters ();%得到卡尔曼的配置工作%对于这个例子trackSingleObject(参数);%可视化结果

探索卡尔曼滤波器配置选项

配置可以非常具有挑战性的卡尔曼滤波器。除了基本的理解卡尔曼滤波器,它通常需要实验为了想出一套合适的配置参数。的trackSingleObject上面定义的函数,可以帮助你探索提供的各种配置选项configureKalmanFilter函数。

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

kalmanFilter = configureKalmanFilter (MotionModel InitialLocation、InitialEstimateError MotionNoise, MeasurementNoise)

MotionModel设置必须对应于物体的物理特性的运动。您可以将它设置为一个恒定的速度或加速度恒定模型。下面的例子说明了制造一个次优选择的后果。

param = getDefaultParameters ();%得到参数,工作得很好参数。motionModel =“ConstantVelocity”;%从ConstantAcceleration%,ConstantVelocity%后切换运动模型、降噪音规范条目%的加速度。参数。initialEstimateError = param.initialEstimateError (1:2);参数。motionNoise = param.motionNoise (1:2);trackSingleObject(参数);%可视化结果

注意球出现在一个地方,从预测的位置是不同的。从球的时候被释放了,这是需要不断减速,由于电阻的地毯。因此,恒定加速度模型是一个更好的选择。如果你保持恒定的速度模型,跟踪结果将是次优的不管你选择什么其他值。

通常,您将设置InitialLocation输入第一次被探测目标的位置。您还将设置InitialEstimateError大值自初始状态向量可能非常吵,因为它来自一个单一的检测。下图演示了错误地配置这些参数的影响。

param = getDefaultParameters ();%得到参数,工作得很好参数。initialLocation = (0,0);%的位置,不是基于一个实际的检测参数。initialEstimateError = 100 * 1 (1、3);%使用相对较小的值trackSingleObject(参数);%可视化结果

配置错误的参数,它走了几步之前返回的位置卡尔曼滤波器结合实际对象的轨迹。

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

param = getDefaultParameters ();参数。segmentationThreshold = 0.0005;%较小的值导致噪声检测参数。measurementNoise = 12500;%增加价值补偿为测量噪声的增加%trackSingleObject(参数);%可视化结果

一般对象不要移动加速度恒定或恒定速度。您使用MotionNoise指定数量的偏离理想的运动模型。增加运动噪声时,卡尔曼滤波器更依赖的测量比它的内部状态。试着尝试MotionNoise学习更多关于它的影响参数。

既然您熟悉如何使用卡尔曼滤波器,如何配置它,下一节将帮助您了解如何使用它为多个对象跟踪。

注意:为了简化配置过程在上面的例子中,我们使用了configureKalmanFilter函数。这个函数使几个假设。有关详细信息,请参阅函数的文档。如果您需要更大程度的控制配置过程,您可以使用vision.KalmanFilter直接对象。

使用卡尔曼滤波跟踪多个对象

跟踪多个对象提出了几个额外的挑战:

  • 多个检测必须与正确的轨道

  • 你必须处理新对象出现在一个场景

  • 必须维护对象的身份当多个对象合并成一个单一的检测

vision.KalmanFilter对象在一起assignDetectionsToTracks函数可以帮助解决的问题

  • 外派检测跟踪

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

  • 就像在一个闭塞的情况下单一对象,预测可以帮助独立的对象彼此接近

学习更多关于使用卡尔曼滤波跟踪多个对象,看到标题的例子动态的多个对象跟踪

效用函数中使用的例子

效用函数被用于检测对象和显示结果。本节的例子说明了如何实现这些功能。

获取创建的默认参数卡尔曼滤波和分割球。

函数param = getDefaultParameters参数。motionModel =“ConstantAcceleration”;参数。initialLocation =首次发现一样的;参数。initialEstimateError = 1 e5 *的(1、3);参数。motionNoise =[1] 25日10日;参数。measurementNoise = 25;参数。segmentationThreshold = 0.05;结束

检测和注释的球视频。

函数param = getDefaultParameters showDetections () ();公用事业= createUtilities(参数);trackedLocation = [];idx = 0;hasFrame (utilities.videoReader)帧= readFrame (utilities.videoReader);detectedLocation = detectObject(框架);%显示当前视频帧的检测结果。annotateTrackedObject ();%强调测量噪声的影响,显示了检测% 40帧的结果在一个单独的图。idx = idx + 1;如果idx = = 40 combinedImage = max (repmat(公用事业。foregroundMask, (1, 1, 3)), im2single(帧));图中,imshow (combinedImage);结束结束%,而%关闭窗口用来显示单个视频帧。uiscopes.close (“所有”);结束

检测球在当前视频帧。

函数(检测、isObjectDetected) = detectObject(帧)grayImage = rgb2gray (im2single(帧));实用工具。foregroundMask =步骤(实用程序。foregroundDetector grayImage);检测=步骤(实用程序。blobAnalyzer utilities.foregroundMask);如果isempty(检测)isObjectDetected = false;其他的%简化跟踪过程中,只使用第一个检测对象。:检测=检测(1);isObjectDetected = true;结束结束

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

函数accumulateResults annotateTrackedObject () ();%将前台面具与当前视频帧来%显示检测结果。combinedImage = max (repmat(公用事业。foregroundMask, (1, 1, 3)), im2single(帧));如果~ isempty (trackedLocation)形状=“圆”;地区= trackedLocation;区域(:,3)= 5;combinedImage = insertObjectAnnotation (combinedImage、形状、地区,{标签},“颜色”,“红色”);结束步骤(实用程序。放像机、combinedImage);结束

显示轨迹球的覆盖所有视频帧上。

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

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

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

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

函数detectedLocation loc = computeInitialLocation(参数)如果比较字符串(param.initialLocation首次发现一样的)loc = detectedLocation;其他的loc = param.initialLocation;结束结束

为阅读视频创建工具,检测运动物体,并显示结果。

函数公用事业= createUtilities(参数)%为阅读视频创建系统对象,显示视频,提取%的前景,分析连接组件。实用工具。videoReader = videoReader (“singleball.mp4”);实用工具。放像机= vision.VideoPlayer (“位置”[100100500400]);实用工具。foregroundDetector = vision.ForegroundDetector (“NumTrainingFrames”10“InitialVariance”,param.segmentationThreshold);实用工具。blobAnalyzer = vision.BlobAnalysis (“AreaOutputPort”假的,“MinimumBlobArea”,70,“CentroidOutputPort”,真正的);实用工具。accumulatedImage = 0;utilities.accumulatedDetections= zeros(0, 2); utilities.accumulatedTrackings = zeros(0, 2);结束
结束