
简介面向毫米波雷达数据处理与机器学习学习者这份代码和数据集打包了聚类算法系列文章的配套资源以车载毫米波雷达回波数据处理为典型场景覆盖K-means、DBSCAN、谱聚类、层次聚类等经典方法在目标检测与回波分析中的应用。压缩包共40个文件以32个txt数据集和8个m脚本为主整体仅848KBtxt文件包含Iris、Wine、Segment、Letter等常用UCI聚类数据集及其标签可作为雷达多维度回波验证数据m脚本则提供funcKmeans、funcDBSCAN、Cal_DBI、Cal_Silhouette等Matlab函数覆盖聚类实现与内部/外部评估指标。已有875人学习下载。借助这套资源读者可以快速复现不同算法的聚类全过程对比簇划分效果结合博主在车载毫米波雷达上的处理经验还能练习从原始信号中提取目标特征、完成目标检测与跟踪的实战流程尤其适合需要系统掌握聚类选型、参数调整与效果评估的开发者。 搞毫米波雷达点云处理的朋友大概率都遇到过同一个尴尬原始检测出来的点云又散又吵直接扔给跟踪模块目标框能跳成鬼畜动画。聚类算法在这个环节扮演的角色就是把零散点云归成有物理意义的目标为后续跟踪、识别和决策打基础。这次我把工作中常用的聚类方法整理成一个系列配套一份整理好的代码仓库和数据集方便复现和对比实验。内容覆盖DBSCAN、KMeans、层次聚类这三种主流思路以毫米波雷达场景为核心也提供可视化、评估指标的完整脚本。无论你是刚入门雷达数据处理还是已经在做多目标跟踪想优化上游聚类效果这套内容都能直接用起来。1. 项目概述雷达点云聚类为什么是绕不开的一环1.1 毫米波雷达点云的特点与聚类难点毫米波雷达输出的点云和激光雷达差别很大。激光雷达的点云稠密、均匀地面点、墙面点清晰可辨毫米波雷达一个目标往往只反射出十几个甚至几个有效点还夹杂着大量由多径反射、旁瓣泄漏和环境杂波产生的虚假点。数据稀疏、噪声密度高、目标边缘点不稳定这三个特点叠加在一起直接决定了聚类算法的选型不能照搬视觉或激光方案。另一个容易忽略的点是雷达点云带有多普勒速度维。同一个刚体目标上的所有反射点理论上径向速度是接近的这是一个非常有价值的分群依据。但速度维和距离维的量纲不同直接拼在一起做距离计算会把空间结构稀释掉所以聚类前要么单独加权要么手动构造混合特征。这个细节我在后文的代码里具体演示。聚类结果的评价也是个难点。雷达点云没有图像里的像素级真值通常只有目标级标注聚类是“过度分裂”还是“过度合并”很难用一个通用指标判断。实际操作里我会结合DBCV这种无真值指标和抽样目检来综合评估这套代码仓库里也内置了对应的脚本。1.2 系列博文的组织思路与代码数据集设计为了方便阅读整个系列按“数据集准备—预处理—聚类实现—结果评估—场景调优”的顺序编排。代码仓库对应每篇博文拆成了独立模块数据也做了分类存放尽量做到拿到手就能跑通复现实验。仓库结构大致如下radar_cluster/ ├── data/ │ ├── raw/ # 原始点云CSV按帧保存 │ ├── processed/ # 预处理后的点云 │ └── labels/ # 目标级标注JSON格式 ├── src/ │ ├── loader.py # 点云读取 │ ├── preprocess.py # 去噪、坐标转换、特征构造 │ ├── clustering.py # DBSCAN/KMeans/层次聚类封装 │ ├── metrics.py # 聚类评估 │ └── visualize.py # 2D/3D可视化 ├── experiments/ │ ├── run_dbscan.py │ ├── run_kmeans.py │ └── run_hierarchical.py └── configs/ ├── dbscan.yaml └── kmeans.yaml这样拆分的意图很明确不同博文聚焦不同的算法时只需要改配置文件或调用对应的脚本而不需要复读数据加载和可视化的代码。做算法对比实验时也能保证除算法本身外其他环节完全一致避免变量污染。2. 数据集说明格式、来源与标注2.1 数据格式设计数据集的原始文件是逐帧保存的CSV每一行代表一个有效检测点。字段设计参考了几个开源自动驾驶数据集的风格同时针对毫米波雷达增加了物理量信息。字段名说明单位frame_id帧序号-timestamp时间戳sx雷达坐标系下的横向位置my纵向位置mz高度mdoppler径向速度m/srcs反射截面dBsmamplitude幅度dB之所以保留z轴是为了兼顾4D雷达的使用场景。如果是3D雷达z字段统一填0即可聚类时通过配置决定是否启用该维。doppler和rcs在传统聚类里往往是直接被丢掉的但我在实验中发现距离权重量化构造后它们对分离近距两个径向速度差异明显的目标非常有帮助。CSV读取用pandas一行就能搞定但为了在嵌入式环境跑仓库里也提供了一个不依赖pandas的纯Python加载版本用的是标准库csv模块性能相差不大。2.2 标注信息与场景分布标注文件采用JSON以目标为单位记录每个目标的中心点坐标、包围框尺寸和帧内点云索引列表。目标级标注的好处是制作成本低不要求对每个点做精细语义分割对大部分工程场景已经够用。{ frame_id: 128, timestamp: 4.26, targets: [ { id: 1, class: pedestrian, center: [2.3, 8.5, 0.0], size: [0.8, 0.7, 1.7], points_index: [12, 13, 14, 15] } ] }数据集场景覆盖了空旷道路、城市交叉口、停车场、高速多目标等典型情况同时也放了几个路边施工场景的数据。在后续博文里我会专门针对这些不同场景做参数敏感度分析同样的算法和参数在空旷场景可能很好用到密集停车场就完全失效。3. 聚类算法代码实现与对比实验3.1 DBSCAN雷达场景的默认选项DBSCAN是雷达点云聚类里我最常用的算法没有之一。它不需要预先指定类别数能自动识别噪声点而且聚类形状不限于凸簇这和雷达点云不规则的几何形态很匹配。核心参数只有两个eps邻域半径和min_samples邻域内最少点数。我的实际调参经验是对于10米内的目标eps取1.2到1.5米、min_samples取3到4整体效果比较稳定。如果场景距离拉远到30米以上点云会变得稀疏eps要适当增大到2米左右否则同一目标被拆成多个簇。import numpy as np from sklearn.cluster import DBSCAN def dbscan_cluster(points, eps1.5, min_samples3, use_dopplerFalse, doppler_weight0.1): # 基础特征前三列x, y, z features points[:, :3].copy() if use_doppler and points.shape[1] 4: # 多普勒与距离量纲差异大加权后作为第四维 doppler_feat points[:, 3:4] * doppler_weight features np.hstack([features, doppler_feat]) model DBSCAN(epseps, min_samplesmin_samples) labels model.fit_predict(features) return labels关心两个细节。第一doppler_weight这个系数不是随便拍的我一般先统计数据集中目标内点云的速度标准差取标准差累积分布的80%分位数作为参考值。第二特征列的顺序会影响距离计算的语义把空间维放前面速度维的权重自然就是“相对”的这一点要写进注释里避免后人看不懂。3.2 KMeans与层次聚类的适配性分析KMeans在雷达点云上表现一般核心原因是需要预先知道目标数K。实际场景中雷达视野里的目标数量随时变化提前设定K没有任何工程意义。不过KMeans在有粗粒度先验的场景下仍有价值比如你已经通过区域划分知道了某条车道上大概率只有一个目标那么用KMeans做局部分割比DBSCAN更快计算开销也更可控。层次聚类AGNES在雷达上的定位更偏离线分析。它的优点是聚类过程可以用树状图直观展示方便观察数据内在层次结构缺点是计算复杂度高点云量上来后跑得很慢。我通常只在做场景分析与参数探索时使用工程部署不推荐。from sklearn.cluster import AgglomerativeClustering def agnes_cluster(points, distance_threshold2.0): model AgglomerativeClustering( n_clustersNone, distance_thresholddistance_threshold ) labels model.fit_predict(points[:, :3]) return labels3.3 三种算法在雷达数据上的实测对比用同一个场景城市交叉口约40个点3个目标跑三种算法结果很能说明问题。算法聚类簇数噪声点数单帧耗时效果评价DBSCAN(eps1.5)350.8ms目标完整两近距行人分离良好KMeans(K3)300.5ms簇边界错乱行人点被划给旁车AGNES(阈值2.0)3012.6ms簇结果与DBSCAN接近耗时偏高KMeans的问题很典型因为点必须归属到某个簇噪声点会被强行分配同时簇是凸形的遇到L形分布的目标点容易把非目标区域也圈进来。DBSCAN虽然多了一些噪声点但每个簇的完整性更好。AGNES效果不错但单帧12毫秒的耗时在实时系统里几乎没有工程价值。4. 从数据到结果的完整实操流程4.1 数据加载与预处理拿到原始CSV后建议先用统计滤波的方式剔除孤立点。做法是以每个目标点为中心搜半径1.5米的邻域如果邻域内点云数量少于2直接标记为疑似噪声。这一步实现的逻辑和DBSCAN的邻域查询类似但耗时极低可以有效减小后续聚类输入的数据量。坐标转换也是预处理的重点。数据保存时使用的是雷达极坐标系推导出的三维直角坐标但部分开源数据需要使用标定参数转换到车体坐标系比如KITTI中的数据就是另一套坐标约定。若不做转换直接聚类结果会出现系统性偏移尤其影响目标间的空间距离计算。仓库里提供了对应的转换函数记得在调用聚类前先执行。预处理完成后强烈建议先做一遍可视化再进入算法实验。用matplotlib绘制BEV鸟瞰图散点颜色按照点云强度或多普勒速度映射很多数据问题一眼就能看出来比对着数值排查快得多。import matplotlib.pyplot as plt def visualize_bev(points, labelsNone): fig, ax plt.subplots(figsize(8, 8)) if labels is None: sc ax.scatter(points[:, 0], points[:, 1], s6, cpoints[:, 3], cmapviridis) plt.colorbar(sc, labeldoppler (m/s)) else: sc ax.scatter(points[:, 0], points[:, 1], s6, clabels, cmapplasma) ax.set_xlabel(x (m)) ax.set_ylabel(y (m)) ax.set_aspect(equal) plt.grid(alpha0.3) plt.show()4.2 聚类运行与结果可视化实验脚本统一从配置文件读取参数运行方式保持简单直接。python experiments/run_dbscan.py --config configs/dbscan.yaml配置文件示例data: raw_path: data/raw/frame_0128.csv use_columns: [x, y, z, doppler, rcs] preprocess: outlier_radius: 1.5 min_neighbors: 2 clustering: algorithm: dbscan eps: 1.5 min_samples: 3 use_doppler: true doppler_weight: 0.1运行结束后脚本会输出每个簇的质心、点数、包围框以及包含噪声在内的统计信息。可视化模块会生成两幅图一幅是原始点云按速度着色另一幅是聚类结果按簇着色。这两幅图放一起看能够直观发现参数问题也是后续写分析报告时的重要素材。4.3 聚类效果评估有标注数据时我使用调整兰德指数ARI来评估聚类与真值的一致性。它不要求簇编号一一对应随机划分得分接近0、完全一致的聚类得分接近1对雷达这种点云标注比较友好。没有标注数据时推荐DBCV基于密度的聚类有效性指标。DBCV不需要真实标签只根据簇内密度和簇间密度差距给出评分数值越高代表聚类结构越合理。仓库的metrics.py里实现了这两个指标并做了对照实验帮助评估聚类参数是否合理。from src.metrics import dbcv_score, adjusted_rand_index def evaluate(labels, pred_labels, points_xyz, gt_labelsNone): score_dbcv dbcv_score(points_xyz, pred_labels) print(fDBCV: {score_dbcv:.4f}) if gt_labels is not None: ari adjusted_rand_index(labels, pred_labels) print(fARI: {ari:.4f})5. 常见问题与排查技巧实录5.1 DBSCAN参数怎么调才合理很多新手拿到数据第一件事就是把eps和min_samples挨个试调参调到头大。我给一个尽量减少盲目尝试的流程先只统计空间距离把每个点到最近第3个邻近点的距离值画成k-distance图选择曲线拐点处对应的距离作为eps初值。min_samples则根据雷达一帧内目标的平均反射点数来定一般取3到5不要超过8否则近距小目标很容易被当成噪声滤掉。有一个我踩过的坑特别提醒eps和min_samples并非独立变量。增大min_samples的同时需要相应降低eps才能保持簇识别的灵敏度。两者一起增大时小目标几乎必挂两个距离1米以内的行人会直接被粘成一坨。反过来两个参数一起减小单目标的点又会碎成几块。5.2 目标粘连与噪声误聚的处理城市道路场景下行人和车辆在空间距离很近时聚类结果极易把两者合并成一个簇。如果只用xyz坐标聚类这类问题几乎无法避免。实测有效的方法是引入多普勒维做加权距离行人步行速度一般低于2m/s而车辆即使在拥堵路况也有一定速度差速度维度会显著拉开两者的距离。如果目标之间的径向速度差仍然很小比如静止行人旁边停着一辆静止汽车这时可以从时序角度入手利用多帧点云累积的方式增加目标表面的点密度再进行第二轮聚类。这个方案会增加一帧延迟但对静态交通场景很有效。噪声误聚则多半来自杂波点恰好落在两个目标之间形成“桥接效应”。遇到这种情况最简单的办法是在预处理阶段加入RCS过滤毫米波雷达的墙面杂波和金属反射物RCS差异很大通过阈值可以过滤掉一部分桥接点。5.3 坐标与数据来源的坑使用公开数据集时一定要先弄清楚坐标系定义。KITTI这类视觉和激光数据的坐标约定x向右、y向下、z向前与常规雷达坐标系x向前、y向左、z向上差别很大点云直接混合使用会让聚类结果看似正常实则在空间距离上全部错误。仓库里的坐标转换模块建议在任何数据输入时强制调用统一到车体坐标系后再运算。还有一个容易被忽视的问题不同数据集的有效距离范围不同远距离点云稀疏程度差异极大。同一个DBSCAN参数在近距离效果很好到了50米外就可能一个目标也聚不出来。建议方案是按距离分段设置不同的eps参数比如0-20米用1.220-50米用2.0代码里用一句np.digitize配合分段配置就能实现。以上这些经验都沉淀在配套的代码和实验中。如果你打算把这套方案用到自己的项目里建议先从DBSCAN基线开始跑通全流程再逐步叠加场景化配置。多花点时间在可视化数据上比一上来就调算法参数收益大得多。后续我还会继续整理多目标跟踪与聚类联动调优的内容顺带分享一些数据标注效率提升的小技巧欢迎持续关注。本文还有配套的精品资源点击获取