2022年1月10日,看到相关教程跟做
代码存在C:\Users\10133\PycharmProjects\Project_PictureProcessing
目录
一、调研
Opencv
MediaPipe
二、大概步骤
安装MediaPipe
导入opencv、MediaPipe和time库(其中time库是自带的,不用下载)
创建手部检测模型
结果输出
画图样式
三、代码段
OpenCV 是一个基于 Apache2.0 许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。
它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了 Python、Ruby、MATLAB 等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
MediaPipe 是一款由 Google Research 开发并开源的多媒体机器学习模型应用框架,可以直接调用其 API 完成目标检测、人脸检测以及关键点检测等。
MediaPipe官网:
Home - mediapipe (google.github.io)https://google.github.io/mediapipe/
手势说明文档:
Hands - mediapipe (google.github.io)https://google.github.io/mediapipe/solutions/hands.html#static_image_mode
pip install mediapipe
import cv2
import mediapipe as mp
import time
# 从摄像头捕获视频
# 参数为0表示打开计算机内置摄像头(我的电脑有点带不动,很卡) 也可以用视频的路径
cap = cv2.VideoCapture(0)
mpHands = mp.solutions.hands
hands = mpHands.Hands()
其中 cv2.VideoCapture() 内的参数,0表示打开计算机内置摄像头,1表示导入已拍摄好的视频
hands是检测手部关键点的函数,其中有4个输入参数量可以选择(如下):
while True:
# 会返回两个值ret和img
ret,img = cap.read()
if ret: # 这表示如果ret没有问题,也就是ret = true
imgRGB = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #将BGR格式的图片转换成RGB的格式
result = hands.process(imgRGB)
print(result.multi_hand_landmarks) #映射出手上的21个点的坐标
# 把每一帧显示出来
cv2.imshow('img',img)
# 卡1ms跳出
if cv2.waitKey(0) == ord('q'):
break
result.multi_hand_landmarks: 手部21个点的坐标,其中 x,y,z 是归一化后的坐标(后面会对窗长进行计算,从而得到真实的坐标值)
刚只是得到了点的坐标,并没有画出来,下面将画出每个点
# 画手上landmarks的点的坐标
mpDraw = mp.solutions.drawing_utils
# 点的样式 三个值分别是b、g、r
handLms_Style = mpDraw.DrawingSpec(color=(0, 0, 255), thickness = 5)
# 线的样式
handCon_Style = mpDraw.DrawingSpec(color=(0, 0, 255), thickness = 10)
参数都是可以修改的,然后再在输出结果中加入循环,对每张图中每个点进行循环
# 把21个点画出来
if result.multi_hand_landmarks:
# 对每个点进行循环
for handLms in result.multi_hand_landmarks:
mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS, handLms_Style, handCon_Style)
# 得到21个点的坐标,得到得是比例
# 循环每只手的每个点(i从0到20)
for i, lm, in enumerate(handLms.landmark):
# 根据前面得到的窗长和窗宽得到真实的x和y的位置,并转换成整数
xPos = int(lm.x * imgWidth)
yPos = int(lm.y * imgHeight)
cv2.putText(img, str(i), (xPos+25, yPos-5), cv2.FONT_HERSHEY_COMPLEX_SMALL, 0.4, (0, 0, 255), 2)
if i ==4:
cv2.circle(img, (xPos, yPos), 20, (166, 56, 56), cv2.FILLED)
print(i, xPos, yPos)
cv2.putText 可以在点旁进行标注
import cv2
import mediapipe as mp
import time
# 从摄像头捕获视频
# 参数为0表示打开计算机内置摄像头(我的电脑有点带不动,很卡) 也可以用视频的路径
cap = cv2.VideoCapture(0)
mpHands = mp.solutions.hands
hands = mpHands.Hands() #如果使用函数本身的预设值的话,括号内不用写参数设置 按住ctrl点击函数可以看到函数的定义
# 画手上landmarks的点的坐标
mpDraw = mp.solutions.drawing_utils
# 点的样式 三个值分别是b、g、r
handLms_Style = mpDraw.DrawingSpec(color=(0, 0, 255), thickness = 5)
# 线的样式
handCon_Style = mpDraw.DrawingSpec(color=(0, 0, 255), thickness = 10)
# 设置两个时间 为了计算fps:每秒传输帧数
pTime = 0
cTime = 0
while True:
# 会返回两个值ret和img
ret,img = cap.read()
if ret: # 这表示如果ret没有问题,也就是ret = true
imgRGB = cv2.cvtColor(img,cv2.COLOR_BGR2RGB) #将BGR格式的图片转换成RGB的格式
result = hands.process(imgRGB)
# print(result.multi_hand_landmarks) #映射出手上的21个点的坐标
# 为了下面得到的坐标从比例转换为真实坐标,这里首先得到窗长和窗宽
imgHeight = img.shape[0]
imgWidth = img.shape[1]
# 把21个点画出来
if result.multi_hand_landmarks:
# 对每个点进行循环
for handLms in result.multi_hand_landmarks:
mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS, handLms_Style, handCon_Style)
# 得到21个点的坐标,得到得是比例
# 循环每只手的每个点(i从0到20)
for i, lm, in enumerate(handLms.landmark):
# 根据前面得到的窗长和窗宽得到真实的x和y的位置,并转换成整数
xPos = int(lm.x * imgWidth)
yPos = int(lm.y * imgHeight)
cv2.putText(img, str(i), (xPos+25, yPos-5), cv2.FONT_HERSHEY_COMPLEX_SMALL, 0.4, (0, 0, 255), 2)
if i ==4:
cv2.circle(img, (xPos, yPos), 20, (166, 56, 56), cv2.FILLED)
print(i, xPos, yPos)
# 计算得到每秒传输帧数
cTime = time.time()
fps = 1/(cTime-pTime)
pTime = cTime
cv2.putText(img, f"FPS: {int(fps)}", (30, 50), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1, (255, 0, 0), 3)
# 把每一帧显示出来
cv2.imshow('img',img)
# 卡1ms跳出
if cv2.waitKey(0) == ord('q'):
break
电脑太拉了,FPS只有1(可怕)
参考来自:
手部21个关键点检测+手势识别-[MediaPipe]_开鑫9575的博客-CSDN博客_mediapipehttps://blog.csdn.net/weixin_45930948/article/details/115444916