[教程]【Mind+Mediapipe+pinpong】机械手
本帖最后由 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
imgWidth = img.shape
if result.multi_hand_landmarks :
a='4.拇指部分代码
<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='0'
s1.angle(80) #s1.angle(70)
else:
a='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='0'
s2.angle(60)
else:
a='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>五、测试视频
我的模型大拇指设计有问题,归位有时会失灵
https://www.bilibili.com/video/BV1pe411V7wC/?vd_source=b5e397a1126de2f7f0afc12a847753ba
计算机性能跟不上功能,对识别有影响
https://www.bilibili.com/video/BV1t8411s7M7/?vd_source=b5e397a1126de2f7f0afc12a847753ba
增加延时,效果稍有改进
https://www.bilibili.com/video/BV1kG41177sq/?vd_source=b5e397a1126de2f7f0afc12a847753ba
https://www.bilibili.com/video/BV16W4y1J7yn/?vd_source=b5e397a1126de2f7f0afc12a847753ba
六、完整代码下载
附:参考网址
https://blog.csdn.net/kalakalabala/article/details/122530825
https://google.github.io/mediapipe/solutions/hands
{:5_116:} 赞一个 谢谢记录分享 {:6_209:}
页:
[1]