文章目录

  • 更新日记
  • 前言
  • 前期准备
  • 识别手部模型
  • 识别视频输入方法
  • 手势识别方法
  • 完整代码
  • 结语

更新日记

更新日记:
2022.04.18:应各位网友需求,已mp库更新后的手部识别模型代码。目前可以正常的RUN啦!!

前言

人工智能的浪潮正在席卷全球。一个已经被谈论了几十年的概念,如今这几年,相关技术的发展速度越来越快。机器学习、深度学习、计算机视觉等名词逐渐走进人们的生活,它们同属于人工智能的范畴之中。

计算机视觉是人工智能领域的一个分支计算机视觉实际上是一个跨领域的交叉学科,包括计算机科学,数学,工程学,物理学,生物学和心理学等领域。许多科学家认为,计算机视觉为人工智能的发展开拓了道路。

简单来说,计算机视觉就是赋予计算机一双观察世界的眼睛,再使用计算机优秀的大脑快速的计算,服务人类。

今天我们将深入浅出,简单介绍Python计算机视觉中的手势识别方法,识别手势——数字(一、二、三、四、五和大拇指的赞赏)。如果你喜欢本篇文章或对你有帮助的话,别忘了点赞+关注噢!

前期准备

本篇我们将会用到Python的OpenCV模块和手部模型模块mediapipe,在Python的pip安装方法中,安装方法如下:

opencv是常用的图像识别模块

mediapipe是谷歌开发并开源的多媒体机器学习模型应用框架。

pip install opencv-python
pip install mediapipe

如果你的电脑装有Anaconda,建议选择在Anaconda的环境命令行中进行相应模块的安装,以此构建更具体的机器学习环境

当你安装好OpenCV和mediapipe模块以后,你可以在Python代码中写入

import cv2
import mediapipe as mp

如果运行成功,那么你的Opencv-python模块即为安装成功,那么我们现在就开始进入今天的正题吧!

识别手部模型

既然要做手势识别,那么就要去找到我们传入图像的手部信息。本处我们将使用mediapipe模型去找到手部模型,并完成手部模型的识别模块,并命名,我们将在后续手势识别内容中将其作为模块引入

HandTrackingModule.py

# -*- coding:utf-8 -*-"""CODE >>> SINCE IN CAIXYPROMISE.
MOTTO >>> STRIVE FOR EXCELLENT.
CONSTANTLY STRIVING FOR SELF-IMPROVEMENT.@ By: CaixyPromise
@ Date: 2021-10-17"""import cv2
import mediapipe as mpclass HandDetector:"""使用mediapipe库查找手。导出地标像素格式。添加了额外的功能。如查找方式,许多手指向上或两个手指之间的距离。而且提供找到的手的边界框信息。"""def __init__(self, mode=False, maxHands=2, detectionCon=0.5, minTrackCon = 0.5):""":param mode: 在静态模式下,对每个图像进行检测:param maxHands: 要检测的最大手数:param detectionCon: 最小检测置信度:param minTrackCon: 最小跟踪置信度"""self.mode = modeself.maxHands = maxHandsself.modelComplex = Falseself.detectionCon = detectionConself.minTrackCon = minTrackCon# 初始化手部识别模型self.mpHands = mp.solutions.handsself.hands = self.mpHands.Hands(self.mode, self.maxHands, self.modelComplex,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):"""从图像(BRG)中找到手部。:param img: 用于查找手的图像。:param draw: 在图像上绘制输出的标志。:return: 带或不带图形的图像"""imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 将传入的图像由BGR模式转标准的Opencv模式——RGB模式,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 imgdef findPosition(self, img, handNo=0, draw=True):"""查找单手的地标并将其放入列表中像素格式。还可以返回手部周围的边界框。:param img: 要查找的主图像:param handNo: 如果检测到多只手,则为手部id:param draw: 在图像上绘制输出的标志。(默认绘制矩形框):return: 像素格式的手部关节位置列表;手部边界框"""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.shapepx, 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 - yminbbox = xmin, ymin, boxW, boxHcx, 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, bboxInfodef fingersUp(self):"""查找列表中打开并返回的手指数。会分别考虑左手和右手:return:竖起手指的列表"""if self.results.multi_hand_landmarks:myHandType = self.handType()fingers = []# Thumbif 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 Fingersfor 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 fingersdef handType(self):"""检查传入的手部是左还是右:return: "Right" 或 "Left""""if self.results.multi_hand_landmarks:if self.lmList[17][0] < self.lmList[5][0]:return "Right"else:return "Left"

识别视频输入方法

完成手部模型的获取与识别,现在我们就要将内容传入到计算机当中,使其能进行手部的识别以及手势的识别。本处我们将使用OpenCV进行内容的输入流,开启计算机的摄像头获取内容,并使用刚刚我们写的HandTrackingModule模块作为手部的识别模块。

Main.py


# -*- coding:utf-8 -*-"""CODE >>> SINCE IN CAIXYPROMISE.
MOTTO >>> STRIVE FOR EXCELLENT.
CONSTANTLY STRIVING FOR SELF-IMPROVEMENT.@ By: CaixyPromise
@ Date: 2021-10-17"""
import cv2
from HandTrackingModule import HandDetectorclass Main:def __init__(self):self.camera = cv2.VideoCapture(0,cv2.CAP_DSHOW) # 以视频流传入self.camera.set(3, 1280) # 设置分辨率self.camera.set(4, 720)def Gesture_recognition(self):while True:self.detector = HandDetector()frame, img = self.camera.read()img = self.detector.findHands(img) # 找到你的手部lmList, bbox = self.detector.findPosition(img) # 获取你手部的方位cv2.imshow("camera", img)if cv2.getWindowProperty('camera', cv2.WND_PROP_VISIBLE) < 1:break# 通过关闭按钮退出程序cv2.waitKey(1)   # if cv2.waitKey(1) & 0xFF == ord("q"):#     break # 按下q退出

现在,当我们运行程序后,程序会运行你的计算机默认摄像头,当你露出你的手时,会传出图像圈住你的手部,并且绘制出你的手部主要关节点。

其中,你的手部主要关节点已经标好序号,你的手部分为了21个关节点,指尖分别为4 8 12 16 20

具体关节分为:

手势识别方法

通过前面的讲解,我们完成了手部获取与识别、识别内容的输入,那么我们现在就来开始写我们的手势识别方法。这里,我们用到识别模块里的fingersUp()方法。

找到我们刚刚写的Main.py文件(识别内容输入方法),当我们找到并绘制出我们的手部位置以后,此时的findPosition()方法会得到你的手部具体方位,其中lmList是关节位置方位(type:list),bbox是边框方位(type:dict),当未识别到内容时两者均为。所以,我们只需要写当数组中存在数据(非空),进行手指判断即可,那么我们可以写成


# -*- coding:utf-8 -*-"""CODE >>> SINCE IN CAIXYPROMISE.
MOTTO >>> STRIVE FOR EXCELLENT.
CONSTANTLY STRIVING FOR SELF-IMPROVEMENT.@ By: CaixyPromise
@ Date: 2021-10-17"""
def Gesture_recognition(self):while True:self.detector = HandDetector()frame, img = self.camera.read()img = self.detector.findHands(img)lmList, bbox = self.detector.findPosition(img)if lmList:x1, x2, x3, x4, x5 = self.detector.fingersUp()

上面我们fingersUp()方法谈到,fingersUp()方法会传回从大拇指开始数的长度为5的数组,立起的手指标记为1,放下标记为0。

本次我们的目的时写一个识别我们生活常见的数字手势以及一个赞扬大拇指的手势。结合我们生活,识别你的手势可以写为

# -*- coding:utf-8 -*-"""CODE >>> SINCE IN CAIXYPROMISE.
MOTTO >>> STRIVE FOR EXCELLENT.
CONSTANTLY STRIVING FOR SELF-IMPROVEMENT.@ By: CaixyPromise
@ Date: 2021-10-17"""
def Gesture_recognition(self):while True:self.detector = HandDetector()frame, img = self.camera.read()img = self.detector.findHands(img)lmList, bbox = self.detector.findPosition(img)if lmList:x1, x2, x3, x4, x5 = self.detector.fingersUp()if (x2 == 1 and x3 == 1) and (x4 == 0 and x5 == 0 and x1 == 0):# TWOelif (x2 == 1 and x3 == 1 and x4 == 1) and (x1 == 0 and x5 == 0):# THREEelif (x2 == 1 and x3 == 1 and x4 == 1 and x5 == 1) and (x1 == 0):# FOURelif x1 == 1 and x2 == 1 and x3 == 1 and x4 == 1 and x5 == 1:# FIVEelif x2 == 1 and (x1 == 0, x3 == 0, x4 == 0, x5 == 0):# ONEelif x1 and (x2 == 0, x3 == 0, x4 == 0, x5 == 0):# NICE_GOOD

完成基本的识别以后,我们要把内容表达输出出来。这里我们结合bbox返回的手部方框方位,再使用opencv里的putText方法,实现识别结果的输出。


# -*- coding:utf-8 -*-"""CODE >>> SINCE IN CAIXYPROMISE.
MOTTO >>> STRIVE FOR EXCELLENT.
CONSTANTLY STRIVING FOR SELF-IMPROVEMENT.@ By: CaixyPromise
@ Date: 2021-10-17"""
def Gesture_recognition(self):while True:self.detector = HandDetector()frame, img = self.camera.read()img = self.detector.findHands(img)lmList, bbox = self.detector.findPosition(img)if lmList:x_1, y_1 = bbox["bbox"][0], bbox["bbox"][1]x1, x2, x3, x4, x5 = self.detector.fingersUp()if (x2 == 1 and x3 == 1) and (x4 == 0 and x5 == 0 and x1 == 0):cv2.putText(img, "2_TWO", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)elif (x2 == 1 and x3 == 1 and x4 == 1) and (x1 == 0 and x5 == 0):cv2.putText(img, "3_THREE", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)elif (x2 == 1 and x3 == 1 and x4 == 1 and x5 == 1) and (x1 == 0):cv2.putText(img, "4_FOUR", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)elif x1 == 1 and x2 == 1 and x3 == 1 and x4 == 1 and x5 == 1:cv2.putText(img, "5_FIVE", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)elif x2 == 1 and (x1 == 0, x3 == 0, x4 == 0, x5 == 0):cv2.putText(img, "1_ONE", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)elif x1 and (x2 == 0, x3 == 0, x4 == 0, x5 == 0):cv2.putText(img, "GOOD!", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)cv2.imshow("camera", img)if cv2.getWindowProperty('camera', cv2.WND_PROP_VISIBLE) < 1:breakcv2.waitKey(1)

现在,我们已经完成手势的识别与结果输出,我们把完整代码运行一下,即可验证出我们的代码效果。

完整代码

完整代码如下


# -*- coding:utf-8 -*-"""CODE >>> SINCE IN CAIXYPROMISE.
STRIVE FOR EXCELLENT.
CONSTANTLY STRIVING FOR SELF-IMPROVEMENT.
@ by: caixy
@ date: 2021-10-1"""import cv2
from HandTrackingModule import HandDetectorclass Main:def __init__(self):self.camera = cv2.VideoCapture(0,cv2.CAP_DSHOW)self.camera.set(3, 1280)self.camera.set(4, 720)def Gesture_recognition(self):while True:self.detector = HandDetector()frame, img = self.camera.read()img = self.detector.findHands(img)lmList, bbox = self.detector.findPosition(img)if lmList:x_1, y_1 = bbox["bbox"][0], bbox["bbox"][1]x1, x2, x3, x4, x5 = self.detector.fingersUp()if (x2 == 1 and x3 == 1) and (x4 == 0 and x5 == 0 and x1 == 0):cv2.putText(img, "2_TWO", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)elif (x2 == 1 and x3 == 1 and x4 == 1) and (x1 == 0 and x5 == 0):cv2.putText(img, "3_THREE", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)elif (x2 == 1 and x3 == 1 and x4 == 1 and x5 == 1) and (x1 == 0):cv2.putText(img, "4_FOUR", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)elif x1 == 1 and x2 == 1 and x3 == 1 and x4 == 1 and x5 == 1:cv2.putText(img, "5_FIVE", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)elif x2 == 1 and (x1 == 0, x3 == 0, x4 == 0, x5 == 0):cv2.putText(img, "1_ONE", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)elif x1 and (x2 == 0, x3 == 0, x4 == 0, x5 == 0):cv2.putText(img, "GOOD!", (x_1, y_1), cv2.FONT_HERSHEY_PLAIN, 3,(0, 0, 255), 3)cv2.imshow("camera", img)if cv2.getWindowProperty('camera', cv2.WND_PROP_VISIBLE) < 1:breakcv2.waitKey(1)# if cv2.waitKey(1) & 0xFF == ord("q"):#     breakif __name__ == '__main__':Solution = Main()Solution.Gesture_recognition()

效果一目了然,计算机成功识别了你的手势并把内容输出。快去试试吧!

结语

本篇计算机视觉的手势识别内容写完了,这也是本人第一篇关于人工智能类计算机视觉的推文,后续我们也会持续输出有关于人工智能类的文章,如果本篇写作有纰漏和错误或疑问的地方,还望各位能在评论区指出,让我们一起共同进步一起学习。

创作不易,如果你觉得这篇文章对你有用的话,别忘了点赞在看+关注噢!

下一篇我们将介绍手势识别的进阶——动态手势的识别,我们会将文章第一时间发送在微信公众号:“01编程小屋”当中,别忘了关注我们的公众号以免错过了噢!

【计算机视觉】基于Python—OpenCV的手势识别详解(一)相关推荐

  1. Python OpenCV相机参数详解:实现准确的相机标定和图像处理

    Python OpenCV相机参数详解:实现准确的相机标定和图像处理 在计算机视觉领域,相机参数是非常重要的元素.通过相机参数的标定,可以将图像中的像素坐标转化为真实世界中的坐标,从而实现准确的图像处 ...

  2. python的图书管理项目教程_基于python图书馆管理系统设计实例详解

    写完这个项目后,导师说这个你完全可以当作毕业项目使用了,写的很全,很多的都设计考虑周全,但我的脚步绝不止于现在,我想要的是星辰大海!与君共勉! 这个项目不是我的作业, 只是无意中被拉进来了,然后就承担 ...

  3. python图书馆管理系统实验报告_基于python图书馆管理系统设计实例详解

    写完这个项目后,导师说这个你完全可以当作毕业项目使用了,写的很全,很多的都设计考虑周全,但我的脚步绝不止于现在,我想要的是星辰大海!与君共勉! 这个项目不是我的作业, 只是无意中被拉进来了,然后就承担 ...

  4. python中如何取余_基于python 取余问题(%)详解

    取余的公式: 余数=除数-被除数*商 python的的余数是按照整除(向下取整)得到的商来计算的. 取余问题主要分为 : 正数与正数,负数与负数,正数与负数 ,0 正数与正数 #大数/小数:因为得出的 ...

  5. python取余还是相乘_python取余还是相乘_基于python 取余问题(%)详解

    取余的公式: 余数=除数-被除数*商 python的的余数是按照整除(向下取整)得到的商来计算的. 取余问题主要分为 : 正数与正数,负数与负数,正数与负数 ,0 正数与正数 #大数/小数:因为得出的 ...

  6. python opencv 直方图均衡_详解python OpenCV学习笔记之直方图均衡化

    本文介绍了python OpenCV学习笔记之直方图均衡化,分享给大家,具体如下: 官方文档 – https://docs.opencv.org/3.4.0/d5/daf/tutorial_py_hi ...

  7. 基于Python +Selenium的爬虫详解

    一.selenium简介 由于requests模块是一个不完全模拟浏览器行为的模块,只能爬取到网页的HTML文档信息,无法解析和执行CSS.JavaScript代码,因此需要我们做人为判断: 1.什么 ...

  8. python中exchange函数使用_python基于exchange函数发送邮件过程详解

    python基于exchange函数发送邮件过程详解 作者: shuzihua 更新时间:2020-11-06 10:40:35 原文链接 1.Python hasattr() 函数 描述 hasat ...

  9. python是基于什么原理_Python基于class()实现面向对象原理详解

    首先,类是一个集合,包含了数据,操作描述的一个抽象集合 你可以首先只把类当做一个容器来使用 class Cycle: def __init__(self,r): self.pi=3.14 self.r ...

最新文章

  1. (入门)上传GitHub怎么忽略node_modules
  2. python各个解释器的用途-python解释器有哪些?
  3. leaflet的入门开发(一)
  4. 新建虚拟机与window的连接
  5. Blogger建立Blog部落格​​ - Blog透视镜
  6. Linux 自带的LED 灯驱动实验
  7. 没有暑假的Ada 要好好努力咯 C#继续
  8. 浙大计算机硕士比本科985,二本出身的985研究生与985本科生,哪个更厉害?网友:差的太多!...
  9. 外汇交易所巨头 Travelex 遭攻击暂停服务,详情不明
  10. 英雄由此诞生------直击微软2008发布大会
  11. Codeforces 659F Polycarp and Hay【BFS】
  12. TwinCAT3入门教程4-伺服常用功能程序实现
  13. 如何使用Python 画笔
  14. Parsing error: No Babel config file detected for ....
  15. python 监控键盘输入_python 监控键盘输入
  16. 使用python计算内含报酬率
  17. 建设数字经济引领型城市 CDEC2022中国数字智能生态大会广州举行
  18. 一阶的RC高低通电路和微积分电路有什么区别
  19. shell一键部署mysql
  20. 来个大佬帮看下这个密文如何解密

热门文章

  1. 果断MARK Flex的那些资源
  2. matlab弹跳球代码,基于MatlabSimulink的小球弹跳仿真及动画实现.pdf
  3. LeetCode每日一题(题1028)
  4. 最新免费申请微软OneDrive5TB云盘超详细教程!(已亲测!)
  5. 【重心坐标插值、透视矫正插值】原理以及用法见解(GAMES101深度测试部分讨论)
  6. java Preferences 使用
  7. python海象运算符_浅析PEP572: 海象运算符
  8. 多线程-使用大全 基础使用 / 锁 / 线程池 / 原子类 / 并发包 / CAS / AQS (2022版)
  9. CLion工具(cmake) 快速开始
  10. 2022上海新能源物流车展|快递物流配送展|3月高端品牌展,引领绿色城配出行