一文带你读懂Python计算机视觉中的OpenCV手势识别方法

前言人工智能的浪潮正在席卷全球 。一个已经被谈论了几十年的概念,如今这几年,相关技术的发展速度越来越快 。机器学习、深度学习、计算机视觉等名词逐渐走进人们的生活,它们同属于人工智能的范畴之中 。
计算机视觉是人工智能领域的一个分支计算机视觉实际上是一个跨领域的交叉学科,包括计算机科学,数学,工程学,物理学,生物学和心理学等领域 。许多科学家认为,计算机视觉为人工智能的发展开拓了道路 。
简单来说,计算机视觉就是赋予计算机一双观察世界的眼睛,再使用计算机优秀的大脑快速的计算,服务人类 。
今天我们将深入浅出,简单介绍Python计算机视觉中的手势识别方法,识别手势——数字(一、二、三、四、五和大拇指的赞赏) 。
前期准备
本篇我们将会用到Python的OpenCV模块和手部模型模块mediapipe,在Python的pip安装方法中,安装方法如下:
opencv是常用的图像识别模块
mediapipe是谷歌开发并开源的多媒体机器学习模型应用框架 。
pip install opencv-pythonpip install mediapipe如果你的电脑装有Anaconda,建议选择在Anaconda的环境命令行中进行相应模块的安装,以此构建更具体的机器学习环境
当你安装好OpenCV和mediapipe模块以后,你可以在Python代码中写入
import cv2import 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 cv2import 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.detectionCon = detectionConself.minTrackCon = minTrackConself.mpHands = mp.solutions.handsself.hands = self.mpHands.Hands(self.mode, self.maxHands,self.detectionCon, self.minTrackCon)self.mpDraw = mp.solutions.drawing_utilsself.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:竖起手指的数组(列表),数组长度为5,其中,由大拇指开始数,立起标为1,放下为0 。"""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"


推荐阅读