【四】恒定虚警率CFAR检测
5/5/2026 | 4 minutes to read | Tags: 雷达信号处理, FMCW雷达, 英飞凌
恒定虚警率 (CFAR) 检测是雷达系统中使用的一种常见自适应算法形式,其核心任务是在背景噪声和杂波功率随时间、空间不断变化的情况下,通过动态调整检测阈值,使系统保持恒定的虚警概率。
假设检测阈值为T,有
其中是阈值因子,表示噪声功率估计。也就是说阈值设置为检测单元附近噪声功率的倍。
滑动窗口检测器

如图所示,它由三部分组成:检测单元(CUT, cell under test)、保护单元(GC)和参考单元(RC)。
- 检测单元:当前正在判断是否有目标的单元。
- 保护单元:紧邻 CUT 的单元。由于目标能量(主瓣)可能会泄露到相邻单元,设置保护单元可以防止目标自身的能量被当成噪声,从而导致阈值被错误地拉高。
- 参考单元:用于计算背景噪声平均功率的采样区域。
CFAR检测算法
CA-CFAR
平均单元恒定虚警率 (Cell Averaging CFAR) 假设背景噪声是均匀分布的。它计算窗口中参考单元的平均能量作为背景噪声的能量,因此进行判决。
在CA-CFAR中,阈值因子可以通过下式计算:
其中表示虚警概率,也就是将信号不存在但误检为存在的概率。 尤其要注意的是,计算能量的时候一定要记得取模。
下面是对RD图做CFAR检测,因此采用2D CA-CFAR算法。
def ca_cfar_2d(rd_map, guard_len, ref_len, pfa): """ 简易二维 CA-CFAR 实现 rd_map: 能量图 (注意这里要是实数。一定要先取模再代入) guard_len: 保护带宽度 (单侧) ref_len: 参考带宽度 (单侧)
""" rows, cols = rd_map.shape
# 计算 alpha 因子 num_ref_cells = (2*ref_len + 2*guard_len + 1)**2 - (2*guard_len + 1)**2 alpha = num_ref_cells * (pfa**(-1/num_ref_cells) - 1) detections = np.zeros_like(rd_map)
# 滑动窗口遍历 (忽略边缘) for r in range(ref_len + guard_len, rows - (ref_len + guard_len)): for c in range(ref_len + guard_len, cols - (ref_len + guard_len)):
# 1. 提取大窗口能量 full_window = rd_map[r-(ref_len+guard_len):r+(ref_len+guard_len)+1, c-(ref_len+guard_len):c+(ref_len+guard_len)+1]
# 2. 提取保护单元窗口 guard_window = rd_map[r-guard_len:r+guard_len+1, c-guard_len:c+guard_len+1]
# 3. 计算参考单元的总能量并求平均 noise_sum = np.sum(full_window) - np.sum(guard_window) p_n = noise_sum / num_ref_cells
# 4. 判决 threshold = alpha * p_n if rd_map[r, c] > threshold: detections[r, c] = 1 return detections运行结果如图所示。

OS-CFAR
对所有参考单元的能量进行排序,选取排序后第 个值作为背景估计。 同样要注意的是,计算能量的时候一定要记得取模。
通常来讲,k的取值一般为参考元素数量的0.75倍。
def os_cfar_2d(rd_map, guard_len, ref_len, rank, scale=1.0):
""" 二维 OS-CFAR (Ordered-Statistic CFAR) 实现 guard_len: 保护带宽度 (单侧) ref_len: 参考带宽度 (单侧) rank: 参考单元排序后取第 rank 个 (0-based) scale: 阈值缩放系数 """
rows, cols = rd_map.shape detections = np.zeros_like(rd_map) win = ref_len + guard_len
for r in range(win, rows - win): for c in range(win, cols - win): full_window = rd_map[r - win:r + win + 1, c - win:c + win + 1] ref_cells = get_ref_cells(full_window, guard_len, ref_len)
if ref_cells.size == 0: continue
ref_sorted = np.sort(ref_cells) idx = min(max(rank, 0), ref_sorted.size - 1) threshold = scale * ref_sorted[idx]
if rd_map[r, c] > threshold: detections[r, c] = 1 return detections
参考文献
← Back to blog