自制基于图像识别的猜拳机械手


本文从硬件开始再到控制、算法层面一步一步搭建一个猜拳用的机械手,当然本次实现的是之前做的一个小玩意,可能在实时性上并不算特别好,仅做学习和参考用途。当然基本的玩耍功能还是有的啦~

一、准备

软件环境

Arduino IDE安装
Python(Pycharm可选)
OpenCV-Python
TensorFlow(版本为1)
Keras


硬件

机械手(大伙自己淘宝吧,省的被说打广告。当然也可以自己DIY,看这篇:我的diy之自制体感机械手篇
Arduino UNO开发板
舵机
PCA9685舵机控制板
电压转换模块
电源及开关等
摄像头(当然用电脑自带的也行)


参考资料

以下都是收集的GitHub上面相关的手势识别或者人机交互的项目源码,可用作参考

https://github.com/HiminDong/gesture-vrep
https://github.com/Oranges520/2019-HMI-ISP-06
https://github.com/AravinthPanch/gesture-recognition-for-human-robot-interaction
https://github.com/Dhivin/Gesture-control-for-robotics-in-Matlab

二、硬件及底层控制

组装

发几张自己组装的流程图,组装的过程注意要让每根手指的动作至少不会有太大的阻力,防止卡顿

在这里插入图片描述

接线

电路接线如下,将Arduino开发板的GPIO与舵机控制板PCA9685的I2C接口相接,电池电源连通开关(此处兼具电压转换功能)接到PCA9685的供电端口(一定要接电源,否则难以驱动多个电机)。然后,选择PCA9685上的输出引脚对与机械手上的舵机相连接(16路舵机控制板,编号从左至右为0~15)。此处选择为:

  • 大拇指 0号位
  • 食指 2号位
  • 中指 4号位
  • 无名指 6号位
  • 小拇指 7号位

在这里插入图片描述

Arduino控制源码

底层控制流程如下:
在这里插入图片描述

Arduino源码如下,注意大拇指与其他手指的弯曲角度有所区别。通过串口获取从电脑上发送来的控制信号

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>

char var;
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();	// 获取舵机地址

#define SERVOMIN  150 // this is the 'minimum' pulse length count (out of 4096)
//这是“最小”脉冲长度计数(在4096)中
#define SERVOMAX  600 // this is the 'maximum' pulse length count (out of 4096)
//这是“最大”脉冲长度计数(在4096中)
#define SERVOMED  320 // this is the 'medium' pulse length count (out of 4096)
//这是手指默认位置的脉冲长度计数(在4096中)

//给定各个手指在舵机控制板上的位
#define thumb           0     //大拇指
#define index_finger    2     //食指
#define middle_finger   4     //中指
#define ring_finger     6     //无名指
#define little_finger   7     //小拇指

void setup() {
    
    
  Serial.begin(9600);
  pwm.begin();
  pwm.setPWMFreq(50);
}

void scissors(){
    
    
    pwm.setPWM(thumb, 0, SERVOMED);
    pwm.setPWM(index_finger, 0, SERVOMAX);
    pwm.setPWM(middle_finger, 0, SERVOMAX);
    pwm.setPWM(ring_finger, 0, SERVOMED);
    pwm.setPWM(little_finger, 0, SERVOMED);
}

void rock(){
    
    
    pwm.setPWM(thumb, 0, SERVOMED);
    pwm.setPWM(index_finger, 0, SERVOMED);
    pwm.setPWM(middle_finger, 0, SERVOMED);
    pwm.setPWM(ring_finger, 0, SERVOMED);
    pwm.setPWM(little_finger, 0, SERVOMED);
}

void paper(){
    
    
    pwm.setPWM(thumb, 0, SERVOMED+180);
    pwm.setPWM(index_finger, 0, SERVOMAX);
    pwm.setPWM(middle_finger, 0, SERVOMAX);
    pwm.setPWM(ring_finger, 0, SERVOMAX);
    pwm.setPWM(little_finger, 0, SERVOMAX);
}


void loop() {
    
    
  while(Serial.available()>0)
  {
    
    
    var = Serial.read();
    if(var == '1')
    {
    
    
      //delay(1000);
      scissors();
      Serial.write("scissors");
      delay(50);
    }
    if(var == '2')
    {
    
    
      //delay(1000);
      rock();
      Serial.write("rock");
      delay(50); 
    }
    if(var == '3')
    {
    
    
      //delay(1000);
      paper();
      Serial.write("paper");
      delay(50); 
    }
  }
}

调试界面

为了方便调试,这边提供了python编写的调试界面

import tkinter as tk
import serial

serialPort = "COM5"		# 注意此处需要查找你电脑上的连接端口并且进行替换
baudRate = 9600			# 注意波特率配置
ser = serial.Serial(serialPort,baudRate,timeout=1)
print("参数设置:串口 = %s, 波特率 = %d" % (serialPort, baudRate))

demo1 = b'1'        # case scissors
demo2 = b'2'        # case rock
demo3 = b'3'        # case paper

def scissors():
    ser.write(demo1)

def rock():
    ser.write(demo2)

def paper():
    ser.write(demo3)

window = tk.Tk()
window.title('机械手测试')
window.geometry('300x200')

l = tk.Label(window,text = '机械手测试').pack()

b1 = tk.Button(window, text = '剪刀', command = scissors)
b1.pack()
b2 = tk.Button(window, text = '石头', command = rock)
b2.pack()
b3 = tk.Button(window, text = '布', command = paper)
b3.pack()

window.mainloop()

调试无误之后,可以进行模型的训练及图像识别过程

三、手势识别

接来下的实现过程参考了GitHub上的源码项目:

https://github.com/Oranges520/2019-HMI-ISP-06

希望大家多多支持原开发者。也可参考对应的源码进行自己的修改。

实现过程是在卷积神经网络中添加了SE-Block。该算法模式是在2017年由自动驾驶公司Momenta的团队所提出,他通过对特征通道之间的相关性进行建模,把重要的特征进行强化啊,对无用的特征进行抑制来提高识别准确率。

论文:Squeeze-and-Excitation Networks

在这里插入图片描述

网络架构如下:

在这里插入图片描述
源码及训练好的文件:图像识别训练结果及程序

注意在内部需要在完成手势识别之后,将对应的识别结果通过串口发送给Arduino,然后通过Arduino内部的控制程序再控制机械手做出相应的反应。程序最后面通过添加多个if判断语句实现对信号的限幅及滤波,防止识别结果跳变时导致的机械手的抖动,以避免损坏舵机。

以下为电脑上显示的识别结果。当然在单一颜色背景下效果是最好的,这边也只是记录和分享一下自己的制作过程,如果能对大家有所帮助也再好不过。大佬就请无视本菜鸡吧。

在这里插入图片描述

以上内容仅做学习和分享用途

猜你喜欢

转载自blog.csdn.net/moumde/article/details/109131320
今日推荐