opencv实战项目 手势识别-手势控制键盘

这篇具有很好参考价值的文章主要介绍了opencv实战项目 手势识别-手势控制键盘。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

手势识别是一种人机交互技术,通过识别人的手势动作,从而实现对计算机、智能手机、智能电视等设备的操作和控制。

1.  opencv实现手部追踪(定位手部关键点)

2.opencv实战项目 实现手势跟踪并返回位置信息(封装调用)

3.opencv实战项目 手势识别-手势控制鼠标

4.opencv实战项目 手势识别-手势控制键盘

未完待续

本专栏记录作者的学习之旅会一直更新下去,欢迎订阅一起学习进步

本项目是使用了谷歌开源的框架mediapipe,里面有非常多的模型提供给我们使用,例如面部检测,身体检测,手部检测等opencv实战项目 手势识别-手势控制键盘,opencv实战,计算机外设,opencv,计算机视觉

 代码需要用到opencv   HandTraqckModule模块   mediapipe模块和一个键盘控制模块pynput,cvzone模块

一、HandTraqckModule模块 

前面的文章中有封装手部检测模块的教程,这边简单的介绍一下,有新增加的模块可以简单学习一下

import cv2
import mediapipe as mp
import math


class HandDetector:
    """
    Finds Hands using the mediapipe library. Exports the landmarks
    in pixel format. Adds extra functionalities like finding how
    many fingers are up or the distance between two fingers. Also
    provides bounding box info of the hand found.
    """

    def __init__(self, mode=False, maxHands=2, detectionCon=0.5, minTrackCon=0.5):
        """
        :param mode: In static mode, detection is done on each image: slower
        :param maxHands: Maximum number of hands to detect
        :param detectionCon: Minimum Detection Confidence Threshold
        :param minTrackCon: Minimum Tracking Confidence Threshold
        """
        self.mode = mode
        self.maxHands = maxHands
        self.detectionCon = detectionCon
        self.minTrackCon = minTrackCon

        self.mpHands = mp.solutions.hands
        self.hands = self.mpHands.Hands(self.mode, self.maxHands,
                                        self.detectionCon, self.minTrackCon)
        self.mpDraw = mp.solutions.drawing_utils
        self.tipIds = [4, 8, 12, 16, 20]
        self.fingers = []
        self.lmList = []

    def findHands(self, img, draw=True):
        """
        Finds hands in a BGR image.
        :param img: Image to find the hands in.
        :param draw: Flag to draw the output on the image.
        :return: Image with or without drawings
        """
        imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        self.results = self.hands.process(imgRGB)

        if self.results.multi_hand_landmarks:
            for handLms in self.results.multi_hand_landmarks:
                if draw:
                    self.mpDraw.draw_landmarks(img, handLms,
                                               self.mpHands.HAND_CONNECTIONS)
        return img

    def findPosition(self, img, handNo=0, draw=True):
        """
        Finds landmarks of a single hand and puts them in a list
        in pixel format. Also finds the bounding box around the hand.
        :param img: main image to find hand in
        :param handNo: hand id if more than one hand detected
        :param draw: Flag to draw the output on the image.
        :return: list of landmarks in pixel format; bounding box
        """

        xList = []
        yList = []
        bbox = []
        bboxInfo = []
        self.lmList = []
        if self.results.multi_hand_landmarks:
            myHand = self.results.multi_hand_landmarks[handNo]
            for id, lm in enumerate(myHand.landmark):
                h, w, c = img.shape
                px, py = int(lm.x * w), int(lm.y * h)
                xList.append(px)
                yList.append(py)
                self.lmList.append([px, py])
                if draw:
                    cv2.circle(img, (px, py), 5, (255, 0, 255), cv2.FILLED)
            xmin, xmax = min(xList), max(xList)
            ymin, ymax = min(yList), max(yList)
            boxW, boxH = xmax - xmin, ymax - ymin
            bbox = xmin, ymin, boxW, boxH
            cx, cy = bbox[0] + (bbox[2] // 2), \
                     bbox[1] + (bbox[3] // 2)
            bboxInfo = {"id": id, "bbox": bbox, "center": (cx, cy)}

            if draw:
                cv2.rectangle(img, (bbox[0] - 20, bbox[1] - 20),
                              (bbox[0] + bbox[2] + 20, bbox[1] + bbox[3] + 20),
                              (0, 255, 0), 2)

        return self.lmList, bboxInfo

    def fingersUp(self):
        """
        Finds how many fingers are open and returns in a list.
        Considers left and right hands separately
        :return: List of which fingers are up
        """
        if self.results.multi_hand_landmarks:
            myHandType = self.handType()
            fingers = []
            # Thumb
            if myHandType == "Right":
                if self.lmList[self.tipIds[0]][0] > self.lmList[self.tipIds[0] - 1][0]:
                    fingers.append(1)
                else:
                    fingers.append(0)
            else:
                if self.lmList[self.tipIds[0]][0] < self.lmList[self.tipIds[0] - 1][0]:
                    fingers.append(1)
                else:
                    fingers.append(0)

            # 4 Fingers
            for id in range(1, 5):
                if self.lmList[self.tipIds[id]][1] < self.lmList[self.tipIds[id] - 2][1]:
                    fingers.append(1)
                else:
                    fingers.append(0)
        return fingers

    def findDistance(self, p1, p2, img, draw=True):
        """
        Find the distance between two landmarks based on their
        index numbers.
        :param p1: Point1 - Index of Landmark 1.
        :param p2: Point2 - Index of Landmark 2.
        :param img: Image to draw on.
        :param draw: Flag to draw the output on the image.
        :return: Distance between the points
                 Image with output drawn
                 Line information
        """

        if self.results.multi_hand_landmarks:
            x1, y1 = self.lmList[p1][0], self.lmList[p1][1]
            x2, y2 = self.lmList[p2][0], self.lmList[p2][1]
            cx, cy = (x1 + x2) // 2, (y1 + y2) // 2

            if draw:
                cv2.circle(img, (x1, y1), 15, (255, 0, 255), cv2.FILLED)
                cv2.circle(img, (x2, y2), 15, (255, 0, 255), cv2.FILLED)
                cv2.line(img, (x1, y1), (x2, y2), (255, 0, 255), 3)
                cv2.circle(img, (cx, cy), 15, (255, 0, 255), cv2.FILLED)

            length = math.hypot(x2 - x1, y2 - y1)
            return length, img, [x1, y1, x2, y2, cx, cy]

    def handType(self):
        """
        Checks if the hand is left or right
        :return: "Right" or "Left"
        """
        if self.results.multi_hand_landmarks:
            if self.lmList[17][0] < self.lmList[5][0]:
                return "Right"
            else:
                return "Left"


def main():
    cap = cv2.VideoCapture(0)
    detector = HandDetector(detectionCon=0.8, maxHands=1)
    while True:
        # Get image frame
        success, img = cap.read()
        # Find the hand and its landmarks
        img = detector.findHands(img)
        lmList, bboxInfo = detector.findPosition(img)
        print(detector.handType())

        # Display
        cv2.imshow("Image", img)
        cv2.waitKey(1)


if __name__ == "__main__":
    main()
  1. 导入库:导入了必要的库,包括 OpenCV (cv2) 用于图像处理和显示,Mediapipe (mediapipe) 用于手部检测和跟踪,以及数学库 (math)。

  2. HandDetector 类:这是主要的手势检测器类,提供了多个方法来处理手部检测和分析手势。

    • __init__ 方法:初始化检测器的参数,例如检测模式、最大检测手数、检测和跟踪的置信度阈值等。

    • findHands 方法:在给定的图像中寻找手部,可以选择是否绘制检测结果。

    • findPosition 方法:找到单个手部的关键点位置(landmarks)并将它们存储在像素格式的列表中,同时计算手部的边界框信息。

    • fingersUp 方法:确定手势中有多少个手指打开,将结果以列表形式返回。

    • findDistance 方法:计算两个指定关键点之间的距离,并在图像上绘制结果。

    • handType 方法:确定手的类型是左手还是右手。

具体就不展开讲了

这个函数在有一个专门的包叫做cvzone里有,但是不知道是不是版本的问题,少了一些东西,运行不起来,只能自己手撸检测模块。

下面是主函数的代码

import cv2
from cvzone.HandTrackingModule import HandDetector
from HandTrackingModule import *
from time import sleep
import numpy as np
import cvzone
from pynput.keyboard import Controller

cap = cv2.VideoCapture(0)
cap.set(3, 1280)
cap.set(4, 720)

detector =HandDetector(detectionCon=0.5)
keys = [["Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P"],
        ["A", "S", "D", "F", "G", "H", "J", "K", "L", ";"],
        ["Z", "X", "C", "V", "B", "N", "M", ",", ".", "/"]]
finalText = ""

keyboard = Controller()


def drawAll(img, buttonList):
    for button in buttonList:
        x, y = button.pos
        w, h = button.size
        cvzone.cornerRect(img, (button.pos[0], button.pos[1], button.size[0], button.size[1]),
                          20, rt=0)
        cv2.rectangle(img, button.pos, (x + w, y + h), (255, 0, 255), cv2.FILLED)
        cv2.putText(img, button.text, (x + 20, y + 65),
                    cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
    return img


#
# def drawAll(img, buttonList):
#     imgNew = np.zeros_like(img, np.uint8)
#     for button in buttonList:
#         x, y = button.pos
#         cvzone.cornerRect(imgNew, (button.pos[0], button.pZXos[1], button.size[0], button.size[1]),
#                           20, rt=0)
#         cv2.rectangle(imgNew, button.pos, (x + button.size[0], y + button.size[1]),
#                       (255, 0, 255), cv2.FILLED)
#         cv2.putText(imgNew, button.text, (x + 40, y + 60),
#                     cv2.FONT_HERSHEY_PLAIN, 2, (255, 255, 255), 3)
#
#     out = img.copy()
#     alpha = 0.5
#     mask = imgNew.astype(bool)
#     print(mask.shape)
#     out[mask] = cv2.addWeighted(img, alpha, imgNew, 1 - alpha, 0)[mask]
#     return out


class Button():
    def __init__(self, pos, text, size=[85, 85]):
        self.pos = pos
        self.size = size
        self.text = text


buttonList = []
for i in range(len(keys)):
    for j, key in enumerate(keys[i]):
        buttonList.append(Button([100 * j + 50, 100 * i + 50], key))

while True:
    success, img = cap.read()
    img = detector.findHands(img)
    lmList, bboxInfo = detector.findPosition(img)
    img = drawAll(img, buttonList)

    if lmList:
        for button in buttonList:
            x, y = button.pos
            w, h = button.size

            if x < lmList[8][0] < x + w and y < lmList[8][1] < y + h:
                cv2.rectangle(img, (x - 5, y - 5), (x + w + 5, y + h + 5), (175, 0, 175), cv2.FILLED)
                cv2.putText(img, button.text, (x + 20, y + 65),
                            cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
                l, _, _ = detector.findDistance(8, 12, img, draw=False)
                print(l)

                ## when clicked
                if l < 30:
                    keyboard.press(button.text)
                    cv2.rectangle(img, button.pos, (x + w, y + h), (0, 255, 0), cv2.FILLED)
                    cv2.putText(img, button.text, (x + 20, y + 65),
                                cv2.FONT_HERSHEY_PLAIN, 4, (255, 255, 255), 4)
                    finalText += button.text
                    sleep(0.15)

    cv2.rectangle(img, (50, 350), (700, 450), (175, 0, 175), cv2.FILLED)
    cv2.putText(img, finalText, (60, 430),
                cv2.FONT_HERSHEY_PLAIN, 5, (255, 255, 255), 5)

    cv2.imshow("Image", img)
    cv2.waitKey(1)
  1. 导入库:导入了需要的库,包括 OpenCV (cv2) 用于图像处理和显示,Mediapipe 中的 HandDetector 用于手部检测,cvzone 用于绘制按钮外观,numpy 用于数组处理,pynput.keyboard 中的 Controller 用于模拟键盘输入,time 用于延时。

  2. 设置摄像头参数:通过 OpenCV 设置摄像头的分辨率为 1280x720。

  3. 创建 HandDetector 实例:使用 HandDetector 类创建一个手势检测器实例,设置检测的置信度阈值为 0.5。

  4. 创建按钮列表:创建了一个包含虚拟键盘按钮信息的列表,按键布局通过嵌套列表 keys 定义。

  5. 创建 Button 类:用于创建虚拟按钮的类,每个按钮包含位置、文本内容和大小。

  6. 主循环:进入一个无限循环,用于处理实时的摄像头捕获图像帧。

    • 读取图像帧:从摄像头捕获图像帧。

    • 手部检测:使用手势检测器找出图像中的手部和关键点。

    • 绘制按钮:调用 drawAll 函数在图像上绘制虚拟按钮。

    • 遍历按钮列表:对每个按钮进行检查,看是否有手指触摸到按钮。

      • 如果手指在按钮范围内,绘制高亮效果。

      • 计算手指触摸点与按钮中心的距离,如果小于一定阈值,则模拟键盘按下并记录输入。

    • 绘制已输入的文本:在图像上绘制已输入的文本。

    • 显示图像:通过 OpenCV 显示处理后的图像。

    • 等待键盘输入:等待 1 毫秒,以便保持图像窗口的响应性。

  7. 运行主程序:执行主循环,处理实时的摄像头捕获和手势识别。

opencv实战项目 手势识别-手势控制键盘,opencv实战,计算机外设,opencv,计算机视觉

如果有遇到问题可以评论区留言,大家一起相互学习!文章来源地址https://www.toymoban.com/news/detail-645285.html

到了这里,关于opencv实战项目 手势识别-手势控制键盘的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Python实战项目:手势识别控制电脑音量

    今天给大家带来一个OpenCV的实战小项目——手势识别控制电脑音量 先上个效果图: 通过大拇指和食指间的开合距离来调节电脑音量,即通过识别大拇指与食指这两个关键点之间的距离来控制电脑音量大小 技术要学会分享、交流,不建议闭门造车。一个人走的很快、一堆人可

    2024年02月09日
    浏览(35)
  • Opencv项目实战:14 手势控制音量

    目录 0、项目介绍 1、项目展示 2、项目搭建 3、项目的代码与讲解 4、项目资源

    2024年02月02日
    浏览(28)
  • 基于计算机视觉手势识别控制系统YoloGesture (利用YOLO实现) 有详细代码+部署+在线服务器尝试+开源可复现

    Streamlit在线服务器体验网址: https://kedreamix-yologesture.streamlit.app/ HuggingFace在线服务器体验网址:https://huggingface.co/spaces/Kedreamix/YoloGesture 为了解答大家的问题,我录了个视频,大家也可以看看,https://www.bilibili.com/video/BV1LV4y1d7pg/,如果有问题可以在github上给我发issue进行探讨,

    2024年02月03日
    浏览(38)
  • 计算机视觉实战--OpenCV进行红绿灯识别

    前言: Hello大家好,我是Dream。 OpenCV是一个开源的计算机视觉库 ,可以用于实现各种图像和视频处理任务,包括红绿灯识别。可以帮助自动驾驶汽车、智能交通系统等设备准确地识别红绿灯的状态,以便做出正确的决策。今天,就有Dream带领大家复盘一下计算机视觉中最经典

    2024年02月07日
    浏览(30)
  • 手势识别-手势音量控制(opencv)

     本项目是使用了谷歌开源的框架mediapipe,里面有非常多的模型提供给我们使用,例如面部检测,身体检测,手部检测等。 手势识别系列文章 1.opencv实现手部追踪(定位手部关键点) 2.opencv实战项目 实现手势跟踪并返回位置信息(封装调用) 3.手势识别-手势音量控制(open

    2024年02月13日
    浏览(39)
  • 【实战精选】基于计算机视觉OpenCV的答题卡识别系统

    项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义: 随着科技的不断发展,计算机视觉技术在各个领域中的应用越来越广泛。其中,基于计算机视觉的答题卡识别系统在教育领域中具有重要的意义。传统的答题卡批阅方式需要大量的人力和时间,容易

    2024年04月25日
    浏览(36)
  • 计算机视觉项目实战-目标检测与识别

    😊😊😊 欢迎来到本博客 😊😊😊 本次博客内容将继续讲解关于OpenCV的相关知识 🎉 作者简介 : ⭐️⭐️⭐️ 目前计算机研究生在读。主要研究方向是人工智能和群智能算法方向。目前熟悉深度学习(keras、pytorch、yolov5),python网页爬虫、机器学习、计算机视觉(OpenCV)

    2024年02月02日
    浏览(36)
  • 基于计算机视觉的手势识别技术

    一个不知名大学生,江湖人称菜狗 original author: Jacky Li Email : 3435673055@qq.com Time of completion:2023.5.2 Last edited: 2023.5.2 手语是一种主要由听力困难或耳聋的人使用的交流方式。这种基于手势的语言可以让人们轻松地表达想法和想法,克服听力问题带来的障碍。 这种便捷的交流方式

    2024年02月04日
    浏览(38)
  • 计算机java项目 - 基于opencv与SVM的车牌识别系统

    基于opencv与SVM的车牌识别系统 提示:适合用于课程设计或毕业设计,工作量达标,源码开放 用python3+opencv3做的中国车牌识别,包括算法和客户端界面,只有2个文件,surface.py是界面代码,predict.py是算法代码,界面不是重点所以用tkinter写得很简单。 python3.7.3 opencv4.0.0.21 numpy

    2024年02月20日
    浏览(40)
  • 计算机视觉实战项目(图像分类+目标检测+目标跟踪+姿态识别+车道线识别+车牌识别)

    教程博客_传送门链接:链接 在本教程中,您将学习如何使用迁移学习训练卷积神经网络以进行图像分类。您可以在 cs231n 上阅读有关迁移学习的更多信息。 本文主要目的是教会你如何自己搭建分类模型,耐心看完,相信会有很大收获。废话不多说,直切主题… 首先们要知道深

    2024年02月07日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包