Python手势识别检测系统 基于MediaPipe的改进SSD算法 opencv+mediapipe 深度学习 大数据 (建议收藏)✅

博主介绍:✌全网粉丝50W+,前互联网大厂软件研发、集结硕博英豪成立软件开发工作室,专注于计算机相关专业项目实战6年之久,累计开发项目作品上万套。凭借丰富的经验与专业实力,已帮助成千上万的学生顺利毕业,选择我们,就是选择放心、选择安心毕业✌
> 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与我联系了。🍅

1、2026年计算机专业毕业设计选题大全(建议收藏)✅

2、大数据、计算机专业选题(Python/Java/大数据/深度学习/机器学习)(建议收藏)✅

1、项目介绍

技术栈:Python语言、opencv、mediapipe、基于MediaPipe的改进SSD算法(深度学习)、pyqt库

2、项目界面

(1)功能界面

(2)摄像头实时检测识别-- 多目标检测识别

(3)摄像头实时检测识别-- 多目标检测识别

(4)摄像头实时检测识别-- 多目标检测识别

(5)上传图片实时检测识别-- 多目标检测识别

3、项目说明

手势识别采用了基于MediaPipe的改进SSD算法,进行手掌检测后对手部关节坐标进行关键点定位;在系统界面中可以选择手势图片、视频进行检测识别,也可通过电脑连接的摄像头设备进行实时识别手势;可对图像中存在的多个手势进行姿势识别,可选择任意一个手势显示结果并标注,实时检测速度快、识别精度较高。

1、识别手势数字: 0、1、2、3、4、5、6、7、8、9

2、提示:一次只能识别1-2个手势

MediaPipe的改进SSD算法是基于深度学习的。SSD是一种用于目标检测的深度学习算法,它能够在一次前向传播中同时进行目标的定位和分类。MediaPipe对SSD算法进行了改进,以提高目标检测的准确性和效率。改进的过程通常涉及使用更强大的网络结构、优化训练过程、增加数据增强方法等等。因此,MediaPipe的改进SSD算法仍然属于深度学习的范畴。

使用python调用MediaPipe实现手势识别。

主要从三个方面来写这个脚本:

第一个如果识别静态照片的手势;

第二个如何识别视频流中的手势;

第三个如果实时识别摄像头图像。

4、核心代码

python 复制代码
# -*- coding: utf-8 -*-


import mediapipe as mp
import cv2
import time
import math

cap = cv2.VideoCapture(0)  # 0代表电脑自带摄像头
mp_drawing = mp.solutions.drawing_utils  # 点和线的样式
mp_drawing_styles = mp.solutions.drawing_styles  # 点和线的风格
mp_hands = mp.solutions.hands  # 手势识别的API
'''
  def __init__(self,
               static_image_mode=False,
               max_num_hands=2,
               model_complexity=1,  # 将其设置为更高的值可以增加解决方案的健壮性,
                            但代价是延迟更长。如果static_image_mode为true则被忽略
               min_detection_confidence=0.5,
               min_tracking_confidence=0.5):
'''
gesture = [0, 1, 2, 3, 4, 5]  # 预设数字


def ges(hand_landmarks):
    flag = 0
    p0_x = hand_landmarks.landmark[0].x  # 获取关键点0的x坐标
    p0_y = hand_landmarks.landmark[0].y  # 获取关键点0的x坐标
    p5_x = hand_landmarks.landmark[5].x  # 获取食指底部关键点5的x坐标
    p5_y = hand_landmarks.landmark[5].y  # 获取食指底部关键点5的y坐标
    distance_0_5 = math.sqrt(pow(p0_x - p5_x, 2) ** 2 + pow(p0_y - p5_y, 2) ** 2)  # 计算两个观点的距离
    base = distance_0_5 / 0.6  # 人工经验将距离缩小0.6倍作为基础值

    p4_x = hand_landmarks.landmark[4].x  # 获取大拇指顶部关键点4的x坐标
    p4_y = hand_landmarks.landmark[4].y  # 获取大拇指顶部关键点4的y坐标
    distance_5_4 = math.sqrt(pow(p5_x - p4_x, 2) ** 2 + pow(p5_y - p4_y, 2) ** 2)  # 计算关键点4到关键点5的距离,判断大拇指是否处于张开状态

    p8_x = hand_landmarks.landmark[8].x  # 获取食指顶部关键字8的x坐标
    p8_y = hand_landmarks.landmark[8].y  # 获取食指顶部关键字8的y坐标
    distance_0_8 = math.sqrt(pow(p0_x - p8_x, 2) ** 2 + pow(p0_y - p8_y, 2) ** 2)  # 计算关键点0到关键点8的距离,判断食指是否处于张开状态

    p12_x = hand_landmarks.landmark[12].x  # 获取中指顶部关键点12的x坐标
    p12_y = hand_landmarks.landmark[12].y  # 获取中指顶部关键点12的y坐标
    distance_0_12 = math.sqrt(pow(p0_x - p12_x, 2) ** 2 + pow(p0_y - p12_y, 2) ** 2)  # 计算关键点0到关键点12的距离,判断中指是否处于张开状态

    p16_x = hand_landmarks.landmark[16].x  # 获取无名指关键点16的x坐标
    p16_y = hand_landmarks.landmark[16].y  # 获取无名指关键点16的y坐标
    distance_0_16 = math.sqrt(pow(p0_x - p16_x, 2) ** 2 + pow(p0_y - p16_y, 2) ** 2)  # 计算关键点0到关键点16的距离,判断无名指是否处于张开状态

    p20_x = hand_landmarks.landmark[20].x  # 获取小拇指关键点20的x坐标
    p20_y = hand_landmarks.landmark[20].y  # 获取小拇指关键点20的y坐标
    distance_0_20 = math.sqrt(pow(p0_x - p20_x, 2) ** 2 + pow(p0_y - p20_y, 2) ** 2)  # 计算关键点0到关键点20的距离,判断小拇指是否处于张开状态
    '''
    判断有几根手指处于张开状态
    '''
    if distance_0_8 > base:
        flag += 1
    if distance_0_12 > base:
        flag += 1
    if distance_0_16 > base:
        flag += 1
    if distance_0_20 > base:
        flag += 1
    if distance_5_4 > base * 0.2:  # 调低大拇指伸直阈值
        flag += 1

    return gesture[flag]  # 通过索引值返回数字


with mp_hands.Hands(
        static_image_mode=False,  # False表示为视频流检测
        max_num_hands=2,  # 最大可检测到两只手掌
        model_complexity=0,  # 可设为0或者1,主要跟模型复杂度有关
        min_detection_confidence=0.5,  # 最大检测阈值
        min_tracking_confidence=0.5  # 最小追踪阈值
) as hands:
    while cap.isOpened():  # 判断相机是否打开
        success, image = cap.read()  # 返回两个值:一个表示状态,一个是图像矩阵
        if not success:
            print('无效相机流')
            continue

        image.flags.writeable = False  # 将图像矩阵修改为仅读模式
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        t0 = time.time()
        results = hands.process(image)  # 使用API处理图像图像
        '''
        results.multi_handedness
        包括label和score,label是字符串"Left"或"Right",score是置信度
        results.multi_hand_landmarks
        results.multi_hand_landmrks:被检测/跟踪的手的集合
        其中每只手被表示为21个手部地标的列表,每个地标由x、y和z组成。
        x和y分别由图像的宽度和高度归一化为[0.0,1.0]。Z表示地标深度
        以手腕深度为原点,值越小,地标离相机越近。 
        z的大小与x的大小大致相同。
        '''
        t1 = time.time()
        fps = 1 / (t1 - t0)  # 实时帧率
        # print('++++++++++++++fps',fps)
        image.flags.writeable = True  # 将图像矩阵修改为读写模式
        image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)  # 将图像变回BGR形式
        dict_handnumber = {}  # 创建一个字典。保存左右手的手势情况
        if results.multi_handedness:  # 判断是否检测到手掌
            if len(results.multi_handedness) == 2:  # 如果检测到两只手
                for i in range(len(results.multi_handedness)):
                    label = results.multi_handedness[i].classification[0].label  # 获得Label判断是哪几手
                    index = results.multi_handedness[i].classification[0].index  # 获取左右手的索引号
                    hand_landmarks = results.multi_hand_landmarks[index]  # 根据相应的索引号获取xyz值
                    mp_drawing.draw_landmarks(
                        image,
                        hand_landmarks,
                        mp_hands.HAND_CONNECTIONS,  # 用于指定地标如何在图中连接。
                        mp_drawing_styles.get_default_hand_landmarks_style(),  # 如果设置为None.则不会在图上标出关键点
                        mp_drawing_styles.get_default_hand_connections_style())  # 关键点的连接风格
                    gesresult = ges(hand_landmarks)  # 传入21个关键点集合,返回数字
                    dict_handnumber[label] = gesresult  # 与对应的手进行保存为字典
            else:  # 如果仅检测到一只手
                label = results.multi_handedness[0].classification[0].label  # 获得Label判断是哪几手
                hand_landmarks = results.multi_hand_landmarks[0]
                mp_drawing.draw_landmarks(
                    image,
                    hand_landmarks,
                    mp_hands.HAND_CONNECTIONS,  # 用于指定地标如何在图中连接。
                    mp_drawing_styles.get_default_hand_landmarks_style(),  # 如果设置为None.则不会在图上标出关键点
                    mp_drawing_styles.get_default_hand_connections_style())  # 关键点的连接风格
                gesresult = ges(hand_landmarks)  # 传入21个关键点集合,返回数字
                dict_handnumber[label] = gesresult  # 与对应的手进行保存为字典
        if len(dict_handnumber) == 2:  # 如果有两只手,则进入
            # print(dict_handnumber)
            leftnumber = dict_handnumber['Right']
            rightnumber = dict_handnumber['Left']
            '''
            显示实时帧率,右手值,左手值,相加值
            '''
            s = 'FPS:{0}\nRighthand Value:{1}\nLefthand Value:{2}\nAdd is:{3}'.format(int(fps), rightnumber, leftnumber,
                                                                                      str(leftnumber + rightnumber))  # 图像上的文字内容
        elif len(dict_handnumber) == 1:  # 如果仅有一只手则进入
            labelvalue = list(dict_handnumber.keys())[0]  # 判断检测到的是哪只手
            if labelvalue == 'Left':  # 左手,不知为何,模型总是将左右手搞反,则引入人工代码纠正
                number = list(dict_handnumber.values())[0]
                s = 'FPS:{0}\nRighthand Value:{1}\nLefthand Value:0\nAdd is:{2}'.format(int(fps), number, number)
            else:  # 右手
                number = list(dict_handnumber.values())[0]
                s = 'FPS:{0}\nLefthand Value:{1}\nRighthand Value:0\nAdd is:{2}'.format(int(fps), number, number)
        else:  # 如果没有检测到则只显示帧率
            s = 'FPS:{0}\n'.format(int(fps))

        y0, dy = 50, 25  # 文字放置初始坐标
        image = cv2.flip(image, 1)  # 反转图像
        for i, txt in enumerate(s.split('\n')):  # 根据\n来竖向排列文字
            y = y0 + i * dy
            cv2.putText(image, txt, (50, y), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 3)
        cv2.imshow('MediaPipe Gesture Recognition', image)  # 显示图像
        # cv2.imwrite('save/{0}.jpg'.format(t1),image)
        if cv2.waitKey(5) & 0xFF == 27:
            break
cap.release()

🍅✌**感兴趣的可以先收藏起来,点赞关注不迷路,想学习更多项目可以查看主页,大家在毕设选题,项目编程以及论文编写等相关问题都可以给我留言咨询,希望可以帮助同学们顺利毕业!**🍅✌

5、源码获取方式

🍅**由于篇幅限制,获取完整文章或源码、代做项目的,拉到文章底部即可看到个人联系方式。**🍅

点赞、收藏、关注,不迷路,下方查看 👇🏻获取联系方式👇🏻

相关推荐
兜兜风d'3 小时前
RabbitMQ 持久性详解
spring boot·分布式·rabbitmq·1024程序员节
Lab4AI大模型实验室3 小时前
【每日Arxiv热文】还在为视频编辑发愁?港科大&蚂蚁集团提出Ditto框架刷新SOTA!
人工智能·计算机视觉·视频编辑·ai agent·智能体学习
MeowKnight9584 小时前
【Linux】常见的系统调用 函数和功能简单总结
linux·1024程序员节
分布式存储与RustFS4 小时前
RustFS:MinIO的“平替”还是“乱杀”?
python·rust·对象存储·minio·存储·企业存储·rustfs
游戏开发爱好者84 小时前
iOS 26 App 开发阶段性能优化 从多工具协作到数据驱动的实战体系
android·ios·小程序·uni-app·iphone·webview·1024程序员节
爱幻想-hjyp4 小时前
【Python】uv包管理器常用命令
开发语言·python·uv
爱隐身的官人4 小时前
Ubuntu安装开源堡垒机JumpServer
linux·ubuntu·堡垒机·1024程序员节
用什么都重名4 小时前
UV工具安装配置使用教程
python·uv·包管理器
杨筱毅4 小时前
【底层机制】Linux内核4.10版本的完整存储栈架构讲解--用户空间到物理设备完整IO路径
linux·架构·1024程序员节·底层机制