Node-RED 图像处理
Node-RED 图像处理
本节介绍如何在 Node-RED 中接收、处理和显示来自 ESP32-CAM 的图片。学习完成后,您将能够:
- 在 Node-RED 中安装和配置图片显示节点
- 接收 MQTT 传输的二进制图片数据
- 将图片保存到服务器文件系统
- 在 Dashboard 中实时显示监控画面
┌─────────────────────────────────────────────────────────────┐│ Node-RED 图片处理流程 │├─────────────────────────────────────────────────────────────┤│ ││ [MQTT In: esp32cam/photo] ││ │ ││ ├──→ [Function: 转换格式] ││ │ │ ││ │ ├──→ [Image Output: 显示预览] ││ │ │ ││ │ ├──→ [Write File: 保存到服务器] ││ │ │ ││ │ └──→ [Function: 切片处理/Dashboard 输出] ││ │ ││ [MQTT In: esp32cam/photo_meta] ││ │ ││ └──→ [Function: 记录元数据] → [Debug] ││ │└─────────────────────────────────────────────────────────────┘- 已完成 11-04. Photo Capture via MQTT
- 已完成 11-07. MQTT Image Transmission
- Node-RED 已安装并可访问 Palette 管理界面
- Docker 环境中 Node-RED 数据卷已持久化
Step 1: Install Image Display Node
Section titled “Step 1: Install Image Display Node”在 Node-RED 中安装图片输出节点:
# 通过 Node-RED Palette 管理界面安装# 菜单 → Manage Palette → Install → 搜索 "node-red-contrib-image-output"# 点击 Install
# 或通过命令行安装 (Docker 环境)docker exec -it nodered npm install node-red-contrib-image-output安装完成后,左侧 Palette 将出现新的 image 节点(位于 output 分类下)。
Step 2: Receive and Display Binary Image
Section titled “Step 2: Receive and Display Binary Image”Node-RED 流程
Section titled “Node-RED 流程”[MQTT In: esp32cam/photo] ──→ [image: 显示图片] ──→ [debug]MQTT In 节点配置
Section titled “MQTT In 节点配置”| 参数 | 值 |
|---|---|
| Topic | esp32cam/photo |
| QoS | 1 |
| Output | a parsed JSON object (默认) |
注意: 即使图片是二进制数据,MQTT In 节点仍能接收。Node-RED 自动处理二进制 payload,将其作为 Buffer 对象传递。
Image Output 节点配置
Section titled “Image Output 节点配置”无需特殊配置,只需将 MQTT In 的输出连接到 Image Output 节点即可自动渲染图片。
部署后触发 ESP32-CAM 拍照,Image 节点将显示:
┌────────────────┐│ [Image] ││ ┌──────────┐ ││ │ │ ││ │ 照片 │ ││ │ 预览 │ ││ │ │ ││ └──────────┘ ││ ││ Size: 32.5KB ││ 2026-05-18 │└────────────────┘Step 3: Save Image to Server
Section titled “Step 3: Save Image to Server”为了持久保存图片(供后续推送通知或归档),使用 Write File 节点:
Node-RED 流程
Section titled “Node-RED 流程”[MQTT In: esp32cam/photo] ──→ [Function: 设置文件名] ──→ [Write File: 保存]Function 节点配置
Section titled “Function 节点配置”// Function: 设置文件保存参数// 为图片文件生成带时间戳的文件名
var filePath = "/data/esp32cam/photo_" + Date.now() + ".jpg";
// 可以改为覆盖模式,只保留最新一张// var filePath = "/data/esp32cam/latest.jpg";
msg.filename = filePath;msg.payload = msg.payload; // 保持二进制数据不变
return msg;Write File 节点配置
Section titled “Write File 节点配置”| 参数 | 值 |
|---|---|
| Filename | msg.filename (由 Function 节点设置) |
| Action | overwrite file (或 append to file) |
| Create directory if needed | ✅ 勾选 |
Docker 数据持久化验证
Section titled “Docker 数据持久化验证”# 进入 Node-RED Docker 容器docker exec -it nodered ls -la /data/esp32cam/
# 输出示例:# -rw-r--r-- 1 node-red node-red 33280 May 18 14:30:25 photo_1716013825000.jpg# -rw-r--r-- 1 node-red node-red 28901 May 18 14:35:12 photo_1716014112000.jpg
# 查看最新图片docker exec -it nodered cat /data/esp32cam/latest.jpg > ~/latest_photo.jpgopen ~/latest_photo.jpgStep 4: Node-RED Dashboard Integration
Section titled “Step 4: Node-RED Dashboard Integration”将图片显示集成到 Node-RED Dashboard:
安装 Dashboard 节点
Section titled “安装 Dashboard 节点”# 如果尚未安装npm install node-red-dashboard# 或通过 Palette 搜索安装Dashboard 流程配置
Section titled “Dashboard 流程配置”[MQTT In: esp32cam/photo] │ ├──→ [Function: 编码为 base64] │ │ │ └──→ [ui_template: 显示图片] │ └──→ [Function: 提取元数据] │ └──→ [ui_text: 状态信息]ui_template HTML 模板
Section titled “ui_template HTML 模板”<!-- ui_template: ESP32-CAM 图片显示 --><div style="text-align: center; padding: 10px;"> <img id="camImage" src="data:image/jpeg;base64,{{msg.payload}}" style="max-width: 100%; border-radius: 8px; box-shadow: 0 4px 8px rgba(0,0,0,0.2);"> <p style="color: #666; font-size: 12px; margin-top: 5px;"> 最后更新: {{msg.topic}} </p></div>Function 节点 - Base64 编码
Section titled “Function 节点 - Base64 编码”// Function: 将二进制 Buffer 编码为 Base64 字符串// 供 ui_template 显示
// msg.payload 是二进制 Buffermsg.payload = msg.payload.toString('base64');
// 附加元数据msg.topic = new Date().toLocaleString();
return msg;Dashboard 布局示例:
┌──────────────────────────────────────────────┐│ 📷 远程巡检 - 实时监控 │├──────────────────────────────────────────────┤│ ││ ┌──────────────────────────────────────┐ ││ │ │ ││ │ ESP32-CAM 实时画面 │ ││ │ │ ││ │ │ ││ └──────────────────────────────────────┘ ││ ││ 📊 状态: 在线 📸 上次拍照: 14:30:25 ││ 📏 照片大小: 32.5 KB ││ ││ [📷 拍照] [💡 闪光灯] [⏰ 定时 30分] ││ │└──────────────────────────────────────────────┘Step 5: Periodic Cleanup
Section titled “Step 5: Periodic Cleanup”为避免服务器磁盘空间被图片占满,添加定时清理机制:
// Function: 定时清理旧图片// 由 Inject 节点每小时触发
var fs = require('fs');var path = '/data/esp32cam/';var maxAge = 7 * 24 * 60 * 60 * 1000; // 7 天var now = Date.now();var deleted = 0;
try { var files = fs.readdirSync(path); files.forEach(function(file) { var filePath = path + file; var stats = fs.statSync(filePath); if (now - stats.mtimeMs > maxAge) { fs.unlinkSync(filePath); deleted++; node.warn("Deleted old photo: " + file); } }); msg.payload = "Cleaned up " + deleted + " old photos";} catch (e) { msg.payload = "Cleanup error: " + e.message;}
return msg;# Inject 节点配置# 定时: cron 表达式 "0 * * * *" (每小时整点)# 1. 触发拍照mosquitto_pub -t "esp32cam/command" -m "take_photo"
# 2. 检查 Node-RED Image 节点是否显示图片# 3. 检查文件系统docker exec -it nodered ls -la /data/esp32cam/
# 4. 检查 Dashboard 是否更新# 打开浏览器访问 http://<node-red-ip>:1880/ui
# 5. 测试定时清理mosquitto_pub -t "esp32cam/command" -m "cleanup"Common Customer Questions
Section titled “Common Customer Questions”Q1: 图片在 Node-RED 中显示模糊?
Section titled “Q1: 图片在 Node-RED 中显示模糊?”原因: MQTT 传输的 JPEG 质量设置过低,或分辨率太小。
解决方案: 调整 ESP32 的 JPEG 质量参数:
// 在 ESP32 摄像头配置中调整config.jpeg_quality = 12; // 默认 12 (0-63, 越小质量越好)config.frame_size = FRAMESIZE_VGA; // 640×480// 或使用 FRAMESIZE_SVGA (800×600), FRAMESIZE_XGA (1024×768)Q2: Node-RED 接收图片时内存不足?
Section titled “Q2: Node-RED 接收图片时内存不足?”场景: 频繁拍照导致 Node-RED 内存持续增长。
解决方案:
- 增加 Node-RED 的
--max-old-space-size参数 - 限制图片分辨率不超过 VGA
- 增加拍照间隔(至少 10 秒)
# docker-compose.yml 中调整 Node-RED 内存services: nodered: image: nodered/node-red:latest environment: - NODE_OPTIONS=--max-old-space-size=256Q3: 如何保存多张图片而不是覆盖?
Section titled “Q3: 如何保存多张图片而不是覆盖?”修改 Function 节点,使用计数器或随机数生成文件名:
// 使用时间戳 + 随机数var filePath = "/data/esp32cam/photo_" + Date.now() + "_" + Math.random().toString(36).substr(2, 5) + ".jpg";✅ 推荐做法:
- 使用独立的 Topic 传输图片数据和元数据
- Image Output 节点配合 Debug 节点排查传输问题
- 图片文件按日期分目录存储 (
/data/esp32cam/2026/05/18/) - 定期清理 7 天前的历史图片
- Dashboard 中使用 Base64 内联显示而非文件 URL
❌ 避免做法:
- 在 Function 节点中对大图片进行 JSON 序列化
- 不限制图片保存数量导致磁盘占满
- 多个图片节点共用相同的文件名
- 直接在 Dashboard 中显示超过 500KB 的大图
Summary
Section titled “Summary”- node-red-contrib-image-output 可直接显示 MQTT 传输的二进制图片
- Write File 节点将图片持久化到服务器文件系统
- Dashboard UI Template 通过 Base64 编码显示最新监控画面
- 定时清理机制防止磁盘空间被历史图片占满
- 图片分辨率和质量在 ESP32 端控制
References
Section titled “References”
正在开发商业 IoT 产品?
我们提供 ESP32 ODM 定制设计与制造服务。从原型到量产——编写这套教程的团队,可以和你一起实现。
联系我们 →