TOF多区传感器: ND06
ND06是一款微型多区高集成度ToF测距传感器,其支持24个区域(6 x 4)同步测距,测距范围远达5m,具有测距范围广、精度高、测距稳定等特点。适用于投影仪的无感自动对焦和梯形校正、AIoT、手势识别、智能面板和智能灯具等多种场景。
如果用ND06进行手势识别,只需要经过三个步骤:
第一步 : 对ND06的数据采集,要多快好省。
多 --- 指的是一次采集24个区域(6 x 4) 的数据。
快 --- 30HZ 的采集速度。
好---数据要准确
省是省电 。
你想,每秒30*24 个数据, 假设一个手势用时1.2s, 则需要 1.2*30*24 个数据来分析。
每次手势还不同,如果同这么多数据分析出您是左滑还是右滑,还是画个Z,
如果用单纯程序来分析出来,估计会让所有的程序员崩溃。
好在现在这种分析,可以让AI 来干。
采集数据 就是在传感器前面,做出100个(这个越多越好,我是由于体力不支外加懒惰)正确的动作,譬如说左滑,让传感器采集。
从而得到要训练的数据。
鉴于数据量大,保证在MCU不合适, 因此每采集一帧,用UART口传到PC 上进行保存。
无论动作快慢,都上传保存1.2s 的数据。
MCU 用的是ESP32, 软件可以用arduino IDE, 但是我用的PlatformIO
ESP32 Arduino 2.0.3
关于安装之类的就不进行基础说明了。
第二步是训练。
得到训练的数据后,首先要进行数据的转换。
因为上传上来的数据是BIN格式, 是16进制的数据, 存放在文件中。
这时候 BIN 文件 转换成 SCV 文件 ,格式转换是为了给PYTHON 分析和使用。
转换文件:bin2scv.py
这个程序的作用就是打开,取出数据,转换成字符串, 每个字符串中间加分隔符,每一帧字符串后 加 换行符。
数据分析用的一下版本: 这个要注意,有些软件版本兼容性比较差,一旦改版本,出现的错误会让人头大。
python 3.8.10
TensorFlowLite_esp32 0.9.0
训练程序 :tinyml.py (注明:本程序是大神HIGHT 所写,我只是为自己的应用改动了一点点参数)
tinyml.py 的主要作用有5个步。
1) 数据标准化
把数据变成-1 至1 之间的浮点数,并存入数组。
这个过程内存消耗有点惊人。
2) 创建模型: 一共创建了3层模型。
第一层输入层是1.2 秒采集的所有数据。 偏置是32;
model.add(layers.Dense(32, activation='relu', input_shape=(16*SAMPLES_PER_GESTURE,)))
第二层是隐藏层 ,偏置16
model.add(layers.Dense(16, activation='relu')) #隐藏层
第三层是输出层
model.add(layers.Dense(2, activation='softmax')) #最后输出2个。 输出层
3) 训练模型 (核心)
SampleCount = len(x)
# split into train, validation, test
TRAIN_SPLIT = int(0.8 * SampleCount) #用80%的用来训练
x_train, x_validate = np.split(x, [TRAIN_SPLIT, ]) #训练集
y_train, y_validate = np.split(y, [TRAIN_SPLIT, ])
history = model.fit(x_train, y_train, epochs=600, batch_size=16, validation_data=(x_validate, y_validate))
可以看出,训练的程序也很简单,就一句话的事情。
关于为什么用80%的数据来训练,是因为要保留20% 的数据来进行验证。
我理解这个训练 , 就是拟合。
我增加了一段图形程序 ,来看看是否有过拟合的现象
# 用图形软件 查看是否过拟合,欠拟合
loss = history.history['loss']
val_loss = history.history['val_loss']
epochs = range(1,len(loss)+1)
plt.plot(epochs,loss,'g.',label = 'Training loss')
plt.plot(epochs,val_loss,'b',label='Validation loss')
plt.title('Training and validation loss')
plt.xlabel('Epochs')
plt.ylabel('loss')
plt.legend()
plt.show()
过拟合就是你给的数据都太一致,重复性太强,AI学习的曲线太一致,造成的结果就是一旦给出的手势稍微不一样,AI就会判断出错。 太认死理。
4) #模型优化 把tensorflow 的模型 转换成 tensorflow lite ; 做个简化版本
这步的作用是我们用的MCU ,资源受限,不要太臃肿的模型。
5)把 简化版本tensorflow lite 转换成能用于C 编程的头文件
最终的结果是得到一个生成的model.h
第三步 得到.H 文件后, 放入MCU
#include
#include
#include
#include "tensorflow/lite/experimental/micro/kernels/all_o
#include "tensorflow/lite/experimental/micro/micro_error_r
#include "tensorflow/lite/experimental/micro/micro_interpr
#include
// #include "sine_model_data.h"
#include "model.h" // 加载TENSORflow LITE 模型
在MCU 程序中,采集到1.2秒的数据后,就把数据标准化后 放在模型的端口上,让其分析。
根据输出的tflOutputTensor->data 的值,比较阀值 ,得出结论。
if (Inference()) Result();
核心程序:
bool Inference()
{
bool ret = false;
// Copy Data to Model Input
for (int k = 0; k < SAMPLE_COUNT; k++) {
for (int i = 0; i < 16; i++) {
tflInputTensor->data.f[k * 16 + i] = Samples[k]; //把模型数据 放到模型的端口上
}
}
// ExeTimer.Start();
TfLiteStatus invokeStatus = tflInterpreter->Invoke(); // 启动模型推理
// unsigned long t = ExeTimer.End();
// Check Result
if (invokeStatus == kTfLiteOk)
{
// sprintf(SerialBuffer, "Invoke In %8.6f(ms)", t / 1000.0);
// Serial.println(SerialBuffer);
ret = true;
}
else
{
Serial.println("Invoke failed!");
}
return ret;
}
return ret;
}
文章评论(0条评论)
登录后参与讨论