今天为大家介绍一篇利用opencv库和mediapipe库进行手部识别的python代码
首先,需建立两个Python文件并分别命名为hand.py和handms.py,在终端中安装两个工具包分别为opencv-python和mediapipe
如果安装太慢,可利用清华大学提供的镜像网站:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple 包名称
代码成功运行后,大概是这个样子的:左手食指指尖为红色,右手食指指尖为绿色
hand.py
import cv2
from handms import HandDetector
"""
1.使用opencv来获取摄像头信息
2.使用mediapipe将手的信息传给opencv
"""
#打开电脑上的摄像头,笔记本的参数是0
camera = cv2.VideoCapture(0)
#在另一个文件中创建一个类,里面存放mediapipe实现的功能,并导入该文件
hand_detector = HandDetector()
while True:
#从摄像头里面读,获取摄像头视频帧的数据
#会返回两个数据,一个是判断是否读成功,另一个是返回视频帧的图片
success,img = camera.read()
#如果读取成功
if success:
#opencv获取到的视频是翻转的,需要将视频改为镜像的
img = cv2.flip(img,1)
#调用类里面的函数process,将img放到mediapipe中进行处理
hand_detector.process(img,True)
#储存position字典
position = hand_detector.find_position(img)
#获取到左手的食指指尖,如果获取不到返回None
left_finger = position['Left'].get(8,None)
if left_finger:
#如果获取到,在指尖画一个小圆,0表示x坐标,1表示y坐标,半径,颜色,实心
cv2.circle(img,(left_finger[0],left_finger[1]),10,(0,0,255),cv2.FILLED)
# 获取到右手的食指指尖,如果获取不到返回None
right_finger = position['Right'].get(8, None)
if right_finger:
# 如果获取到,在指尖画一个小圆,0表示x坐标,1表示y坐标,半径,颜色,实心
cv2.circle(img,(right_finger[0],right_finger[1]),10,(0,255,0),cv2.FILLED)
#代码运行后,会产生一个窗口,名为Video,
cv2.imshow('Video',img)
#按下一个按键,使其停止运行(结束while循环)
#等待按键按下,如果在1毫秒之内感知到的话,waitKey就会接收该键值,并把该键赋值给k
k = cv2.waitKey(1)
if k == ord('q'):
break
#关闭摄像头,解除程序占用摄像头
camera.release()
#cv2把所有打开的窗口关闭掉
cv2.destroyAllWindows()
handms.py
import cv2
import mediapipe as mp
class HandDetector():
def __init__(self):
# 获取视频中有没有手的信息
self.hand_detector = mp.solutions.hands.Hands()
#给mp.solutions.drawing_utils一个比较简单的名字drawer
self.drawer = mp.solutions.drawing_utils
def process(self,img,draw):
# 将opencv获取到的视频色彩由bgr(blue,green,red)转化为rgb
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 处理视频图片
self.hand_data = self.hand_detector.process(img_rgb)
if draw:
# 如果有手势数据
if self.hand_data.multi_hand_landmarks:
# 遍历手的21个数据
for handlms in self.hand_data.multi_hand_landmarks:
# 用mp把21个handlms数据画到img图片上,第三个参数表示把关节点连起来
self.drawer.draw_landmarks(img, handlms,mp.solutions.hands.HAND_CONNECTIONS)
def find_position(self,img):
#获取视频的高度、宽度
h,w,c = img.shape
#定义一个position变量,存放每一只手的数据,存放在字典中
position = {'Left':{},'Right':{}}
#如果有手势数据
if self.hand_data.multi_hand_landmarks:
i = 0
for point in self.hand_data.multi_handedness:
#获取手的分类(是伸的左手还是右手)
#有三个数据 index、score(表示是哪一手的概率)、label(哪一只手)
"""
classification{
index:0
score:0.9611464738845825
label:"Left"
"""
#把score数据读出来
score = point.classification[0].score
if score >= 0.8:
#获取的左手或右手的数据
label = point.classification[0].label
#把21个关节取出来,分别存到hand_lms中
hand_lms = self.hand_data.multi_hand_landmarks[i].landmark
#id从0开始,lm有3个值,分别为x,y,z
for id,lm in enumerate(hand_lms):
#获取点的位置
x, y = int(lm.x * w),int(lm.y * h)
#放在position字典中,记录哪只手的哪个关节在哪个坐标
position[label][id] = (x, y)
i = i+1
return position