利用TensorFlow和ArduinoNano对桌面物体进行分类
立即解锁
发布时间: 2025-08-31 00:22:48 阅读量: 11 订阅数: 24 AIGC 


TinyML实战:微控制器上的机器学习
# 利用 TensorFlow 和 Arduino Nano 对桌面物体进行分类
## 1. 图像采集优化
在使用摄像头进行图像采集时,若无法获取之前的测试图案,建议先验证摄像头与 Arduino Nano 之间的接线。此前在编译 Arduino Nano 草图时,可能会在 IDE 输出日志中看到“内存不足,可能影响稳定性”的警告,这是因为 RGB565 格式的 QVGA 图像需要 153.6 KB 的缓冲区,约占微控制器可用 SRAM 的 60%。
为解决内存问题,可降低图像分辨率并采用更高效的颜色编码方式。常见的降低图像分辨率的方法是使用比 QVGA(320x240)更小的分辨率,如 QQVGA(160x120)或 QQQVGA(80x60)。而 OV7670 摄像头模块提供了一种更高效的颜色编码格式 YCbCr422。
### 1.1 YCbCr422 格式介绍
YCbCr422 是一种数字颜色编码,它不是用红、绿、蓝强度来表示像素颜色,而是用亮度(Y)、蓝色差(Cb)和红色差(Cr)色度分量来表示。在 YCbCr422 格式中,Cb 和 Cr 分量在单条扫描线上的两个相邻像素之间共享,一个 YCbCr422 单元由 4 个字节编码 2 个像素。
与 RGB565 相比,YCbCr422 图像字节数相同,但图像质量更好,接近 RGB888。不过,将 YCbCr422 转换为 RGB888 需要更多的算术运算。
### 1.2 操作步骤
以下是使用 OV7670 摄像头模块以 QQVGA 分辨率和 YCbCr422 颜色格式采集图像的步骤:
1. **调整相机缓冲区大小**:
```cpp
uint8_t data[160 * 120 * 2];
```
QQVGA 分辨率使帧缓冲区比之前的草图小四倍。
2. **编写限制值范围的函数**:
```cpp
template <typename T>
inline T clamp_0_255(T x) {
return std::max(std::min(x, (T)(255)), (T)(0));
}
```
该函数用于确保从 Y、Cb 和 Cr 值导出的 RGB888 颜色通道在 0 到 255 之间。
3. **编写从 Y、Cb 和 Cr 分量提取 RGB888 像素的函数**:
```cpp
void ycbcr422_rgb888(int32_t Y, int32_t Cb,
int32_t Cr, uint8_t* out) {
Cr = Cr - 128;
Cb = Cb - 128;
int32_t r;
int32_t g;
int32_t b;
r = Y + Cr + (Cr >> 2) + (Cr >> 3) + (Cr >> 5);
g = Y - ((Cb >> 2) + (Cb >> 4) + (Cb >> 5)) -
((Cr >> 1) + (Cr >> 3) + (Cr >> 4));
b = Y + Cb + (Cb >> 1) + (Cb >> 2) + (Cb >> 6);
out[0] = clamp_0_255(r);
out[1] = clamp_0_255(g);
out[2] = clamp_0_255(b);
}
```
该函数每次只能返回一个 RGB888 像素,要获取两个 RGB888 像素,需调用该函数两次,并传入不同的 Y 值。
4. **初始化相机**:
```cpp
if (!Camera.begin(QQVGA, YUV422, 1)) {
Serial.println("Failed to initialize camera!");
while(1);
}
```
注意,虽然传入的是 YUV422,但实际上是为 YCbCr422 初始化设备。
5. **读取并转换像素**:
```cpp
int32_t step_bytes = Camera.bytesPerPixel() * 2;
int32_t i = 0;
for(; i < bytes_per_frame; i+=step_bytes) {
const int32_t Y0 = data[i + 0];
const int32_t Cr = data[i + 1];
const int32_t Y1 = data[i + 2];
const int32_t Cb = data[i + 3];
ycbcr422_rgb888(Y0, Cb, Cr, &rgb888[0]);
Serial.println(rgb888[0]);
Serial.println(rgb888[1]);
Serial.
```
0
0
复制全文
相关推荐









