译者:飞龙
协议:CC BY-NC-SA 4.0>
-
学习率:0.0005
-
验证大小:20%
因此,我们的训练结果如下:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file573.png
模型配置文件预测233 KB 的 RAM 和 546 KB 的闪存,这表明 Xiao ESP32S3 没有问题,它有 8 MB 的 PSRAM。此外,工作室表明延迟约为 1160 ms,这非常高。然而,这是可以预料的,因为我们正在使用 ESP-EYE,其 CPU 是 Extensa LX6,而 ESP32S3 使用的是更新、更强大的 Xtensa LX7。
使用测试数据,我们甚至实现了 100%的准确率,即使是在量化 INT8 模型的情况下。这个结果在真实项目中并不典型,但我们的项目相对简单,只有两个彼此非常不同的对象。
模型部署
我们可以部署训练好的模型:
-
作为
.TFLITE用于SenseCraft AI -
作为Edge Impulse Studio中的
Arduino 库。
让我们从更简单、更直观的 SenseCraft 开始。
在 SenseCraft AI 上的模型部署
在仪表板上,你可以以几种不同的格式下载训练好的模型。让我们下载TensorFlow Lite (int8 量化),其大小为 623KB。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file574.png
在SenseCraft AI Studio中,转到工作区标签,选择XIAO ESP32S3,相应的端口,并连接设备。
你应该能看到最后上传到设备上的模型。选择绿色按钮 [上传模型]。一个弹出窗口将提示你输入模型名称、模型文件和类名(对象)。我们应该使用按字母顺序排列的标签:0: background,1: box,和2: wheel,然后按 [发送]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file575.png
几秒钟后,模型将被上传(闪存)到我们的设备,相机图像将实时出现在 预览 区域。分类结果将在图像预览下方显示。您还可以使用 设置 中的光标选择推理的 置信度阈值。
在 设备日志 中,我们可以查看串行监视器,其中可以观察到延迟,预处理大约为 81 毫秒,推理大约为 205 毫秒,对应于每秒 3.4 帧(FPS)的帧率,这是我们使用 SenseCraft 训练模型时得到的两倍,因为我们正在处理更小的图像(96x96 与 224x224)。
总延迟大约比在 Xtensa LX6 CPU 上 Edge Impulse Studio 中的估计快 4 倍;现在我们在 Xtensa LX7 CPU 上进行推理。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file576.png
后处理
可以获取模型推理的输出,包括延迟、类别 ID 和置信度,如 SenseCraft AI 的设备日志中所示。这使我们能够将 XIAO ESP32S3 感应器 作为 AI 传感器使用。换句话说,我们可以根据项目需求使用不同的通信协议,如 MQTT、UART、I2C 或 SPI 来检索模型数据。
这个想法与我们之前在 Seeed Grove Vision AI V2 图像分类后处理实验室 中所做的是类似的。
下面是使用 I2C 总线的连接示例。
请参阅 Seeed Studio Wiki 获取更多信息。
在 EI Studio 中将模型部署为 Arduino 库
在 Edge Impulse Studio 的 部署 部分选择 Arduino 库、TensorFlow Lite、量化(int8) 并按 [构建]。训练好的模型将以 .zip Arduino 库的形式下载:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file577.png
打开你的 Arduino IDE,在 草图 下,转到 包含库 并 添加 .ZIP 库。然后,选择从 Edge Impulse Studio 下载的文件并按 [打开]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file578.png
前往 Arduino IDE 的 示例,根据其名称查找项目(在本例中为:“Box_versus_Whell_…Interfering”。打开 esp32 -> esp32_camera。esp32_camera.ino 草图将被下载到 IDE。
这个草图是为标准 ESP32 开发的,与 XIAO ESP32S3 感应器不兼容。需要进行修改。让我们从项目的 GitHub 下载修改后的版本:Image_class_XIAOML-Kit.ino。
XIAO ESP32S3 图像分类代码解释
代码从板上摄像头捕获图像,处理它们,并使用 EI Studio 上的训练模型对它们进行分类(在这种情况下,“Box”,“Wheel”或“Background”)。它持续运行,在边缘设备上执行实时推理。
简而言之:
摄像头 → JPEG 图像 → RGB888 转换 → 调整大小到 96x96 → 神经网络 → 分类结果 → 串行输出
关键组件
- 库包含和依赖项
#include <Box_versus_Wheel_-_XIAO_ESP32S3_inferencing.h>
#include "edge-impulse-sdk/dsp/image/image.hpp"
#include "esp_camera.h"
-
Edge Impulse 推理库:包含我们的训练模型和推理引擎
-
图像处理:提供图像操作功能
-
ESP Camera:摄像头模块的硬件接口
- 摄像头引脚配置
XIAO ESP32S3 Sense 可以与不同的摄像头传感器(OV2640 或 OV3660)一起工作,这些传感器可能具有不同的引脚配置。代码定义了三种可能的配置:
// Configuration 1: Most common OV2640 configuration
#define CONFIG_1_XCLK_GPIO_NUM 10
#define CONFIG_1_SIOD_GPIO_NUM 40
#define CONFIG_1_SIOC_GPIO_NUM 39
// ... more pins
这种灵活性允许代码在第一个引脚映射不工作的情况下自动尝试不同的引脚映射,使其在不同硬件版本上更具鲁棒性。
- 内存管理设置
#define EI_CAMERA_RAW_FRAME_BUFFER_COLS 320
#define EI_CAMERA_RAW_FRAME_BUFFER_ROWS 240
#define EI_CLASSIFIER_ALLOCATION_HEAP 1
-
帧缓冲区大小:定义原始图像大小(320x240 像素)
-
堆分配:使用动态内存分配以提供灵活性
-
PSRAM 支持:ESP32S3 有 8MB 的 PSRAM 用于存储大型数据,如图像
setup() - 初始化
void setup() {
Serial.begin(115200);
while (!Serial);
if (ei_camera_init() == false) {
ei_printf("Failed to initialize Camera!\r\n");
} else {
ei_printf("Camera initialized\r\n");
}
ei_sleep(2000); // Wait 2 seconds before starting
}
此函数:
-
初始化串行通信以进行调试输出
-
使用自动配置检测初始化摄像头
-
在开始连续推理前等待 2 秒
loop() - 主处理循环
循环持续执行以下步骤:
第 1 步:内存分配
snapshot_buf = (uint8_t*)ps_malloc(EI_CAMERA_RAW_FRAME_BUFFER_COLS *
EI_CAMERA_RAW_FRAME_BUFFER_ROWS *
EI_CAMERA_FRAME_BYTE_SIZE);
为图像缓冲区分配内存,优先使用 PSRAM(更快的外部 RAM),如果需要则回退到常规堆。
第 2 步:图像捕获
if (ei_camera_capture((size_t)EI_CLASSIFIER_INPUT_WIDTH,
(size_t)EI_CLASSIFIER_INPUT_HEIGHT,
snapshot_buf) == false) {
ei_printf("Failed to capture image\r\n");
free(snapshot_buf);
return;
}
从摄像头捕获图像并将其存储在缓冲区中。
第 3 步:运行推理
ei_impulse_result_t result = { 0 };
EI_IMPULSE_ERROR err = run_classifier(&signal, &result, false);
在捕获的图像上运行机器学习模型。
第 4 步:输出结果
for (uint16_t i = 0; i < EI_CLASSIFIER_LABEL_COUNT; i++) {
ei_printf(" %s: %.5f\r\n",
ei_classifier_inferencing_categories[i],
result.classification[i].value);
}
打印分类结果,显示每个类别的置信度分数。
ei_camera_init() - 智能摄像头初始化
此函数实现了一个智能初始化序列:
bool ei_camera_init(void) {
// Try Configuration 1 (OV2640 common)
update_camera_config(1);
esp_err_t err = esp_camera_init(&camera_config);
if (err == ESP_OK) goto camera_init_success;
// Try Configuration 2 (OV3660)
esp_camera_deinit();
update_camera_config(2);
err = esp_camera_init(&camera_config);
if (err == ESP_OK) goto camera_init_success;
// Continue trying other configurations...
}
该函数:
-
尝试多种引脚配置
-
测试不同的时钟频率(10MHz 或 16MHz)
-
首先尝试 PSRAM,然后回退到 DRAM
-
根据检测到的硬件应用传感器特定设置
ei_camera_capture() - 图像处理管道
bool ei_camera_capture(uint32_t img_width, uint32_t img_height, uint8_t *out_buf) {
// 1\. Get frame from camera
camera_fb_t *fb = esp_camera_fb_get();
// 2\. Convert JPEG to RGB888 format
bool converted = fmt2rgb888(fb->buf, fb->len, PIXFORMAT_JPEG, snapshot_buf);
// 3\. Return frame buffer to camera driver
esp_camera_fb_return(fb);
// 4\. Resize if needed
if (do_resize) {
ei::image::processing::crop_and_interpolate_rgb888(...);
}
}
此函数:
-
从摄像头捕获 JPEG 图像
-
将其转换为 RGB888 格式(ML 模型所需)
-
将图像调整大小以匹配模型的输入大小(96x96 像素)
推理
- 将代码上传到 XIAO ESP32S3 Sense。
⚠️ 注意
- Xiao ESP32S3 必须启用 PSRAM。您可以在 Arduino IDE 的上级菜单中检查它:
工具–>PSRAM:OPI PSRAM
- Arduino 板包(
esp32 by Espressif Systems)应为版本 2.017。请勿更新
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file579.png
-
打开串行监视器
-
将摄像头对准物体,并在串行监视器上检查结果。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file580.png
后处理
在边缘人工智能应用中,推理结果的价值仅取决于我们对其采取行动的能力。虽然串行输出提供了详细的调试和开发信息,但现实世界的部署需要立即、人类可读的反馈,这种反馈不依赖于外部监视器或连接。
XIAOML Kit 0.42” OLED 显示屏(72×40 像素)作为关键的后处理组件,将原始机器学习推理结果转换为即时、人类可读的反馈——直接在设备上显示检测到的类别名称和置信度,消除了对外部监视器的需求,并使工业、农业或零售环境中的独立边缘人工智能部署成为可能,在这些环境中,对人工智能预测的即时视觉确认至关重要。
因此,让我们修改草图以自动适应在 Edge Impulse 上训练的模型,通过直接从模型中读取类别名称和计数。显示屏将显示缩写后的类别名称(3 个字母),字体较大,以便在小型 72x40 像素显示屏上获得更好的可见性。从 GitHub 下载代码:XIAOML-Kit-Img_Class_OLED_Gen。
运行代码,我们可以看到结果:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file581.png
摘要
XIAO ESP32S3 Sense 是一个令人印象深刻的、灵活的平台,适用于图像分类应用。通过这个实验室,我们探索了两种不同的开发方法,以满足不同的技能水平和项目需求。
-
SenseCraft AI Studio 提供了一个易于访问的入口,其 无代码界面 允许快速原型设计和部署预训练模型,如人体检测。通过实时推理和集成后处理功能,它展示了如何在不进行大量编程或机器学习知识的情况下部署人工智能。
-
对于更高级的应用,Edge Impulse Studio 提供了全面的机器学习管道工具,包括自定义数据集管理、与多个预训练模型(如 MobileNet)的迁移学习以及模型优化。
本实验室的关键见解包括图像分辨率权衡的重要性、迁移学习在小数据集上的有效性以及边缘人工智能部署的实际考虑,例如功耗和内存限制。
该实验室展示了超越特定硬件的 TinyML 基本原理:资源受限的推理、实时处理需求以及从数据收集到模型部署再到实际应用的完整流程。内置的后处理功能包括 GPIO 控制、通信协议等,XIAO 不仅是一个推理引擎,还成为了一个完整的 AI 传感器平台。
这个图像分类的基础知识将为你准备更复杂的计算机视觉任务,同时展示了现代边缘人工智能如何使复杂的计算机视觉变得可访问、成本效益高,并且能够在从工业自动化到智能家居系统等现实世界的嵌入式应用中部署。
资源
目标检测
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file582.png
DALL·E 提示 - 以 1950 年代动画风格的卡通,展示一个带有传感器的详细板,特别是相机,放在带有图案布料的桌子上。板子后面,一台带有大型背板的计算机展示了 Arduino IDE。IDE 的内容暗示了 LED 引脚分配和用于检测语音命令的机器学习推理。在独立的窗口中,串行监视器显示了“是”和“否”命令的输出。
概述
在关于计算机视觉(CV)和 XIAO ESP32S3 的最后一节中,我们学习了如何使用这款卓越的开发板设置和分类图像。继续我们的 CV 之旅,我们将探索微控制器上的 目标检测。
目标检测与图像分类的比较
对于图像分类模型来说,主要任务是识别图像上最可能存在的对象类别,例如,在猫和狗之间进行分类,图像中的主要“对象”:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file583.jpg
但如果图像中没有主导类别会发生什么呢?
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file584.png
图像分类模型将上述图像完全错误地识别为“灰桶”,可能是由于色彩色调的原因。
之前图像中使用的模型是 MobileNet,它使用大型数据集 ImageNet 进行训练,在 Raspberry Pi 上运行。
为了解决这个问题,我们需要另一种类型的模型,其中不仅 可以找到多个类别(或标签),而且还可以确定对象在给定图像中的 位置。
如我们所想,这样的模型要复杂得多,体积也更大,例如,MobileNetV2 SSD FPN-Lite 320x320,使用 COCO 数据集进行训练。这个预训练的目标检测模型旨在在一幅图像中定位多达 10 个对象,并为每个检测到的对象输出一个边界框。下面是这样一个模型在 Raspberry Pi 上运行的结果:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file585.png
用于目标检测的模型(如 MobileNet SSD 或 YOLO)通常有数 MB 的大小,这对于与 Raspberry Pi 一起使用是可以的,但用于嵌入式设备则不合适,因为嵌入式设备的 RAM 通常最多只有几 MB,就像 XIAO ESP32S3 的情况一样。
目标检测的创新解决方案:FOMO
Edge Impulse 于 2022 年推出,FOMO(更快的目标,更多目标),这是一种在嵌入式设备上执行目标检测的新颖解决方案,例如 Nicla Vision 和 Portenta(Cortex M7),在 Cortex M4F CPU(Arduino Nano33 和 OpenMV M4 系列)以及 Espressif ESP32 设备(ESP-CAM、ESP-EYE 和 XIAO ESP32S3 Sense)上。
在这个动手项目中,我们将探索使用 FOMO 进行目标检测。
要了解有关 FOMO 的更多信息,您可以访问 Edge Impulse 的 官方 FOMO 宣布,其中 Louis Moreau 和 Mat Kelcey 详细解释了它是如何工作的。
对象检测项目目标
所有机器学习项目都需要从详细的目标开始。让我们假设我们在一个工业或农村设施中,必须对 橙子(水果) 和特定的 青蛙(虫子) 进行分类和计数。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file586.png
换句话说,我们应该执行多标签分类,其中每张图像可以有三个类别:
-
背景(无对象)
-
水果
-
虫子
这里有一些未标记的图像样本,我们应该使用它们来检测对象(水果和虫子):
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file587.jpg
我们对图像中的哪个对象感兴趣,它的位置(质心),以及我们能在上面找到多少个。与 MobileNet SSD 或 YOLO 一样,FOMO 不检测对象的大小,其中边界框是模型输出之一。
我们将使用 XIAO ESP32S3 开发项目以进行图像捕获和模型推理。机器学习项目将使用 Edge Impulse Studio 开发。但在 Studio 中开始对象检测项目之前,让我们创建一个 原始数据集(未标记)包含要检测的对象的图像。
数据收集
您可以使用 XIAO、您的手机或其他设备捕获图像。在这里,我们将使用 XIAO 和来自 Arduino IDE ESP32 库的代码。
使用 XIAO ESP32S3 收集数据集
打开 Arduino IDE 并选择 XIAO_ESP32S3 板(以及它连接的端口)。在 文件 > 示例 > ESP32 > Camera 中选择 CameraWebServer。
在 板管理器 面板中,确认您已安装最新的“稳定”包。
⚠️ 注意
Alpha 版本(例如,3.x-alpha)与 XIAO 和 Edge Impulse 不兼容。请使用最后一个稳定版本(例如,2.0.11)。
您还应该注释掉所有相机模型,除了 XIAO 模型引脚:
#define CAMERA_MODEL_XIAO_ESP32S3 // 有 PSRAM
在 工具 中启用 PSRAM。输入您的 Wi-Fi 凭据并将代码上传到设备:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file588.jpg
如果代码执行正确,你应该在串行监视器中看到地址:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file589.png
在浏览器中复制地址并等待页面上传。选择相机分辨率(例如,QVGA)并选择 [开始流]。根据您的连接等待几秒钟/几分钟。您可以使用 [保存] 按钮将图像保存到您的计算机下载区域。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file590.jpg
Edge Impulse 建议对象应该大小相似且不重叠,以便获得更好的性能。在工业设施中这是可以的,因为相机应该固定,保持与要检测的对象相同的距离。尽管如此,我们也会尝试使用不同大小和位置来查看结果。
我们不需要为我们的图片创建单独的文件夹,因为每个都包含多个标签。
我们建议使用大约 50 张图片来混合物体并改变场景中每个物体出现的数量。尽量捕捉不同的角度、背景和光照条件。
存储的图片使用 QVGA 帧大小320×240320\times 240和 RGB565(颜色像素格式)。
在捕获您的数据集后,点击[停止流]并将您的图片移动到一个文件夹中。
Edge Impulse Studio
设置项目
前往Edge Impulse Studio,在登录处输入您的凭据(或创建一个账户),并开始一个新的项目。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file591.png
在这里,您可以克隆为这个动手实践开发的工程:XIAO-ESP32S3-Sense-Object_Detection
在您的项目仪表板上,向下滚动到项目信息,并选择边界框(目标检测)和Espressif ESP-EYE(与我们板最相似)作为您的目标设备:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file592.png
上传未标记的数据
在工作室中,转到“数据采集”标签,在“上传数据”部分,从您的计算机上传作为文件夹捕获的文件。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file593.png
您可以让工作室自动在训练和测试之间分割您的数据,或者手动进行。我们将上传所有这些作为训练数据。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file594.png
所有未标记的图片(47 张)已上传,但在用作项目数据集之前必须适当标记。工作室有一个用于此目的的工具,您可以在链接“标记队列(47)”中找到。
您可以使用两种方式在 Edge Impulse Studio(免费版)上执行 AI 辅助标记:
-
使用 yolov5
-
跟踪帧间物体
Edge Impulse 为企业客户推出了自动标记功能,简化了目标检测项目中的标记任务。
普通物体可以快速识别和标记,使用 YOLOv5(使用 COCO 数据集训练)现有的预训练目标检测模型库。但由于在我们的情况下,物体不是 COCO 数据集的一部分,我们应该选择跟踪物体的选项。使用此选项,一旦在一个帧中绘制边界框并标记图片,物体将自动从帧到帧跟踪,部分标记新的物体(并非所有都正确标记)。
如果您已经有一个包含边界框的标记数据集,可以使用EI 上传器导入您的数据。
标记数据集
从您未标记数据的第一个图像开始,使用鼠标拖动一个框围绕一个对象以添加标签。然后点击保存标签以进入下一个项目。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file595.png
继续此过程,直到队列清空。最后,所有图像都应该像以下样本那样标记了对象:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file596.jpg
接下来,在“数据采集”标签页上查看标记的样本。如果其中一个标签错误,您可以在样本名称后面的三个点菜单中编辑它:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file597.png
您将被引导替换错误的标签并纠正数据集。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file598.jpg
平衡数据集和分割训练/测试
标记所有数据后,发现水果类别比虫子类别的样本多得多。因此,收集了 11 张新的额外虫子图像(总计 58 张)。标记它们后,是时候选择一些图像并将它们移动到测试数据集了。您可以在图像名称后面的三个点菜单中完成此操作。我选择了 6 张图像,占总数据集的 13%。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file599.png
冲击设计
在这个阶段,您应该定义如何:
-
预处理包括将单个图像从320×240320\times 240调整大小到96×9696\times 96并压缩它们(平方形式,不裁剪)。之后,图像从 RGB 转换为灰度。
-
设计一个模型,在这种情况下,“对象检测”。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file600.png
预处理整个数据集
在本节中,将颜色深度选为灰度,适用于与 FOMO 模型一起使用并保存参数。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file601.png
Studio 会自动移动到下一部分,生成特征,其中所有样本都将进行预处理,生成一个包含单个96×96×196\times 96\times 1图像或 9,216 个特征的数据库。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file602.png
特征探索器显示,在特征生成后,所有样本都表现出良好的分离。
一些样本似乎位于错误的空间中,但点击它们可以确认正确的标记。
模型设计、训练和测试
我们将使用 FOMO,这是一个基于 MobileNetV2(alpha 0.35)的对象检测模型,旨在将图像粗略分割为背景与感兴趣对象(在此处为框和轮)的网格。
FOMO 是一种创新的机器学习对象检测模型,与传统模型如 Mobilenet SSD 和 YOLOv5 相比,可以节省多达 30 倍的能量和内存。FOMO 可以在小于 200 KB RAM 的微控制器上运行。这之所以可能,是因为其他模型通过围绕对象绘制一个正方形(边界框)来计算对象的大小,而 FOMO 忽略了图像的大小,仅通过其质心坐标提供有关对象在图像中位置的信息。
FOMO 是如何工作的?
FOMO 将图像转换为灰度并使用 8 的因子将其划分为像素块。对于输入的96×9696\times 96,网格将是12×1212\times 12 (96/8=12)(96/8=12)。接下来,FOMO 将对每个像素块运行一个分类器,以计算其中每个像素块包含一个框或轮子的概率,并随后确定具有最高概率包含对象的区域(如果一个像素块没有对象,它将被分类为背景)。从最终区域的重叠部分,FOMO 提供了该区域质心的坐标(与图像尺寸相关)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file603.png
对于训练,我们应该选择一个预训练的模型。让我们使用FOMO(更快的目标,更多目标)MobileNetV2 0.35。此模型大约使用 250 KB 的 RAM 和 80 KB 的 ROM(闪存),非常适合我们的板。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file604.png
关于训练超参数,模型将使用以下参数进行训练:
-
迭代次数:60
-
批处理大小:32
-
学习率:0.001。
在训练期间的验证中,我们将保留 20%的数据集(validation_dataset)。对于剩余的 80%(train_dataset),我们将应用数据增强,这会随机翻转、改变图像的大小和亮度,并裁剪它们,从而在训练数据集上人工增加样本数量。
因此,该模型最终的整体 F1 分数为 85%,与使用测试数据(83%)的结果相似。
注意,FOMO 自动为之前定义的两个标签(框和轮子)添加了第三个标签背景。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file605.png
在目标检测任务中,准确率通常不是主要的评估指标。目标检测涉及对对象进行分类并在其周围提供边界框,这使得它比简单的分类更复杂。问题是我们没有边界框,只有质心。简而言之,使用准确率作为指标可能是误导性的,并且可能无法完全理解模型的性能。因此,我们将使用 F1 分数。
使用“实时分类”测试模型
一旦我们的模型训练完成,我们可以使用实时分类工具对其进行测试。在相应的部分,点击连接开发板图标(一个小型 MCU)并使用您的手机扫描二维码。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file606.png
连接后,您可以使用智能手机捕获实际图像,以便在 Edge Impulse Studio 上由训练模型进行测试。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file607.png
需要注意的是,该模型可能会产生误报和漏报。这可以通过定义合适的置信度阈值(使用三个点菜单进行设置)来最小化。尝试使用 0.8 或更高。
模型部署(Arduino IDE)
选择 Arduino 库和量化(int8)模型,在部署选项卡上启用 EON 编译器,然后按 [构建]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file608.png
打开您的 Arduino IDE,然后在“草图”下,转到“包含库”并添加.ZIP 库。选择您从 Edge Impulse Studio 下载的文件,然后完成操作!
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file609.png
在 Arduino IDE 的“示例”选项卡下,您应该在您的项目名称下找到名为 (esp32 > esp32_camera) 的草图代码。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file610.png
您应该更改 32 到 75 行,这些行定义了摄像头模型和引脚,使用与我们的模型相关的数据。复制并粘贴以下行,替换 32-75 行:
#define PWDN_GPIO_NUM -1
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 10
#define SIOD_GPIO_NUM 40
#define SIOC_GPIO_NUM 39
#define Y9_GPIO_NUM 48
#define Y8_GPIO_NUM 11
#define Y7_GPIO_NUM 12
#define Y6_GPIO_NUM 14
#define Y5_GPIO_NUM 16
#define Y4_GPIO_NUM 18
#define Y3_GPIO_NUM 17
#define Y2_GPIO_NUM 15
#define VSYNC_GPIO_NUM 38
#define HREF_GPIO_NUM 47
#define PCLK_GPIO_NUM 13
这里您可以查看生成的代码:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file611.png
将代码上传到您的 XIAO ESP32S3 Sense,然后您应该可以开始检测水果和昆虫。您可以在串行监视器中检查结果。
背景
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file612.png
水果
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file613.png
故障
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file614.png
注意,模型的延迟为 143 毫秒,每秒帧率约为 7 fps(与我们从图像分类项目中获得的类似)。这是因为 FOMO 是巧妙地建立在 CNN 模型之上,而不是像 SSD MobileNet 这样的目标检测模型。例如,当在 Raspberry Pi 4 上运行 MobileNetV2 SSD FPN-Lite 320×320320\times 320 模型时,延迟大约高五倍(大约 1.5 fps)。
模型部署(SenseCraft-Web-Toolkit)
如同在图像分类章节中讨论的那样,在 Arduino IDE 上验证图像模型的推理非常具有挑战性,因为我们无法看到摄像头聚焦在哪里。再次,让我们使用 SenseCraft-Web Toolkit。
按照以下步骤启动 SenseCraft-Web-Toolkit:
-
将 XIAO 连接到您的电脑:
- 连接好 XIAO 后,选择如下:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file615.jpg
- 选择设备/端口,然后按
[连接]:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file616.jpg
您可以尝试之前由 Seeed Studio 上传的几个计算机视觉模型。尝试它们并享受乐趣!
在我们的情况下,我们将使用页面底部的蓝色按钮:[上传自定义 AI 模型]。
但首先,我们必须从 Edge Impulse Studio 下载我们的 量化 .tflite 模型。
- 前往 Edge Impulse Studio 中的您的项目,或克隆此项目:
- 在
仪表板上,下载模型(“块输出”):Object Detection model - TensorFlow Lite (int8 quantized)
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file617.jpg
- 在 SenseCraft-Web-Toolkit 上,使用页面底部的蓝色按钮:
[上传自定义 AI 模型]。一个窗口将弹出。将你从 Edge Impulse Studio 下载到电脑上的模型文件输入,选择一个模型名称,并输入标签(ID: Object):
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file618.jpg
注意,你应该使用在 EI Studio 训练的标签,并按字母顺序输入它们(在我们的情况下,背景,虫子,水果)。
几秒钟(或几分钟)后,模型将上传到你的设备,相机图像将实时出现在预览区域:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file619.jpg
被检测到的对象将被标记(质心)。你可以选择你推理光标的置信度 Confidence 和 IoU,这是用来评估预测边界框与真实边界框准确性的。
点击顶部按钮(设备日志),你可以打开一个串行监视器来跟踪推理,就像我们在 Arduino IDE 中做的那样。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file620.png
在设备日志中,你将获得如下信息:
-
预处理时间(图像捕获和裁剪):3 毫秒,
-
推理时间(模型延迟):115 毫秒,
-
后处理时间(显示图像和标记对象):1 毫秒。
-
输出张量(框),例如,其中一个框:[[30,150, 20, 20,97, 2]];其中 30,150, 20, 20 是框的坐标(围绕质心);97 是推理结果,2 是类别(在这种情况下 2:水果)。
注意,在上面的例子中,我们得到了 5 个框,因为没有任何水果有 3 个质心。一个解决方案将是后处理,我们可以将接近的质心聚合为一个。
这里是其他截图:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file621.jpg
摘要
FOMO 是图像处理空间中的一个重大飞跃,正如路易斯·莫罗和马特·凯利在 2022 年发布时所说:
FOMO 是一个突破性的算法,首次将实时目标检测、跟踪和计数带到微控制器。
在嵌入式设备上探索目标检测(以及更精确地,计数它们)存在多种可能性。
资源
运动分类和异常检测
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file664.jpg
DALL·E 提示 - 1950 年代风格的卡通插图,场景设定在复古音频实验室。科学家们穿着经典的白色实验服,专注地分析大型黑板上的音频数据。黑板上显示着复杂的快速傅里叶变换(FFT)图和时间域曲线。复古音频设备散布四周,但数据表示清晰且详细,表明他们专注于音频分析。
概述
运输是全球贸易的支柱。每天通过各种方式,如船只、卡车和火车,将数百万个集装箱运往世界各地。确保这些集装箱的安全和高效运输是一项艰巨的任务,需要利用现代技术,而 TinyML 无疑是关键解决方案之一。
在这个动手实验室中,我们将解决与运输相关的真实世界问题。我们将使用 XIAOML 套件、Arduino IDE 和 Edge Impulse Studio 开发运动分类和异常检测系统。这个项目将帮助我们了解集装箱在运输的不同阶段(包括陆地和海上运输、通过叉车垂直移动以及仓库中的静止存储期)所经历的不同力和运动。
学习目标
-
设置 XIAOML 套件
-
数据收集和预处理
-
构建运动分类模型
-
实施异常检测
-
真实世界测试与分析
到这个实验室结束时,你将拥有一个可以分类不同类型运动并在集装箱运输过程中检测异常的工作原型。这些知识可以作为进入蓬勃发展的 TinyML 领域更高级项目的垫脚石,特别是那些涉及振动的项目。
安装 IMU
XIAOML 套件在扩展板上内置了 LSM6DS3TR-C 6 轴 IMU 传感器,消除了外部传感器连接的需求。这种集成方法提供了一个干净且可靠的平台,适用于基于运动的机器学习应用。
LSM6DS3TR-C 将 3 轴加速度计和 3 轴陀螺仪集成在一个封装中,通过 I2C 连接到 XIAO ESP32S3 的地址 0x6A,提供以下功能:
-
加速度计范围: ±2/±4/±8/±16 g (默认使用 ±2g)
-
陀螺仪范围: ±125/±250/±500/±1000/±2000 dps (默认使用 ±250 dps)
-
分辨率: 16 位 ADC
-
通信: 地址 0x6A 的 I2C 接口
-
功耗: 超低功耗设计
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file665.png
坐标系: 传感器在右手坐标系内运行。当你从底部(你可以看到带有标记点的 IMU 传感器)看扩展板时:
-
X 轴: 指向右侧
-
Y 轴: 指向前方(远离你)
-
Z 轴: 指向上方(出板外)
设置硬件
由于 XIAOML Kit 已预装了扩展板,因此不需要额外的硬件连接。LSM6DS3TR-C IMU 已经通过 I2C 正确连接。
已连接的内容:
-
LSM6DS3TR-C IMU → I2C(SDA/SCL)→ XIAO ESP32S3
-
I2C 地址:0x6A
-
电源:来自 XIAO ESP32S3 的 3.3V
所需库:您应该在设置过程中安装库。如果没有,请按照以下步骤安装 Seeed Arduino LSM6DS3 库:
-
打开 Arduino IDE 库管理器
-
搜索“LSM6DS3”
-
安装 Seeed Studio 的**“Seeed Arduino LSM6DS3”**
-
重要:不要安装“Arduino_LSM6DS3 by Arduino” - 那是针对不同板子的!
测试 IMU 传感器
让我们从一项简单的测试开始,以验证 IMU 是否正常工作。上传此代码以测试传感器:
#include <LSM6DS3.h>
#include <Wire.h>
// Create IMU object using I2C interface
LSM6DS3 myIMU(I2C_MODE, 0x6A);
float accelX, accelY, accelZ;
float gyroX, gyroY, gyroZ;
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("XIAOML Kit IMU Test");
Serial.println("LSM6DS3TR-C 6-Axis IMU");
Serial.println("====================");
// Initialize the IMU
if (myIMU.begin() != 0) {
Serial.println("ERROR: IMU initialization failed!");
while(1) delay(1000);
} else {
Serial.println("✓ IMU initialized successfully");
Serial.println("Data Format: AccelX,AccelY,AccelZ,"
"GyroX,GyroY,GyroZ");
Serial.println("Units: g-force, degrees/second");
Serial.println();
}
}
void loop() {
// Read accelerometer data (in g-force)
accelX = myIMU.readFloatAccelX();
accelY = myIMU.readFloatAccelY();
accelZ = myIMU.readFloatAccelZ();
// Read gyroscope data (in degrees per second)
gyroX = myIMU.readFloatGyroX();
gyroY = myIMU.readFloatGyroY();
gyroZ = myIMU.readFloatGyroZ();
// Print readable format
Serial.print("Accel (g): X="); Serial.print(accelX, 3);
Serial.print(" Y="); Serial.print(accelY, 3);
Serial.print(" Z="); Serial.print(accelZ, 3);
Serial.print(" | Gyro (°/s): X="); Serial.print(gyroX, 2);
Serial.print(" Y="); Serial.print(gyroY, 2);
Serial.print(" Z="); Serial.println(gyroZ, 2);
delay(100); // 10 Hz update rate
}
当套件平放在桌子上时,你应该看到:
-
Z 轴加速度约为+1.0g(重力)
-
X 和 Y 加速度接近 0.0g
-
所有陀螺仪值接近 0.0°/s
移动套件以查看相应值的变化。
TinyML 运动分类项目
我们将通过模拟各种场景来模拟集装箱(或更准确地说,包裹)的运输,使本教程更具相关性和实用性。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file666.jpg
使用 XIAOML Kit 的加速度计,我们将通过手动模拟以下条件来捕捉运动数据:
-
海事(船上的托盘)- 在所有轴向上以波浪状模式移动
-
地面(卡车/火车上的托盘)- 主要水平移动
-
提升(叉车移动的托盘)- 主要垂直移动
-
空闲(存储中的托盘)- 最小移动
从上面的图像中,我们可以为我们的模拟定义,主要水平移动(xx或yy轴)应与“地面类别”相关联。垂直移动(zz-轴)与“提升类别”相关联,没有活动与“空闲类别”相关联,所有三个轴上的移动到海事类别。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file667.jpg
数据收集
对于数据收集,我们有几个选项可供选择。在实际场景中,我们可以将我们的设备,例如,直接连接到一个容器上,并将收集到的数据存储在 SD 卡上的文件中(例如,CSV 文件)。数据也可以通过 Wi-Fi 或蓝牙(如本项目所示:Sensor DataLogger)远程发送到附近的存储库,如手机。一旦您的数据集收集并存储为.CSV 文件,就可以使用CSV 向导工具上传到工作室。
在这个视频中,你可以学习将数据发送到 Edge Impulse Studio 的替代方法。
准备数据收集代码
在这个实验室中,我们将直接将套件连接到 Edge Impulse Studio,它也将用于数据预处理、模型训练、测试和部署。
对于数据收集,我们首先应该将套件连接到 Edge Impulse Studio,它也将用于数据预处理、模型训练、测试和部署。
由于 XIAOML 套件不是 Edge Impulse 完全支持的开发板,例如,我们应该使用CLI 数据转发器来捕获我们的传感器数据并将其发送到 Studio,如图所示:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file668.jpg
我们将修改测试代码以输出适合 Edge Impulse 的数据格式:
#include <LSM6DS3.h>
#include <Wire.h>
#define FREQUENCY_HZ 50
#define INTERVAL_MS (1000 / (FREQUENCY_HZ + 1))
LSM6DS3 myIMU(I2C_MODE, 0x6A);
static unsigned long last_interval_ms = 0;
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("XIAOML Kit - Motion Data Collection");
Serial.println("LSM6DS3TR-C IMU Sensor");
// Initialize IMU
if (myIMU.begin() != 0) {
Serial.println("ERROR: IMU initialization failed!");
while(1) delay(1000);
}
delay(2000);
Serial.println("Starting data collection in 3 seconds...");
delay(3000);
}
void loop() {
if (millis() > last_interval_ms + INTERVAL_MS) {
last_interval_ms = millis();
// Read accelerometer data
float ax = myIMU.readFloatAccelX();
float ay = myIMU.readFloatAccelY();
float az = myIMU.readFloatAccelZ();
// Convert to m/s² (multiply by 9.81)
float ax_ms2 = ax * 9.81;
float ay_ms2 = ay * 9.81;
float az_ms2 = az * 9.81;
// Output in Edge Impulse format
Serial.print(ax_ms2);
Serial.print("\t");
Serial.print(ay_ms2);
Serial.print("\t");
Serial.println(az_ms2);
}
}
将代码上传到 Arduino IDE。我们应该在串行监视器中看到加速度计的值(转换为 m/s²):
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file669.png
保持代码运行,但关闭串行监视器。套件生成的数据将通过串行连接发送到 Edge Impulse Studio。
连接到 Edge Impulse 进行数据收集
创建 Edge Impulse 项目 - 前往 Edge Impulse Studio 并创建一个新的项目 - 选择一个描述性的名称(为了与 Arduino 库兼容,名称长度请保持在 63 个字符以内)
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file670.png
设置 CLI 数据转发器 - 在你的计算机上安装 Edge Impulse CLI - 确认 XIAOML 套件已连接到计算机,代码正在运行且串行监视器已关闭,否则我们可能会遇到错误。 - 在计算机终端运行:edge-impulse-data-forwarder --clean - 输入你的 Edge Impulse 凭据 - 选择你的项目并配置设备设置
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file671.png
- 前往 Edge Impulse Studio 项目。在“设备”部分可以验证套件是否正确连接(点应该是绿色的)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file672.png
在 Studio 进行数据收集
如前所述,我们应该从所有四个运输类别中捕获数据。想象一下,你有一个内置加速度计的容器(在这种情况下,我们的 XIAOML 套件)。现在想象你的容器在一艘船上,面对愤怒的大海:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file673.png
或者在一个卡车、在道路上行驶,或者被叉车移动等情况下。
运动模拟
海事类别:
-
持住套件并模拟船只运动
-
以波浪状、起伏的运动在三个轴上移动
-
包括轻微的滚动和俯仰运动
地面类别:
-
将套件沿直线水平移动(从左到右和相反方向)
-
通过小幅度的水平震动来模拟卡车/火车的振动
-
偶尔轻微的颠簸和转弯
提升类别:
-
主要在垂直方向上移动套件(上升和下降)
-
模拟叉车操作:上升,暂停,下降
-
包含一些短的水平定位运动
空闲类别:
-
将套件放置在稳定的表面上
-
最小或无运动
-
捕获环境振动和传感器噪声
数据采集
在 数据采集 部分,您应该看到您的板 [xiaoml-kit] 已连接。传感器可用: [具有 3 个轴(accX,accY,accZ)的传感器],采样频率为 [50 Hz]。工作室建议样本长度为 [10000] 毫秒(10 秒)。最后要做的就是定义样本标签。让我们从[陆地]开始。
按下 [开始采样] 并将您的套件水平移动(从左到右),保持在一个方向上。10 秒后,我们的数据将被上传到工作室。
下面是 10 秒收集数据的其中一个样本(原始数据)。值得注意的是,波动运动主要沿着 Y 轴(左右)发生。其他轴几乎处于静止状态(X 轴围绕零中心,Z 轴由于重力围绕 9.8 ms²中心)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file674.png
您应该为每个类别捕获大约 2 分钟(十个到十二个 10 秒的样本)。在每个样本之后使用“3 个点”,选择两个并将它们移动到测试集。或者,您可以使用仪表板标签页的危险区域上的自动训练/测试分割工具。下面,您可以看到结果数据集:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file675.png
数据预处理
加速度计捕获的原始数据类型是“时间序列”,应将其转换为“表格数据”。我们可以通过在样本数据上使用滑动窗口来完成此转换。例如,在下面的图中,
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file676.png
我们可以看到以 50 Hz 的采样率捕获的 10 秒加速度计数据。2 秒窗口将捕获 300 个数据点(3 轴 ×\times 2 秒 ×\times 50 个样本)。我们将每 200ms 滑动这个窗口,创建一个更大的数据集,其中每个实例都有 300 个原始特征。
您应该根据尼奎斯特定理使用最适合您情况的采样率,该定理指出,周期性信号必须以高于信号最高频率成分两倍以上的速率进行采样。
数据预处理是嵌入式机器学习的挑战领域。然而,Edge Impulse 通过其数字信号处理(DSP)预处理步骤以及更具体的频谱特征帮助克服这一挑战。
在 Studio 中,这个数据集将是频谱分析模块的输入,该模块非常适合分析重复运动,如加速度计的数据。此模块将执行 DSP(数字信号处理),提取“FFT”或“小波”等特征。在最常见的案例中,FFT,每个轴/通道的时域统计特征如下:
-
均方根
-
偏度
-
峰度
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file677.png
每个轴/通道的频域特征如下:
-
频谱功率
-
偏度
-
峰度
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file678.png
例如,对于 32 点的 FFT 长度,频谱分析模块的结果输出将是每个轴 21 个特征(总共 63 个特征)。
这 63 个特征将作为神经网络分类器和异常检测模型(K-Means)的输入张量。
您可以通过深入了解实验室的 DSP 频谱特征来了解更多信息。
模型设计
我们的分类器将是一个密集神经网络(DNN),其输入层将有 63 个神经元,两个隐藏层分别有 20 和 10 个神经元,以及一个输出层,有四个神经元(每个类别一个),如图所示:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file679.png
冲激设计
冲激从原始数据中提取特征,使用信号处理提取特征,然后使用学习模块(密集模型)对新数据进行分类。
我们还利用第二个模型,即K-means,它可以用于异常检测。如果我们想象我们的已知类别可以作为簇,那么任何无法适应这些簇的样本可能是一个异常值,一个异常(例如,在海洋上滚出船的集装箱或倒置在地面上)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file680.jpg
想象我们的 XIAOML 套件滚动或倒置移动,在一个与训练时不同的运动补全上。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file681.png
在最终的冲激设计下方:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file682.png
生成特征
在我们的项目这个阶段,我们已经定义了预处理方法,并且模型已经设计完成。现在,是时候完成任务了。首先,让我们将原始数据(时间序列类型)转换为表格数据。转到“频谱特征”标签并选择“[保存参数]”。或者,我们也可以选择“[自动调整参数]”按钮。在这种情况下,Studio 将根据原始数据定义新的超参数,如滤波器设计和 FFT 长度。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file683.png
在顶部菜单中,选择“生成特征”标签,然后在那里选择选项,“计算特征重要性”,“归一化特征”,然后按“[生成特征]”按钮。每个 2 秒的数据窗口(300 个数据点)将被转换成一个包含 63 个特征的单一表格数据点。
特征探索器将使用UMAP(均匀流形近似和投影)在 2D 中显示这些数据。UMAP 是一种降维技术,可用于可视化,类似于 t-SNE,但也可以用于一般的非线性降维。
可视化使得人们可以验证这些类别表现出优秀的分离,这表明分类器应该表现良好。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file684.png
可选地,你可以分析每个特征相对于其他类别的相对重要性。
训练
我们的分类器将是一个密集神经网络(DNN),其输入层将有 63 个神经元,两个隐藏层分别有 20 和 10 个神经元,输出层有四个神经元(每个类别一个),如图所示:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file685.png
作为超参数,我们将使用学习率 0.005 和 20%的数据进行验证,持续 30 个 epoch。训练后,我们可以看到准确率为 100%。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file686.png
对于异常检测,我们应该选择建议的特征,这些特征正是特征提取中最重要的一部分。簇的数量将是 32,如工作室所建议。训练后,我们可以选择一些数据进行测试,例如海洋数据。得到的异常分数为min: -0.1642, max: 0.0738, avg: -0.0867。
当更改数据时,可能会发现小的或负的异常分数表明数据是正常的。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file687.png
测试
使用在数据捕获阶段留下的 20%的数据,我们可以验证我们的模型在未知数据上的表现;如果不是 100%(预期的结果),结果仍然非常好(8%)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file688.png
你还应该使用你的套件(仍然连接到工作室)并执行一些实时分类。例如,让我们测试一些“地面”运动:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file689.png
注意,在这里,你将使用你的设备捕获真实数据并将其上传到工作室,在那里将使用训练好的模型进行推理(注意模型不在你的设备上)。
部署
现在是时候施展魔法了!工作室将打包所有需要的库、预处理函数和训练好的模型,并将它们下载到你的电脑上。你应该选择 Arduino 库选项,然后在底部选择量化(Int8),然后点击“[构建]”。将创建一个 ZIP 文件并下载到你的电脑上。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file690.png
在你的 Arduino IDE 中,转到“草图”选项卡,选择添加.ZIP 库的选项,并选择由工作室下载的.zip 文件:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file691.png
推理
现在,是时候进行真正的测试了。我们将进行与工作室完全断开的推理。让我们更改在部署 Arduino 库时创建的一个代码示例。
在你的 Arduino IDE 中,转到“文件/示例”选项卡,找到你的项目,在示例中,选择nano_ble_sense_accelerometer:
当然,这不是你的板子,但我们可以通过仅做少量修改使代码工作。
例如,在代码的开头,你有与 Arduino Sense IMU 相关的库:
/* Includes -------------------------------------------- */
#include <XIAOML_Kit_Motion_Class_-_AD_inferencing.h>
#include <Arduino_LSM9DS1.h>
将与 IMU 相关的代码部分“includes”进行修改:
#include <XIAOML_Kit_Motion_Class_-_AD_inferencing.h>
#include <LSM6DS3.h>
#include <Wire.h>
修改常量定义
// IMU setup
LSM6DS3 myIMU(I2C_MODE, 0x6A);
// Inference settings
#define CONVERT_G_TO_MS2 9.81f
#define MAX_ACCEPTED_RANGE 2.0f * CONVERT_G_TO_MS2
在设置函数中,初始化 IMU:
// Initialize IMU
if (myIMU.begin() != 0) {
Serial.println("ERROR: IMU initialization failed!");
return;
}
在循环函数中,缓冲区 buffer[ix]、buffer[ix + 1]和 buffer[ix + 2]将接收加速度计捕获的 3 轴数据。在原始代码中,你有以下行:
IMU.readAcceleration(buffer[ix], buffer[ix + 1], buffer[ix + 2]);
用以下代码块替换它:
// Read IMU data
float x = myIMU.readFloatAccelX();
float y = myIMU.readFloatAccelY();
float z = myIMU.readFloatAccelZ();
你应该重新排列以下两个代码块。首先,将原始数据转换为“每平方秒米(m/s²)”,然后进行关于最大接受范围的测试(在这里是 m/s²,但在 Arduino 上是 Gs):
// Convert to m/s²
buffer[i + 0] = x * CONVERT_G_TO_MS2;
buffer[i + 1] = y * CONVERT_G_TO_MS2;
buffer[i + 2] = z * CONVERT_G_TO_MS2;
// Apply range limiting
for (int j = 0; j < 3; j++) {
if (fabs(buffer[i + j]) > MAX_ACCEPTED_RANGE) {
buffer[i + j] = copysign(MAX_ACCEPTED_RANGE, buffer[i + j]);
}
}
而且这就足够了。我们还可以调整在串行监视器中显示推理的方式。你现在可以上传下面的完整代码到你的设备上,并继续进行推理。
// Motion Classification with LSM6DS3TR-C IMU
#include <XIAOML_Kit_Motion_Class_-_AD_inferencing.h>
#include <LSM6DS3.h>
#include <Wire.h>
// IMU setup
LSM6DS3 myIMU(I2C_MODE, 0x6A);
// Inference settings
#define CONVERT_G_TO_MS2 9.81f
#define MAX_ACCEPTED_RANGE 2.0f * CONVERT_G_TO_MS2
static bool debug_nn = false;
static float buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE] = { 0 };
static float inference_buffer[EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE];
void setup() {
Serial.begin(115200);
while (!Serial) delay(10);
Serial.println("XIAOML Kit - Motion Classification");
Serial.println("LSM6DS3TR-C IMU Inference");
// Initialize IMU
if (myIMU.begin() != 0) {
Serial.println("ERROR: IMU initialization failed!");
return;
}
Serial.println("✓ IMU initialized");
if (EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME != 3) {
Serial.println("ERROR: EI_CLASSIFIER_RAW_SAMPLES_PER_FRAME"
"should be 3");
return;
}
Serial.println("✓ Model loaded");
Serial.println("Starting motion classification...");
}
void loop() {
ei_printf("\nStarting inferencing in 2 seconds...\n");
delay(2000);
ei_printf("Sampling...\n");
// Clear buffer
for (size_t i = 0; i < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; i++) {
buffer[i] = 0.0f;
}
// Collect accelerometer data
for (int i = 0; i < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; i += 3) {
uint64_t next_tick = micros() +
(EI_CLASSIFIER_INTERVAL_MS * 1000);
// Read IMU data
float x = myIMU.readFloatAccelX();
float y = myIMU.readFloatAccelY();
float z = myIMU.readFloatAccelZ();
// Convert to m/s²
buffer[i + 0] = x * CONVERT_G_TO_MS2;
buffer[i + 1] = y * CONVERT_G_TO_MS2;
buffer[i + 2] = z * CONVERT_G_TO_MS2;
// Apply range limiting
for (int j = 0; j < 3; j++) {
if (fabs(buffer[i + j]) > MAX_ACCEPTED_RANGE) {
buffer[i + j] = copysign(MAX_ACCEPTED_RANGE,
buffer[i + j]);
}
}
delayMicroseconds(next_tick - micros());
}
// Copy to inference buffer
for (int i = 0; i < EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE; i++) {
inference_buffer[i] = buffer[i];
}
// Create signal from buffer
signal_t signal;
int err = numpy::signal_from_buffer(inference_buffer,
EI_CLASSIFIER_DSP_INPUT_FRAME_SIZE, &signal);
if (err != 0) {
ei_printf("ERROR: Failed to create signal from buffer (%d)\n",
err);
return;
}
// Run the classifier
ei_impulse_result_t result = { 0 };
err = run_classifier(&signal, &result, debug_nn);
if (err != EI_IMPULSE_OK) {
ei_printf("ERROR: Failed to run classifier (%d)\n", err);
return;
}
// Print predictions
ei_printf("Predictions (DSP: %d ms, Classification: %d ms, "
"Anomaly: %d ms):\n",
result.timing.dsp, result.timing.classification, result.timing.anomaly);
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
ei_printf(" %s: %.5f\n", result.classification[ix].label,
result.classification[ix].value);
}
// Print anomaly score
#if EI_CLASSIFIER_HAS_ANOMALY == 1
ei_printf("Anomaly score: %.3f\n", result.anomaly);
#endif
// Determine prediction
float max_confidence = 0.0;
String predicted_class = "unknown";
for (size_t ix = 0; ix < EI_CLASSIFIER_LABEL_COUNT; ix++) {
if (result.classification[ix].value > max_confidence) {
max_confidence = result.classification[ix].value;
predicted_class = String(result.classification[ix].label);
}
}
// Display result with confidence threshold
if (max_confidence > 0.6) {
ei_printf("\n🎯 PREDICTION: %s (%.1f%% confidence)\n",
predicted_class.c_str(), max_confidence * 100);
} else {
ei_printf("\n❓ UNCERTAIN: Highest confidence is %s (%.1f%%)\n",
predicted_class.c_str(), max_confidence * 100);
}
// Check for anomaly
#if EI_CLASSIFIER_HAS_ANOMALY == 1
if (result.anomaly > 0.5) {
ei_printf("⚠️ ANOMALY DETECTED! Score: %.3f\n", result.anomaly);
}
#endif
delay(1000);
}
void ei_printf(const char *format, ...) {
static char print_buf[1024] = { 0 };
va_list args;
va_start(args, format);
int r = vsnprintf(print_buf, sizeof(print_buf), format, args);
va_end(args);
if (r > 0) {
Serial.write(print_buf);
}
}
完整的代码可在实验室的 GitHub上找到
现在你应该尝试你的动作,查看每个类别的推理结果在图像上的显示:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file692.png
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file693.png
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file694.png
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file695.png
当然,还有一些“异常”,例如将 XIAO 倒置。异常分数将超过 0.5:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file696.png
后处理
既然我们知道模型正在工作,我们建议修改代码以查看套件完全离线(断开与 PC 的连接,由电池、移动电源或独立的 5V 电源供电)的结果。
理念是如果检测到特定的动作,相应的信息将出现在 OLED 显示屏上。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file697.png
修改后的推理代码,用于 OLED 显示屏,可在实验室的 GitHub上找到。
摘要
本实验室展示了如何使用 XIAOML 套件的内置 LSM6DS3TR-C IMU 传感器构建完整的运动分类系统。主要成就包括:
技术实现:
-
利用集成的 6 轴 IMU 进行运动感应
-
收集了四种交通场景的标记训练数据
-
实现了时间序列分析的光谱特征提取
-
部署了针对微控制器推理优化的神经网络分类器
-
添加了异常检测以识别不寻常的动作
机器学习流程:
-
直接从嵌入式传感器收集数据
-
使用频域分析进行特征工程
-
在 Edge Impulse 中训练和优化模型
-
在资源受限的硬件上进行实时推理
-
性能监控和验证
实际应用: 学习到的技术可以直接应用于现实场景,包括:
-
资产跟踪和物流监控
-
机器设备的预测性维护
-
人类活动识别
-
车辆和设备监控
-
智能城市中的物联网传感器网络
关键学习点:
-
与 IMU 坐标系统和传感器融合工作
-
在边缘设备上平衡模型准确性与推理速度
-
实现稳健的数据收集和预处理管道
-
将机器学习模型部署到嵌入式系统
-
集成多个传感器(IMU + 显示)以实现完整解决方案
将运动分类与 XIAOML 套件集成展示了现代嵌入式系统如何本地执行复杂的 AI 任务,实现无需依赖云端的实时决策。这种方法对于工业物联网、自主系统和智能设备应用中边缘 AI 的未来至关重要。
资源
-
DSP 频谱特征
概述
这些实验室提供了在高端且紧凑的嵌入式设备(Seeed Studio Grove Vision AI V2)上获得机器学习(ML)系统实际操作经验的机会。与需要数据中心规模资源的庞大模型相比,这些实验室允许您直接使用 TinyML 与硬件和软件进行交互。这种动手方法提供了对部署 AI 挑战和机会的切实理解,尽管是在小规模上。然而,这些原则与您在处理更大或更小系统时遇到的原则基本相同。
Grove Vision AI V2 在嵌入式 AI 领域占据独特位置,弥合了基本微控制器解决方案(如 Seeed XIAO ESP32S3 Sense 或 Arduino Nicla Vision)和更强大的单板计算机(如 Raspberry Pi)之间的差距。其核心是 Himax WiseEye2 HX6538 处理器,配备双核 Arm Cortex-M55 和集成的 ARM Ethos-U55 神经网络单元。
Arm Ethos-U55 代表了一种专门的机器学习处理器类别,特别设计为微 NPU,用于加速在区域受限的嵌入式和物联网设备中的 ML 推理。Ethos-U55 与 AI 功能的 Cortex-M55 处理器的强大组合,在现有基于 Cortex-M 的系统上实现了令人瞩目的 480 倍性能提升。在 400 MHz 的频率下运行,具有可配置的内部系统内存(SRAM)高达 2.4 MB,Grove Vision AI V2 提供了专业级的计算机视觉能力,同时保持了边缘应用所需的功耗效率和紧凑型外形。
这种定位使其成为学习高级 TinyML 概念的理想平台,它提供了较小系统所具有的简单性和降低的功耗要求,同时提供了远超传统基于微控制器解决方案的能力。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file698.jpg
Grove - 视觉 AI 模块 V2。来源:SEEED Studio。
先决条件
-
Grove Vision AI V2 板:确保您有 Grove Vision AI V2 板。
-
Raspberry Pi OV5647 摄像头模块:摄像头应连接到 Grove Vision AI V2 板以进行图像捕获。
-
主控制器:可以是 Seeed XIAO ESP32S3、XIAO ESP32C6 或其他设备。
-
USB-C 线缆:用于将板连接到您的计算机。
-
网络:具有互联网访问权限以下载必要的软件。
-
XIAO 扩展板基础:这有助于将主设备连接到物理世界(可选)。
设置和无代码应用
- 设置和无代码应用
练习
| 模态 | 任务 | 描述 | 链接 |
| — | — | — | — |
| 视觉 | 图像分类 | 学习对图像进行分类 | 链接 |
| 视觉 | 目标检测 | 实现目标检测 | TBD |
设置和无代码应用
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file699.jpg
在这个实验室中,我们将探索使用 Seeed Studio Grove Vision AI 模块 V2 的计算机视觉 (CV) 应用,这是一个专为嵌入式机器学习应用设计的强大而紧凑的设备。基于 Himax WiseEye2 芯片,该模块旨在使边缘设备具备 AI 功能,使其成为边缘机器学习 (ML) 应用的理想工具。
简介
Grove Vision AI 模块 (V2) 概述
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file700.jpg
Grove Vision AI (V2) 是一个基于 MCU 的视觉 AI 模块,它使用一个 Himax WiseEye2 HX6538 处理器,该处理器具有双核 Arm Cortex-M55 和一个集成的 ARM Ethos-U55 神经网络单元。Arm Ethos-U55 是一个机器学习 (ML) 处理器类别,特别设计为微 NPU,以加速在区域受限的嵌入式和物联网设备中的 ML 推理。Ethos-U55 与 AI 兼容的 Cortex-M55 处理器结合,在基于 Cortex-M 的现有系统中提供了 480 倍的 ML 性能提升。其时钟频率为 400 MHz,其内部系统内存(SRAM)可配置,最大容量为 2.4 MB。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file701.jpg
注意:根据 Seeed Studio 文档,除了 Himax 内部内存 2.5MB(2.4MB SRAM + 64KB ROM)外,Grove Vision AI (V2) 还配备了一个 16MB/133 MHz 的外部闪存。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file702.jpg
下面是 Grove Vision AI (V2) 系统的框图,包括一个摄像头和一个主控制器。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file703.png
通过IIC、UART、SPI 和 Type-C等接口,Grove Vision AI (V2) 可以轻松连接到 XIAO、Raspberry Pi、BeagleBoard 和基于 ESP 的产品等设备,以进行进一步开发。例如,将 Grove Vision AI V2 与 XIAO 系列设备之一集成,可以通过 Arduino IDE 或 MicroPython 容易地访问设备推理的结果数据,并方便地连接到云端或专用服务器,如家庭助手。
使用I2C Grove 连接器,Grove Vision AI V2 可以轻松连接到任何主设备。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file704.png
除了性能之外,另一个值得评论的领域是功耗。例如,在与 XIAO ESP32S3 Sense 的比较测试中,运行 Swift-YOLO Tiny 96x96,尽管实现了更高的性能(30 FPS 对 5.5 FPS),但与 XIAO ESP32S3 Sense 相比,Grove Vision AI V2 表现出更低的功耗(0.35 W 对 0.45 W)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file705.png
上述比较(以及与其他设备的比较)可以在文章 2024 MCU AI 视觉板:性能比较 中找到,该文章证实了 Grove Vision AI (V2) 的强大功能。
摄像头安装
准备好 Grove Vision AI (V2) 和摄像头后,您可以通过 CSI 线连接,例如 Raspberry Pi OV5647 摄像头模块。
连接时,请注意引脚排的方向,并确保它们正确插入,而不是反方向。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file706.jpg
SenseCraft AI Studio
SenseCraft AI Studio 是一个强大的平台,提供各种与各种设备兼容的 AI 模型,包括 XIAO ESP32S3 Sense 和 Grove Vision AI V2。在本实验中,我们将介绍如何使用 Grove Vision AI V2 的 AI 模型,并预览模型的输出。我们还将探讨一些关键概念、设置以及如何优化模型性能。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file707.png
模型也可以使用 SenseCraft Web Toolkit 部署,这是 SenseCraft AI Studio 的简化版本。
为了简单起见,我们可以开始使用 SenseCraft Web Toolkit,或者直接进入 SenseCraft AI Studio,那里有更多资源。
SenseCraft Web-Toolkit
SenseCraft Web Toolkit 是 SSCMA(Seeed SenseCraft Model Assistant) 中包含的可视化模型部署工具。此工具使我们能够通过简单的操作轻松地将模型部署到各种平台。该工具提供用户友好的界面,无需任何编码。
SenseCraft Web Toolkit 是基于 Himax AI Web Toolkit 的,它可以从 这里 (可选)下载。下载后解压到本地 PC,双击 index.html 以本地运行。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file708.png
但在我们的情况下,让我们按照以下步骤开始 SenseCraft-Web-Toolkit:
-
在 Chrome 浏览器中打开 SenseCraft-Web-Toolkit 网站。
-
使用 Type-C 线将 Grove Vision AI (V2) 连接到您的计算机。
-
连接 XIAO 后,选择如下:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file709.png
- 选择设备/端口,然后按
[连接]:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file710.png
注意:WebUSB 工具可能在某些浏览器中无法正常工作,例如 Safari。请使用 Chrome。
我们可以尝试 Seeed Studio 之前上传的几个基本计算机视觉模型。将光标移过 AI 模型,我们可以了解一些关于它们的信息,例如名称、描述、类别(图像分类、目标检测或姿态/关键点检测)、算法(如 YOLO V5 或 V8、FOMO、MobileNet V2 等)和指标(准确度或 mAP)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file711.png
我们可以通过点击它并按 [发送] 按钮选择那些现成的 AI 模型之一,或者上传我们的模型。
对于SenseCraft AI平台,请按照这里的说明操作。
探索 CV AI 模型
目标检测
目标检测是计算机视觉中的一个关键技术,它专注于在数字图像或视频帧中识别和定位对象。与将整个图像分类为单个标签的图像分类不同,目标检测识别图像中的多个对象并确定它们的精确位置,通常由边界框表示。这种能力对于广泛的用途至关重要,包括自动驾驶汽车、安全、监控系统以及增强现实,在这些应用中,理解视觉环境中的上下文和内容是至关重要的。
在目标检测中设定基准的常见架构包括 YOLO(You Only Look Once)、SSD(Single Shot MultiBox Detector)、FOMO(Faster Objects, More Objects)和 Faster R-CNN(基于区域的卷积神经网络)模型。
让我们选择一个现成的 AI 模型,例如人员检测,它使用 Swift-YOLO 算法进行训练。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file712.png
一旦模型成功上传,你可以在右侧预览区域看到 Grove Vision AI (V2)摄像头的实时流。此外,通过点击顶部的 [设备日志] 按钮可以在串行监视器上显示推理详情。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file713.png
在 SenseCraft AI Studio 中,设备日志始终在屏幕上。
将摄像头对准我,只检测到一个人,因此模型输出将是一个单独的“框”。仔细观察,模块会连续发送两行信息:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file714.png
perf(性能),显示毫秒级的延迟。
-
预处理时间(图像捕获和裁剪):7ms;
-
推理时间(模型延迟):76ms (13 fps)
-
后处理时间(显示图像和数据包含):小于 0ms。
boxes: 显示图像中检测到的对象。在这种情况下,只有一个。
- 框的坐标为 x, y, w, h (245, 292,449,392),并且对象(人,标签 0)的捕获值为 .89。
如果我们用摄像头指向有几个人的图像,我们将为每个人(对象)得到一个框:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file715.png
在 SenseCraft AI Studio 上,推理延迟(48ms)低于 SenseCraft ToolKit(76ms),这是由于独特的部署实现。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file716.png
功耗
运行这个 Swift-YOLO 模型时的峰值功耗为 410 毫瓦。
预览设置
我们可以看到,在设置中,有两个设置选项可以调整以优化模型的识别精度。
-
置信度:指模型对其预测赋予的确定性或概率水平。此值确定模型认为检测有效所需的最小置信度水平。较高的置信度阈值将导致检测数量减少但确定性更高,而较低的阈值将允许更多检测,但可能包括一些误报。
-
IoU:用于评估预测边界框与真实边界框的准确性。IoU 是一个度量指标,用于衡量预测边界框与真实边界框之间的重叠。它用于确定目标检测的准确性。IoU 阈值设置了对检测被认为是真正阳性的最小 IoU 值。调整此阈值可以帮助微调模型的精确度和召回率。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file717.png
尝试调整置信度阈值和 IoU 阈值的不同值,以找到在准确检测人员的同时最小化误报的最佳平衡。最佳设置可能因我们的具体应用和图像或视频流的特点而异。
姿态/关键点检测
姿态或关键点检测是计算机视觉中的一个复杂领域,它专注于在图像或视频帧中识别特定的兴趣点,通常与人体、面部或其他感兴趣的对象相关。这项技术可以检测并绘制出主题的各种关键点,如人体上的关节或面部的特征,从而实现姿态、运动和手势的分析。这对于各种应用具有深远的影响,包括增强现实、人机交互、运动分析和医疗监测,在这些应用中,理解人体运动和活动至关重要。
与一般目标检测不同,目标检测识别并定位对象,姿态检测则深入到更细致的细节,捕捉特定部分的细微位置和方向。该领域的领先架构包括 OpenPose、AlphaPose 和 PoseNet,每个架构都旨在以不同复杂度和精度解决姿态估计的挑战。通过深度学习和神经网络的发展,姿态检测变得越来越准确和高效,为视觉数据中捕获的主题的复杂动态提供实时洞察。
因此,让我们探索这个流行的计算机视觉应用,姿态/关键点检测。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file718.png
通过在预览区域按 [停止] 来停止当前模型的推理。选择模型并按 [发送]。一旦模型成功上传,您可以在右侧预览区域的预览区域中查看 Grove Vision AI(V2)摄像头的实时流,以及通过点击顶部 [设备日志] 按钮可访问的串行监视器中显示的推理细节。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file719.png
YOLOV8 姿态模型使用COCO-Pose 数据集进行训练,该数据集包含 200K 张带有17个关键点的图像,用于姿态估计任务。
让我们看看单个推理截图(为了简化,让我们分析包含一个人的图像)。我们可以注意到我们有两行,一行是推理性能(121 毫秒),另一行是以下关键点:
-
1 个信息框,与目标检测示例中得到的相同(框坐标(113,119,67,208),推理结果(90),标签(0)。
-
17 组 4 个数字代表身体的 17 个“关节”,其中‘0’是鼻子,‘1’和‘2’是眼睛,‘15’和‘16’是脚,等等。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file720.png
要更深入地了解姿态估计项目,请参阅教程:探索边缘 AI!- 姿态估计。
图像分类
图像分类是计算机视觉中的一个基础任务,旨在将整个图像分类到预定义的几个类别之一。这个过程涉及分析图像的视觉内容,并根据它包含的主要物体或场景,从固定的类别集中分配一个标签。
图像分类在各种应用中至关重要,从组织并搜索数字图书馆和社交媒体平台中的大型图像数据库,到使自主系统能够理解其周围环境。显著推进图像分类领域的常见架构包括卷积神经网络(CNNs),如 AlexNet、VGGNet 和 ResNet。这些模型通过学习视觉数据的高级表示,在具有挑战性的数据集(如ImageNet)上展示了显著的准确性。
作为许多计算机视觉系统的基石,图像分类推动了创新,为更复杂任务如目标检测和图像分割奠定了基础,并促进了各行业对视觉数据的更深入理解。因此,让我们也来探索这个计算机视觉应用。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file721.png
此示例可在 SenseCraft ToolKit 中找到,但不在 SenseCraft AI Studio 中。在最后一个示例中,可以找到其他图像分类的示例。
模型成功上传后,我们可以在右侧的预览区域查看 Grove Vision AI (V2)摄像头的实时流,同时显示在串行监视器(通过点击顶部的 [设备日志] 按钮)中的推理细节。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file722.png
因此,我们将收到一个分数和类别作为输出。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file723.png
例如,[99, 1] 表示类别:1(人物)得分为 0.99。一旦这个模型是二元分类,类别 0 将是“无人”(或背景)。推理延迟为15ms或大约 70fps。
功耗
要运行 Mobilenet V2 0.35,Grove Vision AI V2 在 5.24V 时的峰值电流为 80mA,导致功耗为 420mW。
在 XIAO ESP32S3 Sense 上运行相同的模型,功耗为 523mW,延迟为 291ms。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file724.png
在 SenseCraft AI Studio 上探索其他模型
还可以从 SenseCraft AI 网页 下载几个公共 AI 模型。例如,你可以运行一个 Swift-YOLO 模型,检测交通灯 如此所示:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file725.png
此模型的延迟大约为 86ms,平均功耗为 420mW。
一个图像分类项目
让我们创建一个完整的图像分类项目,使用 SenseCraft AI Studio。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file726.png
在 SenseCraft AI Studio 上:让我们打开标签页 训练:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file727.png
如果有 WebCam,默认情况下训练一个分类模型。让我们选择 Grove Vision AI V2。按下绿色按钮[连接],将出现一个弹出窗口。选择相应的端口,然后按蓝色按钮 [连接]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file728.png
从 Grove Vision AI V2 流出的图像将被显示。
目标
第一步始终是定义一个目标。例如,让我们分类两个简单的物体——例如,一个玩具盒子和一个玩具轮子。我们还应该包括一个图像类别,背景,其中场景中没有物体。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file729.png
数据收集
让我们创建类,例如按照字母顺序:
-
类 1:背景
-
类 2:盒子
-
类 3:轮子
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file730.png
选择一个类别,并持续按预览区域下的绿色按钮。收集的图像将出现在图像样本屏幕上。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file731.png
收集图像后,检查它们并删除任何错误的图像。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file732.png
从每个类别收集大约 50 张图像,然后转到训练步骤:
训练
确认是否选择了正确的设备(Grove Vision AI V2),然后按 [开始训练]
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file733.png
测试
训练后,可以预览推理结果。
注意,模型当前并未在设备上运行。实际上,我们只是在用设备捕捉图像,并使用在 Studio 中运行的训练模型进行实时预览。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file734.png
现在是真正在设备上部署模型的时候了:
部署
在部署到设备上选择训练好的模型,选择 Grove Vision AI V2:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file735.png
Studio 将带我们转到视觉工作空间标签。确认部署,选择合适的端口,并连接:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file736.png
模型将被烧录到设备中。自动重置后,模型将在设备上开始运行。在设备日志中,我们可以看到推理的延迟约为 8 ms,对应每秒 125 帧(FPS)。
此外,请注意,可以调整模型的置信度。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file737.png
要运行图像分类模型,Grove Vision AI V2 在 5.24V 下的峰值电流为 80mA,导致功耗为 420mW。
保存模型
在 SenseCraft AI Studio 中可以保存模型。Studio 将保留所有我们的模型,这些模型可以在以后部署。为此,返回到训练标签并选择按钮[保存到 SenseCraft]:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file738.png
摘要
在这个实验室中,我们使用Seeed Studio Grove Vision AI 模块 V2探索了几个计算机视觉(CV)应用,展示了它作为一款专为嵌入式机器学习应用设计的强大而紧凑设备的卓越能力。
性能卓越:Grove Vision AI V2 在多个计算机视觉任务中表现出色。凭借其Himax WiseEye2 芯片,该芯片具有双核 Arm Cortex-M55 和集成的 ARM Ethos-U55 神经网络单元,设备提供了:
-
图像分类:15 ms推理时间(67 FPS)
-
物体检测(人物):48 ms 到 76 ms推理时间(21 FPS 到 13 FPS)
-
姿态检测:121 ms实时关键点检测,17 关节跟踪(8 FPS)
能效领先:Grove Vision AI V2 最引人注目的优势之一是其卓越的能效。比较测试显示,与传统嵌入式平台相比有显著改进:
-
Grove Vision AI V2:峰值功耗 80 mA(410 mW),(60+ FPS)
-
XIAO ESP32S3:执行类似的 CV 任务(图像分类)523 mW(3+ FPS)
实际应用:通过一个全面的端到端项目展示了设备的通用性,包括数据集创建、模型训练、部署和离线推理。
开发者友好生态系统:SenseCraft AI Studio 凭借其无代码部署和集成能力,为定制应用程序提供了对 Grove Vision AI V2 的访问,使得初学者和高级开发者都能使用。丰富的预训练模型库和自定义模型部署支持为各种应用提供了灵活性。
Grove Vision AI V2 代表了边缘 AI 硬件的重大进步,它以紧凑、节能的包装形式提供了专业级的计算机视觉能力,使嵌入式应用在工业、物联网和教育领域的 AI 部署民主化。
关键要点
本实验室证明,复杂的计算机视觉应用不仅限于基于云的解决方案或能耗高的硬件,如 Raspberry Pi 或 Jetson Nanos——它们现在可以以出色的效率和性能在边缘有效部署。
可选,我们可以使用XIAO 视觉 AI 相机。这个创新的视觉解决方案无缝结合了 Grove Vision AI V2 模块、XIAO ESP32-C3 控制器和 OV5647 相机,所有这些都被封装在一个定制的 3D 打印外壳中:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file739.png
资源
图像分类
使用 Seeed Studio Grove Vision AI 模块 V2 (Himax WiseEye2)
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file740.jpg
在这个实验中,我们将探索使用 Seeed Studio Grove Vision AI 模块 V2 进行图像分类,这是一个专为嵌入式机器学习应用设计的强大而紧凑的设备。基于Himax WiseEye2芯片,该模块旨在使边缘设备具备 AI 功能,使其成为边缘机器学习(ML)应用的理想工具。
简介
到目前为止,我们已经探索了 Seeed Studio 之前上传的几个计算机视觉模型,或者使用 SenseCraft AI Studio 进行图像分类,而没有选择一个特定的模型。现在,让我们从头开始开发我们的图像分类项目,我们将选择我们的数据和模型。
下面,我们可以看到项目的主要步骤以及我们将如何与它们一起工作:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file741.png
项目目标
任何机器学习(ML)项目的第一步是定义目标。在这种情况下,目标是检测和分类单个图像中存在的两个特定对象。对于这个项目,我们将使用两个小玩具:一个机器人和一只小型巴西鹦鹉(命名为Periquito)。此外,我们还将收集两个对象不存在的背景图像。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file742.png
数据收集
在定义了机器学习项目目标后,数据集收集是下一个且最重要的步骤。假设你的项目使用的是公开数据集上的图像,例如,用于人员检测项目。在这种情况下,你可以下载Wake Vision数据集用于项目。
但是,在我们的情况下,我们定义了一个图像在公共领域不存在的项目,因此我们需要生成它们。我们可以使用手机、计算机摄像头或其他设备来拍摄照片,离线或连接到 Edge Impulse Studio。
如果你想使用 Grove Vision AI V2 捕获你的数据集,你可以像之前实验中那样使用 SenseCraft AI Studio,或者使用我们将在本实验的后处理/获取视频流部分中描述的camera_web_server草图。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file743.png
在这个实验中,我们将使用 SenseCraft AI Studio 来收集数据集。
使用 SenseCraft AI Studio 收集数据
在 SenseCraft AI Studio 上:让我们打开训练标签页。
默认情况下,如果可用,将使用 WebCam 训练一个分类模型。让我们选择Grove Vision AI V2。按下绿色按钮[连接](1),将出现一个弹出窗口。选择相应的端口**(2),然后按下蓝色按钮[连接](3)**。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file744.png
将显示来自 Grove Vision AI V2 的图像流。
图像收集
让我们创建类别,例如,按照字母顺序排列:
-
Class1: 背景
-
Class 2: 小鹦鹉
-
第 3 类:机器人
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file745.png
选择一个类别(注意窗口周围将有一个绿色线条)并持续按下预览区域下的绿色按钮。收集的图像将出现在图像样本屏幕上。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file746.png
收集图像后,检查它们,并在必要时删除任何错误的图像。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file747.png
从每个类别收集大约 50 张图像。收集完三个类别后,打开每个类别的菜单并选择 Export Data。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file748.png
在计算机的下载区域,我们将获得三个 zip 文件,每个文件都对应一个类名。每个 zip 文件包含一个包含图像的文件夹。
将数据集上传到 Edge Impulse Studio
我们将使用 Edge Impulse Studio 来训练我们的模型。Edge Impulse 是边缘设备上机器学习的领先开发平台。
-
在 Edge Impulse 输入您的账户凭证(或创建一个免费账户)。
-
接下来,创建一个新的项目:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file749.png
数据集大约包含每个标签 50 张图像,其中 40 张用于训练,10 张用于测试。
脉冲设计和预处理
脉冲设计
一个脉冲会提取原始数据(在这种情况下,图像),提取特征(调整图片大小),然后使用学习块对新数据进行分类。
将图像分类是深度学习最常见应用,但完成这项任务需要大量的数据。我们每个类别大约有 50 张图像。这个数量足够吗?根本不够!我们需要数千张图像来“教学”或“建模”每个类别,以便我们能够区分它们。然而,我们可以通过使用数千张图像重新训练一个先前训练好的模型来解决这个问题。我们将这种技术称为“迁移学习”(TL)。使用 TL,我们可以在我们的数据上微调预训练的图像分类模型,即使是在相对较小的图像数据集上也能实现良好的性能,就像我们的情况一样。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file750.jpg
因此,从原始图像开始,我们将调整它们的大小(96x96)像素,并将它们输入到我们的迁移学习块中:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file751.png
为了比较,我们将保持图像大小为 96 x 96。然而,请注意,使用 Grove Vision AI 模块 V2 及其内部 2.4 MB 的 SRAM,可以使用更大的图像(例如,160 x 160)。
还在右上角选择 Target 设备(Himax WiseEye2 (M55 400 MHz + U55))。
预处理(特征生成)
除了调整图像大小外,我们还可以将它们转换为灰度或保留它们的原始 RGB 颜色深度。让我们在“图像”部分选择 [RGB]。这样做,每个数据样本将具有 27,648 个特征维度(96x96x3)。按下 [Save Parameters] 将打开一个新标签页,Generate Features。按下 [Generate Features] 按钮以生成特征。
模型设计、训练和测试
2007 年,谷歌推出了MobileNetV1。2018 年,推出了MobileNetV2:倒置残差和线性瓶颈,2019 年推出了 V3。MobileNet 是一系列通用计算机视觉神经网络,专为移动设备设计,以支持分类、检测和其他应用。MobileNets 是小型、低延迟、低功耗的模型,参数化以满足各种用例的资源限制。
尽管基础 MobileNet 架构已经紧凑且具有低延迟,但特定的用例或应用可能经常需要模型更小、更快。MobileNets 引入了一个简单的参数,α(alpha),称为宽度乘数,以构建这些更小、计算成本更低的模型。宽度乘数α的作用是在每一层均匀地瘦化网络。
Edge Impulse Studio 提供了 MobileNet V1(96x96 图像)和 V2(96x96 和 160x160 图像),具有几个不同的α值(从 0.05 到 1.0)。例如,您将使用 V2,160x160 图像,α=1.0 获得最高的准确性。当然,这里有一个权衡。准确性越高,运行模型所需的内存(大约 1.3M RAM 和 2.6M ROM)就越多,这意味着更大的延迟。在 MobileNet V1 和α=0.10 的情况下,将获得更小的占用空间(大约 53.2K RAM 和 101K ROM)。
为了比较,我们将使用MobileNet V2 0.1作为我们的基础模型(但也可以使用具有更大 alpha 值的模型)。我们的模型在输出层之前的最底层将有 8 个神经元,并具有 10%的 dropout 率以防止过拟合。
另一个与深度学习一起使用的必要技术是数据增强。数据增强是一种方法,可以通过创建额外的合成数据来帮助提高机器学习模型的准确性。数据增强系统在训练过程中对训练数据进行小的、随机的更改(例如翻转、裁剪或旋转图像)。
设置超参数:
-
迭代次数:20,
-
批处理大小:32
-
学习率:0.0005
-
验证集大小:20%
训练结果:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file752.png
模型配置文件预测需要146 KB 的 RAM 和 187 KB 的闪存,这表明 Grove AI 视觉(V2)没有问题,它几乎有 2.5 MB 的内部 SRAM。此外,工作室还指出大约 4 毫秒的延迟。
尽管如此,当使用备用数据进行测试时,验证集的准确率为 100%,我们确认使用量化(Int8)训练模型的准确率为 81%。然而,对于我们在实验室中的目的来说,这是足够的。
模型部署
在“部署”选项卡上,我们应该选择:Seeed Grove 视觉 AI 模块 V2 (Himax WiseEye2)并点击 [构建]。一个 ZIP 文件将被下载到我们的电脑上。
Zip 文件包含model_vela.tflite,这是一个使用 Vela 编译器优化的 TensorFlow Lite(TFLite)模型,Vela 编译器是由 Arm 开发的工具,用于将 TFLite 模型适配到 Ethos-U NPUs。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file753.png
我们可以按照README.txt中的说明来闪存模型,或者使用 SenseCraft AI Studio。我们将使用后者。
在 SenseCraft AI Studio 上部署模型
在 SenseCraft AI Studio 上,转到Vision Workspace标签,并连接设备:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file754.png
您应该看到最后上传到设备上的模型。选择绿色按钮 [上传模型]。一个弹出窗口将要求输入模型名称、模型文件以及输入类名(对象)。我们应该使用按字母顺序排列的标签:0: background,1: periquito,2: robot,然后按 [Send]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file755.png
几秒钟后,模型将被上传(闪存)到我们的设备上,相机图像将实时出现在预览区域。分类结果将在图像预览下方显示。您还可以使用设置中的光标选择您的推理的置信度阈值。
在设备日志器中,我们可以查看串行监视器,在那里我们可以观察到延迟,预处理大约为 1 到 2 毫秒,推理大约为 4 到 5 毫秒,与 Edge Impulse Studio 中的估计相一致。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file756.png
这里是其他截图:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file757.png
此模型的功耗约为 70 mA,相当于 0.4 W。
图像分类(非官方)基准
几种开发板可用于嵌入式机器学习(tinyML),其中最常见(到目前为止)用于计算机视觉应用(低功耗)的是ESP32 CAM、Seeed XIAO ESP32S3 Sense和 Arduino Nicla Vision。
利用这个机会,一个类似训练的模型,MobilenetV2 96x96,alpha 值为 0.1,也被部署到了 ESP-CAM、XIAO 和 Raspberry Pi Zero W2 上。以下是结果:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file758.png
Grove Vision AI V2 配备ARM Ethos-U55比 ARM-M7 的设备快约 14 倍,比 Xtensa LX6(ESP-CAM)快 100 多倍。即使与拥有更强大 CPU 的 Raspberry Pi 相比,U55 也能将延迟减少近一半。此外,功耗低于其他设备(有关功耗比较,请参阅此处完整文章)。
后处理
现在我们已经将模型上传到板子上并且工作正常,正在对图像进行分类,让我们连接一个主设备以将其推理结果导出到它,并完全离线(断开与 PC 的连接,例如,由电池供电)查看结果。
注意,我们可以使用任何微控制器作为主控制器,例如 XIAO、Arduino 或 Raspberry Pi。
获取视频流
图像处理和模型推理在 Grove Vision AI (V2) 本地处理,我们希望结果通过 IIC 输出到 XIAO (主控制器)。为此,我们将使用 Arduino SSMA 库。这个库的主要目的是处理 Grove Vision AI 的数据流,不涉及模型推理。
Grove Vision AI (V2) 通过 IIC 与 XIAO 通信(推理结果);设备的 IIC 地址是 0x62。图像信息传输通过 USB 串行端口。
步骤 1:从其 GitHub 下载 Arduino SSMA 库作为 zip 文件:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file759.png
步骤 2:在 Arduino IDE 中安装它(sketch > Include Library > Add .Zip Library)。
步骤 3:安装 ArduinoJSON 库。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file760.png
步骤 4:安装 Eigen 库
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file761.png
步骤 3:现在,通过设备背面的插座(一排引脚)连接 XIAO 和 Grove Vision AI (V2)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file762.jpg
注意:请注意连接的方向,Grove Vision AI 的 Type-C 连接器应与 XIAO 的 Type-C 连接器方向一致。
步骤 5:将 XIAO USB-C 端口连接到您的计算机
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file763.png
步骤 6:在 Arduino IDE 中选择 Xiao 板和相应的 USB 端口。
一旦我们想要将视频流式传输到网页,我们将使用具有 Wi-Fi 和足够内存处理图像的 XIAO ESP32S3。选择 XIAO_ESP32S3 和合适的 USB 端口:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file764.png
默认情况下,PSRAM 是禁用的。打开 Tools 菜单,在 PSRAM: "OPI PSRAM" 选择 OPI PSRAM。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file765.png
步骤 7:在 Arduino IDE 中打开示例:
文件 -> 示例 -> Seeed_Arduino_SSCMA -> camera_web_server。
并在 camera_web_server.ino 草图中编辑 ssid 和 password 以匹配 Wi-Fi 网络。
步骤 8:将草图上传到板子并打开串行监视器。当连接到 Wi-Fi 网络,板子的 IP 地址将显示出来。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file766.png
使用网页浏览器打开地址。将有一个视频应用可用。要查看 仅 来自 Grove Vision AI V2 的视频流,请按 [Sample Only] 和 [Start Stream]。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file767.png
如果你想创建一个图像数据集,可以使用这个应用,保存设备生成的视频帧。按下 [Save Frame],图像将被保存在我们桌面下载区域。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file743.png
在未选择 [Sample Only] 的情况下打开应用 (不选择),推理结果应显示在视频屏幕上,但这种情况在图像分类中不会发生。对于目标检测或姿态估计,结果会嵌入视频流中。
例如,如果模型是使用 YoloV8 进行的人脸检测:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file768.png
获取推理结果
-
前往
文件->示例->Seeed_Arduino_SSCMA->inference_class。 -
将草图上传到板子上,并打开串行监视器。
-
将摄像头对准我们的其中一个物体,我们可以在串行终端上看到推理结果。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file769.png
在 Arduino IDE 上运行的推理平均消耗为 160 mA 或 800 mW,峰值消耗为 330 mA 1.65 W,当将图像发送到应用程序时。
LED 后处理
我们后处理背后的想法是,每当检测到特定的图像(例如,Periquito - 标签:1),用户 LED 将打开。如果检测到机器人或背景,LED 将关闭。
复制以下代码并将其粘贴到您的 IDE 中:
#include <Seeed_Arduino_SSCMA.h>
SSCMA AI;
void setup()
{
AI.begin();
Serial.begin(115200);
while (!Serial);
Serial.println("Inferencing - Grove AI V2 / XIAO ESP32S3");
// Pins for the built-in LED
pinMode(LED_BUILTIN, OUTPUT);
// Ensure the LED is OFF by default.
// Note: The LED is ON when the pin is LOW, OFF when HIGH.
digitalWrite(LED_BUILTIN, HIGH);
}
void loop()
{
if (!AI.invoke()){
Serial.println("\nInvoke Success");
Serial.print("Latency [ms]: prepocess=");
Serial.print(AI.perf().prepocess);
Serial.print(", inference=");
Serial.print(AI.perf().inference);
Serial.print(", postpocess=");
Serial.println(AI.perf().postprocess);
int pred_index = AI.classes()[0].target;
Serial.print("Result= Label: ");
Serial.print(pred_index);
Serial.print(", score=");
Serial.println(AI.classes()[0].score);
turn_on_led(pred_index);
}
}
/**
* @brief turn_off_led function - turn-off the User LED
*/
void turn_off_led(){
digitalWrite(LED_BUILTIN, HIGH);
}
/**
* @brief turn_on_led function used to turn on the User LED
* @param[in] pred_index
* label 0: [0] ==> ALL OFF
* label 1: [1] ==> LED ON
* label 2: [2] ==> ALL OFF
* label 3: [3] ==> ALL OFF
*/
void turn_on_led(int pred_index) {
switch (pred_index)
{
case 0:
turn_off_led();
break;
case 1:
turn_off_led();
digitalWrite(LED_BUILTIN, LOW);
break;
case 2:
turn_off_led();
break;
case 3:
turn_off_led();
break;
}
}
此草图使用 Seeed_Arduino_SSCMA.h 库与 Grove Vision AI 模块 V2 交互。AI 模块和 LED 在 setup() 函数中初始化,并开始串行通信。
loop() 函数会反复调用 invoke() 方法,使用 Grove Vision AI 模块 V2 内置算法进行推理。推理成功后,草图会将性能指标打印到串行监视器,包括预处理、推理和后处理时间。
草图处理并打印出有关推理结果的详细信息:
-
(
AI.classes()[0]) 识别图像的类别(.target)及其置信度分数(.score)。 -
推理结果(类别)存储在整数变量
pred_index中,它将被用作turn_on_led()函数的输入。因此,LED 将根据分类结果打开。
这里是结果:
如果检测到 Periquito(标签:1),LED 将打开:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file770.png
如果检测到机器人(标签:2)LED 将关闭(与背景(标签:0)相同):
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file771.png
因此,我们现在可以使用外部电池为 Grove Vision AI V2 + Xiao ESP32S3 提供电源,并且推理结果将完全离线通过 LED 显示。消耗量约为 165 mA 或 825 mW。
还可以通过 WiFi、BLE 或其他在所使用的主设备上可用的通信协议发送结果。
可选:在外部设备上进行后处理
当然,与 EdgeAI 一起工作的一个显著优势是设备可以完全断开与云的连接,从而实现与真实世界的无缝交互。我们在上一节中做到了这一点,但使用的是内部 Xiao LED。现在,我们将连接外部 LED(可以是任何执行器)。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file772.png
LED 应通过一个 220 欧姆的电阻连接到 XIAO 地面。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file773.png
策略是修改之前的草图以处理三个外部 LED。
目标:每当检测到 Periquito 的图像时,LED 绿灯 将打开;如果是 机器人,LED 黄灯 将打开;如果是 背景,红灯 将打开。
图像处理和模型推理在 Grove Vision AI(V2)本地处理,我们希望结果通过 IIC 输出到 XIAO。为此,我们将再次使用 Arduino SSMA 库。
这里是使用的草图:
#include <Seeed_Arduino_SSCMA.h>
SSCMA AI;
// Define the LED pin according to the pin diagram
// The LEDS negative lead should be connected to the XIAO ground
// via a 220-ohm resistor.
int LEDR = D1; # XIAO ESP32S3 Pin 1
int LEDY = D2; # XIAO ESP32S3 Pin 2
int LEDG = D3; # XIAO ESP32S3 Pin 3
void setup()
{
AI.begin();
Serial.begin(115200);
while (!Serial);
Serial.println("Inferencing - Grove AI V2 / XIAO ESP32S3");
// Initialize the external LEDs
pinMode(LEDR, OUTPUT);
pinMode(LEDY, OUTPUT);
pinMode(LEDG, OUTPUT);
// Ensure the LEDs are OFF by default.
// Note: The LEDs are ON when the pin is HIGH, OFF when LOW.
digitalWrite(LEDR, LOW);
digitalWrite(LEDY, LOW);
digitalWrite(LEDG, LOW);
}
void loop()
{
if (!AI.invoke()){
Serial.println("\nInvoke Success");
Serial.print("Latency [ms]: prepocess=");
Serial.print(AI.perf().prepocess);
Serial.print(", inference=");
Serial.print(AI.perf().inference);
Serial.print(", postpocess=");
Serial.println(AI.perf().postprocess);
int pred_index = AI.classes()[0].target;
Serial.print("Result= Label: ");
Serial.print(pred_index);
Serial.print(", score=");
Serial.println(AI.classes()[0].score);
turn_on_leds(pred_index);
}
}
/**
* @brief turn_off_leds function - turn-off all LEDs
*/
void turn_off_leds(){
digitalWrite(LEDR, LOW);
digitalWrite(LEDY, LOW);
digitalWrite(LEDG, LOW);
}
/**
* @brief turn_on_leds function used to turn on a specific LED
* @param[in] pred_index
* label 0: [0] ==> Red ON
* label 1: [1] ==> Green ON
* label 2: [2] ==> Yellow ON
*/
void turn_on_leds(int pred_index) {
switch (pred_index)
{
case 0:
turn_off_leds();
digitalWrite(LEDR, HIGH);
break;
case 1:
turn_off_leds();
digitalWrite(LEDG, HIGH);
break;
case 2:
turn_off_leds();
digitalWrite(LEDY, HIGH);
break;
case 3:
turn_off_leds();
break;
}
}
我们应该使用 Grove Vision AI V2 的 I2C Grove 连接器将其与 XIAO 连接。对于 XIAO,我们将使用 扩展板来方便连接(尽管可以直接将 I2C 连接到 XIAO 的引脚上)。我们将使用 USB-C 连接器为板供电,但也可以使用电池。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file774.png
这里是结果:
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file775.png
功耗达到了峰值 240 mA(绿色 LED),相当于 1.2 W。驱动黄色和红色 LED 消耗 14 mA,相当于 0.7 W。通过串行向终端发送信息对功耗没有影响。
摘要
在这个实验室中,我们探讨了使用 Himax WiseEye2 芯片驱动的 Seeed Studio Grove Vision AI 模块 V2 开发图像分类系统的完整过程。我们走过了机器学习工作流程的每一个阶段,从定义我们的项目目标到部署具有现实交互的工作模型。
Grove Vision AI V2 表现出令人印象深刻的性能,推理时间仅为 4-5ms,显著优于其他常见的 tinyML 平台。我们的基准比较表明,它比 ARM-M7 设备快约 14 倍,比 Xtensa LX6(ESP-CAM)快 100 多倍。即使与 Raspberry Pi Zero W2 相比,Edge TPU 架构在消耗更少能量的同时提供了近两倍的速度。
通过这个项目,我们看到了迁移学习如何使我们能够使用相对较小的自定义图像数据集实现良好的分类结果。具有 alpha 值 0.1 的 MobileNetV2 模型为我们三个类别的难题提供了精确性和效率之间的出色平衡,仅需要 146 KB 的 RAM 和 187 KB 的闪存,完全在 Grove Vision AI 模块 V2 的 2.4 MB 内部 SRAM 能力范围内。
我们还探索了多种部署选项,从通过 SenseCraft AI Studio 查看推理结果到使用 LED 创建具有视觉反馈的独立系统。将视频流式传输到网页浏览器并本地处理推理结果的能力展示了边缘 AI 系统在实际应用中的多功能性。
我们最终系统的功耗保持得令人印象深刻,从基本推理的约 70mA(0.4W)到驱动外部组件时的 240mA(1.2W)。这种效率使 Grove Vision AI 模块 V2 成为电池供电应用中的绝佳选择,在这些应用中,功耗至关重要。
这个实验室已经证明,复杂的计算机视觉任务现在可以在边缘端完全执行,无需依赖云服务或强大的计算机。借助 Edge Impulse Studio 和 SenseCraft AI Studio 等工具,开发过程甚至对没有广泛机器学习专业知识的人来说也变得可行。
随着边缘人工智能技术的持续发展,我们可以期待来自紧凑、节能设备(如 Grove Vision AI 模块 V2)的更强大功能,这将为智能传感器、物联网应用以及日常物体中的嵌入式智能开辟新的可能性。
资源
SenseCraft AI Studio - 视觉工作空间(部署模型)
目标检测
本实验室正在开发中
概述
这些实验室提供了宝贵的动手经验,使用机器学习系统,利用树莓派平台的灵活性和易用性。与需要大量云资源的大规模模型工作不同,这些练习允许您直接在紧凑而强大的边缘计算环境中与硬件和软件进行交互。通过利用树莓派从高效的 Zero 到更坚固的 4 或 5 型号的能力,您将获得在边缘部署 AI 的实用见解。这种方法提供了在资源受限环境中实施机器学习解决方案的挑战和机遇的切实理解。虽然我们在较小的规模上工作,但您将学习的原理和技术与在更大系统中使用的原理和技术基本相似。树莓派运行整个操作系统的能力及其广泛的 GPIO 功能,为将理论知识与实际应用之间的差距连接起来提供了丰富的学习体验。通过这些实验室,您将掌握 EdgeML 的复杂性,并发展适用于广泛 AI 部署场景的技能。
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file776.jpg
树莓派 Zero 2-W 和带摄像头的树莓派 5
前提条件
-
树莓派: 确保您至少有一块以下板子:用于 Vision Labs 的树莓派 Zero 2 W、树莓派 4 或 5,以及用于 GenAi labs 的树莓派 5。
-
电源适配器: 用于给板子供电。
-
树莓派 Zero 2-W:2.5 W,带 Micro-USB 适配器
-
树莓派 4 或 5:3.5 W,带 USB-C 适配器
-
-
网络: 用于下载必要的软件和远程控制板子。
-
SD 卡(至少 32 GB)和 SD 卡适配器: 用于树莓派操作系统。
设置
- 设置树莓派
练习
| 模态 | 任务 | 描述 | 链接 |
| — | — | — | — |
| 视觉 | 图像分类 | 学习对图像进行分类 | 链接 |
| 视觉 | 物体检测 | 实现物体检测 | 链接 |
| 通用人工智能 | 小型语言模型 | 在边缘部署 SLMs | 链接 |
| 通用人工智能 | 视觉语言模型 | 在边缘部署 VLMs | 链接 |
设置
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file777.jpg
DALL·E 提示 - 一个受 20 世纪 50 年代启发的电子实验室环境,采用卡通风格。实验室应配备复古设备、大型示波器、老式收音机和大型、方形的计算机。Raspberry Pi 5 板显著展示,准确展示了其实际尺寸,类似于信用卡,在工作台上。Pi 板周围环绕着经典的实验室工具,如烙铁、电阻和电线。整体场景应充满活力,具有卡通特有的夸张色彩和趣味细节。不应包含任何标志或文本。
本章将指导您设置 Raspberry Pi Zero 2 W(Raspi-Zero)和 Raspberry Pi 5(Raspi-5)型号。我们将涵盖硬件设置、操作系统安装、初始配置和测试。
Raspi-5的一般说明也适用于较老的 Raspberry Pi 版本,如 Raspi-3 和 Raspi-4。
概述
Raspberry Pi 是一款功能强大且多功能的单板计算机,已成为各个学科工程师的必备工具。由Raspberry Pi 基金会开发,这些紧凑型设备提供了独特的性价比、计算能力和广泛的 GPIO(通用输入/输出)功能,使其成为原型设计、嵌入式系统开发和高级工程项目的理想选择。
关键特性
-
计算能力:尽管体积小巧,Raspberry Pi 提供了显著的计算能力,最新型号配备了多核 ARM 处理器,最高可达 8 GB RAM。
-
GPIO 接口:40 引脚 GPIO 接口允许直接与传感器、执行器和其他电子组件交互,促进硬件和软件集成项目。
-
广泛的连接性:内置 Wi-Fi、蓝牙、以太网和多个 USB 端口,可实现多样化的通信和网络项目。
-
低级硬件访问:Raspberry Pi 提供了访问 I2C、SPI 和 UART 等接口的能力,允许对外部设备进行详细控制和通信。
-
实时能力:通过适当的配置,Raspberry Pi 可用于软实时应用,使其适用于控制系统和信号处理任务。
-
功率效率:低功耗使得电池供电和节能设计成为可能,尤其是在像 Pi Zero 这样的型号中。
Raspberry Pi 型号(本书涵盖)
-
Raspberry Pi Zero 2 W (Raspi-Zero):
-
适用范围:紧凑型嵌入式系统
-
关键规格:1 GHz 单核 CPU(ARM Cortex-A53),512 MB RAM,功耗低
-
-
Raspberry Pi 5 (Raspi-5):
-
适用范围:更复杂的应用,如边缘计算、计算机视觉和边缘 AI 应用,包括 LLMs。
-
关键规格:2.4 GHz 四核 CPU(ARM Cortex A-76),最高 8 GB RAM,支持 PCIe 接口的扩展
-
工程应用
-
嵌入式系统设计:开发和原型化嵌入式系统,用于实际应用。
-
物联网和网络设备:创建互联设备,并探索 MQTT、CoAP 和 HTTP/HTTPS 等协议。
-
控制系统:实现反馈控制回路、PID 控制器,并与执行器接口。
-
计算机视觉和 AI:利用 OpenCV 和 TensorFlow Lite 等库进行边缘图像处理和机器学习。
-
数据采集和分析:收集传感器数据,进行实时分析,并创建数据记录系统。
-
机器人技术:构建机器人控制器,实现运动规划算法,并与电机驱动器接口。
-
信号处理:执行实时信号分析、滤波和 DSP 应用。
-
网络安全:设置 VPN、防火墙,并探索网络渗透测试。
本教程将指导您设置最常用的 Raspberry Pi 型号,使您能够快速开始机器学习项目。我们将涵盖硬件设置、操作系统安装和初始配置,重点关注为 Pi 准备机器学习应用。
硬件概述
Raspberry Pi Zero 2W
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file778.jpg
-
处理器:1 GHz 四核 64 位 Arm Cortex-A53 CPU
-
RAM:512 MB SDRAM
-
无线:2.4 GHz 802.11 b/g/n 无线局域网,蓝牙 4.2,BLE
-
端口:迷你 HDMI,微型 USB OTG,CSI-2 摄像头连接器
-
电源:通过微型 USB 端口供电 5 V
Raspberry Pi 5
https://github.com/OpenDocCN/dsai-notes-pt3-zh/raw/master/docs/hav-cs249r-mlsys/img/file779.jpg
-
处理器:
-
Pi 5:四核 64 位 Arm Cortex-A76 CPU @ 2.4 GHz
-
Pi 4:四核 Cortex-A72(ARM v8)64 位 SoC @ 1.5 GHz
-
-
RAM:2 GB、4 GB 或 8 GB 选项(AI 任务推荐 8 GB)
-
无线:双频段 802.11ac 无线,蓝牙 5.0
-
端口:2 个微型 HDMI 端口,2 个 USB 3.0 端口,2 个 USB 2.0 端口,CSI 摄像头端口,DSI 显示端口
-
电源:通过 USB-C 连接器供电 5 V DC(3A)
在实验室中,我们将使用不同的名称来称呼 Raspberry:
Raspi、Raspi-5、Raspi-Zero等。通常,Raspi用于指令或注释适用于每个型号的情况。
安装操作系统
操作系统(OS)
操作系统(OS)是一种基本软件,它管理计算机的硬件和软件资源,为计算机程序提供标准服务。它是运行在计算机上的核心软件,作为硬件和应用软件之间的中介。操作系统管理计算机的内存、进程、设备驱动程序、文件和安全协议。
-
主要功能:
-
进程管理:为不同的程序分配 CPU 时间
-
内存管理:根据需要分配和释放内存
-
文件系统管理:组织和跟踪文件和目录
-
设备管理:与连接的硬件设备通信
-
用户界面:为用户提供与计算机交互的方式
-
-
组件:
-
内核:管理硬件资源的操作系统核心
-
Shell:与操作系统交互的用户界面
-
文件系统:组织和管理工作存储
-
设备驱动程序:允许操作系统与硬件通信的软件
-
Raspberry Pi 运行的是专为嵌入式系统设计的 Linux 专用版本。这个操作系统通常是 Debian 的一个变种,称为 Raspberry Pi OS(以前称为 Raspbian),针对 Pi 的 ARM 架构和有限资源进行了优化。
Raspberry Pi OS 的最新版本基于Debian Bookworm。
关键特性:
-
轻量级:针对 Pi 的硬件高效运行。
-
多功能:支持广泛的应⽤程序和编程语言。
131



被折叠的 条评论
为什么被折叠?



