概述
如果你对Arduino Nano 33 BLE Sense上的嵌入式机器学习(TinyML)感兴趣,你会发现开发板上有大量的传感器——数字麦克风、加速计、陀螺、磁强计、光线、接近度、温度、湿度和颜色——但你要实现视觉识别你需要增加一个外部摄像头。
在这篇文章中,我们将向你展示如何用一个低成本的VGA摄像头模块获取图像数据。我们将使用Arduino_OVD767x库。使摄像头软件方面的工作大大简化。
硬件配置
要开始学习和实验,需要以下硬件:
- Arduino Nano 33 BLE Sense带针座
- OV7670 CMOS VGA摄像头模块
- 16根母头跳线
- 一根连接Arduino和电脑的microUSB数据线
你当然可以用一块没有排针的板,用焊接代替跳线,如果喜欢焊接的话。
这种设置的一个缺点是(以模块形式)有很多跳线要连接。这并很容易,但你需要注意在两端连接是否正确和可靠。一旦连接完成,你可以用胶带固定电线,以免其中一根松动。
您需要按照下表所示连接导线:
软件安装
首先,安装Arduino IDE或注册Arduino Create在线工具。安装并打开环境之后,就可以在库管理器中使用camera库了。
- 安装Arduino IDE或注册Arduino Create在线编程工具
- 从菜单栏的工具>管理库,并搜索OV767库
- 点击安装按钮
现在,我们将使用示例示程序来测试导线是否连接正确:
示例> Arduino_OV767X > CameraCaptureRawBytes
从第48行取消注释(删除//) 以显示一个测试模式
Camera.testPattern();
- 编译并上传到你的开发板
Arduino现在通过串口输出原始图像二进制文件。为了将其视为图像,我们包含了一个特殊的应用程序,用于使用Processing查看摄像机输出的图像。
Processing是一个简单的编程环境,它是由麻省理工学院媒体实验室的研究生们创建的,用于更容易地开发以视觉为导向的应用程序,重点是动画,并通过交互为用户提供即时反馈。这个软件在我专栏的一篇文章有详细介绍。
安装和打开“Processing”
将CameraVisualizerRawBytes代码粘贴到Processing 示例中
编辑第31-37行以匹配您的Arduino所连接的机器和串口
在处理中点击播放按钮,你应该会看到一个测试模式(图像更新需要几秒钟):
如果一切顺利,您应该看到上面的彩色条纹测试模式!
接下来,我们将回到Arduino IDE编辑程序,这样Arduino就会摄像头发送一个实时图像到Processing viewer中:
- 返回Arduino IDE
- 注释掉Arduino示例程序的第48行
// 我们已经禁用了测试模式,并将显示一个实时图像
// Camera.testPattern();
编译并上传到开发板
一旦程序上传完成,再次点击Processing 播放按钮
几秒钟后,你现在应该看到一个实时图像,如下图所示:
连接嵌入式机器学习库(TinyML)
- 我们的小相机输出的完整的VGA(640×480分辨率)对于目前的TinyML应用来说太大了。uTensor使用28×28幅图像的MNIST(手写数字识别)进行笔迹检测。TensorFlow Lite微控制器示例中的人员检测示例使用了96×96像素,这已经足够了。即使是最先进的“Big ML”应用程序通常也只能使用320×320像素的图像(参见TinyML手册)。也考虑8位灰度VGA图像不压缩将占用300KB的存储空间,而Nano 33 BLE Sense只有256KB的RAM。我们必须做些什么来压缩图像的大小!
相机格式选项
OV7670模块通过配置选项支持低分辨率。这些选项在到达Arduino之前修改图像数据。目前通过库可进行的配置有:
- VGA – 640 x 480
- CIF – 352 x 240
- QVGA – 320 x 240
- QCIF – 176 x 144
这是一个很好的开始,因为它减少了将图像从相机发送到Arduino板的延时。它还减少了Arduino程序中所需的图像数据数组的大小。通过改变Camera.begin中的值来选择分辨率。同时也不要忘记更改数组的大小。
Camera
相机库还提供了不同的颜色格式:YUV422、RGB444和RGB565。它们定义了颜色值是如何编码的,并且在我们的图像数据中每像素占用2字节。我们使用的是RGB565格式,5位表示红色,6位表示绿色,5位表示蓝色:
通过以下的操作将2字节的RGB565像素转换为图形中单独的红、绿、蓝值:
// Convert from RGB565 to 24-bit RGB
在Arduino上调整图像大小
一旦我们将图像数据传输到Arduino板上,我们就可以进一步压缩图像的大小。只是移除像素将会使图像出现锯齿(别名)。为了更顺利地完成这一任务,我们需要一个下缩减像素采样算法来插入像素值,并用它们来创建一个更小的图像。
用于重新采样图像的技术本身就是一个有趣的话题。我们发现这个来自Eloquent Arduino的缩减像素采样示例可以很好地处理Arduino_OV767X相机库输出(参见上面的GIF动画)。
应用程序如TensorFlow Lite Micro Person Detection example,使用基于CNN的模型在Arduino上进行机器视觉,可能不需要对图像进行任何进一步的预处理——除了平均RGB值,以去除每像素8位灰度数据的颜色。
但是,如果您确实希望执行标准化,那么使用Arduino max和min函数在像素之间迭代是获得输入像素值的上限和下限的一种方便的方法。然后可以使用map将输出像素值缩放到0-255范围。
byte pixelOut = map(input[y][x][c], lower, upper, 0, 255);
结论
本文介绍了如何将OV7670摄像头模块连接到Arduino Nano 33 BLE Sense开发板上,以及为TinyML应用程序从摄像头获取数据时的一些注意事项。关于Arduino上的机器视觉,还有很多值得探索的地方——这只是一个开始!