ESP32-S3 TinyML 实战:离线语音唤醒、视觉检测与端侧小智能体

引言:边缘智能体正在从“能跑模型”变成“能做闭环” 过去几年,端侧 AI 的讨论大多停留在模型能不能塞进设备:摄像头能不能跑目标检测,MCU 能不能跑唤醒词,工业网关能不能离线识别异常。到了 2025 和 2026 年,问题已经变了。现在更值得关心的是:设备能否在本地理解环境、调用工具、管理状态,并在网络不稳定甚至完全离线时完成一个业务闭环。 这也是边缘硬件和 AI Agent 结合后最有价值的地方。真正落地时,模型只是其中一层,摄像头、麦克风、传感器、NPU、DSP、缓存、队列、OTA、日志和安全策略都会影响最终效果。如果只把注意力放在参数量和 TOPS 上,很容易做出一个演示很好看、现场不稳定的系统。 本文关注的主题是 把 ESP32-S3 当作常开感知节点,用低功耗语音、低帧率视觉和本地规则 Agent 完成离线闭环。 它不是简单地把云端大模型搬到开发板上,而是围绕功耗、内存、实时性、隐私、硬件加速和工程可维护性重新设计一套端侧智能系统。 端侧智能体参考架构 输入设备Camera / MicSensor / Bus 预处理ISP / DSP滤波 / 特征 模型推理NPU / GPUINT8 / Cache Agent 决策状态 / 工具策略 / 记忆 设备执行GPIO / UARTMQTT / CAN 云端同步日志 / OTA模型更新 从传感输入到动作反馈,端侧 Agent 需要处理的不只是模型推理。 一、先把系统边界画清楚 边缘 Agent 与普通边缘推理最大的区别,是它要处理“感知—判断—动作—反馈”这条链路。一个只会输出分类结果的模型,通常只需要输入张量和输出张量;一个能工作的端侧智能体,还需要记住最近发生了什么、知道哪些工具可以调用、判断什么时候应该上报云端,以及在失败时如何降级。 ...

June 4, 2026 · 2 min · 👁️ 0 · Tech Snippets

OpenCV 光流法原理与实战指南:从 Lucas-Kanade 到稠密光流

前言 在计算机视觉的众多技术中,光流法(Optical Flow)可以说是最古老也最具生命力的算法之一。从 1950 年代心理学家 Gibson 首次提出视觉运动感知理论,到 1981 年 Lucas 和 Kanade 发表那篇经典论文,再到今天深度学习时代的 RAFT、GMFlow 等现代光流网络,这项技术已经走过了半个多世纪的历程。 我第一次接触光流法是在大学的计算机视觉课程上。当时教授在黑板上写下那个著名的光流方程 Iₓu + Iᵧv + Iₜ = 0,然后告诉我们:“这个简单的方程,蕴含了理解运动的全部秘密。” 那时候我还不太理解这句话的含义,直到后来在实际项目中用它实现了一个简单的视频目标跟踪系统,才真正体会到光流法的强大之处。 在今天的边缘计算和嵌入式 AI 场景中,光流法依然占据着不可替代的地位。相比于深度学习的目标跟踪算法,传统光流法具有以下优势: 计算量小:不需要复杂的神经网络,可以在资源受限的嵌入式设备上实时运行 无需训练:不需要标注数据,开箱即用 实时性好:很多优化后的实现可以轻松达到 30 FPS 以上 适用范围广:从无人机的视觉导航,到视频防抖,再到动作识别,光流法无处不在 本文将带您从零开始深入理解光流法的原理,从最基本的亮度恒定假设,到经典的 Lucas-Kanade 算法,再到 OpenCV 中的各种光流法实现。我们会通过大量代码示例,让您不仅理解理论,更能在实际项目中应用这项技术。 一、什么是光流法? 1.1 光流的定义 简单来说,光流就是空间中运动物体在成像平面上像素运动的瞬时速度。当你盯着窗外行驶的汽车时,视网膜上汽车图像的移动速度就是光流。 更正式的定义是:给定图像序列 I(x, y, t),光流法的目标是为每个像素点 (x, y) 找到一个速度向量 (u, v),使得: I ( x , y , t ) = I ( x + u · d t , y + v · d t , t + d t ) 这个等式表达的就是:经过微小的时间间隔 dt 后,像素点 (x, y) 移动到了 (x + u·dt, y + v·dt),而亮度保持不变。 ...

May 22, 2026 · 9 min · 👁️ 0 · Tech Snippets

MediaPipe 实时手势识别与动作追踪完整实战指南

前言 在人机交互技术不断演进的今天,手势识别作为一种自然、直观的交互方式,正在从实验室走向实际应用。从智能电视的手势操控,到 VR/AR 的手部追踪,再到工业场景中的无接触控制,手势识别正在改变我们与数字世界互动的方式。 然而,手势识别技术的落地面临着诸多挑战:复杂的光照环境、多变的手部姿态、不同的肤色差异、实时性要求……这些问题让很多开发者望而却步。直到 Google 推出了 MediaPipe —— 一个跨平台的机器学习应用框架,让高精度的实时手势识别变得触手可及。 MediaPipe 最令人惊叹的地方在于它的平衡艺术:在保持毫秒级延迟的同时,能够稳定检测出手部的 21 个三维关键点,即使在普通手机上也能流畅运行。这种性能与精度的完美平衡,让 MediaPipe 成为了手势识别领域的事实标准。 本文将从零开始,系统地讲解如何使用 MediaPipe 构建一套完整的手势识别系统。我们不仅会讲解基础的关键点检测,还会深入到静态手势分类、动态动作追踪、性能优化、移动端部署等高级主题。无论你是想做一个简单的手势控制小项目,还是开发专业的人机交互产品,这篇文章都能为你提供实用的指导。 一、为什么选择 MediaPipe? 在开始实战之前,我们首先要回答一个问题:市面上有这么多手势识别方案,为什么要选择 MediaPipe? 1.1 真正的跨平台一致性 很多开源项目只针对特定平台优化,换个设备性能就急剧下降。MediaPipe 的设计理念是"一次开发,处处运行": 移动端:Android 和 iOS 原生支持,针对手机 NPU 进行了深度优化 桌面端:Windows、macOS、Linux 全平台支持 Web 端:通过 WebAssembly 直接在浏览器中运行 边缘端:支持 Raspberry Pi、Jetson Nano 等嵌入式设备 更重要的是,在所有平台上,MediaPipe 输出的关键点格式完全一致,算法逻辑可以无缝迁移。 1.2 令人难以置信的性能 让我们来看一组实际测试数据(单帧处理时间): 设备 CPU 模式 GPU/NPU 加速 iPhone 15 Pro 2.3ms 0.8ms 骁龙 8 Gen 3 3.1ms 1.2ms Intel i7-13700K 1.8ms 0.6ms Raspberry Pi 4B 28ms - 即使在 Raspberry Pi 这种资源受限的设备上,MediaPipe 也能达到约 35 FPS 的处理速度,这在以前是无法想象的。 ...

May 16, 2026 · 8 min · 👁️ 0 · Tech Snippets

基于 OpenCV 的红色物体识别与多目标跟踪实战

前言 在计算机视觉领域,颜色检测是最基础也最实用的技术之一。红色作为一种醒目的颜色,在交通标志、安全警示、工业自动化等场景中应用广泛。今天我们来深入探讨如何用 OpenCV 实现红色物体的识别,并在此基础上实现多目标跟踪功能。 这篇文章不是简单的 API 调用演示,而是从原理出发,结合实际场景中的问题,一步步构建一个健壮的检测与跟踪系统。我们会遇到光照变化、噪声干扰、部分遮挡等实际问题,然后逐一解决。 一、为什么选择 HSV 颜色空间? 当我们谈论颜色检测时,很多新手第一反应是直接在 RGB 图像上做阈值处理。比如,红色物体的 R 通道值比较高,那么我们设定一个阈值,只保留 R > 200 的像素。但实际一试就会发现,这种方法效果非常差。 问题出在哪里?RGB 颜色空间虽然直观,但它把亮度和颜色信息混在一起了。同一个红色物体,在强光下和阴影下,RGB 值可能差异巨大,但人眼感知到的颜色其实是一样的。这就导致基于 RGB 的阈值检测非常不稳定。 这时候 HSV 颜色空间就派上用场了。HSV 把颜色信息分解成三个独立的通道: H (Hue, 色调):表示颜色的种类,取值范围在 OpenCV 中是 0-179 S (Saturation, 饱和度):表示颜色的鲜艳程度,0-255 V (Value, 明度):表示颜色的明亮程度,0-255 HSV 的优势在于,颜色信息主要由 H 通道决定,而 V 通道单独控制亮度。这意味着,即使光线变化导致 V 值波动,只要 H 值在我们设定的红色范围内,我们仍然能稳定地检测到目标。 二、红色在 HSV 空间中的特殊性 红色有个有意思的特性:它在色相环的两端都有分布。在标准的 0-360 度色相环中,红色出现在 0 度附近和 360 度附近。OpenCV 为了用 8 位表示,把这个范围减半成了 0-179,所以红色就分布在 0-10 和 170-179 这两个区间。 ...

April 23, 2026 · 6 min · 👁️ 3 · Tech Snippets

实时检测指定颜色和形状的物体:算法方案对比与实现

引言 在工业检测、机器人视觉、智能分拣等应用场景中,我们经常需要实时检测特定颜色和形状的物体。例如: 冰壶比赛自动计分系统:检测冰面上的圆形冰壶 工业零件分拣:检测红色圆形螺丝、蓝色方形螺母 自动驾驶交通标志识别:检测圆形红圈禁令标志 AGV 小车导航:识别地面彩色圆形二维码 本文将从简单到复杂,介绍几种常见的实现方案,对比它们的性能,并提供完整的开源参考代码,帮助你根据实际场景选择最合适的方案。 方案对比总览 我们主要对比四种主流方案: 方案 原理 计算量 准确率 适合场景 MCU 能否运行 颜色分割 + 轮廓检测 阈值分割 + 形状分析 极低 对颜色形状变化敏感 背景简单、光照稳定 ✅ Cortex-M7 可以 颜色空间转换 + Hough 变换 Hough 圆/直线检测 低 圆形检测较好 固定形状检测 ✅ Cortex-M4 可以 Blob 分析 + 特征匹配 连通域分析 + 形状分类 中 中等 多目标批量处理 ✅ Cortex-M7 可以 深度学习目标检测 YOLO/SSD 直接检测 高 鲁棒性强 复杂背景、光照变化 ❌ 需要 MCU+NPU 或 Linux 下面详细介绍每种方案的实现。 方案一:颜色分割 + 轮廓检测 1.1 算法流程 原始图像 RGB/BGR 颜色空间转换 RGB → HSV 颜色阈值分割 二值掩码 形态学处理 腐蚀 + 膨胀 查找轮廓 cv2.findContours 形状特征计算 面积、周长、圆形度 输出:符合颜色和形状要求的目标 颜色分割 + 轮廓检测流程图 1.2 核心原理 颜色空间转换:从 RGB 转到 HSV 颜色空间,更容易按颜色分割 阈值分割:对 H/S/V 三个通道设置范围,得到二值掩码 形态学处理:腐蚀 + 膨胀去除噪声 轮廓查找:找到所有连通区域 形状特征计算:计算面积、周长、圆形度、矩形度等特征 特征匹配:筛选符合指定形状的目标 1.3 完整 Python 实现 import cv2 import numpy as np def detect_color_shape( image, color_lower=np.array([0, 120, 70]), color_upper=np.array([10, 255, 255]), shape_type="circle", min_area=100, max_area=10000, circularity_threshold=0.8, aspect_ratio_range=(0.9, 1.1) ): """ 检测指定颜色和形状的物体 参数: image: 输入 RGB/BGR 图像 color_lower: HSV 颜色下限 color_upper: HSV 颜色上限 shape_type: "circle" / "square" / "rectangle" min_area: 最小面积(像素) max_area: 最大面积(像素) circularity_threshold: 圆形度阈值(0~1,越大越圆) aspect_ratio_range: 宽高比范围(方形接近 1) 返回: detections: 检测结果列表 [(x, y, w, h, contour), ...] mask: 颜色分割掩码(用于调试) """ # 1. 颜色空间转换:BGR → HSV hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # 2. 颜色阈值分割 mask = cv2.inRange(hsv, color_lower, color_upper) # 3. 形态学处理去除噪声 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) # 4. 查找轮廓 contours, hierarchy = cv2.findContours( mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE ) detections = [] for contour in contours: # 计算轮廓面积,过滤太小/太大的 area = cv2.contourArea(contour) if area < min_area or area > max_area: continue # 计算轮廓周长 perimeter = cv2.arcLength(contour, True) # 多边形逼近 approx = cv2.approxPolyDP(contour, 0.04 * perimeter, True) # 获取外接矩形 x, y, w, h = cv2.boundingRect(contour) # 形状判断 matched = False if shape_type == "circle": # 圆形度 = 4π * 面积 / (周长^2) # 完美圆形 = 1,越不规则值越小 circularity = 4 * np.pi * area / (perimeter * perimeter) if circularity >= circularity_threshold: matched = True elif shape_type == "square": # 宽高比接近 1,且顶点数约为 4 aspect_ratio = float(w) / h if (len(approx) == 4 and aspect_ratio >= aspect_ratio_range[0] and aspect_ratio <= aspect_ratio_range[1]): matched = True elif shape_type == "rectangle": # 顶点数约为 4 即可 if len(approx) == 4: matched = True elif shape_type == "triangle": if len(approx) == 3: matched = True if matched: center_x = x + w // 2 center_y = y + h // 2 detections.append((center_x, center_y, w, h, contour)) return detections, mask 1.4 使用示例 # 检测红色圆形物体 # HSV 红色范围(两种分段,因为红色在 H 通道首尾) lower_red1 = np.array([0, 120, 70]) upper_red1 = np.array([10, 255, 255]) lower_red2 = np.array([170, 120, 70]) upper_red2 = np.array([180, 255, 255]) # 读取图像 image = cv2.imread("test_image.jpg") # 第一次检测 detections1, mask1 = detect_color_shape( image, lower_red1, upper_red1, shape_type="circle", min_area=500 ) # 第二次检测(另一红色区间) detections2, mask2 = detect_color_shape( image, lower_red2, upper_red2, shape_type="circle", min_area=500 ) # 合并结果 all_detections = detections1 + detections2 combined_mask = mask1 | mask2 # 在原图上绘制结果 for (x, y, w, h, contour) in all_detections: cv2.drawContours(image, [contour], -1, (0, 255, 0), 2) cv2.circle(image, (x, y), 3, (0, 0, 255), -1) cv2.putText(image, "Red Circle", (x-20, y-h-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) cv2.imwrite("result.jpg", image) print(f"检测到 {len(all_detections)} 个红色圆形物体") 1.5 常见颜色 HSV 范围参考 颜色 H 下限 H 上限 S 下限 S 上限 V 下限 V 上限 红色 0/170 10/180 120 255 70 255 橙色 11 25 120 255 70 255 黄色 26 35 120 255 70 255 绿色 36 70 120 255 70 255 青色 71 99 120 255 70 255 蓝色 100 124 120 255 70 255 紫色 125 155 120 255 70 255 粉色 156 169 120 255 70 255 黑色 0 180 0 255 0 46 灰色 0 180 0 43 47 221 白色 0 180 0 30 222 255 注意:不同相机的白平衡和亮度设置不同,实际使用时需要根据你的图像微调范围。建议用 OpenCV 窗口滑动条调参: ...

April 15, 2026 · 8 min · 👁️ 3 · Tech Snippets