资讯动态

TI毫米波雷达人数统计实战:lab0011-pplcount从点云到人数输出全链路解析

发布时间:2026/10/21 3:08:47 来源:尧图企业网站定制
简介这份资源是TI毫米波实验lab0011-pplcount的完整工程包面向学习毫米波雷达与嵌入式开发的工程师及学生用于实践基于毫米波传感器的人数统计方案。压缩包共309个文件、约14.67MB以C源码与头文件为核心配合大量工程配置、目标文件、图像素材及PDF文档覆盖硬件配置、信号处理与GUI开发等环节。其中配置文件定义传感器频率、增益与采样率等参数快速启动指南与docs文档帮助理解实验流程项目主体代码实现检测阈值设定、目标跟踪与滤波等算法GUI部分则提供交互式数据监控界面。目前已有360人学习下载适合希望掌握毫米波传感器配置、数据处理与实时人数统计的读者参考也可为智能交通、安防监控等场景的二次开发提供基础。1. 毫米波雷达做人数统计lab0011-pplcount 到底在解决什么问题第一次拿到 lab0011-pplcount 这个实验名很多人会以为它只是个点云可视化的 Demo跑起来看到一堆散点就完事了。实际上它要解决的是一个更硬核的问题用 TI 毫米波雷达的原始回波在没有人脸、没有摄像头、不依赖可见光的条件下稳定输出一个区域内的人数。这件事在会议室占用检测、电梯轿厢人数限制、公共区域人流统计里都是刚需因为摄像头方案有隐私争议红外方案又受环境温度干扰严重。lab0011-pplcount 这个实验名里的 pplcount 就是 people counting 的缩写它属于 TI 毫米波雷达工业工具箱里比较典型的一类应用实验。它跑通之后你能得到的不只是点云还有聚类后的目标簇、每个簇的质心坐标以及最终的人数估计值。适合谁看适合已经拿到 TI 毫米波雷达板子比如 IWR6843 这类单芯片方案、装好了 SDK 和工业工具箱、但卡在“点云有了人数怎么算”这一步的嵌入式工程师和算法工程师。接下来的内容会从数据流、参数配置、聚类算法、避坑到进阶调参把这条链路拆开讲清楚。2. 从原始 ADC 到人数输出lab0011-pplcount 的数据链路拆解2.1 毫米波雷达测人为什么比测车难毫米波雷达测车的逻辑很直接车是一个大面积、高反射率、运动规律的目标雷达截面积大多普勒特征明显。但人不一样人的雷达截面积小而且人体表面是曲面回波能量分散加上人会有微动呼吸、手臂摆动点云在帧与帧之间会“抖”。更麻烦的是多人场景两个人站得近点云在距离-角度二维平面上会糊成一团聚类算法稍微激进一点就把两个人合成一个保守一点又把一个人拆成三四个。lab0011-pplcount 的应对思路不是去追求单帧的完美检测而是利用多帧累积和聚类稳定性来投票。它先在距离-多普勒-角度三维空间里做恒虚警率检测得到稀疏点云再用基于密度的聚类把属于同一个人的点归到一起最后对聚类簇做质心跟踪和计数。这个链路里CFAR 的参数决定了点云是“太干净”还是“太脏”DBSCAN 的邻域半径和最小点数决定了聚类是“太紧”还是“太松”两者是耦合的不能分开调。2.2 在工业工具箱里定位 lab0011-pplcount 的配置入口TI 的毫米波工业工具箱通常把每个实验放在独立的目录下lab0011-pplcount 也不例外。你拿到工具箱后先确认三件事SDK 版本和工具箱版本是否匹配、雷达板型号是否在实验支持列表里、以及实验目录下是否有预编译的二进制和配置文件。常见做法是进入实验目录后先看docs文件夹里的说明再用mmwave_sdk提供的烧录工具把xwr64xx或对应平台的 bin 文件写进板子。下面这段 bash 是典型的目录确认和烧录前检查流程路径按你本地实际解压位置替换# 进入工业工具箱的实验目录确认 lab0011-pplcount 存在 cd ~/mmwave_industrial_toolbox/labs/lab0011-pplcount # 查看实验目录结构确认有预编译 bin 和配置文件 ls -R | head -50 # 确认雷达板串口设备号通常有两个一个配置口一个数据口 ls /dev/ttyUSB* # 用 TI 的烧录工具把 bin 写进板子工具名按你本地实际为准 # 这一步只是示意具体命令以工具箱文档为准逻辑说明第一步是确认实验目录完整避免拿到残缺的包。第二步看目录结构重点是prebuilt_binaries和chirp_config这两个文件夹前者放烧录文件后者放雷达波形配置。第三步确认串口毫米波雷达板一般枚举出两个串口配置口用来发命令数据口用来收点云。参数说明/dev/ttyUSB*在 Linux 下是常见命名Windows 下对应 COM 口设备号会因插拔顺序变化每次实验前都要重新确认这是血泪经验。2.3 雷达波形配置chirp 参数怎么影响人数统计lab0011-pplcount 的检测效果七成取决于 chirp 配置。配置文件里几个关键参数起始频率、斜率、空闲时间、ADC 采样数、帧周期、chirp 循环数。这些参数共同决定了距离分辨率、速度分辨率、最大不模糊距离和最大不模糊速度。人数统计场景下最需要关注的是距离分辨率和角度分辨率因为要把相邻的人分开。常见做法是距离分辨率做到 4 到 5 厘米角度分辨率靠多接收天线虚拟阵列做到 10 度以内。帧周期不要设得太短太短了点云累积不够聚类不稳定也不要太长太长了人走动时点云拖尾严重。我一般会把帧周期设在 50 到 100 毫秒之间具体看场景里人的移动速度。下面是一个典型的 chirp 配置片段用文本形式给出方便你对照自己的配置文件% 雷达波形配置示例参数需按你的板子和场景调整 profileCfg 0 60 7 5 40 0 0 8 1 256 5000 0 0 30 % 起始频率 60GHz空闲时间 7usADC 起始时间 5us % 斜率 40MHz/usADC 采样数 256采样率 5000ksps frameCfg 0 1 16 0 100 1 0 % 两个 chirp 段16 个 chirp 循环帧周期 100ms逻辑说明profileCfg定义单个 chirp 的射频参数frameCfg定义一帧里怎么排布这些 chirp。参数说明起始频率决定波长波长影响多普勒灵敏度斜率乘以 ADC 采样时间得到有效带宽带宽决定距离分辨率帧周期决定点云刷新率。注意斜率不是越大越好斜率大了最大不模糊距离会变小人站在稍远处就检测不到这是新手最容易翻车的地方。2.4 点云聚类DBSCAN 在人数统计里的参数怎么定点云出来之后下一步是聚类。lab0011-pplcount 用的是基于密度的聚类思路核心参数有两个邻域半径 eps 和最小点数 minPts。eps 决定了多远算“邻居”minPts 决定了一个簇至少要有多少个点。这两个参数直接决定人数估计的准不准。我的调参习惯是先固定 minPts 为 3 到 5然后从小到大扫 eps。eps 太小一个人被拆成多个簇人数虚高eps 太大相邻的人被合并人数虚低。判断标准不是看单帧而是看连续 100 帧的人数输出是否稳定。如果人数在真实值上下跳变超过 1说明参数还没到位。下面这段 Python 是离线复现聚类逻辑的简化版用来在 PC 上拿录制的点云数据调参不用每次烧板子import numpy as np from sklearn.cluster import DBSCAN # 假设 points 是 N x 3 的数组列分别是 x, y, z单位米 # 这些点来自雷达数据口解析后的点云 points np.loadtxt(frame_points.csv, delimiter,) # eps 单位是米minPts 是最小点数 # 人数统计场景下 eps 一般从 0.3 开始试minPts 从 3 开始 clustering DBSCAN(eps0.5, min_samples3).fit(points) # 标签 -1 表示噪声点不参与计数 labels clustering.labels_ n_clusters len(set(labels)) - (1 if -1 in labels else 0) print(估计人数:, n_clusters) # 打印每个簇的质心方便判断聚类是否合理 for k in set(labels): if k -1: continue cluster_points points[labels k] centroid cluster_points.mean(axis0) print(f簇 {k} 质心: {centroid}, 点数: {len(cluster_points)})逻辑说明这段代码把点云喂给 DBSCAN输出簇的数量作为人数估计。参数说明eps0.5表示 0.5 米内的点算邻居这个值要结合你的距离分辨率来定min_samples3表示一个簇至少 3 个点低于这个数的当噪声。注意质心可以用来做跨帧跟踪如果两帧之间质心位移小于某个阈值就认为是同一个人这样可以避免同一个人被重复计数。这个离线调参流程能帮你省下大量烧板子的时间是我自己常用的做法。3. 把 lab0011-pplcount 跑起来的完整操作步骤3.1 环境准备SDK、工具箱和串口工具跑 lab0011-pplcount 之前环境要齐。你需要毫米波 SDK提供底层驱动和烧录工具、工业工具箱提供实验源码和预编译 bin、一个串口终端用来发配置命令和收数据、以及 Python 环境用来解析点云和跑聚类。版本匹配是第一个坑SDK 版本和工具箱版本不匹配时预编译 bin 可能跑不起来或者跑起来但数据格式对不上。常见做法是先看工具箱 release note 里写的推荐 SDK 版本然后严格按那个版本装。不要图省事用最新版最新版和工具箱之间经常有兼容性问题。串口工具在 Linux 下可以用 minicom 或 picocomWindows 下用你习惯的串口助手只要能发文本命令、能保存接收数据就行。3.2 烧录与上电bin 文件怎么写进板子烧录这一步不同板子操作不一样。以常见的单芯片板为例需要先把板子打到烧录模式通常是拨码开关或跳线然后用 TI 的烧录工具把 bin 写进去写完再打回运行模式重新上电。烧录模式进不去是高频问题现象是烧录工具找不到设备原因通常是拨码没拨对或者 USB 线只供电不传数据。下面这段 bash 是烧录前后的检查流程具体工具名以你本地为准# 确认板子进入烧录模式后系统识别到设备 lsusb | grep -i texas # 用烧录工具写 bin这里用占位命令示意 # 实际命令请参考工具箱文档里的烧录说明 flash_tool --port /dev/ttyUSB0 --bin prebuilt_binaries/pplcount.bin # 烧录完成后把板子打回运行模式重新上电 # 再次确认串口枚举正常 ls /dev/ttyUSB*逻辑说明第一步确认系统认到了板子认不到就别往下走。第二步写 bin注意 bin 文件要和你的板子型号对应写错型号的 bin 板子起不来。第三步重新上电后确认串口运行模式下应该能看到两个串口。参数说明--port指定烧录口--bin指定固件路径这两个参数写错都会导致烧录失败。注意烧录完成后一定要断电再上电热复位有时候不生效这是踩过的坑。3.3 发送配置并接收点云数据口怎么解析板子跑起来后通过配置口发送 chirp 配置和帧配置然后数据口会开始吐点云。点云是二进制格式需要按 TI 的 TLVType-Length-Value结构解析。TLV 里常见的类型有点云列表、目标列表、聚类结果。lab0011-pplcount 的输出里点云和聚类结果都会通过 TLV 发出来。下面这段 Python 是解析 TLV 的简化逻辑用来把数据口收到的字节流转成点云数组import struct def parse_tlv(data): 解析 TI 毫米波雷达的 TLV 数据流 points [] offset 0 while offset len(data): # TLV 头类型 4 字节长度 4 字节 tlv_type, tlv_length struct.unpack_from(II, data, offset) offset 8 if tlv_type 1: # 类型 1 通常是点云 # 每个点包含 x, y, z, 多普勒, 信噪比等字段 # 具体字段数和顺序以你的 SDK 文档为准 point_size 16 # 假设每个点 16 字节 num_points tlv_length // point_size for i in range(num_points): x, y, z, doppler struct.unpack_from(ffff, data, offset i * point_size) points.append((x, y, z, doppler)) offset tlv_length return points逻辑说明TLV 是自描述结构先读类型和长度再按长度读值。参数说明II表示小端无符号整数TI 的数据一般是小端point_size要按你的 SDK 版本确认不同版本字段数可能不同。注意解析时一定要做长度校验数据流里可能有帧头帧尾不校验的话会解析出乱码点导致聚类结果完全不可信。这个解析逻辑建议先在 PC 上用录制数据跑通再上板子实时跑。3.4 从点云到人数把聚类和计数串起来点云解析出来后接上第 2 章讲的 DBSCAN 聚类就能得到人数。但实际工程里还要加一层跨帧跟踪否则同一个人在两帧里被算两次。常见做法是维护一个质心列表每帧新来的簇质心和已有质心做匹配匹配上就更新匹配不上就新建连续多帧没匹配上的质心就删除。下面这段 Python 是跨帧跟踪的简化实现# 维护一个跟踪列表每个元素是 (质心, 存活帧数) tracks [] MATCH_THRESHOLD 0.5 # 质心匹配距离阈值单位米 MAX_MISS 5 # 连续多少帧没匹配上就删除 def update_tracks(new_centroids): global tracks matched set() for i, centroid in enumerate(new_centroids): best_idx -1 best_dist MATCH_THRESHOLD for j, (track_centroid, _) in enumerate(tracks): dist np.linalg.norm(np.array(centroid) - np.array(track_centroid)) if dist best_dist: best_dist dist best_idx j if best_idx 0: tracks[best_idx] (centroid, 0) matched.add(i) else: tracks.append((centroid, 0)) # 未匹配的跟踪目标存活帧数加一超限删除 tracks [(c, miss 1) for c, miss in tracks if miss 1 MAX_MISS] return len(tracks)逻辑说明每帧拿新簇质心和已有跟踪目标匹配匹配上就更新位置匹配不上就新建跟踪。参数说明MATCH_THRESHOLD决定多近算同一个人设太大人会合并设太小同一个人会分裂MAX_MISS决定目标消失多久才删除设太小人数会闪断设太大离开的人会被一直计数。注意这两个参数和 DBSCAN 的 eps 是联动的调的时候要一起看单独调一个往往按下葫芦浮起瓢。4. lab0011-pplcount 避坑与常见问题排查4.1 点云稀疏到无法聚类现象数据口有数据但解析出来的点云每帧只有几个点DBSCAN 聚不出任何簇人数一直是 0。原因chirp 配置里的发射功率或检测阈值设得太保守或者 CFAR 的虚警率设得太低导致大部分真实目标被当成噪声滤掉了。解决先把 CFAR 的虚警率调高一点让点云“脏”一些确认能看到人形点云后再逐步收紧。不要一上来就追求干净点云干净和漏检往往是一回事。4.2 人数虚高一个人被拆成多个簇现象场景里只有一个人但人数输出是 3 或 4。原因DBSCAN 的 eps 设得太小或者点云在角度维度上分散同一个人的点被分到多个簇。解决先把 eps 从 0.3 逐步加到 0.6 甚至 0.8观察人数是否收敛到 1。如果加了 eps 还是虚高检查角度分辨率是不是太差考虑增加接收天线数量或调整虚拟阵列配置。注意eps 加大会增加相邻人被合并的风险所以要在“拆”和“合”之间找平衡点。4.3 人数虚低两个人被合并成一个簇现象场景里两个人站得比较近人数输出一直是 1。原因eps 设得太大或者两个人的点云在距离-角度平面上本来就分不开。解决先确认雷达的距离分辨率和角度分辨率是否足够如果两个人间距小于分辨率极限任何聚类算法都无能为力这是物理限制。如果分辨率够就减小 eps同时提高 minPts让簇更紧凑。常见做法是把 minPts 从 3 提到 5配合较小的 eps能在一定程度上分开相邻目标。4.4 人数在真实值上下跳变现象人数输出不稳定一会儿 2 一会儿 3没有明显规律。原因跨帧跟踪的匹配阈值和存活帧数没调好或者帧周期太短导致点云累积不够。解决先把帧周期从 50ms 加到 100ms给点云更多累积时间然后调 MATCH_THRESHOLD让同一个人跨帧能稳定匹配上最后调 MAX_MISS让短暂漏检不会导致目标被删除。这三个参数要一起调单独调一个往往解决不了问题。4.5 烧录后板子无响应现象bin 烧进去了但重新上电后配置口没反应发命令不回。原因烧录的 bin 和板子型号不匹配或者烧录模式没退出干净。解决确认 bin 文件名里带的型号和你的板子一致重新进烧录模式擦除再写一次写完断电等几秒再上电。如果还是不行换一根 USB 线有些线只供电不传数据这个坑很隐蔽我遇到过好几次。5. 进阶调参让 lab0011-pplcount 在真实场景里稳下来5.1 用录制数据做离线回归测试真实场景调参最怕的就是“现场调好换个场景又不行”。我的习惯是在几个典型场景里各录一段点云数据存成 CSV然后在 PC 上跑离线聚类和跟踪用同一套参数去测所有场景。这样调出来的参数泛化性更好也方便做回归测试。录制的时候要记录真实人数作为标签离线跑完算准确率准确率低于 90% 的参数直接淘汰。下面这段 Python 是离线批量测试的框架import glob import numpy as np from sklearn.cluster import DBSCAN def count_people(points, eps0.5, min_pts3): labels DBSCAN(epseps, min_samplesmin_pts).fit(points).labels_ return len(set(labels)) - (1 if -1 in labels else 0) # 遍历所有录制场景每个场景一个 CSV文件名里带真实人数 for filepath in glob.glob(recordings/*.csv): true_count int(filepath.split(_)[-1].split(.)[0]) points np.loadtxt(filepath, delimiter,) pred_count count_people(points) print(f场景 {filepath}: 真实 {true_count}, 预测 {pred_count})逻辑说明这段代码把每个录制场景跑一遍聚类输出预测人数和真实人数的对比。参数说明eps和min_pts是你要扫的变量可以写两层循环做网格搜索。注意离线测试用的点云要和在线跑的时候同源否则参数迁移会失效。这个框架搭起来之后调参效率会高很多不用每次都去现场。5.2 多帧投票代替单帧输出单帧聚类的结果受噪声影响大工程上更稳的做法是多帧投票。具体是维护一个长度为 N 的滑动窗口每帧的聚类人数放进窗口输出窗口里的众数。N 一般取 5 到 10太小了投票没效果太大了响应迟钝。这个技巧在人数统计里特别管用能把跳变压下去代价是人数变化时会有几百毫秒的延迟看你能不能接受。5.3 参数敏感度排序与调参顺序调参最忌讳一把抓。我的经验是按敏感度排序先调 chirp 配置里的斜率和帧周期这两个决定了点云的质量上限再调 CFAR 的虚警率决定点云的密度然后调 DBSCAN 的 eps 和 minPts决定聚类效果最后调跨帧跟踪的匹配阈值和存活帧数决定输出稳定性。顺序反了的话前面没调好后面怎么调都是白费。下面这张表是我常用的参数范围和影响方向供你起步参考参数典型范围调大后的影响调小后的影响chirp 斜率30-70 MHz/us距离分辨率变好最大距离变小最大距离变大分辨率变差帧周期50-100 ms点云累积多响应变慢响应快点云稀疏CFAR 虚警率1e-3 到 1e-5点云变多噪声也变多点云变干净漏检增加DBSCAN eps0.3-0.8 m簇变大相邻人易合并簇变小一个人易拆分DBSCAN minPts3-8簇更紧凑小目标被滤掉小目标保留噪声簇增加跟踪匹配阈值0.3-0.8 m同一个人易匹配不同人易混不同人易分开同一个人易断这张表不是标准答案是起点。每个场景的电磁环境、人的密度、走动速度都不一样最终参数一定要在真实场景里微调。我自己的习惯是每次换场景先跑一遍默认参数看人数输出和真实值的偏差方向偏高了就往“合”的方向调偏低了就往“拆”的方向调一般两三轮就能收敛。最后说一个我踩过的坑有一次在会议室场景调好了参数搬到电梯轿厢里直接翻车人数一直虚高。后来发现是轿厢金属壁多径反射严重点云里多了很多虚假簇。解决办法是在聚类前加一层基于信噪比的过滤把低信噪比的点先剔掉再聚类。这个经验告诉我毫米波雷达的参数没有一劳永逸换环境就得重新看数据。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑