基于reTerminal与Pi摄像头的嵌入式AI物体检测实战指南

📅 2026/8/1 10:54:26 👁️ 阅读次数 📝 编程学习
基于reTerminal与Pi摄像头的嵌入式AI物体检测实战指南

1. 从零开始:为什么选择 reTerminal 与 Pi 摄像头做物体检测?

如果你对嵌入式AI和物联网应用感兴趣,想亲手搭建一个能“看见”并“理解”周围世界的智能终端,那么“reTerminal + Pi摄像头”这个组合绝对是一个绝佳的起点。我最近刚完成了一个基于这个平台的物体检测项目,整个过程下来,感觉它完美地平衡了性能、成本和开发友好度,特别适合开发者、创客甚至是有一定动手能力的学生来实践。

reTerminal 本质上是一台高度集成、工业级的 Raspberry Pi CM4 计算模块载体。它自带一块5英寸的触摸屏、丰富的接口(包括专门用于摄像头的CSI接口)、可编程按键,甚至还有环境光传感器和IMU。这意味着你拿到手的就是一个完整的、带交互界面的嵌入式设备,省去了自己组装屏幕、连接各种外设的麻烦。而 Raspberry Pi 官方摄像头(简称 Pi 摄像头)则是经过充分验证的视觉传感器,与树莓派生态无缝兼容,驱动成熟,图像质量稳定。

将这两者结合做物体检测,核心价值在于:你可以在一个巴掌大小、功耗极低的设备上,实现实时的、本地的AI视觉推理,无需依赖云端网络。想象一下,你可以用它做一个智能门铃,识别门口的是人还是包裹;或者做一个生产线上的零件检测工站;甚至是一个能自动识别宠物的智能喂食器。这一切都运行在本地,数据隐私有保障,响应速度也快。最近业界对像嘉楠K230这类端侧AI芯片的讨论很热,其核心诉求也是边缘计算与低功耗,而我们用现成的树莓派生态(CM4+摄像头)就能快速验证类似的概念,门槛要低得多。

接下来,我将详细拆解从硬件准备、软件环境搭建、模型选择与优化,到最终部署和界面交互的完整流程。我会重点分享我在这个过程中踩过的坑和总结出的实用技巧,目标是让你看完就能动手复现一个属于自己的物体检测终端。

2. 硬件准备与环境配置:避开第一个大坑

工欲善其事,必先利其器。硬件连接看起来简单,但这里往往是第一个容易出错的地方。

2.1 硬件清单与正确连接

你需要准备以下核心硬件:

  1. reTerminal 设备:确保是搭载了 Raspberry Pi Compute Module 4(CM4)的版本。
  2. Raspberry Pi 摄像头模块:推荐使用 Pi Camera Module 3,因为它支持自动对焦,画质也更好。Camera Module 2 或 HQ Camera 也可以,但注意接口兼容性。
  3. CSI 排线:一般摄像头会附带。这里有个关键细节:reTerminal 的 CSI 接口是垂直向上的,而排线有金属触点的一面必须朝向 reTerminal 的 PCB 板方向(通常是与网口、USB口相反的方向)。插入后,轻轻拉一下黑色卡扣两侧的耳朵,锁紧排线。连接不牢是导致“无法识别摄像头”的最常见原因。
  4. 电源与存储:为 reTerminal 准备一个 5V/3A 的 Type-C 电源。CM4的eMMC存储已预装系统,无需额外SD卡。

连接好后,启动 reTerminal。第一次启动可能需要几分钟初始化。你会看到基于 Raspberry Pi OS 的桌面环境。

2.2 操作系统与基础软件安装

reTerminal 预装的系统可能不是最新,或者我们需要一个更干净的环境。我推荐从 Seeed Studio 官网下载专为 reTerminal 适配的 Raspberry Pi OS 镜像,它包含了屏幕、按键等所有硬件的驱动。

步骤一:更新系统与启用摄像头打开终端,首先进行全系统更新:

sudo apt update sudo apt full-upgrade -y sudo reboot

更新后,需要确保摄像头接口已启用。虽然 reTerminal 的专用镜像通常已配置好,但检查一下更稳妥:

sudo raspi-config

在配置界面中,选择Interface Options->Legacy Camera(或Camera,取决于系统版本),确保其被设置为Enable。完成后退出并重启。

步骤二:验证摄像头工作重启后,用一个简单命令测试摄像头:

libcamera-hello -t 0

这个命令会打开一个实时预览窗口。如果能看到图像,说明摄像头硬件连接和驱动完全正常。按Ctrl+C退出。

注意:传统的raspistill命令在最新的 Bullseye/Buster 系统上可能已被弃用或无法工作,libcamera系列命令是新的标准,务必使用它。

步骤三:安装 Python 环境与核心库我们的项目将主要使用 Python。安装 pip 和虚拟环境工具,管理项目依赖会更干净:

sudo apt install -y python3-pip python3-venv

然后创建一个项目目录并进入,建立虚拟环境:

mkdir ~/object_detection_project && cd ~/object_detection_project python3 -m venv venv source venv/bin/activate

激活虚拟环境后,命令提示符前会出现(venv)标识。接下来安装核心的计算机视觉库。这里有个选择:OpenCV。在树莓派上安装 OpenCV 如果从 pip 直接安装opencv-python,可能会遇到性能问题或缺少某些优化。我推荐使用针对 ARM 架构预编译的版本,或者从源码编译(耗时较长)。一个更快捷稳定的方法是安装libopencv系统包和 Python 绑定:

sudo apt install -y python3-opencv

在虚拟环境中,链接到系统已安装的 OpenCV:

pip install opencv-python-headless

此外,我们还需要安装图像处理库 PIL/Pillow,以及用于模型推理的框架。由于我们可能使用 TensorFlow Lite 或 ONNX Runtime 等轻量级引擎,先一并安装:

pip install pillow numpy pip install tflite-runtime

tflite-runtime是 TensorFlow Lite 的精简版,比安装完整的tensorflow包体积小得多,更适合嵌入式设备。

3. 物体检测模型的选择、获取与优化

模型是物体检测的大脑。在资源受限的 reTerminal(CM4通常为2GB或4GB内存)上,我们不能直接使用像 YOLOv8 原生 PyTorch 版本这样的大型模型,必须进行精心的选择和优化。

3.1 模型选型:在精度与速度间寻找平衡

对于边缘设备,我们的选型标准依次是:模型大小、推理速度(FPS)、精度(mAP)、易用性。以下是几个经过实战检验的候选:

  1. MobileNet SSD (TensorFlow Lite):经典中的经典。基于 MobileNet 骨干网络的单次检测器(SSD),模型小(约几MB到20MB),速度极快,在 COCO 数据集上能识别80类常见物体。缺点是对于小物体和密集场景的精度一般。
  2. YOLOv5/v8 Nano/Small (导出为 TFLite 或 ONNX):YOLO 系列在精度和速度的平衡上做得很好。YOLOv5n 或 YOLOv8n 是专为移动端设计的纳米版本,模型大小在 3-5MB 左右,在 CM4 上使用适当的推理引擎(如 ONNX Runtime)可以达到接近实时的速度。
  3. EfficientDet-Lite (TensorFlow Lite Model Maker):谷歌专门为 TFLite 优化的 EfficientDet 版本,在同等计算量下通常比 MobileNet SSD 精度更高。TFLite Model Maker 工具还能让你用自己的数据轻松微调。

我的选择与理由:对于初次实践和大多数通用场景,我推荐从MobileNet SSD COCO 量化模型开始。原因有三:首先,它极其成熟,社区资料和示例代码最多,踩坑容易找到解决方案;其次,TFLite 运行时在树莓派上优化得很好,部署最简单;最后,它的速度足够快,在 reTerminal 上实现 5-10 FPS 的检测预览是可行的,能满足很多实时性要求不极端的场景。

3.2 获取与准备模型文件

以 MobileNet SSD v2(COCO 数据集)为例,我们可以直接从 TensorFlow 官方模型仓库下载预训练的 TFLite 模型。

在项目目录下,创建一个models文件夹并下载模型:

mkdir models cd models wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip unzip coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.zip

你会得到detect.tflite(模型文件)和labelmap.txt(标签文件)。标签文件定义了模型能识别的 80+1 个类别(+1 是背景)。

重要:理解量化模型我们下载的是“量化”(Quantized)模型。这意味着模型权重从浮点数(float32)转换成了整数(int8)。量化能大幅减少模型体积和提升推理速度,对 CPU 非常友好,是边缘部署的标配。代价是精度会有轻微损失,但对于很多应用而言完全可以接受。

3.3 测试模型推理:编写第一个检测脚本

在项目根目录,创建一个test_detection.py脚本,进行静态图片测试,验证整个链路是否通畅。

import cv2 import numpy as np import tflite_runtime.interpreter as tflite from PIL import Image # 1. 加载模型和标签 MODEL_PATH = ‘models/detect.tflite’ LABEL_PATH = ‘models/labelmap.txt’ interpreter = tflite.Interpreter(model_path=MODEL_PATH) interpreter.allocate_tensors() # 获取输入输出详情 input_details = interpreter.get_input_details() output_details = interpreter.get_output_details() _, height, width, _ = input_details[0][‘shape’] # 通常为 300x300 with open(LABEL_PATH, ‘r’) as f: labels = [line.strip() for line in f.readlines()] # 2. 准备输入图像(这里用一张本地测试图,或直接用摄像头抓一帧) # 假设有一张 test.jpg image = cv2.imread(‘test.jpg’) image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) image_pil = Image.fromarray(image_rgb) # 调整尺寸并归一化(量化模型期望输入为 uint8) input_data = np.expand_dims(image_pil.resize((width, height)), axis=0) # 3. 推理 interpreter.set_tensor(input_details[0][‘index’], input_data.astype(np.uint8)) interpreter.invoke() # 4. 解析输出 boxes = interpreter.get_tensor(output_details[0][‘index’])[0] # 边界框 classes = interpreter.get_tensor(output_details[1][‘index’])[0] # 类别索引 scores = interpreter.get_tensor(output_details[2][‘index’])[0] # 置信度 num = interpreter.get_tensor(output_details[3][‘index’])[0] # 检测数量 # 5. 可视化结果 for i in range(int(num)): if scores[i] > 0.5: # 置信度阈值 ymin, xmin, ymax, xmax = boxes[i] # 将归一化坐标转换为原图坐标 (left, right, top, bottom) = (xmin * image.shape[1], xmax * image.shape[1], ymin * image.shape[0], ymax * image.shape[0]) cv2.rectangle(image, (int(left), int(top)), (int(right), int(bottom)), (0, 255, 0), 2) label = ‘{}: {:.2f}%’.format(labels[int(classes[i])], scores[i]*100) cv2.putText(image, label, (int(left), int(top)-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) cv2.imshow(‘Detection Result’, image) cv2.waitKey(0) cv2.destroyAllWindows()

运行这个脚本python test_detection.py,如果一切正常,你应该能看到图片中的物体被框出并标上了标签。这一步的成功,标志着模型和推理环境完全正确。

4. 实现实时摄像头流物体检测

静态图片测试通过后,我们就可以进入核心环节:连接 Pi 摄像头,进行实时视频流检测。这里的关键是高效地读取摄像头帧,并组织一个稳定的推理循环

4.1 使用 libcamera 与 OpenCV 捕获视频

如前所述,在新版系统上,我们使用libcamera作为底层驱动。但 OpenCV 的cv2.VideoCapture默认可能无法直接与libcamera通信。一个可靠的方法是使用libcamera-vid管道,或者使用一个名为picamera2的新库,它是为libcamera设计的 Python 接口。

首先安装picamera2

sudo apt install -y python3-picamera2

然后,我们编写实时检测脚本realtime_detection.py

import cv2 import numpy as np import tflite_runtime.interpreter as tflite from picamera2 import Picamera2 from PIL import Image import time # 初始化摄像头 picam2 = Picamera2() # 配置预览格式:主流格式,与模型输入兼容 config = picam2.create_preview_configuration(main={“size”: (640, 480), “format”: “RGB888”}) picam2.configure(config) picam2.start() # 加载模型和标签(同上,此处省略以节省篇幅) interpreter = tflite.Interpreter(model_path=‘models/detect.tflite’) interpreter.allocate_tensors() input_details = interpreter.get_input_details() output_details = interpreter.get_output_details() _, input_height, input_width, _ = input_details[0][‘shape’] # 加载标签 with open(‘models/labelmap.txt’, ‘r’) as f: labels = [line.strip() for line in f.readlines()] # 帧率计算 fps_start_time = time.time() fps_frame_count = 0 fps = 0 print(“开始实时检测,按 ‘q’ 键退出...”) try: while True: # 从摄像头捕获一帧 frame = picam2.capture_array() # 直接得到 numpy array (RGB) if frame is None: continue # 计算并显示FPS fps_frame_count += 1 if fps_frame_count >= 30: fps = fps_frame_count / (time.time() - fps_start_time) fps_start_time = time.time() fps_frame_count = 0 cv2.putText(frame, f“FPS: {fps:.1f}”, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 准备模型输入 img_pil = Image.fromarray(frame) input_data = np.expand_dims(img_pil.resize((input_width, input_height)), axis=0) # 推理 interpreter.set_tensor(input_details[0][‘index’], input_data.astype(np.uint8)) interpreter.invoke() # 获取结果 boxes = interpreter.get_tensor(output_details[0][‘index’])[0] classes = interpreter.get_tensor(output_details[1][‘index’])[0] scores = interpreter.get_tensor(output_details[2][‘index’])[0] num = interpreter.get_tensor(output_details[3][‘index’])[0] # 在原图上绘制检测框 for i in range(int(num)): if scores[i] > 0.5: # 置信度阈值 ymin, xmin, ymax, xmax = boxes[i] left = int(xmin * frame.shape[1]) right = int(xmax * frame.shape[1]) top = int(ymin * frame.shape[0]) bottom = int(ymax * frame.shape[0]) cv2.rectangle(frame, (left, top), (right, bottom), (0, 255, 0), 2) label = f“{labels[int(classes[i])]}: {scores[i]*100:.1f}%” cv2.putText(frame, label, (left, top-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) # 显示结果 (BGR格式供OpenCV显示) frame_bgr = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR) cv2.imshow(‘Object Detection on reTerminal’, frame_bgr) # 按 ‘q’ 退出 if cv2.waitKey(1) & 0xFF == ord(‘q’): break finally: # 释放资源 picam2.stop() cv2.destroyAllWindows() print(“程序结束。”)

这个脚本创建了一个稳定的检测循环。picamera2直接提供 numpy 数组,避免了格式转换的额外开销。我们同时计算并显示了帧率(FPS),这是评估性能的关键指标。

4.2 性能调优与实战踩坑记录

直接运行上述脚本,你可能会发现 FPS 并不高,可能在 2-4 之间。这对于实时体验来说有点卡顿。下面是我经过多次尝试后总结的优化策略:

1. 降低输入分辨率与巧用线程:模型输入是300x300,但摄像头捕获是640x480。resize操作是 CPU 计算,有开销。我们可以尝试在摄像头配置时就用一个更低的分辨率,比如直接匹配模型输入:

config = picam2.create_preview_configuration(main={“size”: (300, 300), “format”: “RGB888”})

但这样预览窗口会很小。一个折中方案是:用低分辨率做推理,高分辨率做显示。我们可以配置摄像头输出两个流(still stream 和 preview stream),但这稍复杂。更简单实用的优化是使用生产者-消费者模型,将图像捕获和模型推理放在两个线程中,避免因推理阻塞导致掉帧。

2. 模型推理加速 - 使用 Coral USB 加速器(可选进阶):如果对速度有极致要求(例如需要 20+ FPS),可以考虑添加硬件加速器。Google Coral USB Accelerator 是一个即插即用的边缘 TPU 设备,能极大加速量化 TFLite 模型。你需要下载专门编译的、兼容 Edge TPU 的模型文件(后缀为_edgetpu.tflite),并安装pycoral库。使用后,FPS 可以轻松提升一个数量级。这对于需要快速响应的应用(如高速流水线检测)是质的飞跃。

3. 发热与稳定性:长时间运行,CM4 会发热。reTerminal 的金属外壳有助于散热,但在高负载下仍可能过热降频。我建议:

  • /boot/config.txt中添加temp_soft_limit=85(如果不存在),这允许芯片在更高温度下运行。
  • 考虑在 reTerminal 背面粘贴小型散热片。
  • 对于 24/7 运行的应用,最好在代码中添加温度监控,在温度过高时暂停检测或降低推理频率。

4. 一个常见的坑:picamera2的权限问题有时运行脚本会报错,提示无法打开摄像头。除了检查物理连接,还需要确保用户有访问摄像头的权限。将当前用户加入video组通常可以解决:

sudo usermod -a -G video $USER

然后需要注销并重新登录,或者重启系统,这个改动才能生效。

5. 打造交互式应用:利用 reTerminal 的硬件特性

reTerminal 不仅仅是一台“无头”的树莓派,它的屏幕和按键为我们提供了打造独立交互式应用的绝佳条件。我们可以摆脱对 SSH 和远程桌面的依赖,制作一个即开即用的检测终端。

5.1 使用 PyGame 或 Kivy 创建本地 GUI

OpenCV 的cv2.imshow()窗口在 reTerminal 的桌面环境下可以运行,但它不是一个原生的、全屏的、易于控制的应用。为了更好的体验,我们可以使用 PyGame 或 Kivy 这类 GUI 库来创建界面。

这里以 PyGame 为例,因为它更轻量,且适合简单的图像显示和按键交互。我们将修改之前的实时检测脚本,用 PyGame 窗口替代 OpenCV 的显示。

首先安装 PyGame:

pip install pygame

然后创建detection_gui.py

import pygame import cv2 import numpy as np import tflite_runtime.interpreter as tflite from picamera2 import Picamera2 from PIL import Image import time from threading import Thread, Lock # 初始化 Pygame pygame.init() screen_width, screen_height = 800, 480 # reTerminal 屏幕分辨率 screen = pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption(“reTerminal Object Detector”) clock = pygame.time.Clock() # 摄像头和模型初始化(与之前类似,略去细节) picam2 = Picamera2() config = picam2.create_preview_configuration(main={“size”: (640, 480)}) picam2.configure(config) picam2.start() interpreter = tflite.Interpreter(model_path=‘models/detect.tflite’) interpreter.allocate_tensors() # ... 加载标签等代码 ... # 线程安全的帧和结果存储 current_frame = None current_detections = [] # 存储格式: [(label, score, (x1,y1,x2,y2)), ...] frame_lock = Lock() def inference_thread(): global current_frame, current_detections while True: with frame_lock: if current_frame is None: time.sleep(0.01) continue frame_copy = current_frame.copy() # 在此帧上进行推理... # ... 推理代码,更新 current_detections ... time.sleep(0.05) # 控制推理频率,避免过度占用CPU # 启动推理线程 Thread(target=inference_thread, daemon=True).start() running = True while running: # 处理 Pygame 事件(如退出、按键) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: # 按ESC退出 running = False elif event.key == pygame.K_SPACE: # 按空格保存截图 pygame.image.save(screen, f“capture_{int(time.time())}.jpg”) # 从摄像头获取最新帧 frame_rgb = picam2.capture_array() with frame_lock: current_frame = frame_rgb display_frame = frame_rgb.copy() # 在显示帧上绘制检测结果(从 current_detections 读取) # ... 绘制矩形和文本的代码 ... # 将 OpenCV 图像(RGB)转换为 Pygame 表面(需要转置和BGR2RGB?注意通道) # Pygame 期望的格式是 (width, height, RGB) frame_surface = pygame.surfarray.make_surface(np.transpose(display_frame, (1, 0, 2))) # 缩放表面以适应屏幕(可选) frame_surface = pygame.transform.scale(frame_surface, (screen_width, screen_height)) # 刷新屏幕 screen.blit(frame_surface, (0, 0)) pygame.display.flip() clock.tick(30) # 限制帧率 picam2.stop() pygame.quit()

这个框架将图像捕获(主线程)、模型推理(子线程)和界面渲染(主线程)分离,保证了界面的流畅性。同时,它响应了 reTerminal 的物理按键(通过 PyGame 的键盘事件),例如用 ESC 键退出,用空格键保存当前检测结果的截图。

5.2 利用 reTerminal 侧边按键与传感器

reTerminal 的侧边有5个可编程按键(A, B, C, D, 以及一个功能键)。我们可以将这些按键映射为应用功能,例如:

  • A键:切换检测模型(例如在“人”检测和“车”检测模型间切换)。
  • B键:调整置信度阈值。
  • C键:开启/关闭检测结果显示,仅显示原始视频流。
  • D键:拍照并保存。
  • 功能键:退出应用。

在 PyGame 中,我们可以通过监听pygame.KEYDOWN事件,并判断event.key的值来捕获这些按键。需要先确认 reTerminal 上这些按键映射到了哪个键值,通常可以通过写一个简单的测试脚本来打印event.key得知。

此外,reTerminal 板载的环境光传感器和 IMU(惯性测量单元)也大有可为。例如,可以用环境光传感器自动调节屏幕亮度;用 IMU 检测设备姿态,当 reTerminal 被拿起或移动时,自动唤醒或进入检测模式。这些传感器的访问通常需要通过 I2C 或特定的 Linux 设备文件,需要安装额外的 Python 库(如smbus2读取 I2C)。

6. 项目进阶与优化思路

一个基础的可视化检测应用完成后,我们可以从以下几个方向进行深化,让它变成一个更“有用”的项目。

6.1 模型定制化:训练识别特定物体

预训练的 COCO 模型能识别80类物体,但如果你只想识别“螺丝刀”、“某种特定零件”或“自家宠物”,就需要定制模型。这里推荐使用TensorFlow Lite Model Maker。它大大简化了迁移学习的过程。

基本流程如下:

  1. 收集数据:为你想要识别的物体(例如,“咖啡杯”)拍摄至少100-200张照片,最好在不同的角度、光照和背景下拍摄。用标注工具(如 LabelImg)标注出物体位置,生成 XML(VOC格式)或 JSON(COCO格式)文件。
  2. 准备环境:在一台性能更强的机器(如你的开发电脑)上安装 TensorFlow 和 Model Maker。
  3. 运行训练脚本:Model Maker 提供了示例脚本,你只需指定数据路径和预训练模型(如efficientdet-lite0),它就能自动完成数据转换、训练和导出 TFLite 模型。
  4. 部署:将生成的.tflite文件拷贝到 reTerminal,替换之前的模型文件,更新标签路径,你的应用就变成了一个专属检测器。

6.2 集成与联动:从“看见”到“行动”

单纯的检测和显示价值有限,真正的威力在于与外部世界联动。

  • 网络通信:检测到特定物体后,通过 reTerminal 的 Wi-Fi 或以太网,向服务器(如 Home Assistant, MQTT Broker)发送一条消息。例如,检测到“人”,就发送一条person_detected事件到智能家居系统,触发灯光或警报。
  • 控制 GPIO:reTerminal 有可用的 GPIO 引脚(通过 40-pin 排针引出)。你可以通过gpiozeroRPi.GPIO库控制继电器、LED 灯或蜂鸣器。例如,检测到“猫”靠近喂食器,就触发 GPIO 信号打开一个舵机,放出猫粮。
  • 本地日志与存储:将检测到的事件(时间、物体类别、置信度)记录到本地的 SQLite 数据库或 CSV 文件中,用于后续分析。

6.3 性能与功耗的终极权衡

对于电池供电或长期值守的应用,功耗是关键。

  • 动态帧率:不是每一帧都需要检测。当场景静止时,可以降低检测频率(如每秒1次);当 IMU 检测到运动或画面变化剧烈时,再提升到全速检测。
  • 模型休眠:在无人时段,可以完全停止摄像头和推理进程,让系统进入低功耗的休眠状态,由定时器或外部传感器唤醒。
  • 选择更优模型:对比不同轻量级模型(如 YOLO-Fastest, NanoDet)在你的特定场景下的精度、速度和功耗,选择最优解。

经过以上步骤,你手中的 reTerminal 就不再只是一个开发板,而是一个功能完整、可交互、能解决实际问题的智能视觉终端。从硬件连接、软件配置、模型推理到应用开发,整个流程走下来,你会对边缘AI视觉项目有一个非常扎实的理解。最重要的是,这个过程是可复现、可扩展的,你可以基于这个框架,去实现任何你想象中的视觉应用。