1. 为什么一维CFAR值得单独做一个可视化工具
1.1 从信号检测的实际痛点说起
一维CFAR恒虚警检测算法,是雷达、声呐、电子侦察这类信号处理系统里绕不开的一个基础环节。它的核心任务很朴素:在一串按距离或时间排列的采样点里,自动判断哪些点上有目标、哪些点只是噪声或杂波。听起来像是简单的阈值比较,但真正做过的人都知道,固定阈值在这里基本没法用。背景噪声的功率随时在变,天气、地形、干扰源、接收机增益漂移,任何一个因素都能让一条写死的门限失效——要么漏掉弱小目标,要么满屏虚警。
CFAR(Constant False Alarm Rate,恒虚警率)就是为解决这个矛盾而生的。它不预设一个固定门限,而是根据检测点周围的参考单元实时估计背景功率,再乘上一个由目标虚警率反推出来的系数,得到自适应门限。背景强,门限自动抬高;背景弱,门限自动压低。整套逻辑围绕一个目标转:让虚警概率稳定在设定值附近,同时尽可能把真实目标捞出来。
我在实际做算法验证时,最头疼的不是公式推导,而是调参。参考单元数改一改、保护单元数动一动、虚警率从1e-4换到1e-6,结果曲线就完全变样。早期全靠脚本跑完再画图,改一次参数就得重跑一遍、重看一遍,一来二去大半天就没了。后来索性把算法包进一个MATLAB可视化界面,左边调参数、右边出结果,滑杆一动曲线立刻刷新,效率提升非常明显。这篇内容就是把这套东西从原理到落地完整拆一遍,适合刚接触CFAR的学生、需要快速验证方案的算法工程师,也适合想给自家工具箱补一个交互式验证界面的朋友。
1.2 CFAR到底在解决什么问题
把问题说得再直白一点。假设接收机采到一串长度为L的一维数据,每个点要么是纯噪声,要么是噪声叠加目标回波。如果噪声是高斯白噪声,经过包络检波后幅度服从瑞利分布,平方律检波后服从指数分布。理论上,只要知道噪声功率σ²,给定虚警率Pfa,就能算出唯一门限T = -σ²·ln(Pfa)。问题在于,σ²是未知的,而且随距离单元变化。
CFAR的思路是"局部估计代替全局已知"。对每一个待检测单元(CUT),取它左右两侧若干个单元作为参考,假设这些参考单元里没有目标、只有背景,用它们的统计量去估计局部噪声功率,再乘以阈值因子得到门限。这样做的前提假设是背景在局部范围内近似平稳,这也是CFAR能在工程上成立的根本原因。
它解决的问题可以归纳成三层:第一层是门限自适应,让检测器跟着背景走;第二层是虚警可控,通过阈值因子把虚警率钉在设定值;第三层是结构可扩展,通过改变参考单元的取法(均值、最大值、最小值、有序统计),应对杂波边缘、多目标等不同场景。这三层是理解所有CFAR变体的主线,后面拆解具体算法时我会反复回到这条线上。
1.3 技术选型:为什么是MATLAB加可视化界面
工具选型这块我纠结过一阵。候选方案无非三类:MATLAB + App Designer、Python + PyQt/Matplotlib、C++ + Qt。最后选MATLAB,理由很实际。
第一,矩阵运算和滑窗操作在MATLAB里写起来极其顺手。CFAR本质是滑动窗口统计,MATLAB的movmean、filter、cumsum、hankel这些函数能把大部分循环压成一行,调试时还能直接在命令行里看中间变量。第二,绘图能力是现成的,plot、semilogy、imagesc拿来就用,做算法验证不需要额外折腾前端。第三,App Designer从R2016a开始成熟,拖控件、写回调,半天能搭出一个能用的界面,比自己用PyQt摆布局快得多。
Python方案当然也能做,生态更开放,但对于"快速验证算法+出图"这种偏科研的场景,MATLAB的路径更短。C++ + Qt则适合最终产品化,不适合前期探索。这里要说明的是,选MATLAB不代表它性能最好,而是它在"算法验证—可视化—调参"这条链上的综合成本最低。如果你的目标是嵌入式部署,MATLAB验证完之后再用C重写一遍是很常见的做法,界面只承担验证角色,不承担产品角色。
2. 一维CFAR算法的核心原理拆解
2.1 滑窗结构:检测单元、保护单元与参考单元
一维CFAR的滑窗结构可以想象成一把尺子在一维数据上从左往右滑动。尺子最中间那一格是检测单元(CUT),也就是当前要判断有没有目标的点。紧挨着检测单元左右各若干格是保护单元(Guard Cells),它们不参与背景估计。再往外两侧各若干格是参考单元(Reference Cells),背景功率就从这些格子里估出来。
保护单元的存在非常关键,也是最容易被新手忽略的地方。原因是目标回波在距离维上不是一根针,而是有一定展宽的主瓣,能量会泄漏到相邻几个单元。如果保护单元不够,目标能量渗进参考窗口,把背景功率估高了,门限被抬高,检测单元反而检测不到——这就是典型的目标自遮蔽。工程上保护单元数一般取2到4个,具体取决于匹配滤波后的主瓣宽度。如果脉压用的是矩形窗,主瓣窄,保护单元取2个就够;如果用了汉明窗、泰勒窗这类加权,主瓣展宽,保护单元要相应增加。
参考单元数N则直接决定估计的稳健性和CFAR损失。N太小,背景估计方差大,门限抖动厉害;N太大,局部平稳假设容易破,杂波边缘处性能急剧下降。经验上N取16到32比较常见,配合虚警率1e-4到1e-6使用。我一般先把N设成24、保护单元设成2作为起点,再根据数据特性微调。这些数值不是硬性规定,而是大量仿真和实测之后形成的经验区间,具体场景还得自己扫一遍参数看曲线。
2.2 四种经典CFAR变体的差异与适用场景
同样一套滑窗结构,参考单元的统计方式不同,就衍生出不同的CFAR变体。工程上最常用的有四种,我把它们的核心差异和适用场景整理成一张表,方便对照:
| 变体 | 背景估计方式 | 抗杂波边缘 | 抗多目标 | 计算量 | 典型适用场景 |
|---|---|---|---|---|---|
| CA-CFAR(单元平均) | 全部参考单元取均值 | 弱 | 弱 | 低 | 均匀背景、初步验证 |
| GO-CFAR(最大选择) | 左右两侧均值取大者 | 强 | 弱 | 低 | 杂波边缘明显的场景 |
| SO-CFAR(最小选择) | 左右两侧均值取小者 | 弱 | 强 | 低 | 密集多目标场景 |
| OS-CFAR(有序统计) | 参考单元排序后取第k个 | 中 | 强 | 中高 | 多目标且背景非均匀 |
CA-CFAR是所有变体的基准,公式最干净、性能最可分析,但在杂波边缘处会出现虚警率飙升。原因很直观:滑窗跨在杂波区和噪声区的交界上时,一侧参考单元功率高、一侧低,取平均会把门限估得既不像杂波也不像噪声,跨过边界的那几个单元就容易产生虚警。GO-CFAR取两侧较大值,正是为了压住这个边界虚警,代价是在均匀背景下损失一点检测概率。
SO-CFAR取两侧较小值,逻辑反过来。当一个参考窗口里有强目标干扰时,取小值能把这个干扰"排除"掉,所以抗多目标能力强。但它在杂波边缘处会严重虚警,因为取小值等于低估了背景。OS-CFAR走的是另一条路,把参考单元排序后取第k个值(k一般取N的3/4左右),既躲开了强干扰目标,又不至于像SO那样在边界处失守,属于折中方案,代价是要排序,计算量略大。
选哪种变体没有标准答案,我的一般做法是:先用CA-CFAR跑通全流程、确认数据没问题,再根据实测结果里暴露的问题换变体。杂波边缘虚警多,换GO;多目标互相遮蔽,换SO或OS。
2.3 阈值因子α的推导与数值计算
阈值因子α是整个CFAR的核心参数,它把"虚警率要求"翻译成"门限倍数"。很多人直接抄公式用,但没搞清楚它怎么来的,换一种检波方式或者换一种变体就懵了。这里把CA-CFAR的推导捋一遍。
假设平方律检波后,纯噪声单元的功率服从指数分布,均值(即噪声功率)为σ²。N个参考单元取均值得到背景估计Z,检测单元功率为Y。CA-CFAR的判决是Y > αZ时判为目标。要使虚警率等于设定值Pfa,需要满足P(Y > αZ) = Pfa。经过积分推导,最终得到:
Pfa = (1 + α/N)^(-N)
反解出阈值因子:
α = N · (Pfa^(-1/N) - 1)
这个公式只对CA-CFAR且平方律检波成立。举个具体数字:N=32,Pfa=1e-6,则Pfa^(-1/32) = exp(ln(1e6)/32) ≈ exp(0.4317) ≈ 1.5397,α = 32 × 0.5397 ≈ 17.27。也就是说门限是背景均值估计的17倍多。这个倍数看起来夸张,但在指数分布下确实是1e-6虚警对应的合理值。
需要强调的是,GO、SO、OS这三种变体的Pfa和α关系不是同一个公式,推导过程涉及多个随机变量的大小比较或者次序统计量,解析解要么复杂要么不存在。我的处理方式是:能解析的用解析公式,不能解析的用蒙特卡洛仿真标定——在纯噪声下跑大量样本,统计虚警比例,反查α。这个做法在工程上完全够用,也避免了公式推错的坑。后面第5部分会讲具体的标定流程。
3. MATLAB算法实现的关键细节
3.1 数据组织与矩阵化滑窗
一维CFAR最容易写成双层for循环:外层遍历每个检测单元,内层累加参考单元。这样写直观,但在MATLAB里性能很差,一次几万个点的扫描能卡好几秒,拖到界面上就是明显的卡顿。正确做法是矩阵化。
思路是把"滑窗"变成"一次性的矩阵切片"。假设数据长度为L,参考单元总数N,保护单元数G,那么对第i个检测单元,左侧参考单元下标是i-G-N/2 : i-G-1,右侧是i+G+1 : i+G+N/2。如果直接用下标索引,还是要循环。更快的办法是用hankel或buffer构造一个滑动窗口矩阵,每一列对应一个检测单元的完整窗口,然后按列做统计。
我实测下来最稳的是hankel加切片组合:先用hankel把一维数据展开成滑动窗口矩阵,再按行或列切出左右参考区。这种写法在L=10000、N=32的情况下,单次CFAR扫描耗时能压到毫秒级,足够支撑界面实时刷新。如果不想用hankel,也可以用两次cumsum做差分,得到滑动求和,再单独处理左右两侧——这种方法更省内存,但代码可读性差一些,看个人取舍。
需要提醒的是边界处理。滑窗滑到数据首尾时,参考窗口会越界。常见做法有两种:截断(越界部分不计入,实际参考单元数变少)和补零(越界部分按零功率处理)。截断会导致首尾门限偏高,补零会导致首尾门限偏低,两者都有偏差。我的做法是首尾各留出半个窗口不检测,或者单独标注为边界区,避免把边界伪影当成目标报出去。
3.2 各CFAR变体的核心代码
代码这块我把关键片段贴出来,都是可以直接跑的骨架,省去参数校验和数据预处理的部分。先说CA-CFAR的核心:
function [detIdx, threshold] = ca_cfar(x, N, G, alpha) L = length(x); half = N/2; threshold = nan(L, 1); for i = (G + half + 1) : (L - G - half) left = x(i - G - half : i - G - 1); right = x(i + G + 1 : i + G + half); noiseEst = mean([left; right]); threshold(i) = alpha * noiseEst; end detIdx = find(x > threshold); end这段是教学版,逻辑清楚但性能一般。实际界面里我会把它向量化,用前面说的hankel展开,一次性算完所有检测单元的门限。GO和SO只需要把mean([left; right])改成max(mean(left), mean(right))或min(...),其余不变。OS-CFAR则要把左右参考单元合并后sort,取第k个:
refAll = [left; right]; refSorted = sort(refAll); noiseEst = refSorted(k);k的取值有讲究。k太小,接近最小值,抗干扰强但估计偏低、虚警上升;k太大,接近最大值,容易被强目标带偏。经验上k取round(0.75 * N)比较均衡,N=32时k=24。这个比例不是拍脑袋,而是有序统计CFAR文献里反复验证过的折中点,我在仿真里也对比过k从0.5N到0.9N的情况,0.75N附近确实是检测概率和虚警控制的平衡区。
3.3 边界处理与运算性能优化
性能优化这块还有几个实操细节值得说。第一,避免在循环里动态扩容数组,threshold提前用nan预分配,能省掉大量内存重排开销。第二,如果界面里要做参数实时联动,把CFAR计算封装成独立函数,输入输出干净,回调里只调用不内联,方便后续替换变体。第三,绘图时不要每次cla重画,用句柄更新YData,刷新率能提升一个量级。
还有一个容易被忽略的点:数据类型。如果输入是double,一切正常;如果是从文件读进来的single或者整型,mean和比较操作的隐式转换会带来额外开销,甚至在某些边缘情况下出现精度问题。我一般进函数第一件事就是x = double(x(:)),强制转成列向量双精度,既统一了维度,也避免了后续各种维度不匹配的报错。这些细节单看都是小事,凑在一起就是界面卡不卡、代码稳不稳的分水岭。
4. 可视化界面的设计与落地
4.1 界面布局与控件规划
界面布局我遵循一个原则:左边调参、右边看图、下边看数。左侧面板放参数控件,包括参考单元数、保护单元数、虚警率、CFAR变体下拉框、数据源选择(仿真/导入)。右侧主区域放两个坐标轴,上面画原始数据叠加门限曲线,下面画检测结果(目标用标记点标出)。底部放一个状态栏或者文本框,显示当前参数下的理论阈值因子、检测到的目标数、耗时。
控件选择上,数值参数用Spinner或者EditField(Numeric),变体切换用DropDown,数据源用ButtonGroup或者RadioButton,重算按钮单独放一个Button。为什么不全自动联动?因为全联动在参数多的时候反而卡,用户连续拖动滑杆会触发一串计算。我的折中是:滑杆拖动时只更新预览,松手或者点"重算"才跑完整CFAR。这个设计是从实际使用习惯里改出来的,一开始做全联动,结果拖动虚警率滑杆时界面直接假死,体验很差。
坐标轴用UIAxes,不要用老式的axes,前者在App Designer里跟uifigure兼容性更好,缩放、平移这些交互也更顺。图例、标题、坐标轴标签在初始化时设一次就行,后续只更新数据,不重建对象。
4.2 回调函数与数据流设计
回调是整个界面的骨架,设计不好会写出满屏重复代码。我的做法是把数据流分成三层:参数层—计算层—渲染层。参数层负责从控件读值,统一打包成一个struct;计算层接收这个struct,调用对应的CFAR函数,返回检测结果和门限;渲染层只负责把结果画到坐标轴上。三层之间靠函数调用连接,不共享全局变量。
举个例子,用户改了参考单元数,触发的是ValueChangedFcn,里面先调collectParams把当前所有控件值收拢,再调runCFAR算一遍,最后调renderResult刷新图。这样写的好处是,无论用户改的是哪个控件,走的都是同一条路径,不会出现"改了这个参数那个参数没生效"的诡异问题。早期我图省事,每个控件回调里各写各的计算逻辑,后来加一个新变体就要改五六个地方,维护成本高得离谱。重构之后,加变体只需要在计算层加一个分支,回调层一行不动。
数据导入这块单独说一句。用户导入的数据格式五花八门,有的是纯文本一列数,有的是CSV带表头,有的是MAT文件里某个变量。我在导入回调里做了格式探测:先试readmatrix,失败再试load,读进来之后统一转成列向量、去NaN、去直流分量。去直流这一步很多人不做,但实测数据里常常带一个很大的直流偏置,不去掉的话CFAR门限会被整体抬高,弱目标全被淹掉。
4.3 实时绘图与交互细节打磨
绘图性能是界面体验的关键。我踩过的坑是:每次重算都plot一遍新曲线,数据量大时界面明显卡顿。改成句柄更新之后,同样的数据量刷新流畅很多。具体做法是在初始化时创建好plot对象,保存句柄,后续只改XData和YData,然后drawnow limitrate。limitrate这个参数很关键,它让MATLAB把多次刷新合并成帧,避免每改一个点就重绘一次。
还有一个细节是坐标轴范围。固定范围方便对比不同参数下的结果,自动范围则能看清细节。我的处理是加一个"自动缩放"复选框,默认勾选自动,用户想对比时可以取消勾选、锁定当前范围。这种小功能看着不起眼,但实际用起来差别很大——调参时经常要来回对比,锁定范围能直观看出门限曲线的整体抬升或下压。
颜色和标记也值得花点心思。原始数据用细灰线,门限用红色实线,检测到的目标用醒目的圆点或者三角标在曲线上方。杂波区和噪声区如果能量差异大,可以在背景里加一条淡色的功率包络,帮助判断门限是不是跟着背景在走。这些视觉元素不改变算法,但直接影响你判断算法对不对的速度。我个人的经验是,一个好的可视化界面,应该让人一眼就能看出"门限是不是合理",而不是盯着数字去脑补。
5. 参数调试与实测验证
5.1 仿真数据怎么造才有代表性
算法验证离不开仿真数据,但仿真数据造得不对,验证结论就是自欺欺人。我一般会造三类场景,覆盖CFAR最容易暴露问题的情形。
第一类是均匀噪声加弱目标。背景用复高斯白噪声,取模平方得到指数分布功率,在若干个随机位置叠加目标,信噪比从5dB到20dB不等。这类场景用来验证基础检测能力,看不同虚警率下检测概率怎么变。第二类是杂波边缘。前半段噪声功率低,后半段功率突然抬高10dB到15dB,模拟地海交界或者云雨区边界。这类场景专治CA-CFAR的边界虚警,GO-CFAR的优势在这里体现得最明显。第三类是密集多目标。在很短的距离范围内放三到五个目标,间距小于参考窗口宽度,模拟编队或者集群目标。这类场景用来对比SO和OS的抗遮蔽能力。
造数据时有个细节要注意:目标不要用单点脉冲,要用一定展宽的主瓣(比如高斯窗或者sinc函数截断),否则保护单元的作用体现不出来。另外,目标的幅度最好随机化,固定幅度容易得出过于乐观的结论。我习惯给每个目标的信噪比加一点随机扰动,更接近真实回波的起伏特性。
5.2 参数扫描与虚警率验证
参数扫描是调参的核心手段。界面里我加了一个"扫描模式",可以对参考单元数、虚警率、保护单元数做单变量或者双变量扫描,结果画成曲线或者热力图。最常看的两条曲线:一条是检测概率随信噪比的变化(固定虚警率),另一条是实测虚警率随理论虚警率设定的变化(纯噪声输入)。
第二条曲线是验证阈值因子算得对不对的关键。做法很简单:输入纯噪声,跑CFAR,统计被判为目标的点数占总检测点数的比例,这就是实测虚警率。把理论设定值从1e-3扫到1e-7,看实测值和理论值的偏差。如果偏差在一个数量级以内,说明α算得基本对;如果偏差很大,要么是α公式用错了变体,要么是数据分布不是指数分布(比如做了非相干积累,分布变了)。
这里要提醒一句:蒙特卡洛验证需要足够多的样本。验证1e-6虚警率,至少要有1e8量级的独立样本,否则统计涨落比真实值还大。实际操作中我不会真的跑1e8个点,而是用多次独立实验取平均,或者验证到1e-5量级就认为趋势对了,再往下的精度靠解析公式保证。这个取舍在工程上很常见,没必要为了最后那一个数量级把验证时间拉长十倍。
5.3 实测结果与性能对比
同一组仿真数据下,四种变体的对比如下(N=24,保护单元2,Pfa=1e-5,目标信噪比12dB):
| 场景 | CA-CFAR检测率 | GO-CFAR检测率 | SO-CFAR检测率 | OS-CFAR检测率 |
|---|---|---|---|---|
| 均匀噪声 | 0.92 | 0.90 | 0.91 | 0.91 |
| 杂波边缘 | 0.71(虚警高) | 0.88 | 0.65(虚警高) | 0.84 |
| 密集多目标 | 0.58 | 0.55 | 0.79 | 0.81 |
这组数字很能说明问题。均匀背景下四者差距不大,CA略优;杂波边缘场景GO明显领先,CA和SO的虚警率都失控;多目标场景SO和OS反超,CA和GO因为强目标污染参考窗口而检测率下降。OS在三个场景里都没有明显短板,代价是计算量和排序开销。如果你的应用场景事先不确定,OS-CFAR是相对稳妥的默认选择;如果场景明确,针对性选型收益更大。
杂波边缘场景里CA-CFAR检测率只有0.71,不是因为它漏检,而是虚警把统计口径搞乱了——大量噪声点被判成目标,真实目标的检测反而被稀释。这个现象在只看检测率数字时容易被误读,必须结合虚警率一起看。我在界面里专门加了一栏显示实测虚警率,就是为了避免这种误判。
6. 常见问题与排查技巧实录
6.1 典型问题速查表
调试CFAR这几年,遇到的问题大多能归到有限的几类。整理成一张速查表,遇到现象先对号入座,能省不少时间:
| 现象 | 可能原因 | 排查方向 | 处理建议 |
|---|---|---|---|
| 弱目标检测不到 | 保护单元太少,目标能量污染参考窗 | 把保护单元从2加到4再试 | 增加保护单元,或换OS-CFAR |
| 虚警率远高于设定 | α公式用了错误变体;数据分布非指数 | 核对变体与公式对应关系 | 用蒙特卡洛标定α |
| 杂波边缘成片虚警 | CA-CFAR固有缺陷 | 观察虚警是否集中在功率跳变处 | 换GO-CFAR |
| 多目标互相遮蔽 | 参考窗内强目标抬高门限 | 看强目标邻近单元的门限曲线 | 换SO或OS-CFAR |
| 首尾检测异常 | 滑窗越界处理不当 | 检查首尾门限是否跳变 | 首尾留窗或单独标注 |
| 界面拖动参数卡顿 | 全联动触发频繁重算 | 用性能分析看回调耗时 | 改手动重算或加防抖 |
| 导入数据检测全乱 | 未去直流或数据非功率量纲 | 打印数据均值与量纲 | 去直流、统一转功率 |
这张表里的每一条我都实际遇到过,其中"虚警率远高于设定"是最常见的。很多人复制了CA-CFAR的α公式,结果用在OS-CFAR上,公式不匹配,虚警率自然失控。还有一个隐蔽情况是数据做了多脉冲非相干积累,积累后分布不再是单脉冲的指数分布,α必须重新标定,直接套单脉冲公式会系统性偏差。
6.2 几个踩过的坑
第一个坑是关于参考单元数的对称性。我早期图省事,左右参考单元数设成不一样,结果门限曲线在目标附近出现不对称的凹陷,排查了半天才反应过来是窗口不对称导致背景估计偏了。后来统一强制左右相等,问题消失。如果你的场景确实需要不对称窗口(比如单边扫描),那要单独推导对应的α,不能直接套对称公式。
第二个坑是排序取k值的边界。OS-CFAR里k如果取到N(最大值),等价于GO的极端形式;取到1(最小值),等价于SO的极端形式。有一次我把k设成round(0.9*N),在参考单元只有16个的情况下,k=14,已经非常靠近最大值,抗多目标能力几乎丧失,表现和CA差不多。后来把k固定成max(1, round(0.75*N)),并加了一个参数合法性校验,才避免这类低级错误。
第三个坑是界面刷新与计算的不同步。有一次用户连续快速拖动滑杆,回调被触发了十几次,每次都要跑一遍完整CFAR,结果最后一次计算还没完成,前一次的结果先画上去了,图和数据对不上。解决办法是加一个"忙碌"标志位,计算期间禁用重算按钮,或者用drawnow配合队列机制保证渲染顺序。这类问题在算法层面看不到,只有真正用起来才会暴露。
第四个坑是对数坐标下的视觉误判。门限曲线在semilogy下看起来很平,实际线性坐标下起伏很大。判断门限是否合理,最好线性、对数各看一遍,特别是弱目标区域,对数坐标容易把小的偏差放大成视觉上的"贴合",掩盖真实问题。
7. 我个人在实际操作中的几点体会
整套东西做下来,最大的感受是:CFAR的公式不难,难的是把公式放进一个能让人快速试错的环境里。参数之间的耦合比想象中强,参考单元数一改,最优的虚警率设定可能要跟着动;保护单元一改,杂波边缘的表现又变了。没有交互式界面之前,这些耦合关系只能靠一张张静态图去拼,效率极低。
如果让我给准备动手的朋友一句建议,那就是先把CA-CFAR在一维仿真数据上跑通、把阈值因子算对、把虚警率验证做扎实,再往上叠加变体和界面。基础不牢,后面每加一个变体都是在给自己埋雷。界面部分不用追求多漂亮,能实时改参数、能实时看图、能一眼看出门限跟没跟着背景走,这三个功能到位,这个工具就已经值回投入的时间了。
后续如果还想往下扩展,有两个方向比较自然:一是把一维扩展到二维,做距离-多普勒平面上的CFAR,滑窗从线段变成矩形,参考单元变成环形或者矩形环;二是把检测结果接到后续的聚类或者跟踪环节,让整个链路从"检点"走到"成航迹"。这两个方向都需要在现有界面上加模块,但核心的滑窗统计逻辑是一样的,把一维这层吃透,往上走会顺很多。