主要内容

追踪一群鸟

这个例子展示了如何跟踪大量的对象。生成了一大群鸟,一个全球最近邻多目标跟踪器,trackerGNN,用于估计鸟群中每只鸟的运动。

场景定义

采用Reynolds[1]提出的行为模型模拟了蜂群运动。在这个例子中,鸟群由1000只被称为boid的模拟鸟组成,它们的初始位置和速度是预先保存的。它们遵循三种聚群规则:避免碰撞、速度匹配和聚群定心。每条规则都与一个权重相关联,羊群的整体行为从每条规则的相对权重中显现出来。在这种情况下,选择的权重使鸟群围绕某一点飞行,并形成一个密集的中心。其他权重设置可能会导致不同的行为出现。

追踪如此庞大而密集的鸟群有两个挑战:

  1. 如何有效地跟踪1000个boid ?

  2. 如何在如此密集的环境中追踪单个实体?

下面的代码模拟了100步0.1秒的羊群行为。左边的图显示了整个鸟群,右边的图放大了鸟群中心最密集的部分。

S = rng;保持随机数生成器的当前状态rng (2019);为可重复的结果设置随机数生成器负载(“initialFlock.mat”“x”“v”);flock = helperFlock(“NumBoids”、大小(x, 1),“CollisionAviodanceWeight”, 0.5,...“VelocityMatchingWeight”, 0.1,“FlockCenteringWeight”, 0.5,“速度”v,...“位置”, x,“BoidAcceleration”1);truLabels = string(num2str((1:flock.NumBoids)'));Bound = 20;flockCenter = mean(x,1);[tp1,tp2] = helperCreateDisplay(x,bound);模拟100步植群numSteps = 100;allx = repmat(x,[1 1 numSteps]);Dt = 0.1;i = 1:numSteps [x,v] = move(flock,dt);Allx (:,:,i) = x;plotTrack(tp1. ploters (1),x) inView = findInView(x,-bound+flockCenter,bound+flockCenter);plotTrack (tp2.Plotters (1) x(针对我国有关矿山截污库坝,:),truLabels(针对我国有关矿山截污库坝))drawnow结束

跟踪器的定义

如示例所示定义跟踪器如何有效跟踪大量对象

您观察到实体遵循弯曲的路径,并选择由定义的恒定旋转模型initctekf

方法中的粗成本计算阈值可以限制计算成本所需的时间AssignmentThreshold到一个较低的值。

更进一步,你选择更有效率的Jonker-Volgenant作为赋值算法,而不是默认值Munkres算法。

您希望快速确认和删除音轨,请将确认阈值和删除阈值分别设置为[2 3]和[2 2]。

最后,您知道传感器在任何给定的扫描中只扫描鸟群的一小部分,因此您设置HasDetectableTrackIDsInput真正的能够将可检测的跟踪id传递给跟踪器。

下面一行显示了如何使用上述属性配置跟踪器。您可以看到如何为跟踪器生成代码如何为跟踪器生成C代码,本例的跟踪器保存在函数flockTracker_kernel.m中

% tracker = trackerGNN("FilterInitializationFcn",@initctekf,"MaxNumTracks",1500,…% "AssignmentThreshold",[50 800],"Assignment","Jonker-Volgenant",…% "ConfirmationThreshold",[2 3],"DeletionThreshold",[2 2],…%”HasDetectableTrackIDsInput”,真正的);

跟踪羊群

接下来,运行该场景并跟踪鸟群。

仿真了一个简化的传感器模型detectFlock金宝app支持功能。它模拟了一个传感器,从左到右扫描鸟群,并在每次扫描时在x轴上捕获五分之一的鸟群跨度。传感器的检测概率为0.98,噪声模拟采用正态分布,每个位置分量的标准偏差为0.1米。

传感器报告其currentScan边界,用于向跟踪器提供可检测的跟踪id。

清晰的flockTracker_kernelpositionSelector = [1 0 0 0 0 0 0 0;0 0 1 0 0 0;0 0 0 0 0 0 0];trackid = 0 (0,1,“uint32”);Trax = 0 (0,3);边界= inf(3,2);Alltrax = 0(大小(allx));allIDs = repmat({},1,numSteps);trup2 = tp2. ploters (1);trap2 = tp2. plot (2);trup2。历史深度= 2*trap2.历史深度;clearPlotterData (tp1) clearPlotterData (tp2)i = 1:numSteps t = i*dt;[detectFlock(allx(:,:,i),t);bounds(1,:) = currenscan;tracksInScan = findInView(trax,bounds(:,1),bounds(:,2));[tracks,info] = flockTracker_kernel(detects,t,trackIDs(tracksInScan,1));trax = getTrackPositions(tracks,positionSelector);如果~isempty(tracks) trackid = uint32([tracks. trackid]');其他的trackid = 0 (0,1,“uint32”);结束Alltrax (1:size(trax,1),1:3,i) = trax;allIDs{i} = string(trackIDs);helperVisualizeDisplay (tp1, tp2 truLabels、allx allIDs, alltrax,我)结束rng(年代);将随机数生成器重置为以前的状态

生成代码中跟踪器的结果

下面的GIF显示了一个mex文件中的跟踪器的性能。

总结

这个示例展示了如何在现实场景中跟踪大量对象,其中扫描传感器在每次扫描中只报告对象的一小部分。该示例演示了如何为大量对象设置跟踪器,以及如何使用可检测的轨道id输入来防止轨道被删除。

参考文献

Craig W. Reynolds,“羊群、畜群和学校:一种行为模型”,计算机图形学,第21卷,第4期,1987年7月。

金宝app支持功能

helperCreateDisplay

该函数创建示例显示并返回两个戏剧情节的句柄。

函数[tp1,tp2] = helperCreateDisplay(x,bound) f = figure(“可见”“关闭”);集(f,“位置”,[1 1 1425 700]);movegui (f,“中心”) h1 = uipanel(f,“字形大小”12“位置”,(。01 .01 .48 .98],“标题”“群视图”);H2 = uipanel(f,“字形大小”12“位置”,(。51 .01 .48 .98],“标题”“群中心”);flockCenter = mean(x,1);A1 =坐标轴(h1,“位置”,[0.05 0.05 0.9 0.9]);网格(a1,“上”) tp1 = theaterPlot(“父”, a1);%鸟群视图(截断)Halfspan = 250;tp1。XLimits = 100*round([-halfspan+flockCenter(1) halfspan+flockCenter(1)]/100);tp1。YLimits = 100*round([-halfspan+flockCenter(2) halfspan+flockCenter(2)]/100);tp1。ZLimits = 100*round([-halfspan+flockCenter(3) halfspan+flockCenter(3)]/100);trackPlotter (tp1“DisplayName”“真相”“HistoryDepth”0,“标记”“^”“MarkerSize”4“ConnectHistory”“关闭”);集(findall (a1,“类型”“行”“标签”“tpTrackHistory_Truth”),“颜色”“k”);视图(a1, 3)传说(“位置”“东北”%群中心A2 =坐标轴(h2,“位置”,[0.05 0.05 0.9 0.9]);网格(a2,“上”) tp2 = theaterPlot(“父”a2);tp2。XLimits = 10*round([-bound+flockCenter(1) bound+flockCenter(1)]/10);tp2。YLimits = 10*round([-bound+flockCenter(2) bound+flockCenter(2)]/10);tp2。ZLimits = 10*round([-bound+flockCenter(3) bound+flockCenter(3)]/10);trackPlotter (tp2“DisplayName”“真相”“HistoryDepth”0,...“标记”“^”“MarkerSize”6“ConnectHistory”“关闭”“字形大小”1);集(findall (a2,“类型”“行”“标签”“tpTrackHistory_Truth”),“颜色”“k”);%轨迹绘图仪TrackColor = [0 0.4470 0.7410];%的蓝色TrackLength = 50;trackPlotter (tp1“DisplayName”“跟踪”“HistoryDepth”TrackLength,“ConnectHistory”“关闭”...“标记”"."“MarkerSize”3,“MarkerEdgeColor”TrackColor,“MarkerFaceColor”, TrackColor);集(findall (tp1。父母,“类型”“行”“标签”“tpTrackHistory_Tracks”),...“颜色”TrackColor,“MarkerSize”3,“MarkerEdgeColor”, TrackColor);trackPlotter (tp2“DisplayName”“跟踪”“HistoryDepth”TrackLength,“ConnectHistory”“上”...“标记”“s”“MarkerSize”8“MarkerEdgeColor”TrackColor,“MarkerFaceColor”“没有”“字形大小”1);集(findall (tp2。父母,“类型”“行”“标签”“tpTrackPositions_Tracks”),“线宽”2);集(findall (tp2。父母,“类型”“行”“标签”“tpTrackHistory_Tracks”),“颜色”TrackColor,“线宽”1);视图(a2, 3)传说(“位置”“东北”)组(f,“可见”“上”结束

detectFlock

该函数模拟传感器模型。它返回一个检测数组和当前传感器扫描限制。

函数[detectFlock(x,t)]持续的sigma alldetectscan numScans numBoids =大小(x,1);Pd = 0.98;如果Isempty (σ) σ = 0.1;oneDet = objectDetection(0,[0;0;0],“MeasurementNoise”σ,“ObjectAttributes”、结构);allDetections = repmat(oneDet,numBoids,1);currenscan = 1;numScans = 5;结束%所有检测的向量化计算X = X + sigma*randn(size(X));[allDetections。时间]= deal(t);Y = mat2cell(x',3,ones(1,size(x,1)));[allDetections。测量]= deal(y{:});%根据扫描次数限制覆盖区域flockXSpan = [min (x(: 1),[], 1)、马克斯(x (: 1), [], 1)];spanPerScan = (flockXSpan(2)-flockXSpan(1))/numScans;scanLimits = flockXSpan(1) + spanPerScan * [(currentScan-1) currenscan];第1 =,(x (: 1) > = scanLimits (1) x (: 1) < = scanLimits (2));%添加PdDraw = rand(size(inds));Inds = Inds & (draw%提升扫描次数currentScan = currentScan+1;如果currentScan > numScans currentScan = 1;结束结束

findInView

的限制范围内的位置,该函数返回一个逻辑数组minBound而且maxBound

函数inView = findInView(x,minBound,maxBound) inView = false(size(x,1),1);针对我国有关矿山截污库坝(,)= (x (: 1) > minBound(1)和x (: 1) < maxBound & (1))...(x(:,2)>minBound(2) & x(:,2)...(x(:,3)>minBound(3) & x(:,3)结束

helperVisualizeDisplay

该函数显示跟踪后的羊群和轨迹。

函数helperVisualizeDisplay(tp1,tp2,truLabels,allx,allIDs,alltrax,i) trup1 = tp1. ploters (1);trap1 = tp1. ploters (2);trup2 = tp2. ploters (1);trap2 = tp2. plot (2);plotTrack(trup1,allx(:,:,i)) n = numel(allIDs{i});plotTrack(trap1,alltrax(1:n,:,i)) bounds = [tp2.XLimits;tp2.YLimits;tp2.ZLimits];针对我国有关矿山截污库坝= findInView (allx(:,:我),边界(:1),边界(:,2));plotTrack(trup2,allx(inView,:,i),truLabels(inView)) inView = findInView(alltrax(1:n,:,i),bounds(:,1),bounds(:,2));plotTrack (trap2 alltrax(针对我国有关矿山截污库坝,:我),allIDs{我}(针对我国有关矿山截污库坝))drawnow结束