🍓 第十四章 AIoT 实验范例:Node-RED+TensorFlow.js
📄 一句话概括

不写一行代码,把 COCO-SSD 拖上画布:Webcam 拍一张、tensorflowCoco 认一遍、Debug 报结果——80 类物体随手点名。

📝 本节和前面几节的关系

14-1 讲了 TF.js 是什么、14-2 把四件套装好并验证了消息格式;本节把它们拼成第一个完整实验。它和 11-5 的 YOLO 是同一任务的 JS 版:11-5 要写 Python 循环读帧+画框,本节全部工作只是连三根线、调一个阈值——工具换了,任务没换。

一、COCO-SSD 是什么货色

COCO-SSD 是 Google 发布的轻量物体检测模型(TF.js Models 家族成员):

和 11-5 的 YOLO 对位:YOLO 也是单阶段检测器(名 home 里的【you only look once】与【single shot】是同一个思路的两种实现),输入一张图、输出一批 {class, score, bbox}——两个模型输出结构一模一样,只是宿主语言和喂图方式不同。

二、最小可用流:三根线

按 14-2 装好四件套后,在画布上摆三个节点连线:

[Webcam] → [tensorflowCoco] → [Debug]
  1. Webcam:来自 dashboard 类别。部署后打开 dashboard 页面(13-5 的 /ui,装了新版则是 /dashboard),点拍照按钮输出一张 jpeg;
  2. tensorflowCoco:配置里 scoreThreshold 先保持默认 0.5,passthru 选 bbox(把原图连同框一起传下去,方便接 image 节点看图);
  3. Debug:完整消息模式,看输出数组。

点 Webcam 拍照后,Debug 面板出现:

[{"class":"person","score":0.91,"bbox":[98,30,352,470]},
 {"class":"cup","score":0.63,"bbox":[420,390,90,120]}]

想看带框的图,再从 tensorflowCoco 拉一根线到 image 节点(14-2 四件套之一)——框会直接画在图上,验收效果一目了然。

三、阈值调优:0.5 不是圣旨

scoreThreshold 决定【多像才算】:检出太少是漏检(阈值偏高),杂草都认成猫是误检(阈值偏低)。调优口诀:

这些数值没有理论最优,以自己场景的实测为准——每次调完拍同样几张图对比输出数量,比拍脑袋快得多。

四、它是【拍一张认一张】,不是监控视频流

这里要掰正一个从 12-5 带过来的惯性:TFLite 那节是【while 循环读帧、逐帧实时识别】。COCO-SSD 节点在树莓派上的实际节奏是事件驱动——每收到一条消息(一张图)推理一次,单次推理常要一到几秒(tfjs-node 在 ARM 上并不快)。

所以正确用法是【定时拍一张 → 认一次 → 有结果再行动】,而不是幻想 30 FPS 实时监控。想让节点稳定工作:

五、动手 Demo:人员检测提醒器

把识别结果变成动作——检测到 person 就在 dashboard 报字:

[Webcam] → [tensorflowCoco] → [Switch] ─(person)→ [Change] → [Text(dashboard)]
                              └────────────────→ [Debug]

配置三处:

  1. Switch:按 JSONata/消息属性分流,条件取 payload[].class 包含 person(用【数值/属性】规则,遍历数组匹配字符串 person);
  2. Change:设置 msg.payload 为固定文本【有人在镜头前】;
  3. Text:dashboard 组里建一个 text 元素,部署后 dashboard 页面直接显示。

看到什么算成功:镜头前没人时 Text 为空;有人入镜后一拍内(几秒级)dashboard 跳出【有人在镜头前】,同时 Debug 里的数组出现 class:"person" 的元素。

读结果:Switch 只挑 person 这一类做动作,其余类别走 Debug 观察不触发提醒——【识别】和【对识别结果做业务判断】在画布上是两个节点,各司其职。想接继电器开关灯?把 Text 换成 13-4 以后的 Python 桥(HTTP/MQTT 触发 gpiozero)即可,13 章的老结论【Pi 5 上别用 GPIO 节点】原样有效。

30 秒实验

同一个摄像头画面,把 scoreThreshold 依次改成 0.3 和 0.8(改完要重新部署),各拍一张同样的照片对比 Debug 输出:

六、常见误区

  1. COCO-SSD 能认出我家猫叫什么名字 —— 它只认 80 类里的【cat】这个通用类别;认【是不是你家那只】要靠 14-4 的自训练模型。
  2. 部署完第一拍没反应是装坏了 —— 模型首次加载要数秒,先等再拍;报错才回头查 14-2 的重编步骤。
  3. 把 Repeat 设成 0.1 秒就能做实时监控 —— 树莓派上单次推理就是秒级,消息会越积越多把机器压垮;事件驱动的【每 5~10 秒拍一张】才是这台机器的节奏。
  4. 阈值调好了就一劳永逸 —— 光线、角度、距离一变,阈值全部要重调;它是一次实验参数,不是一个常数。
自测三问(点开对答案) 1. COCO-SSD 的输出数组每个元素长什么样? `{class: 类别名, score: 0~1 置信度, bbox: [x, y, 宽, 高]}`——和 11-5 YOLO 的输出结构同构。 2. 安防报警和人数统计,阈值分别往哪边调? 报警类调低(0.3~0.4,宁多报不漏报);统计类调高(0.6~0.7,只留有把握的)。 3. 检测到人之后想开灯,在树莓派上应该怎么接? 识别节点触发消息后经 HTTP/MQTT 交给 Python+gpiozero 做开关——Pi 5 上 GPIO 节点已随底层库退场(13-4 结论)。

相关笔记