本帖最后由 gray6666 于 2022-10-17 15:39 编辑
一直关注群里的各种手势识别案例的帖子,无奈机器不给力,安装起来各种小状况不断;9月份学校升级新电脑,在闲鱼偶遇机械手,给孩子们上课写简单的了一个入门帖子,记录这段无奈的幸运。
一、计算机硬件
1.i5处理器,8GB内存
2.自带摄像头,功能稍微有点弱,后期准备换高清的试试
二、实验硬件
1.机械手1只
2.Romeo 三合一Arduino兼容控制器(DF出品利器,可用其他uno板替换)https://www.dfrobot.com.cn/goods-54.html
3.9V电池*1
4.USB数据线一条
三、实验软件
mind+1.7.2RC Python模式
四、实现过程
1.基于Google的Mediapipe框架,利用其自身返回的坐标,计算手指的弯曲角度;依据官网的说明,mediapipe处理视频流的函数能够返回手部标注节点的三维坐标
判断手指弯曲,可以使用每个手指的三个定位点,比如食指为6-7-8三点;知道坐标点位置,开始计算手指运动过程中的夹角。以食指为例,计算∠876。推导过程比较简单,因为知道三个点的xy坐标,借助三角函数弧度rad=arctan(y/x)分别求出两条直线的正切角,再相减即可。
2.代码实现
导入CV,mediapipe,pinpong库;初始化xy点的坐标,初始化uno板和舵机
- <font size="4" face="微软雅黑">import cv2
- import mediapipe as mp
- import time
- import numpy as np
- from pinpong.board import Board,Pin,Servo
- Board("uno").begin()
- cap=cv2.VideoCapture(0)
- mpHands = mp.solutions.hands
- hands = mpHands.Hands(max_num_hands=1)
- mpDraw = mp.solutions.drawing_utils
- handLmsStyle = mpDraw.DrawingSpec(color=(0,0,255),thickness=10)
- handConStyle = mpDraw.DrawingSpec(color=(0,255,255),thickness=5)
- pTime = 0
- cTime = 0
- #获取定位点,x,y的坐标
- pos2=pos_2=pos3=pos_3=pos4=pos_4=0
- pos5=pos8=pos9=pos12=pos16=pos20=0
- pos6=pos7=pos8=pos_6=pos_7=pos_8=0
- pos10=pos11=pos12=pos_10=pos_11=pos_12=0
- pos14=pos15=pos16=pos_14=pos_15=pos_16=0
- pos18=pos19=pos20=pos_18=pos_19=pos_20=0
- s1 = Servo(Pin(Pin.D3)) #将Pin传入Servo中初始化舵机引脚 大拇指
- s2 = Servo(Pin(Pin.D5)) #将Pin传入Servo中初始化舵机引脚 食指
- s3 = Servo(Pin(Pin.D7)) #将Pin传入Servo中初始化舵机引脚 中指
- s4 = Servo(Pin(Pin.D10)) #将Pin传入Servo中初始化舵机引脚 无名指
- s5 = Servo(Pin(Pin.D11)) #将Pin传入Servo中初始化舵机引脚 小拇指
- s1.angle(170) #控制舵机转到170度位置
- s2.angle(60) #控制舵机转到60度位置
- s3.angle(60) #控制舵机转到60度位置
- s4.angle(60) #控制舵机转到60度位置
- s5.angle(60) #控制舵机转到60度位置
- a=['@','0','0','0','0','0'] #检测是否识别到手<span id="kM0.533716621430318">@表示没检测到,$表示检测到手</span></font>
复制代码
3.主程序部分
- <font size="4" face="微软雅黑">while True:
- ret, img = cap.read()
- if ret:
- imgRGB = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
- result = hands.process(imgRGB)
- imgHeight = img.shape[0]
- imgWidth = img.shape[1]
- if result.multi_hand_landmarks :
- a[0]='[font=微软雅黑][size=4]4.拇指部分代码[/size][/font]
- [code]<font size="4" face="微软雅黑">##########################大拇指################################
- if i == 2:
- cv2.circle(img,(xPos,yPos),10,(255,255,255),cv2.FILLED)
- pos2,pos_2=xPos,yPos
- if i == 3:
- cv2.circle(img,(xPos,yPos),10,(255,255,255),cv2.FILLED)
- pos3,pos_3=xPos,yPos
- if i == 4:
- cv2.circle(img,(xPos,yPos),10,(255,255,255),cv2.FILLED)
- pos4,pos_4=xPos,yPos
- radians_fingers = np.arctan2(pos_2- pos_3, pos2 - pos3) - np.arctan2(pos_4 - pos_3, pos4 - pos3)
- angle = np.abs(radians_fingers * 180.0 / np.pi)
- if angle > 180.0:
- angle = 360 - angle
- if angle<150:
- a[1]='0'
- s1.angle(80) #s1.angle(70)
- else:
- a[1]='1'
- s1.angle(170) #s1.angle(180)</font>
复制代码
5.食指部分,其他三个手指通用该模式
- <font size="4" face="微软雅黑">##############################食指##########################
- if i == 6:
- cv2.circle(img,(xPos,yPos),10,(255,255,255),cv2.FILLED)
- pos6,pos_6=xPos,yPos
- if i == 7:
- cv2.circle(img,(xPos,yPos),10,(255,255,255),cv2.FILLED)
- pos7,pos_7=xPos,yPos
- if i == 8:
- cv2.circle(img,(xPos,yPos),10,(255,255,255),cv2.FILLED)
- pos8,pos_8=xPos,yPos
- radians_fingers = np.arctan2(pos_6- pos_7, pos6 - pos7) - np.arctan2(pos_8 - pos_7, pos8 - pos7)
- angle2 = np.abs(radians_fingers * 180.0 / np.pi)
- if angle2 > 180.0:
- angle2 = 360 - angle2
- if angle2<150:
- a[2]='0'
- s2.angle(60)
- else:
- a[2]='1'
- s2.angle(150)</font>
复制代码
6.检测导出的五个手指弯曲的角度
- <font size="4" face="微软雅黑">##############################################################
- cv2.putText(img,f"hand1 : {int(angle)}",(10,20),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,0))
- cv2.putText(img,f"hand2 : {int(angle2)}",(10,30),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,0))
- cv2.putText(img,f"hand3 : {int(angle3)}",(10,40),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,0))
- cv2.putText(img,f"hand4 : {int(angle4)}",(10,50),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,0))
- cv2.putText(img,f"hand5 : {int(angle5)}",(10,60),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,0))</font>
复制代码
7.结尾部分
- <font size="4" face="微软雅黑">############ftp/s
- cTime = time.time()
- fps = 1/(cTime-pTime)
- pTime = cTime
- cv2.putText(img,f"FPS : {int(fps)}",(130,150),cv2.FONT_HERSHEY_SIMPLEX,0.5,(255,0,0))
- cv2.imshow('img',img)
- #time.sleep(0.3)
- if cv2.waitKey(1) &0xFF == 27: #按q键退出视频
- break
- cap.release()
- cv2.destroyAllWindows()</font>
复制代码
五、测试视频
我的模型大拇指设计有问题,归位有时会失灵
计算机性能跟不上功能,对识别有影响
增加延时,效果稍有改进
六、完整代码下载
handtestv1.0.zip
附:参考网址
https://blog.csdn.net/kalakalabala/article/details/122530825
https://google.github.io/mediapipe/solutions/hands
|