主要内容

如何高效地跟踪大量对象

这个例子展示了如何使用trackerGNN跟踪大量的目标。类似的技术也可以应用于trackerjpda.trackertomht.也是。

介绍

在许多应用中,跟踪器需要跟踪数百或数千个对象。增加由跟踪器维护的轨道数是一个挑战,由每个跟踪器的核心的算法的计算复杂性引起。特别是,跟踪器更新步骤中的两个常见阶段不易扩展:计算分配成本并执行分配。分配成本计算是共同的trackerGNNtrackerjpda.,trackertomht.,本例中显示的技术可以在使用这些跟踪器时应用。每个跟踪器执行分配的方式对每个跟踪器都是独特的,可能需要定制的解决方案来提高跟踪器的性能,这超出了本示例的范围。万博 尤文图斯

设想

出于此示例的目的,您可以定义包含在15×15网格中组织的900平台的方案,每个网格单元包含4个平台。网格电池的目的是证明粗糙成本计算的益处,在该示例后面解释。

下面的代码在网格单元格中排列900个对象并创建可视化。在左侧显示了整个场景。在右侧,可视化放大了4个网格单元格。注意,每个单元格包含4个平台。

[平台,TP,Zoomedtp] = CompentPlatforms;

使用默认分配成本计算

本节显示了跟踪上面定义的平台的结果trackerGNN默认情况下AssignmentThreshold.的AssignmentThreshold属性包含两个值:(C1, C2),在那里C1.阈值是否用于分配和C2.是下一节中解释的粗略计算的阈值。

当通过新的一组检测更新跟踪器时,它会计算为每个轨道分配每个检测的成本。准确的成本计算必须考虑每个检测的测量和不确定性以及从每个轨道的预期测量和预期的不确定性,如下所示。

默认情况下,C2.设置为Inf,这需要计算所有轨道和检测组合的成本。这将导致更精确的赋值,但也需要更多的计算。您应该从默认设置开始,以确保跟踪器以最佳方式为跟踪分配检测,然后考虑降低值C2.减少计算分配成本所需的时间。

在分配成本计算期间,成本矩阵的元素其值高于C1.用inf替换。这样做有助于分配算法忽略不可能的分配。

定义可跟踪最多1000个轨道的跟踪器。跟踪器使用默认的常量速度扩展卡尔曼滤波器,其状态被定义为[x; vx; y; vy; z; vz],它被位置选择下面获取位置组件。

跟踪器= trackergnn('maxnumtracks', 1000,'AssignmentThreshold'[正]30日);positionSelector = [1 0 0 0 0;0 0 1 0 0 0;0 0 0 0 0];

在第一次调用步骤中,跟踪器实例化所有曲目。隔离从第一步所需的处理时间实例化曲目所需的时间,可以调用设置重置在踏上追踪器之前。请参阅支持功能万博1manbetxRunTracker.请在本例的最后了解更多细节。

[trcsummary,trusummary,信息] = runtracker(平台,跟踪器,位置选择,TP,zoomedtp);
跟踪器设置时间:8.3108步骤1时间:3.7554步骤2时间:15.3029步骤3时间:14.1099步骤4时间:14.3506步骤5时间:14.3963

从现在开始的所有步骤都不会被发现。步骤6时间:0.53103步骤7时间:0.52582步骤8时间:0.50639步骤9时间:0.50909步骤10时间:0.16034场景完成。所有轨道现在都被删除了。

通过检查轨道分配度量值来分析跟踪结果。为了完美跟踪,轨道总数应等于平台的数量,并且应该没有假,交换或发散轨道。同样,真相摘要应该没有遗失的真相或休息。

assignmentMetricsSummary (trkSummary truSummary)
轨道分配指标摘要:TotalNumTracks NumFalseTracks MaxSwapCount MaxDivergenceCount MaxDivergenceLength ______________ ______________ ____________ __________________ ___________________ 900 0 0 0 0真理分配指标摘要:TotalNumTruths NumMissingTruths MaxEstablishmentLength MaxBreakCount ______________ ________________ ______________________ _____________ 900 0 1 0

使用粗糙分配成本计算

在前一节中,您看到跟踪器能够跟踪所有平台,但每个更新步骤都需要很长时间。大部分时间都花在计算分配成本矩阵上。

检查成本矩阵,您可以看到它的绝大多数元素实际上是Inf。

厘米= info.CostMatrix;disp (“成本矩阵有”+ numel(cm)+“元素”。);disp ("但有限值的数量是"+ numel(cm(isfinite(cm))) + newline)
成本矩阵有810000元素。但有限值的数量是2700

以上结果表明,成本计算在计算所有跟踪与检测组合的分配成本上花费了过多的时间。然而,由于实际测量与基于传感器特性的轨道预期测量距离太远,大多数组合都太远而无法分配。为了避免在计算所有成本时的浪费,可以使用粗略的成本计算。

完成粗略计算以验证轨道和检测的哪些组合可能需要准确的归一化距离计算。只有粗略分配成本低于的组合C2.准确计算。粗糙成本计算在下面的图像中描绘。检测由其测量表示$ z $和测量噪声R美元.两条轨迹被预测到检测时间,并投影到测量空间,由点描述美元z_ {e_1} $美元z_ {e_2} $.注意,轨迹不确定性没有投影到测量空间,这允许我们对粗略计算进行矢量化。这是一个粗略的估计,因为只考虑了检测周围的不确定性。在描述的例子中,第一个轨道落在粗计算门的外面,而第二个轨道落在它里面。因此,只有将该检测与第二轨道相结合时才能进行准确的成本计算。

使用粗成本计算,释放跟踪器并对其进行修改AssignmentThreshold值[30 200]。然后,重新运行跟踪器。

释放(跟踪器)跟踪器.AssignmentThreshold = [30 200];[trcsummary,trusummary] = runtracker(平台,跟踪器,位置选择,TP,zoomedtp);
跟踪器设置时间:6.5846步骤1时间:3.5863步骤2时间:3.4095步骤3时间:2.9347步骤4时间:2.8555步骤5时间:2.9397

从现在开始的所有步骤都不会被发现。步骤6时间:0.51446步骤7时间:0.52277步骤8时间:0.54865步骤9时间:0.50941步骤10时间:0.19085场景完成。所有轨道现在都被删除了。

您可以看到步骤3-5现在需要的时间明显更少了。步骤2也比以前快,但仍然比步骤3-5慢。

要了解为什么步骤2更慢,请考虑第一个跟踪器更新后的曲目状态。状态包含位置信息,但速度仍然为零。当跟踪器计算分配成本时,它将轨道状态预测到检测时间,但由于轨道具有零速度,因此它们保持在相同的位置。这导致检测测量和来自预测轨道状态的预期测量之间的大距离。这些相对大的分配成本使分配算法更难找到最佳分配,这导致步骤2需要比步骤3-5更多的时间。

重要的是要验证具有粗糙成本计算的轨道分配是否与没有它相同。如果轨道分配指标不相同,则必须增加粗略计算门的大小。以下显示跟踪仍然完美,因为它在上一节中,但每个处理步骤都花了更少的时间。

assignmentMetricsSummary (trkSummary truSummary)
轨道分配指标摘要:TotalNumTracks NumFalseTracks MaxSwapCount MaxDivergenceCount MaxDivergenceLength ______________ ______________ ____________ __________________ ___________________ 900 0 0 0 0真理分配指标摘要:TotalNumTruths NumMissingTruths MaxEstablishmentLength MaxBreakCount ______________ ________________ ______________________ _____________ 900 0 1 0

使用外部成本计算

另一种控制计算成本分配所需时间的方法是使用您自己的分配成本计算,而不是跟踪器使用的默认方法。

外部成本计算可以考虑不属于轨道状态和预期测量的属性。它还可以使用不同的距离度量,例如欧几里德规范而不是归一化距离。选择要应用的成本计算取决于问题的具体细节,测量空间以及定义状态和测量的具体情况。

要使用外部成本计算,请释放跟踪器并设置其hascostmatrixinput.属性为真。您必须将自己的成本矩阵作为额外的输入传递给跟踪器的每个更新。请参阅支持功能万博1manbetxRunTracker.为更多的细节。

释放(跟踪);tracker.hascostmatrixinput = true;[trkSummary, truSummary] = runTracker(平台、跟踪positionSelector、tp zoomedtp);assignmentMetricsSummary (trkSummary truSummary)
跟踪器设置时间:6.559步骤1时间:3.4394步骤2时间:1.7852步骤3时间:1.474步骤4时间:1.5312步骤5时间:1.5152

从现在开始的所有步骤都不会被发现。步骤6时间:0.60809步骤7时间:0.61374步骤8时间:0.616步骤9时间:0.63798步骤10时间:完成0.22762场景。所有轨道现在都被删除了。轨道分配指标摘要:TotalNumTracks NumFalseTracks MaxSwapCount MaxDivergenceCount MaxDivergenceLength ______________ ______________ ____________ __________________ ___________________ 900 0 0 0 0真理分配指标摘要:TotalNumTruths NumMissingTruths MaxEstablishmentLength MaxBreakCount ______________ ________________ ______________________ _____________ 900 0 1 0

正如预期的那样,当使用外部成本计算函数时,处理时间甚至更低。

更改GNN分配算法

尝试使用不同的GNN分配算法可以更有效地通过修改分配来使用不同的GNN分配算法任务跟踪器的属性。

发布追踪(追踪)。赋值='Jonker-Volgenant';tracker.hascostmatrixinput = true;RunTracker(平台,跟踪器,PositeSelector,TP,Zoomedtp);
跟踪器设置时间:6.494步骤1时间:3.5346步骤2时间:1.894步骤3时间:3.1192步骤4时间:3.1212步骤5时间:3.1458

从现在开始的所有步骤都不会被发现。步骤6时间:0.61109步骤7时间:0.62456步骤8时间:0.61849步骤9时间:0.60604步骤10时间:0.22303场景完成。所有轨道现在都被删除了。

Jonker-Volgenant算法相对于默认的MUNKRES算法更快地执行第二步中的分配。

蒙特卡罗模拟

如果希望在不修改跟踪器设置的情况下运行多个场景,则不需要调用释放方法。相反,只要打电话给重置方法从跟踪器中清除以前的跟踪信息。这样,您就节省了实例化所有轨道所需的时间。注意下面的“跟踪器设置时间”相对于以前的运行。

重置(跟踪)runTracker(平台、跟踪positionSelector、tp zoomedtp);
跟踪器设置时间:0.097531步骤1时间:3.4684步骤2时间:1.6592步骤3时间:3.1429步骤4时间:3.1274步骤5时间:3.0994

从现在开始的所有步骤都不会被发现。步骤6时间:0.63232步骤7时间:0.61857步骤8时间:0.61433步骤9时间:0.60698步骤10时间:0.25301场景完成。所有轨道现在都被删除了。

总结

这个例子展示了如何跟踪大量的对象。当跟踪多个目标时,跟踪器花费大量的处理时间来计算每次跟踪和检测组合的成本分配。您看到了如何使用成本计算阈值来改进用于计算分配成本的时间。此外,该示例还展示了如何使用外部成本计算,对于特定的跟踪问题,这种计算效率可能更高。

您可以减少成本分配阈值或使用外部成本计算以提高速度trackerjpda.trackertomht.也是。

万博1manbetx支持功能

CompentPlatforms.

此函数在20x20网格中创建平台,每个网格单元格单元2x2平台。

函数[平台,TP,Zoomedtp] = CompentPlatforms这是一个helper函数,用于运行跟踪器并显示结果。它%将来可能会被移除。nh = 15;%水平网格单元格数nv = 15;%垂直网格单元格数nsq = 2;网格单元中的%2x2平台npl = nh * nv * nsq ^ 2;%平台总数XGV = sort(-50 + repmat(100 * (1:nh), [1 nsq]));Ygv = sort(-50 + repmat(100 * (1:nv), [1 nsq])));(X, Y) = meshgrid (xgv ygv);《不扩散核武器条约》= nsq / 2;Xshift = 10*(((-npts+1):npts) -5;yshift = xshift;Xadd = repmat(xshift, [1 nh]);Yadd = repmat(yshift, [1 nv]); / /显示当前位置[Xx, Yy] = meshgrid(xadd,yadd);X = X + Xx; Y = Y + Yy; pos = [X(:),Y(:),zeros(numel(X),1)];%下面的代码为平台创建了一个结构体数组%以后用于跟踪分配指标。Vel = [3 1 0];%平台速度平台= repmat(结构体('平台',1,“位置”, [0 0 0],'速度'韦尔),不良贷款,1);为了i = 1:nPl平台(i)。PlatformID =我;平台(我).Position (,) = pos(我:);结尾%可视化f =图(“位置”,[1 1 1425 700]);movegui中心;h1 = uipanel (f,“字形大小”,12,“位置”,(。01.01.48.98],“标题”“场景视图”);a1 =轴(h1,“位置”,[0.05 0.05 0.9 0.9]);tp = theaterplot(“父”,a1,“XLimits”,[0 nh * 100],'ylimits'[0 nv * 100]);集(a1,“XTick”0:100: nh * 100)集(a1,“YTick”0:100: nv * 100)网格页= trackPlotter (tp,“标签”“真相”“标记”'^'“MarkerEdgeColor”“k”“MarkerSize”,4,'历史中心'10);plotTrack (pp、重塑([platforms.Position] 3 []) ');Trackplotter(TP,“标签”'轨道'“MarkerEdgeColor”'B'“MarkerSize”6'历史中心'10);c = get(a1.parent,'孩子们');为了i = 1:numel(c)如果ISA(C(i),'matlab.graphics.illustration.Legend')组(c(我),“可见”“关闭”的)结尾结尾h2 = uipanel (f,“字形大小”,12,“位置”,[。51 .01 .48 .98],“标题”'放大景观');A2 =轴(H2,“位置”,[0.05 0.05 0.9 0.9]);zoomedtp = theaterplot(“父”, a2,“XLimits”,[400 500],'ylimits'500年[400]);集(a2,“XTick”,400:100:500)设置(A2,“YTick”400:100:500电网)zoomedpp = trackPlotter (zoomedtp,'显示名称'“真相”“标记”'^'“MarkerEdgeColor”“k”“MarkerSize”6'历史中心'10);plotTrack (zoomedpp重塑([platforms.Position] 3 []) ');trackPlotter (zoomedtp'显示名称''轨道'“MarkerEdgeColor”'B'“MarkerSize”,8,'历史中心',10,'connecthistory''在'“字形大小”1);结尾

RunTracker.

此函数运行跟踪器,更新绘图仪,并收集跟踪分配指标。

函数[trcsummary,trusummary,信息] = runtracker(平台,跟踪器,positeSelector,TP,zoomedtp)这是一个helper函数,用于运行跟踪器并显示结果。它%将来可能会被移除。pp = findplotter(tp,“标签”“真相”);trp = findPlotter (tp,“标签”'轨道');zoomedpp = findPlotter (zoomedtp,'显示名称'“真相”);zoomedtrp = findPlotter (zoomedtp,'显示名称''轨道');%要节省时间,预先分配所有检测并在飞行中分配它们。不良贷款=元素个数(平台);侦破= objectDetection (0, 0, 0, 0));依据= repmat({侦破},[不良贷款,1]);%定义了轨道分配指标对象。tam = trackAssignmentMetrics;把视觉化带回来。集(tp.Parent.Parent.Parent,“可见”'在') hasexternalstfunction = tracker.HasCostMatrixInput;%测量设置跟踪器所需的时间。t如果〜Islocked(跟踪器)如果hasExternalCostFunction设置(追踪,侦破,0,0);其他的设置(跟踪器,DET,0);结尾结尾重置(跟踪)disp (“跟踪器设置时间:”+ toc);%运行5个步骤,具有所有平台的检测。为了t = 1:5为了i = 1:nPl det {i}。时间= t;依据我{}。测量=平台(i) .Position (:);结尾t如果HasexternalCostFunction.如果陷入困境(跟踪器)%使用predictTracksToTime获取所有预测轨道。allTracks = predictTracksToTime(追踪,“所有”t);其他的AllTracks = [];结尾costMatrix = predictedEuclidean (allTracks侦破,positionSelector);[痕迹,~,~,信息]=追踪(侦破t costMatrix);其他的[曲目,〜,〜,INFO] =跟踪器(DETS,T);结尾trPos = getTrackPositions(轨道,位置选择器);trIDs =字符串([tracks.TrackID]”);disp (“步 ”+ T +“:”+ TOC)%更新图表。plotTrack (pp、重塑([platforms.Position] 3 []) ');trPos plotTrack (trp);plotTrack (zoomedpp重塑([platforms.Position] 3 []) ');plotTrack (zoomedtrp trPos trIDs);drawn%更新轨道分配指标对象。如果nargout [trkSummary, trussummary] = tam(轨道,平台);结尾%更新平台位置。为了i = 1:nPl平台(i)。位置=平台(i)。位置+平台(我).Velocity;结尾结尾Snapnow.%在没有检测的情况下运行步骤,直到跟踪器删除所有轨道。disp (“从现在开始的所有步骤都没有检测。”的)~isempty(tracks) t = t+1;t如果hasexternalstfunction allTracks = predictTracksToTime(跟踪器,“所有”t);{}, costMatrix = predictedEuclidean (allTracks positionSelector);跟踪=追踪({}t costMatrix);其他的曲目=跟踪器({},T);结尾disp (“步 ”+ T +“:”+ TOC)%更新要绘制的轨道位置。trpos = getTrackpositions(曲目,位置选择);trIDs =字符串([tracks.TrackID]”);%更新图表。plotTrack (pp、重塑([platforms.Position] 3 []) ');trPos plotTrack (trp);plotTrack (zoomedpp重塑([platforms.Position] 3 []) ');plotTrack (zoomedtrp trPos trIDs);drawn%更新平台位置。为了i = 1:nPl平台(i)。位置=平台(i)。位置+平台(我).Velocity;结尾结尾disp (“完成方案。现在所有的曲目都已删除。”+换行符)cleardata(pp)cleardata(trp)cleardata(zoomedpp)cleardata(zoomedtrp)set(tp.parent.parent.parent,“可见”“关闭”的)%防止快照过多drawn结尾

predicteeuclidean.

该函数计算从探测到的测量位置和从轨道到预测位置之间的欧氏距离。

函数eucliddist = predigeedeuclidean(曲目,检测,位置选择)这是一个helper函数,用于运行跟踪器并显示结果。它%将来可能会被移除。如果isempty(tracks) || isempty(detections) euclidDist = 0 (numel(tracks),numel(detections));返回结尾predictedStates = [tracks.State];predictedPositions = positionSelector * predictedStates;依据=(检测{:});measuredPositions = [dets.Measurement];euclidDist = 0(元素个数(跟踪),元素个数(检测);为了i = 1:numel(检测)diffs = bsxfun(@minus, predictedPositions',measuredPositions(:,i)');euclidDist(:,i) =√(sum((diff .* diff),2));结尾结尾

AssignmentMetricsSummary.

该函数以表格形式显示键分配指标。

函数trkSummary = rmfield(trkSummary, {)'totalswapcount'“TotalDivergenceCount”......“TotalDivergenceLength”'maxredundcount''intinredundandcount'......“MaxRedundancyLength”“TotalRedundancyLength”});trusummary = rmfield(trusummary,{“TotalEstablishmentLength”'totalebreakcount'......“MaxBreakLength”“TotalBreakLength”});trkTable = struct2table (trkSummary);truTable = struct2table (truSummary);disp (“跟踪分配指标总结:”)DISP(TRKTABLE)DISP(“真理分配指标摘要:”)DISP(提供)结尾