
简介一份面向雷达与红外传感器融合研究者的 MATLAB 源代码包聚焦卡尔曼滤波在目标跟踪中的应用解决多传感器数据同步、状态预测与观测校正等典型问题。压缩包共10个文件其中9个为 .m 脚本/函数涵盖雷达与红外异步数据模拟、扩展卡尔曼滤波EKF、源信号生成及融合主流程另有1个程序说明 txt 便于对照运行。资源整体仅14KB代码轻量易读适合电子信息、信号处理方向的初学者或开发者快速上手。已有859人学习下载。通过阅读源码可掌握 EKF 的预测与更新步骤、雷达/红外异构数据的融合思路并可基于示例工程修改参数或扩展至其他传感器场景提升多传感器跟踪系统的实际设计能力。 先把话放前面这套“雷达与红外图像跟踪融合”的工程方案前前后后我改了三个版本最后跑稳定的是下面这套架构。核心就一句话——用毫米波雷达解决“目标在哪、多快、多远”的问题用红外热像仪解决“目标是什么、长什么样”的问题再把两者从时间、空间、置信度三个维度融合起来输出带ID的连续跟踪轨迹。这套东西可以直接用在安防监控、无人车感知、低空无人机探测这类场景你手头如果有雷达和红外相机按这个思路改就能落地如果只是做算法预研源码结构和融合策略同样有参考价值。1. 项目整体设计与融合思路拆解1.1 为什么是雷达加红外而不是雷达加可见光我最早一版用的是雷达加普通可见光摄像头白天效果确实不错一到晚上就露馅。可见光相机靠环境光成像夜间、逆光、雨雾天气下目标对比度很低检测器基本瘫痪。雷达倒是全天候稳定输出但它的角度分辨率有限点云又稀疏只能告诉你“那里有个东西在动”说不清是人、车还是树。后来换成红外热像仪问题迎刃而解红外是被动接收目标的热辐射不依赖环境光夜间照样能看到人和车辆的热轮廓而且热目标天然和背景有温差检测逻辑反而更简洁。雷达和红外的互补关系是这套融合方案能成立的根本前提。雷达能给出精确的距离、径向速度、方位角但拿不出目标形态红外图像能给出目标的像素位置、尺寸、热特征但没有深度信息。两者一结合等于一个人同时有了“尺子”和“眼睛”。1.2 系统架构与数据流向整个系统分成四层每层只负责一件事出了问题能单独定位传感器接入层毫米波雷达通过串口或网口输出点云和检测目标红外热像仪通过USB或GigE接口输出热像图流。这一层要做的基本是驱动适配和数据帧解析。目标检测层雷达侧做距离多普勒处理、CFAR恒虚警检测、DBSCAN聚类输出目标列表红外侧做图像预处理、阈值分割、连通域分析输出目标检测框。融合对齐层对雷达目标和红外目标做时间同步与空间投影把雷达目标的极坐标映射到红外图像的像素坐标系然后执行目标级匹配与置信度融合。跟踪输出层利用卡尔曼滤波维护轨迹预测与更新通过匈牙利算法做帧间数据关联最终输出带稳定ID的融合轨迹。分层设计的优势在调试期特别明显。比如融合结果漂移时你只需要查是检测层的问题还是对齐层的问题不需要把整个链路翻一遍。1.3 融合策略选型为什么我选目标级融合多传感器融合有数据级、特征级、目标级也叫决策级三条路线。数据级融合是把雷达点云和红外像素直接拼到一起处理信息量最大但雷达点云几十个点、红外图像上百万像素数据形态完全不对等直接拼接会让模型很难训练工程上也不稳定。特征级融合效果上限高但需要训练特征提取网络且依赖GPU算力适合发论文不适合快速落地。我最终用的是目标级融合两个传感器各自独立完成检测再把检测结果投到同一个坐标系里做匹配和融合。好处很直白——模块解耦、可解释性强、算力要求低哪个传感器出问题了单独看它的检测结果就能定位。对工程落地来说目标级融合是最稳妥的选择。2. 雷达数据链路从原始回波到目标列表2.1 距离-多普勒处理与CFAR检测我手头的雷达是TI的AWR2243毫米波雷达其他型号的毫米波雷达处理流程基本一致。雷达发射线性调频连续波目标回波和发射信号混频后产生中频信号对这个信号做一维FFT峰值位置对应目标的距离。但是一个距离上可能有多个速度不同的目标所以还要对一帧内多个chirp的回波沿着慢时间维度再做一次FFT得到距离-多普勒二维矩阵。这一步做完矩阵里每一个峰就是一个候选目标点横轴是距离纵轴是径向速度。直接在这个矩阵上取峰值会有一堆虚警因为环境杂波不是均匀的。我用的CFAR恒虚警检测能让检测阈值随背景噪声自适应变化——把每个待检测单元和它周围一圈参考单元的平均功率做比较目标比背景高出一个设定的系数才判为有效。这个系数就是虚警概率的调节旋钮调低了漏检多调高了虚警多具体数值要靠实测场景去卡。2.2 雷达参数设计与计算逻辑雷达参数不是拍脑袋定的要和探测场景挂钩。下面几个公式是我每次换场景都要重新算一遍的距离分辨率ΔR c / (2B)c是光速B是雷达射频带宽。带宽B4GHz时距离分辨率约3.75cm。带宽越大距离分辨率越高但系统成本和功耗也上去了。最大不模糊距离R_max Fs × c / (2S)Fs是ADC采样率S是chirp斜率。采样率固定时chirp斜率越小最大探测距离越大。速度分辨率Δv λ / (2T_f)λ是载波波长T_f是一帧内所有chirp的总时长。总时长越长速度分辨率越高但帧率会降下来。我实际项目里用带宽4GHz、帧率20Hz的配置能在30米范围内做到厘米级距离分辨率和0.1m/s左右的速度分辨率对安防监控场景足够用了。2.3 点云聚类与目标特征输出CFAR输出的点云是散乱的同一辆车可能反射十几个点。直接把这些点全部送进融合模块匹配计算量爆炸。我先用DBSCAN做聚类原因是目标点云形状不规则而DBSCAN不需要预设簇个数只要设置好邻域半径ε和最少点数min_samples就能适应任意形状。聚类后每个簇对应一个目标目标特征包括距离、方位角、径向速度、点云数量和平均信噪比SNR。点云数量和SNR这两个特征容易被忽略但它们在融合权重计算里是很有价值的置信度指标——点云越多、SNR越高说明这个目标回波越可靠。雷达侧目标的几何信息距离、速度是后面跟踪的直接输入一定不要丢。3. 红外图像处理与目标提取3.1 红外图像预处理三件套红外热像仪输出的是温度分布灰度图理论上温度越高像素越亮但直接用原始图做检测效果很差。主要问题有三个电路噪声和坏点、背景热辐射不均匀、目标与背景对比度低。我的预处理流程是固定三件套中值滤波替换掉突兀的脉冲噪声点同时保持目标边缘比高斯滤波更适合红外图。顶帽变换先对图像做形态学开运算先腐蚀后膨胀得到大面积背景估计再用原图减去这个背景把不均匀热背景抑制掉突出局部亮目标。这一步对室外场景特别关键。直方图均衡化当场景整体温差小时用来拉伸对比度注意只做轻度均衡过度增强会把噪声也放大了。3.2 目标检测阈值分割与连通域分析预处理之后我用Otsu自适应阈值分割做二值化。Otsu的原理很简单按像素灰度把图分成前景和背景两类遍历所有可能阈值找出让类间方差最大的那个值作为分割阈值。它不需要人工干预在红外场景下比固定阈值稳得多因为不同时段、不同天气下目标和背景的温差是变化的。二值图还有不少零星噪点目标内部也可能有空洞我按顺序做一次形态学开运算、一次闭运算。开运算去掉孤立噪点闭运算填充目标内部的小空洞。然后做连通域分析把每个连通域当作候选目标计算面积、外接矩形、质心、平均灰度。面积太小的噪声块和面积过大的整片热源直接过滤。这里有一个非常实用的过滤经验白天室外场景里车灯、排气管、阳光反射都可能产生热源单纯按面积滤不干净。我会额外加一个约束——目标应该有“热轮廓”也就是连通域的边界灰度明显高于周边背景用这个特征能把很多静态热源滤掉。4. 时空对齐与门控融合实现4.1 时间同步双缓存最近邻对齐雷达和红外相机的帧率通常不一致我调试时常用雷达20Hz、红外25Hz的组合。直接把两路数据按各自时间戳丢进融合模块移动目标在融合结果里会出现重影因为两帧目标的位置差了十几毫秒到几十毫秒。我的做法是为每个传感器维护一个最近帧缓存融合时取两帧时间戳差值最小的一对送入匹配。这种方式对帧率抖动不敏感实现也简单。如果项目对实时性要求高比如车载场景可以走硬件方案用外部触发信号让雷达和红外相机同时采样做到严格帧同步代价是多一组硬件连线并且红外相机要支持外触发模式不是所有型号都支持。4.2 空间投影从雷达极坐标到图像像素坐标空间对齐的目的是算出雷达目标在红外图像上的像素位置。雷达目标给出的是极坐标参数距离r、方位角θ、俯仰角φ先转成雷达直角坐标x_r r · cosφ · cosθ y_r r · cosφ · sinθ z_r r · sinφ然后用外参矩阵把雷达坐标转到红外相机坐标p_c R · p_r t最后通过相机内参K投影到像素平面u f_x · X_c / Z_c c_x v f_y · Y_c / Z_c c_y这套公式里R和t是外参标定出来的。我的标定做法是做一个同时能被雷达和红外看到的标定物——金属角反射器外面缠加热带雷达能看到角反射器的强回波红外相机能看到发热体。采集多组角反射器在不同位置下的雷达坐标和图像坐标用PnP算法求解R和t。多采几组点、让点分布覆盖整个视场标定精度才有保证。4.3 门控融合置信度动态决策目标匹配完成后融合不是简单地把雷达和红外结果平均我对置信度用了一个门控加权conf_fused g · conf_radar (1 - g) · conf_ir门控系数g σ(w_r · snr_norm w_i · ir_score_norm b)σ是sigmoid函数snr_norm是雷达目标SNR归一化到0-1ir_score_norm是红外目标灰度或面积的归一化分数w_r、w_i、b是权重参数用一小批标注数据拟合出来。这个门控的直观含义是雷达信号强而红外特征弱时多信雷达红外特征清晰而雷达SNR低时多信红外。融合后的目标同时保留雷达的测距和测速信息、红外检测框的像素位置和热特征信息再送给跟踪器跟踪的稳定性和准确率比用单一传感器输出高出一个级别。5. 跟踪器设计卡尔曼滤波与数据关联5.1 卡尔曼滤波匀速模型的预测与更新融合后的目标列表仍然会有漏检和测量噪声不能直接拿来做最终轨迹我引入卡尔曼滤波做平滑和预测。状态向量取[x, y, vx, vy]x和y是目标在笛卡尔坐标系下的位置由雷达距离和方位角换算vx和vy是速度。运动模型用匀速模型。卡尔曼的预测-更新循环是标准流程先预测当前帧的状态和协方差再用融合目标的位置作为观测值更新状态。关键参数是过程噪声协方差Q和观测噪声协方差RQ决定模型对运动突变的适应能力R决定对观测值的信任程度。我实测的经验是Q别设太小否则目标突然加减速时轨迹会被拉成直线跟不上真目标。5.2 数据关联匈牙利算法解匹配问题多目标场景下上一帧的轨迹和当前帧的检测需要配对。我把这个问题建模为线性分配问题构建代价矩阵矩阵元素是轨迹预测位置和当前检测之间的马氏距离然后用匈牙利算法求解最优匹配。Python里直接用scipy.optimize.linear_sum_assignment就能解不需要自己写匈牙利核心逻辑。关键是设置最大关联距离阈值。超过阈值的轨迹和检测不强行配对否则会产生大量ID跳变和轨迹断裂。这个阈值可以根据目标最大速度和帧间隔估算比如目标最快10m/s、帧间隔0.05s那么帧间位移上限是0.5m留出两倍余量设成1m比较合适。5.3 轨迹生命周期管理给轨迹定义三种状态待确认、稳定、丢失。新检测连续命中2帧后状态从待确认转为稳定才允许对外输出。稳定轨迹连续丢失3帧以上标记为丢失并从轨迹池删除。待确认轨迹只要丢失1帧就立即删除防止虚警积累成假轨迹。这套规则是我调试中逐步调整出来的。最开始我让待确认轨迹也输出结果一组虚警目标被当成真实轨迹显示后来改成“两帧确认”策略虚警大幅减少。稳定轨迹的丢失容忍帧数要结合目标遮挡场景来调安防场景我一般容忍3-5帧车载场景因为遮挡更频繁会放宽到8帧。6. 源码工程结构与调试实录6.1 模块化工程目录放一下工程目录结构你可以直接对照复用radar_ir_fusion/ ├── configs/ │ ├── radar.yaml │ ├── camera.yaml │ └── fusion.yaml ├── data_acquisition/ │ ├── radar_reader.py │ ├── ir_camera_reader.py │ └── synchronizer.py ├── detection/ │ ├── radar_detector.py │ ├── ir_detector.py │ └── result_fusion.py ├── tracking/ │ ├── kalman_filter.py │ ├── data_association.py │ └── track_manager.py ├── calibration/ │ ├── radar_camera_calib.py │ └── project_points.py ├── visualization/ │ ├── draw_tracks.py │ └── video_writer.py └── main.py6.2 核心融合代码目标级匹配融合模块的代码逻辑很直白关键是坐标投影和匹配阈值这两点。核心片段可以这样写def fuse_detections(radar_targets, ir_detections, calib, weights): fused_list [] for rt in radar_targets: # 雷达极坐标 - 雷达直角坐标 - 相机像素坐标 px, py calib.project_radar_point( rrt.range, azrt.azimuth, elrt.elevation ) # 在红外检测框中找最匹配项 best_box None best_dist float(inf) for box in ir_detections: center_x (box.x1 box.x2) / 2 center_y (box.y1 box.y2) / 2 dist math.hypot(px - center_x, py - center_y) if dist best_dist: best_dist dist best_box box if best_box and best_dist calib.max_match_pixels: # 置信度门控融合 snr_norm sigmoid(rt.snr / weights.snr_scale) ir_norm sigmoid(best_box.gray_mean / weights.gray_scale) g sigmoid(weights.w_r * snr_norm weights.w_i * ir_norm weights.b) conf g * rt.quality (1 - g) * best_box.confidence fused_list.append(FusedTarget( rangert.range, velocityrt.velocity, bboxbest_box.bbox, confidenceconf, )) return fused_list匹配阈值max_match_pixels是调参重点设大了会把距离较远的两个目标错误融合为一个设小了会漏匹配。我一般以目标在图像中的平均尺寸为参考设成目标框平均宽度的0.5倍左右。6.3 踩过的坑与排查方案整理几个我实际调试中遇到的高频问题给也准备入坑的朋友一份参考问题现象根因分析解决思路融合目标重影时间戳未对齐两传感器帧率不一致改用双缓存最近邻时间同步必要时硬触发雷达目标投影偏出红外框外参标定误差大增加标定点数量并覆盖全视场用最小二乘优化重算R和t红外画面开机后持续漂移热像仪未预热探测器温度未稳定开机后预热5分钟再开始检测开启非均匀性校正轨迹ID频繁跳变关联阈值过小或目标被长时间遮挡调大最大关联距离提高丢失容忍帧数雷达近处目标突然消失毫米波雷达存在近距离盲区融合策略中加入“雷达失效时仅用红外检测”的降级逻辑第二个问题的坑值得单独多说一句。我第一次做外参标定时只放了5个点而且都在画面中央区域结果投影误差在边缘区域被放大目标一出画面边缘投影就偏出去半个框。后来增加到15个点、覆盖整个视场投影误差明显下降。标定的核心原则是多点、分散、覆盖远近距离。一些实际的收尾建议这套系统我前后跑了大半年最大的感触是融合系统的上限不取决于某一个传感器有多强而取决于两个传感器能否在对齐层面配合好。时间对齐和空间标定花掉的时间比检测算法本身多得多但这两件事做扎实了后续融合和跟踪就是水到渠成的事。最后分享一个调试技巧每次改完融合参数别直接看融合结果先把雷达检测结果和红外检测结果分别录一批视频叠加时间戳离线逐帧对比。很多“融合效果差”的问题最后都定位在单侧检测漏检或者时间戳偏差上跟融合算法本身没关系。有了这两份独立的检测录像排查效率会高很多。这套方案接下来我打算加入一个三维可视化前端把雷达点云和红外图像投影到统一场景里做三维展示有兴趣的可以一起交流。本文还有配套的精品资源点击获取