OpenCV 手部识别

今天为大家介绍一篇利用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

猜你喜欢

转载自blog.csdn.net/sunjianghan/article/details/135326333
今日推荐