一、引言
恒虚警率(Constant False Alarm Rate,CFAR)方法最早是用于雷达系统中,用于在动态变化 的杂波或噪声背景下较为稳定地检测目标。
场景:雷达系统在接收信号时,会接收到一系列信号,包含目标自身的回波信号 和环境背景的杂波信号,而我们知道:
- 环境背景中的杂波信号往往随着时空等条件的变化而不断变化;
- 检测目标本身是一个二分类问题,我们以某一种物理量 衡量是否存在目标时,一般是对这个物理量设置一个阈值T,在阈值T的两边则代表是否存在目标。
在雷达检测目标这个二分类问题中,要判断目标是否存在,毫无疑问,我们选择的物理量就是接收到的信号,而该信号可以由下面的式子表示:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> 接收信号 = 目标回波信号 + 背景杂波信号 接收信号=目标回波信号+背景杂波信号 </math>接收信号=目标回波信号+背景杂波信号
针对接收信号这个物理量,我们就需要设定一个阈值T ,由于背景杂波信号是一直存在的,而目标回波信号根据实际情况偶尔才出现,因此我们设定的阈值T应该能做到区分出:单独的背景杂波信号 和目标回波信号+背景杂波信号两部分。
如果是一般的二分类问题,我们直接设置一个固定的阈值T当然没问题,但是现在的背景杂波一直有变动,要是阈值T定死了,就很容易检测出错,好比A、B两国要是国界线一直变动,那么今天放在国界线上的石头墩子明天到底属于谁,那就很难知道了,但是如果每次国界线变动的时候,我们都把这个石头墩子重新移动一下,那便没有问题了。因此针对雷达检测目标的问题,我们要是能设置一个能跟随背景杂波自动变化的阈值T,理论上就能很好地解决问题了。
现在我们回到标题上来:恒虚警率里面这个"恒"是否和我们刚刚提到"变化"有冲突?为什么虚警率要恒定?
首先,我们得知道,虚警率(PFA)的虚警就是"指鹿为马"的过程,也就是把错的认成对的,把不是非目标对象认成目标对象,那么PFA就好理解了,就是指:我们错误判断为正例的概率,用公式表达为:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> P F A = F P F P + T P PFA=\frac{FP}{FP+TP} </math>PFA=FP+TPFP
- FP:错误认成正例的个数
- TP:正确认成正例的个数
- FP+TP:总正例个数
现在就很好理解了,当雷达能稳定检测目标时,实际上稳定的就是错误判断为正例的概率,也即是PFA,而前文提到的变化只是指的阈值T的变化,和PFA的恒定是不冲突的。
二、CFAR的使用
在检测目标时,CFAR既可以用于一维,也可以用于二维,本文以二维为例,最常见的就是针对二维矩阵数据来检测某一目标。
对于CFAR有几个关键概念:
- Cell Under Test (CUT) :当前待检测的像素或小区域
- Guard Cells:保护单元,防止目标本身影响背景估计
- Background Cells (Training Cells) :参考单元,用于估计局部背景统计特性
如图: 上图来源:干货 | FMCW雷达信号处理的二维CFAR(2D -CFAR)检测算法_51CTO博客_雷达cfar检测算法
图中灰色格子及以内部分代表整幅数据,橙色部分及以内是当次正在检测的区域,假设现在中间的黄色小格(接收信号/参考单元)≥阈值T,那我们就能很好地区分出CUT就是我们要的目标了,而我们现在则需要表示出阈值T。
在此之前,那么请问:图中绿色部分的保护单元 有什么用呢?这就不得不提到理论和实践的差距了,理论上来说,我们只要有CUT和背景的参考单元就可以了,但是实际上,CUT区域的临近区域可能会有目标的"能力扩散"现象,也就是目标本身可能不止占一格,或者存在雷达成像特征形成的"旁瓣",可以粗浅地理解为油滴落在纸巾上后会有一圈油晕,关于旁瓣的知识可以参考这篇文章:雷达的旁瓣与副瓣 - 程序员大本营
前面提到阈值T是一个跟随背景信号进行变化的量,根据阈值T的表示方式不同,前辈们提出了许多不同的CFAR方法,常见的方法如下:
算法类型 | 背景统计方式 | 适用场景 |
---|---|---|
CA-CFAR(Cell-Averaging) | 取所有背景单元平均值 | 背景均匀 |
GO-CFAR(Greatest-Of) | 分左右背景区域,取较大的平均 | 背景有干扰或一侧目标 |
SO-CFAR(Smallest-Of) | 分左右区域,取较小平均 | 多目标密集 |
OS-CFAR(Order Statistic) | 排序后选第k大的数 | 抗杂波能力强、适应性好 |
以CA-CFAR 为例,如果背景噪声服从指数分布,设背景像素值为 <math xmlns="http://www.w3.org/1998/Math/MathML"> x 1 , x 2 , . . . , x N x_1, x_2, ..., x_N </math>x1,x2,...,xN,N为背景参考单元个数,其均值为:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> μ b = 1 N ∑ i = 1 N x i μ_{b}=\frac{1}{N}\sum_{i=1}^{N}x_{i} </math>μb=N1i=1∑Nxi
设比例系数为k,则检测阈值T为:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> T = k ⋅ μ b T=k⋅μ_{b} </math>T=k⋅μb
若 <math xmlns="http://www.w3.org/1998/Math/MathML"> x C U T > T x_{CUT}>T </math>xCUT>T,则认为检测到目标。
到目前为止,PFA仍未亮相,那肯定就和k有关系了,但是这里的比例系数k推导较为复杂,感兴趣的bro可以查查相关资料,方便起见我们直接给出:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> k = N ( P f a − 1 / N − 1 ) k=N(P_{fa}^{−1/N}−1) </math>k=N(Pfa−1/N−1)
那么,PFA是"恒定"的,那么肯定是预先设置的,我们应该设置为多少呢?或者应该说,多大的PFA是我们所预期的呢?这个就得见仁见智了,根据自己的能接受程度,1e-3、5e-4等等都是可以的,当然,这里我们也能看出CFAR方法的缺点,就是检测效果很依赖PFA等参数的设置。
最后附上GPT友情提供的python代码:
python
def ca_cfar(image, guard_cells=2, training_cells=10, P_fa=1e-3):
output = np.zeros_like(image)
rows, cols = image.shape
total_cells = 2 * training_cells
k = total_cells * (P_fa**(-1/total_cells) - 1)
for i in range(training_cells + guard_cells, rows - training_cells - guard_cells):
for j in range(training_cells + guard_cells, cols - training_cells - guard_cells):
background = []
# 提取背景窗口(排除CUT与保护单元)
for m in range(-training_cells - guard_cells, training_cells + guard_cells + 1):
for n in range(-training_cells - guard_cells, training_cells + guard_cells + 1):
if abs(m) > guard_cells or abs(n) > guard_cells:
background.append(image[i+m, j+n])
threshold = k * np.mean(background)
if image[i, j] > threshold:
output[i, j] = 1 # 检测目标
return output
下面是一张高分三号卫星数据图片,通过CFAR方法得到的舰船目标结果: