如何使用手势识别和嵌入式机器学习来控制物理模型
扫描二维码
随时随地手机看文章
UoM工程大楼的手势控制模型使用Pi 5 + ML -挥挥手,建筑就会移动。
我们开发了一个交互式的,由手势控制的曼彻斯特大学工程大楼的比例模型,由机器学习和嵌入式系统提供动力。
我们的模型实时响应手势:
•向左滑动→左边的建筑打开
•向右滑动→右侧打开
•举起双臂做t字姿势→整个建筑旋转
这种非接触式控制系统允许用户以一种全新的方式与物理结构进行交互,为教育工具,展览和智能环境提供了无限的可能性。
我们为什么要建造它
我们开始探索如何使用手势识别和嵌入式机器学习来控制物理模型。我们的目标是展示如何利用这些技术来创造直观、身临其境的体验,让用户以一种更自然、更免提的方式与模型或环境互动。
在许多情况下,传统的交互方法(如按钮或屏幕)可能会受到限制。通过结合手势控制,我们使用户无需触摸就能与系统互动,增加了灵活性和可访问性。这一概念适用于:
•智能建筑:对人类输入做出反应的建筑或空间。
•交互式展览:用户可以通过简单的手势控制模型或显示系统。
•公共空间:用于与技术的非接触式交互,确保易用性和可达性。
它是如何工作的
手势识别该系统使用带有摄像头的树莓派5来实时检测手势。使用TensorFlow Lite模型进行有效的手势分类。我们训练模型识别特定的手势:
•向左滑动:启动模型左侧的打开。
•向右滑动:触发右侧打开。
•T-pose:命令模型绕其中心轴旋转。
驱动(树莓派Pico)树莓派Pico作为伺服电机的实时控制器,对模型进行物理操作:
•两个伺服电机控制着建筑左右两侧的开口。
•当检测到t姿势手势时,一个中央伺服电机控制模型的旋转。
•Pi 5(用于手势检测)和Pico(用于实时电机控制)之间的这种分工确保了系统以最小的延迟高效运行。
技术栈
树莓派5:
•使用TensorFlow Lite运行手势检测模型,以实现高效的基于边缘的机器学习推理
•使用OpenCV处理摄像头输入和检测手势。
TensorFlow Lite: TensorFlow的轻量级版本,针对树莓派等边缘设备进行了优化。它可以实现高效的实时手势识别。
有限状态机:跟踪用户手势并解释动作序列以确定适当的模型响应。FSM确保动作只有在正确的手势执行时才会发生。
树莓派Pico:与伺服电机接口的微控制器,用于实时控制模型的运动。
伺服电机:控制模型打开和旋转的物理执行器。这些都是通过树莓派Pico供电和控制的。
定制设计模型:UoM工程建筑模型是用泡沫板和3d打印部件手工制作的,以创建结构的功能表示。该模型设计有三个关键的移动部件:
•左侧开口
•右侧开口
•中心旋转机构
我们学到了什么
嵌入式设备上的实时机器学习:使用树莓派5进行实时手势识别,与TensorFlow Lite配对,证明既高效又响应迅速。
伺服控制:管理树莓派Pico的实时驱动和协调伺服运动是具有挑战性的,但展示了使用低成本硬件创建交互式模型的能力。
手势灵敏度和校准:微调手势检测需要反复测试,以平衡精度和响应在不同的照明条件和环境。
潜在应用
AURA项目展示了基于手势的控制系统在各个领域应用的潜力:
互动展览:博物馆、科学中心和教育机构可以使用手势控制模型来吸引游客,并以动手的方式展示复杂的系统。
智能建筑:这个概念可以演变成一个系统,用户可以通过手势控制建筑元素,比如百叶窗、窗户甚至房间。
公共空间:在商场、公共交通或智能城市等环境中,用户可以通过手势与数字显示器、模型甚至物理结构进行交互,从而减少了对物理接触点的需求。
结论
AURA项目表明,机器学习和嵌入式系统可以无缝集成,以创建免提的交互式体验。通过使用简单的手势来控制物理模型,我们提供了直观的、响应式架构的未来一瞥。
我们相信这个项目只是一个开始,随着进一步的发展,它可以扩展到智慧城市、无障碍技术和教育工具的应用中。
代码
#include
Servo rightServo;
Servo leftServo;
const int ledPin = 25; // Onboard LED for Pico
const int rightPin = 2; // GP2 (physical pin 4)
const int leftPin = 3; // GP3 (physical pin 5)
const int inp1 = 0; // Right servo control (active HIGH)
const int inp2 = 1; // Left servo control (active HIGH)
// Servo states (FSM)
bool rightServoState = false; // false=0°, true=180°
bool leftServoState = false; // false=0°, true=180°
// Previous input states for edge detection
bool prevInp1 = LOW;
bool prevInp2 = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
rightServo.attach(rightPin);
leftServo.attach(leftPin);
pinMode(inp1, INPUT); // pull low resistor, input from Pi5
pinMode(inp2, INPUT); // pull low resistor, input from Pi5
// Initialize
rightServo.write(0);
leftServo.write(0);
digitalWrite(ledPin, LOW);
}
void loop() {
// Read current inputs
bool currentInp1 = digitalRead(inp1);
bool currentInp2 = digitalRead(inp2);
// Right servo control (trigger on rising edge)
if (currentInp1 == HIGH && prevInp1 == LOW) {
rightServoState = !rightServoState; // Toggle state
if (rightServoState) { // If true, set to 90°
rightServo.write(90);
digitalWrite(ledPin, HIGH);
} else { // If false, set to 0°
rightServo.write(0);
digitalWrite(ledPin, LOW);
}
}
prevInp1 = currentInp1;
// Left servo control (trigger on rising edge)
if (currentInp2 == HIGH && prevInp2 == LOW) {
leftServoState = !leftServoState; // Toggle state
if (leftServoState) { // If true, set to 90°
leftServo.write(90);
} else { // If false, set to 0°
leftServo.write(0);
}
}
prevInp2 = currentInp2;
delay(10); // Minimal delay to prevent busy-waiting
}
本文编译自hackster.io