使用mediapipe库做手部的实时跟踪,关于mediapipe的介绍,请自行百度。
mediapipe做手部检测的资料,可以参考这里:
MediaPipe Hands: On-device Real-time Hand Tracking 论文阅读笔记 - 知乎论文地址: https://arxiv.org/abs/2006.10214v1Demo地址:https://hand.mediapipe.dev/研究机构: Google Research 会议: CVPR2020 开始介绍之前,先贴一个模型的流程图,让大家对系统架构有个整体的概念 0. 摘…https://zhuanlan.zhihu.com/p/431523776MediaPipe基础(4)Hands(手)_mediapipe hands-CSDN博客文章浏览阅读1.2w次,点赞6次,收藏66次。1.摘要在各种技术领域和平台,感知手的形状和运动的能力是改善用户体验的重要组成部分。例如,它可以构成手语理解和手势控制的基础,还可以在增强现实中将数字内容和信息叠加在物理世界之上。虽然对人们来说很自然,但强大的实时手部感知绝对是一项具有挑战性的计算机视觉任务,因为手经常遮挡自己或彼此(例如手指/手掌遮挡和握手)并且缺乏高对比度模式。MediaPipe Hands 是一种高保真手和手指跟踪解决方案。它采用机器学习 (ML) 从单个帧中推断出手的 21 个 3D 地标。当前最先进的方法主要依赖于强大的桌面环_mediapipe handshttps://blog.csdn.net/weixin_43229348/article/details/120530937
做手部跟踪时需要搞清楚手部的landmarks,如下图:
需要安装mediapipe,直接使用pip install mediapipe即可。
关于mediapipe.solution.hands的构造方法参数简单说明如下:
static_image_mode为True的话表示只做检测,为False表示当置信度低于阈值时会做检测,如果跟踪的置信度较好则不做检测只做跟踪。
max_num_hands参数就是其意思,最大检测的手数量
min_detection_confidence最小检测置信度阈值,高于此值为检测成功,默认0.5
min_tracking_confidence最小跟踪置信度阈值,高于此值表示手部跟踪成功,默认0.5
代码如下,仅供参考:
import cv2 as cv
import mediapipe as mp
import time
class HandDetector():
def __init__(self, mode=False,
maxNumHands=2,
modelComplexity=1,
minDetectionConfidence=0.5,
minTrackingConfidence=0.5):
self.mode = mode
self.maxNumHands = maxNumHands
self.modelComplexity = modelComplexity
self.minDetectionConfidence = minDetectionConfidence
self.minTrackingConfidence = minTrackingConfidence
#创建mediapipe的solutions.hands对象
self.mpHands = mp.solutions.hands
self.handsDetector = self.mpHands.Hands(self.mode, self.maxNumHands, self.modelComplexity, self.minDetectionConfidence, self.minTrackingConfidence)
#创建mediapipe的绘画工具
mpDrawUtils = mp.solutions.drawing_utils
def findHands(self, img, drawOnImage=True):
#mediapipe手部检测器需要输入图像格式为RGB
#cv默认的格式是BGR,需要转换
imgRGB = cv.cvtColor(img, cv.COLOR_BGR2RGB)
#调用手部检测器的process方法进行检测
self.results = self.handsDetector.process(imgRGB)
#print(results.multi_hand_landmarks)
#如果multi_hand_landmarks有值表示检测到了手
if self.results.multi_hand_landmarks:
#遍历每一只手的landmarks
for handLandmarks in self.results.multi_hand_landmarks:
if drawOnImage:
mpDrawUtils.draw_landmarks(img, handLandmarks, self.mpHands.HAND_CONNECTIONS)
return img;
#从结果中查询某只手的landmark list
def findHandPositions(self, img, handID=0, drawOnImage=True):
landmarkList = []
if self.results.multi_hand_landmarks:
handLandmarks = self.results.multi_hand_landmarks[handID]
for id,landmark in enumerate(handLandmarks.landmark):
#处理每一个landmark,将landmark里的X,Y(比例)转换为帧数据的XY坐标
h,w,c = img.shape
centerX,centerY = int(landmark.x * w), int(landmark.y * h)
landmarkList.append([id, centerX, centerY])
if (drawOnImage):
#将landmark绘制成圆
cv.circle(img, (centerX,centerY), 8, (0,255,0), cv.FILLED)
return landmarkList
def DisplayFPS(img, preTime):
curTime = time.time()
if (curTime - preTime == 0):
return curTime;
fps = 1 / (curTime - preTime)
cv.putText(img, "FPS:" + str(int(fps)), (10,70), cv.FONT_HERSHEY_PLAIN,
3, (0,255,0), 3)
return curTime
def main():
video = cv.VideoCapture('../../SampleVideos/hand.mp4')
#FPS显示
preTime = 0
handDetector = HandDetector()
while True:
ret,frame = video.read()
if ret == False:
break;
frame = handDetector.findHands(frame)
hand0Landmarks = handDetector.findHandPositions(frame)
#if len(hand0Landmarks) != 0:
#print(hand0Landmarks)
preTime = DisplayFPS(frame, preTime)
cv.imshow('Real Time Hand Detection', frame)
if cv.waitKey(1) & 0xFF == ord('q'):
break;
video.release()
cv.destroyAllWindows()
if __name__ == "__main__":
main()
运行效果:
Python Opencv实践 - 手部跟踪