Teachable Machine嵌入式神经网络视觉分类技术
本文介绍使用谷歌可教学机器学习平台训练神经网络,并部署至ArduinoNano33BLESense开发板,结合OV7670摄像头实现实时灰阶图像分类。具体步骤:采集96×96像素灰阶图像,导出TensorFlowLite微控制器模型,在Arduino上运行推理,通过串口输出识别结果及置信度。
本教程将循序渐进地指导你利用 Google Teachable Machine 训练一个轻量级神经网络,并将其成功部署至 Arduino 开发板,从而实现基于 OV7670 摄像头的实时灰阶图像分类。即使你没有深度学习基础,也只需跟随操作步骤即可轻松完成。
硬件准备
Arduino Nano 33 BLE Sense / Nano 33 BLE
目前官方明确仅支持此款板子,若使用其他型号编译时将会报错(官方未来可能会扩展兼容性)。详细技术规格请查阅官方页面:Arduino Nano 33 BLE Sense
实物照片如下(板子越来越小,考验视力):
重要信息印在盒装背面,当然看官网最快:
OV7670 相机模块
本教程选用 OmniVision 推出的 OV7670 摄像头模块,通过将其与 Arduino 连接,你可直接在 Teachable Machine 中采集灰度图像用于训练模型。详细规格参见官方数据手册:OV7670 数据手册
接线步骤
请使用母对母杜邦线,严格按照下表进行连接:
连接完成后的实物图:
温馨提示:接线前务必断开电源,并多次核对引脚编号。建议使用不同颜色的杜邦线来区分各功能引脚,以免接错。
软件环境搭建
Arduino IDE 安装与库配置
首先需要安装 Arduino IDE(本教程以 1.8.5 版本为例)。接着按照以下步骤添加必需的库:
- 安装 Arduino_TensorFlowLite 库:在 Arduino IDE 菜单栏点击
Tools → Manage Libraries,搜索Arduino_TensorFlowLite,选取 2.4.0-ALPHA 及以上版本,并点击安装按钮。 - 安装 Arduino_OV767X 库:同样在库管理器中搜索
Arduino_OV767X并点击安装。
Processing IDE 安装与库配置
Processing 作为桥梁,负责连接 Arduino 与 Teachable Machine 平台。请下载 Processing 3.X 版,可通过下方链接获取:下载地址
安装完成后,启动 Processing IDE,依次点击 Sketch → Add Library → Manage Libraries,搜索并安装以下两个库:
- ControlP5
- Websockets
Teachable Machine 操作步骤
Teachable Machine 内置的嵌入式模型是标准图像分类网络经精简后的迷你版本,专为微控制器(如 Arduino)优化。在开始使用 Teachable Machine 之前,请确保上述硬件和软件设置均已正确完成。
1. 下载并烧录 TMUploader Arduino 程序
首先下载 TMUploader 压缩包,解压后使用 Arduino IDE 打开包含的 .ino 文件。
在工具菜单中选择 Arduino Nano 33 BLE,并正确配置 COM 端口号。
该程序的功能是将 Arduino 摄像头采集到的图像数据发送至 Processing。
代码下载链接:TMUploader 代码库
2. 运行 TMConnector Processing 程序
接下来下载 TMConnector 压缩包,解压后在 Processing IDE 中打开对应的 .pde 文件。点击工具栏上的运行按钮(Play),程序将弹出如下窗口,显示可用的 COM 端口及连接状态:
在窗口列表中选择你的 Arduino 端口(如不确定是哪个,可对照 Arduino IDE 中显示的端口号)。连接成功后,Processing 窗口会实时显示摄像头画面。
温馨提示:若画面停滞或全黑,请检查 OV7670 接线是否牢固且正确。若画面模糊,可尝试旋转摄像头模块前端的镜头环以调节焦距。
3. 在 Teachable Machine 网站中连接设备
访问 Teachable Machine 官网,创建一个新的 Image Project。点击左侧的 Device 选项,再点击 Attempt to connect to device,若所有配置无误,你将看到 OV7670 摄像头传来的实时图像。
收集资料与训练模型
后续步骤与标准的 Teachable Machine 训练流程基本相同:
- 将摄像头对准待识别的目标物体,点击 Webcam 下的 Add Sample 按钮采集图像(采集的图像尺寸固定为 96×96 灰度图)。
- 即便你通过 Upload 上传彩色图片,训练后的模型依然只接受单色(灰度)输入。
- 重要提示:建议使用同一块 OV7670 摄像头模块完成训练与测试(即“原厂考照”原则),以确保模型在实际部署时获得最佳识别效果。
训练过程非常迅速。完成后点击右上角 Export Model 按钮,在弹出的对话框中选择 Tensorflow Lite 选项,并勾选下方的 Tensorflow Lite for Microcontrollers,最后点击 Download myModel 下载模型。
常见问题:如果下载的压缩包文件名并非 converted_tinyml.zip,请检查导出选项是否正确——务必勾选 Tensorflow Lite for Microcontrollers 复选框。
解压后,你会在 converted_tinyml 文件夹中找到模型相关文件:
在 Arduino 上运行模型
首先关闭所有 Processing 程序(因为它们占用了 COM 端口),同时确保 Arduino 仍与电脑保持连接。在 Arduino IDE 中新建项目(或沿用之前的 TMUploader 模板),将导出的模型文件(通常为 model.h 或 model_data.cpp)添加到项目文件夹中,并编写用于调用模型进行推理的代码(可参考官方示例)。然后编译并上传至 Arduino 开发板。
上传完成后,打开 Arduino IDE 的 Serial Monitor,你将看到每帧图像的分类结果及其置信度(置信度数值范围为 -128 至 127)。实时分类效果可参考本文引言部分的演示视频。
常见问题与解答
- Q:为什么 Processing 连接后没有画面?
A:请检查 OV7670 的接线是否准确,尤其注意时钟线和数据线的连接。同时确认 Processing 中已选择了正确的 COM 端口。 - Q:训练后的模型文件如何添加到 Arduino 项目?
A:解压converted_tinyml.zip后,将model.cpp和model.h文件复制到 Arduino 项目文件夹下,并在主程序中通过#include "model.h"包含头文件。 - Q:为什么 Serial Monitor 显示的置信度总是很低?
A:可能是训练样本数量不足或物体背景过于复杂。建议为每个分类类别收集至少 50 张图像,并尽可能在与训练时相似的光照环境下进行测试。 - Q:能否使用 ESP32-CAM 替代?
A:ESP32-CAM 配合 TensorFlow Lite 也可以实现类似功能,但本教程专门针对 Arduino Nano 33 BLE Sense 编写,请根据实际项目需求选择合适的硬件平台。
附录:完整代码
以下是本教程所涉及的 Arduino 程序(TMUploader)与 Processing 程序(TMConnector)的完整代码,你可以直接复制并用于你的项目中。
TMUploader Arduino 程序
#include
#include
#include"ImageProvider.h"
voidsetup() {
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltagelevel)
delay(400); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltageLOW
delay(400); // wait for a second
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltagelevel)
delay(400); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltageLOW
delay(400); // wait for a second
Serial.begin(9600);
while (!Serial);
}
constint kNumCols = 96;
constint kNumRows = 96;
constint kNumChannels = 1;
constint bytesPerFrame = kNumCols * kNumRows;
// QVGA: 320x240 X 2 bytes per pixel (RGB565)
uint8_tdata[kNumCols * kNumRows * kNumChannels];
voidflushCap() {
for (int i = 0; i < kNumCols * kNumRows *kNumChannels; i++) {
data[i] = 0;
}
}
voidloop() {
// Serial.println(000"creatingimage");
GetImage(kNumCols, kNumRows, kNumChannels,data);
// Serial.println("got image");
Serial.write(data, bytesPerFrame);
// flushCap();
}
TMConnector Processing 程序
importprocessing.serial.*;
importja va.nio.ByteBuffer;
importja va.nio.ByteOrder;
importwebsockets.*;
importja vax.xml.bind.DatatypeConverter;
importcontrolP5.*;
importja va.util.*;
SerialmyPort;
WebsocketServerws;
// mustmatch resolution used in the sketch
finalint cameraWidth = 96;
finalint cameraHeight = 96;
finalint cameraBytesPerPixel = 1;
finalint bytesPerFrame = cameraWidth * cameraHeight * cameraBytesPerPixel;
PImagemyImage;
byte[] frameBuffer= new byte[bytesPerFrame];
String[]portNames;
ControlP5cp5;
ScrollableListportsList;
booleanclientConnected = false;
voidsetup()
{
size(448, 224);
pixelDensity(displayDensity());
frameRate(30);
cp5 = new ControlP5(this);
portNames = Serial.list();
portNames = filteredPorts(portNames);
ws = new WebsocketServer(this, 8889,"/");
portsList =cp5.addScrollableList("portSelect")
.setPosition(235, 10)
.setSize(200, 220)
.setBarHeight(40)
.setItemHeight(40)
.addItems(portNames);
portsList.close();
// wait for full frame of bytes
//myPort.buffer(bytesPerFrame);
//myPort = new Serial(this, "COM5",9600);
//myPort = new Serial(this,"/dev/ttyACM0", 9600);
//myPort = new Serial(this, "/dev/cu.usbmodem14201",9600);
myImage = createImage(cameraWidth,cameraHeight, RGB);
noStroke();
}
voiddraw()
{
background(240);
image(myImage, 0, 0, 224, 224);
drawConnectionStatus();
}
voiddrawConnectionStatus() {
fill(0);
textAlign(RIGHT, CENTER);
if (!clientConnected) {
text("Not Connected to TM", 410,100);
fill(255, 0, 0);
} else {
text("Connected to TM", 410,100);
fill(0, 255, 0);
}
ellipse(430, 102, 10, 10);
}
voidportSelect(int n) {
String selectedPortName = (String) cp5.get(ScrollableList.class,"portSelect").getItem(n).get("text");
try {
myPort = new Serial(this, selectedPortName,9600);
myPort.buffer(bytesPerFrame);
}
catch (Exception e) {
println(e);
}
}
booleanstringFilter(String s) {
return (!s.startsWith("/dev/tty"));
}
intlastFrame = -1;
String[] filteredPorts(String[] ports) {
int n = 0;
for (String portName : ports) if(stringFilter(portName)) n++;
String[] retArray = new String[n];
n = 0;
for (String portName : ports) if(stringFilter(portName)) retArray[n++] = portName;
return retArray;
}
voidserialEvent(Serial myPort) {
// read the saw bytes in
myPort.readBytes(frameBuffer);
//println(frameBuffer);
// access raw bytes via byte buffer
ByteBuffer bb = ByteBuffer.wrap(frameBuffer);
bb.order(ByteOrder.BIG_ENDIAN);
int i = 0;
while (bb.hasRemaining()) {
//0xFF & to treat byte as unsigned.
int r = (int) (bb.get() & 0xFF);
myImage.pixels[i] = color(r, r, r);
i++;
//println("adding pixels");
}
if (lastFrame == -1) {
lastFrame = millis();
}
else {
int frameTime = millis() - lastFrame;
print("fps: ");
println(frameTime);
lastFrame = millis();
}
myImage.updatePixels();
myPort.clear();
String data = DatatypeConverter.printBase64Binary(frameBuffer);
ws.sendMessage(data);
}
voidwebSocketServerEvent(String msg) {
if (msg.equals("tm-connected"))clientConnected = true;
}
至此,你已经完成了所有配置,可以开始使用 Arduino 进行嵌入式视觉分类任务了!请根据具体项目需求选择合适的硬件和软件方案。祝你制作顺利!
你是一名 AI 行业编辑,请围绕下面这条热点输出一份资讯解读:
热点:Teachable Machine嵌入式神经网络视觉分类技术要求:
1. 先用一句话解释这条热点在讲什么
2. 再总结它为什么重要
3. 说明会影响哪些 AI 产品或内容方向
4. 最后给出 3 个适合资讯站使用的标题
游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。
相关热点最近留意到一款AI聊天机器人构建工具——Craftman,它的核心思路很有意思:让企业或个人能用自己已有的数据来训练ChatGPT,然后直接嵌入到网站上做智能客服或问答助手。简单来说,就是把通用大模型变成你的专属知识库响应系统。什么是Craftman?Craftman是一个AI聊天机器人构建平台,允
如果告诉你,现在借助AI技术就能一键生成时长16秒、分辨率达1080P的高清视频,并且画面流畅自然、物理规律真实可信,你是不是觉得有些不可思议?事实上,这就是Vidu——由中国生数科技与清华大学联合打造的全球首个长时长、高一致性、高动态性视频大模型。它采用独创的Diffusion与Transform
想象一下,你拥有一个庞大而复杂的知识库,里面堆满了各类文档、PDF文件以及YouTube视频教程。过去想要查找某份资料,往往需要翻遍目录、反复尝试关键词搜索,效率低下令人困扰。如今,借助Hansei这款知识库管理工具,一切变得轻松高效——你只需像与朋友聊天一样,用自然语言提出需求,AI助手就能从你的
Blinkn是基于ChatGPT的智能电商购物助手,具备语义理解、精准产品推荐与比较、多语言支持等功能,可与主流平台无缝集成并个性化定制,提供7×24小时实时客服,高效解决购物疑问,显著减少决策摩擦,提升转化率与用户体验。
- 日榜
- 周榜
- 月榜
热点快看
