这个例子展示了如何执行自动检测和动态跟踪移动物体的视频。它简化了的例子动态的多个对象跟踪并使用
可以在自动驾驶的工具箱™。multiObjectTracker
移动物体检测和动态跟踪是许多计算机视觉应用程序的重要组成部分,包括活动识别、交通监控、和汽车安全。基于运动对象跟踪的问题可以分为两个部分:
每一帧中的运动对象检测
跟踪移动物体从帧到帧
移动物体的检测使用一个基于高斯混合背景减法算法模型。应用形态学操作产生的前景掩模来消除噪声。最后,blob分析检测组连接像素,可能对应于移动对象。
移动物体的跟踪帧到帧的完成multiObjectTracker
对象,负责如下:
分配检测跟踪。
初始化新的跟踪基于未赋值的检测。所有歌曲都初始化为“初步”
,占他们导致错误检测的可能性。
如果他们有超过确认追踪米指定的检测中N帧。
更新现有的跟踪基于指定的检测。
现有未赋值的轨道滑行(预测)。
删除歌曲如果他们仍未赋值的(摸)太长了。
检测到同一个对象的赋值是完全基于运动。每个轨道的运动由卡尔曼滤波估计。滤波器预测跟踪的位置在每一帧,并确定每个检测被分配给每个追踪的可能性。初始化滤波器设计,使用FilterInitializationFcn
财产的multiObjectTracker
。
有关更多信息,请参见多个对象跟踪。
这个例子是一个函数,与顶部的主体和辅助例程的形式嵌套函数如下。看到嵌套函数为更多的细节。
函数MultipleObjectTrackingExample ()
%用于创建对象阅读视频和显示结果。videoObjects = setupVideoObjects (“atrium.mp4”);%创建对象用于检测对象在前台的视频。minBlobArea = 400;%最小斑点大小,像素,被视为一种检测detectorObjects = setupDetectorObjects (minBlobArea);
当创建一个multiObjectTracker
考虑以下:
FilterInitializationFcn
:可能的运动和测量模型。在这种情况下,对象预计将有一个恒定的速度运动。的initDemoFilter
功能配置线性卡尔曼滤波跟踪运动。请定义一个卡尔曼滤波器的部分细节。
AssignmentThreshold
:从跟踪检测可能会下降多少。这个参数的默认值是30。如果有检测不分配给追踪,但应该增加这个值。如果有检测,分配给轨道太远,减少该值。
DeletionThreshold
删除之前多久一个跟踪维护。在这种情况下,由于视频每秒30帧,一个合理的值约为0.75秒(22帧)。
ConfirmationThreshold
:参数控制跟踪确认。与每一个未赋值的检测跟踪初始化。这些检测可能是假的,所以一开始,所有的跟踪“初步”
。确认轨道,它必须至少被探测到米的N帧。的选择米和N取决于对象的可见性。这个例子假定能见度6 10帧。
追踪= multiObjectTracker (…“FilterInitializationFcn”@initDemoFilter,…“AssignmentThreshold”30岁的…“DeletionThreshold”,22岁,…“ConfirmationThreshold”,10 [6]…);
当定义一个跟踪滤波器的运动,完成以下步骤:
步骤1:定义运动模型和状态
在这个例子中,使用一个恒定的速度模型的二维矩形框架。
的状态是[x, vx; y; v]
。
矩阵的状态转换模型(1 dt 0 = 0;0 1 0 0;0 0 1 dt;0 0 0 1)
。
假设dt = 1
。
第二步:定义流程的噪音
过程噪声代表的部分过程模型中不考虑。例如,在一个恒定的速度模型,加速度是被忽视的。
第三步:定义度量模型
在这个例子中,只有位置((x, y)
)是测量。所以,测量模型H = [1 0 0 0;0 0 1 0]
。
注意:preconfigure这些参数,定义“MotionModel”
财产“二维恒定速度”
。
步骤4:初始化状态向量基于传感器测量
在这个例子中,因为测量(x, y)
和国家是[x, vx; y; v]
,初始化状态向量是非常简单的。因为没有测量的速度,初始化vx
和v
组件为0。
步骤5:定义一个初始状态协方差
在这个例子中,测量非常吵闹,所以定义初始状态协方差很大:stateCov =诊断接头([50 50 50,50])
步骤6:创建正确的过滤器
在这个例子中,所有的模型都是线性的,所以使用trackingKF
跟踪滤波器。
函数过滤器= initDemoFilter(检测)%初始化一个卡尔曼滤波器对于这个示例。%定义初始状态。状态= [detection.Measurement (1);0;detection.Measurement (2);0);%定义初始状态协方差。stateCov =诊断接头([50 50 50,50]);%创建跟踪滤波器。过滤器= trackingKF (“MotionModel”,“二维恒定速度”,…“状态”、州、…“StateCovariance”stateCov,…“MeasurementNoise”1:2,detection.MeasurementNoise (1:2)…);结束
下面的循环运行视频剪辑,视频中检测运动目标,追踪他们在视频帧。
%计算帧来创建一个意义上的时间。frameCount = 0;而hasFrame (videoObjects.reader)%读一个视频帧和检测对象。frameCount = frameCount + 1;%促进帧数帧= readFrame (videoObjects.reader);%阅读框架(检测,面具)= detectObjects (detectorObjects框架);%在视频帧中检测对象%在预处理检测运行跟踪。frameCount confirmedTracks = updateTracks(跟踪、检测);%显示视频的跟踪结果。displayTrackingResults (videoObjects confirmedTracks,框架,面具);结束
创建对象用于读取和显示视频帧。
函数videoObjects = setupVideoObjects(文件名)%初始化视频I / O%为阅读视频从一个文件中创建对象,跟踪%每一帧中的对象,和玩视频。%读者创建一个视频文件。videoObjects。读者= VideoReader(文件名);%创建两个视频播放器:一个显示视频,%和一个显示前台面具。videoObjects。maskPlayer = vision.VideoPlayer (“位置”,400,700,400);videoObjects。放像机= vision.VideoPlayer (“位置”,740,400,700,400);结束
创建对象用于检测前景对象。使用minBlobArea
定义斑点的大小,在像素,这被认为是检测。
增加minBlobArea
避免检测小斑点,这更有可能是假的检测,或者几个检测创建同一个对象由于部分阻塞。
减少minBlobArea
如果检测到对象是否太迟了。
函数detectorObjects = setupDetectorObjects (minBlobArea)%为前景检测和blob分析创建系统对象%前台探测器段的移动对象%的背景。它输出二进制掩模,像素值为1%对应0对应的前景和价值%的背景。detectorObjects.detector = vision.ForegroundDetector (“NumGaussians”3,…“NumTrainingFrames”现年40岁的“MinimumBackgroundRatio”,0.7);%连接组的前景像素可能对应%移动对象。发现这样的blob分析系统对象%组织(称为“blob”或“连接组件”)和计算%的特点,比如他们的地区,重心,%边界框。detectorObjects。blobAnalyzer = vision.BlobAnalysis (“BoundingBoxOutputPort”,真的,…“AreaOutputPort”,真的,“CentroidOutputPort”,真的,…“MinimumBlobArea”,minBlobArea);结束
的detectObjects
函数返回的质心和边界框检测对象的列表objectDetection
对象。你可以供应这个列表作为输入multiObjectTracker
。的detectObjects
函数也返回二进制掩码,输入帧大小一样。像素值为1对应于前台。像素值0对应于背景。
使用前景探测器函数执行运动分割。然后执行形态学操作得到的二进制掩模去除噪声像素,来填补这个洞剩余的斑点。
在创建objectDetection
列表,frameCount
作为输入的时候,和质心探测气泡作为测量。也有两个可选名称-值对列表:
MeasurementNoise
Blob检测是嘈杂的,这个例子定义了一个大的测量噪声值。
ObjectAttributes
——检测边界框,传递给跟踪显示被添加到这个论点。
函数(检测,面具)= detectObjects (detectorObjects框架)%为blob重心预期不确定性(噪音)。measurementNoise = 100 *眼(2);%检测前景。掩码= detectorObjects.detector.step(框架);%应用形态学操作来消除噪音和填补漏洞。掩码= imopen(面具,strel (“矩形”(6,6)));掩码= imclose(面具,strel (“矩形”(50,50)));= imfill(面具,面具“黑洞”);%执行团分析找到连接组件。[~,重心,bboxes] = detectorObjects.blobAnalyzer.step(面具);%制定检测objectDetection对象的列表。numDetections =大小(质心,1);检测=细胞(numDetections, 1);为i = 1: numDetections检测{我}= objectDetection (frameCount,质心(我,:)…“MeasurementNoise”measurementNoise,…“ObjectAttributes”{bboxes(我:)});结束结束
的displayTrackingResults
函数将一个边界框和标签ID为每个跟踪在视频帧和前景的面具。然后,它显示了框架和各自的视频播放器的面具。
函数displayTrackingResults (videoObjects confirmedTracks,框架,面具)%转换框架和uint8 RGB的面具。= im2uint8帧(帧);掩码= uint8 (repmat(面具,(1,1,3)))* 255;如果~ isempty (confirmedTracks)%显示对象。如果一个对象没有被发现%在本帧,显示其预测的边界框。numRelTr =元素个数(confirmedTracks);盒= 0 (numRelTr 4);id = 0 (numRelTr 1“int32”);predictedTrackInds = 0 (numRelTr, 1);为tr = 1: numRelTr%得到边界框。盒(tr:) = confirmedTracks (tr) .ObjectAttributes {1} {1};%得到id。id (tr) = confirmedTracks (tr) .TrackID;如果confirmedTracks (tr)。IsCoasted predictedTrackInds (tr) = tr;结束结束predictedTrackInds = predictedTrackInds (predictedTrackInds > 0);%为显示预测的对象而创建标签%比实际位置。标签= cellstr (int2str (ids));isPredicted =细胞(大小(标签));isPredicted (predictedTrackInds) = {“预测”};标签= strcat(标签、isPredicted);%画出对象的框架。= insertObjectAnnotation帧(帧,“矩形”、盒、标签);%画出对象的面具。= insertObjectAnnotation(面具,面具“矩形”、盒、标签);结束%显示面具和框架。videoObjects.maskPlayer.step(面具);videoObjects.videoPlayer.step(框架);结束
结束
在这个示例中,您创建了一个动态的系统的多运动目标检测和跟踪。尝试使用不同的视频,看看你可以探测和跟踪对象。尝试修改的参数multiObjectTracker
。
跟踪在这个例子中是完全基于运动,假设所有对象与等速直线移动。当一个对象的运动明显偏离了这个模型,示例可以产生跟踪错误。注意到错误跟踪的人阻挡树。
你可以减少跟踪误差的可能性通过使用一个更复杂的运动模型,如加速度恒定或常数。要做到这一点,尝试定义一个不同的跟踪滤波器,如trackingEKF
或trackingUKF
。
trackingKF
|trackingEKF
|trackingUKF
|objectDetection
|vision.VideoPlayer
|VideoReader
|multiObjectTracker