Python如何利用opencv实现手势识别

yizhihongxing

下面是详细讲解Python如何利用OpenCV实现手势识别的完整攻略。

1. 准备工作

在开始手势识别之前,我们需要确保OpenCV已经安装在我们的系统上。可以使用以下命令来检查:

$ python3
Python 3.7.3 (default, Apr  3 2019, 05:39:12) 
[GCC 8.3.0] on linux
>>> import cv2
>>> cv2.__version__
'4.1.0'

如果OpenCV已经在我们的系统上安装并准备好使用,我们可以继续下一步。

2. 开始编写代码

2.1 导入必要的库

在开始编写代码之前,我们需要导入一些必要的Python库。

import cv2
import numpy as np
import math

2.2 读取视频并提取手势

我们需要读取从摄像头中获取的实时视频,并对每一帧进行处理。在处理每一帧期间,我们需要提取手势并将其显示在窗口中。以下是代码片段:

cap = cv2.VideoCapture(0)

while True:
    _, img = cap.read()
    cv2.imshow("Original", img)

    # 处理每一帧
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
    _, thresh = cv2.threshold(blur, 20, 255, cv2.THRESH_BINARY_INV)
    cv2.imshow("Thresh", thresh)

    # 寻找轮廓并绘制
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    try:
        hierarchy = hierarchy[0]
    except:
        hierarchy = []
    num_defects = 0

    for i in range(len(contours)):
        cnt = contours[i]
        area = cv2.contourArea(cnt)

        if area < 5000:
            continue

        # 近似边缘
        epsilon = 0.0005 * cv2.arcLength(cnt, True)
        approx = cv2.approxPolyDP(cnt, epsilon, True)

        # 凸包
        hull = cv2.convexHull(cnt)

        # 指尖检测
        defects = cv2.convexityDefects(cnt, cv2.convexHull(cnt, returnPoints=False))
        cv2.drawContours(thresh, [cnt], 0, (0, 255, 0), 2)
        cv2.drawContours(thresh, [approx], 0, (0, 0, 255), 2)

2.3 提取指尖并绘制轮廓

接下来,我们需要提取手势中每个手指的指尖,并在轮廓上进行标记。以下是代码片段:

for i in range(defects.shape[0]):
    s, e, f, d = defects[i][0]
    start = tuple(cnt[s][0])
    end = tuple(cnt[e][0])
    far = tuple(cnt[f][0])
    a = math.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2)
    b = math.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)
    c = math.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)
    angle = math.acos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c)) * 57

    if angle <= 90:
        num_defects += 1
        cv2.circle(img, far, 3, [255, 0, 0], -1)

    cv2.line(img, start, end, [0, 255, 0], 2)

    if num_defects == 0:
        cv2.putText(img, "One", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)
    elif num_defects == 1:
        cv2.putText(img, "Two", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)
    elif num_defects == 2:
        cv2.putText(img, "Three", (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)
    elif num_defects == 3:
        cv2.putText(img, "Four", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)
    elif num_defects == 4:
        cv2.putText(img, "Five", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 2, 2)

cv2.imshow("Gesture", img)

2.4 运行程序并调试

我们的程序已经准备好使用了,我们可以使用以下命令运行程序:

$ python3 gesture_recognition.py

在调试期间,你可能需要修改一些值和参数来使程序工作正常。

3. 示例说明

以下是两个示例说明:

3.1 利用手势控制鼠标移动

我们可以利用手势来控制鼠标的移动。具体步骤如下:

  • 打开摄像头并读取每一帧数据。
  • 如果我们的双手放在视觉范围内,则在视频的中心位置绘制一个绿色的圆。
  • 如果我们提高一只手,那么我们的程序将把它视为鼠标指针。我们可以使用手部的运动来控制鼠标的移动。

以下是代码示例:

# 启动摄像头
cap = cv2.VideoCapture(0)

while True:
    # 读取摄像头中的数据
    _, img = cap.read()
    img = cv2.flip(img, 1)

    # 将图片转为灰色并进行模糊处理
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (15, 15), 0)

    # 检测我们的手
    _, thresh = cv2.threshold(blurred, 50, 255, cv2.THRESH_BINARY_INV)

    # 绘制绿色圆圈
    cv2.circle(img, (320, 240), 15, (0, 255, 0), 2)

    # 检测手部运动来控制鼠标的移动
    # ...

    cv2.imshow("Gesture", img)

    # 按'q'键退出
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

# 释放摄像头并销毁窗口
cap.release()
cv2.destroyAllWindows()

3.2 利用手势控制电灯开关

我们可以利用手势来控制电灯的开关。具体步骤如下:

  • 打开摄像头并读取每一帧数据。
  • 如果我们的右手在视频中平且手指朝下,则关闭电灯;如果我们的右手在视频中竖着,则打开电灯。

以下是代码示例:

# 启动摄像头
cap = cv2.VideoCapture(0)

while True:
    # 读取摄像头中的数据
    _, img = cap.read()
    img = cv2.flip(img, 1)

    # 将图片转为灰色并进行模糊处理
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (15, 15), 0)

    # 检测我们的手势
    _, thresh = cv2.threshold(blurred, 50, 255, cv2.THRESH_BINARY_INV)

    # 寻找手的轮廓
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

    # 检测每个手的手指数目
    finger_count = 0

    for i in range(len(contours)):
        cnt = contours[i]

        if cv2.contourArea(cnt) > 5000:
            hull = cv2.convexHull(cnt, returnPoints=False)
            defects = cv2.convexityDefects(cnt, hull)

            if defects is not None:
                for j in range(defects.shape[0]):
                    s, e, f, d = defects[j][0]
                    start = tuple(cnt[s][0])
                    end = tuple(cnt[e][0])
                    far = tuple(cnt[f][0])

                    a = math.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2)
                    b = math.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)
                    c = math.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)
                    angle = math.acos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c)) * 57

                    if angle <= 90:
                        finger_count += 1

            if finger_count == 0:
                cv2.putText(img, 'Light Off', (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 2, 255)
            else: 
                cv2.putText(img, 'Light On', (100, 100), cv2.FONT_HERSHEY_SIMPLEX, 2, 255)

    cv2.imshow("Gesture", img)

    # 按'q'键退出
    if cv2.waitKey(10) & 0xFF == ord('q'):
        break

# 释放摄像头并销毁窗口
cap.release()
cv2.destroyAllWindows()

以上是如何利用OpenCV实现手势识别的完整攻略,希望对您有所帮助!

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python如何利用opencv实现手势识别 - Python技术站

(0)
上一篇 2023年6月6日
下一篇 2023年6月6日

相关文章

  • 浅析Python 3 字符串中的 STR 和 Bytes 有什么区别

    浅析Python 3 字符串中的 STR 和 Bytes 有什么区别 在 Python 3 中,STR 和 Bytes 是最基础和常用的两个数据类型之一,它们之间的区别是非常重要的。在本文中,我们将深入浅出地讲解 STR 和 Bytes 的含义、区别以及在 Python 中的使用。 STR 和 Bytes 的含义 STR STR 是字符串类型,在 Pytho…

    python 2023年5月31日
    00
  • Python+tkinter实现高清图片保存

    Python+tkinter实现高清图片保存攻略 本攻略将介绍如何使用Python和tkinter库实现高清图片保存。我们将使用Python的Pillow库来处理图片,使用tkinter库来创建GUI界面。 安装Pillow库 在开始之前,我们需要安装Pillow库。我们可以使用以下命令在命令行中安装Pillow库: pip install Pillow 创…

    python 2023年5月15日
    00
  • python 显示数组全部元素的方法

    当我们想要显示 Python 中的数组全部元素时,通常使用如下两种方法: 方法一:使用 for 循环 arr = [1, 2, 3, 4, 5] for i in arr: print(i, end=" ") 上面的代码中,我们将 arr 列表中的全部元素一个一个取出,然后使用 print() 函数将它们打印出来。这里注意,我们使用 en…

    python 2023年6月5日
    00
  • Python数据结构与算法之常见的分配排序法示例【桶排序与基数排序】

    Python数据结构与算法之常见的分配排序法示例【桶排序与基数排序】 什么是分配排序法 分配排序法是一种基于各种数据分布特性和信息量的统计推测方法,通过计数完成排序过程。分配排序法是不基于比较的排序方法,排序效率很高。 常见的分配排序法示例 桶排序 基数排序 下面将对这两种排序进行详细说明。 桶排序 桶排序的思想是把数据分到有限数量的桶里。每个桶再分别进行排…

    python 2023年6月5日
    00
  • python 捕获shell脚本的输出结果实例

    让我们来讲解一下“python 捕获shell脚本的输出结果实例”的完整攻略。 1.背景 在程序开发中,有时候需要通过运行shell脚本来完成一些任务,比如文件备份、数据导出等。在实际操作中,我们可能需要捕获shell脚本的输出结果,并对其进行处理或分析。Python提供了多种方式来实现这个功能,下面我将介绍其中两种常用方法。 2.方法一:使用subproc…

    python 2023年6月5日
    00
  • Python的进程及进程池详解

    Python的进程及进程池详解 在Python中,进程是一种执行计算机程序的方式。它们是操作系统分配资源的基单位。本文将为您提供一个完整攻略,详细讲解Python的进程进程池,包括进程的创建启动停止、等待和进程池的使用,并提供两个示例说明。 1. 进的创建、启动、停止和等待 在Python中可以使用multiprocessing模块创建和管理进程。以下是一个…

    python 2023年5月14日
    00
  • 【K哥爬虫普法】12亿公民信息泄露,仅判3年,个人信息是否为爬虫“禁区”?

    我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K 哥特设了“K哥爬虫普法”专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识,知晓如何合法合规利用爬虫技术,警钟长鸣,做一个守法、护法、有原则的技术人员。 案情介绍 出生于1983年12月的黎某是湖南省浏阳市人,从2012年开始做淘宝客生意,即通过做淘宝推广…

    python 2023年4月18日
    00
  • python执行使用shell命令方法分享

    下面是关于python执行使用shell命令的完整攻略: 1. 背景知识 在Linux下,我们可以使用shell命令来完成一些系统管理操作,比如创建、删除、移动目录、查看文件列表等等。Python提供了执行shell命令的方法,使得我们可以在Python程序中执行shell命令,这样就可以方便地完成一些系统管理操作。 2. shell命令执行函数 在Pyth…

    python 2023年6月2日
    00
合作推广
合作推广
分享本页
返回顶部