欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 【python】OpenCV—Hand Landmarks Detection

【python】OpenCV—Hand Landmarks Detection

2025/3/22 21:13:48 来源:https://blog.csdn.net/bryant_meng/article/details/146425219  浏览:    关键词:【python】OpenCV—Hand Landmarks Detection

在这里插入图片描述

文章目录

  • 1、功能描述
  • 2、代码实现
  • 3、效果展示
  • 4、完整代码
  • 5、涉及到的库函数
  • 6、参考


更多有趣的代码示例,可参考【Programming】


1、功能描述

基于 opencv-python 和 mediapipe 实现手部关键点的检测(无法检测出手,不过可以根据关键点的信息外扩出来)

在这里插入图片描述

拇指(Thumb):位于手掌的最外侧,通常是最粗、最短的手指,具有对掌功能,使人类能够抓握和操作物体。

食指(Index Finger):又称示指,紧挨着拇指,通常用于指示方向或物体,也是打字和书写时常用的手指。

中指(Middle Finger):位于食指和无名指之间,是手指中最长的一根,有时也被用于表达某些情绪或态度。

无名指(Ring Finger):又称环指,在传统文化中,人们习惯将戒指戴在这根手指上,象征着婚姻或爱情。

小指(Little Finger):又称小拇指,是手指中最细、最短的一根,通常用于支撑或稳定物体。

Pinky 是小指的俗称,尤其在非正式场合或口语中常用。


Landmark 0 (Wrist): The base of the palm (root landmark).
Landmark 1 (Thumb base): The base joint of the thumb, near the wrist.
Landmark 2 (Thumb first joint): The first joint of the thumb.
Landmark 3 (Thumb second joint): The second joint of the thumb.
Landmark 4 (Thumb tip): The tip of the thumb.
Landmark 5 (Index base): The base joint of the index finger.
Landmark 6 (Index first joint): The first joint of the index finger.
Landmark 7 (Index second joint): The second joint of the index finger.
Landmark 8 (Index tip): The tip of the index finger.
Landmark 9 (Middle base): The base joint of the middle finger.
Landmark 10 (Middle first joint): The first joint of the middle finger.
Landmark 11 (Middle second joint): The second joint of the middle finger.
Landmark 12 (Middle tip): The tip of the middle finger.
Landmark 13 (Ring base): The base joint of the ring finger.
Landmark 14 (Ring first joint): The first joint of the ring finger.
Landmark 15 (Ring second joint): The second joint of the ring finger.
Landmark 16 (Ring tip): The tip of the ring finger.
Landmark 17 (Pinky base): The base joint of the pinky finger.
Landmark 18 (Pinky first joint): The first joint of the pinky.
Landmark 19 (Pinky second joint): The second joint of the pinky.
Landmark 20 (Pinky tip): The tip of the pinky finger.

2、代码实现

导入必要的库函数

import cv2
import mediapipe as mp
import time

调用 mediapipe 的手部关键点检测和绘制手部关键点的接口

mpHands = mp.solutions.hands
hands = mpHands.Hands(static_image_mode=False,max_num_hands=2,min_detection_confidence=0.5,min_tracking_confidence=0.5)
mpDraw = mp.solutions.drawing_utils

统计时间和帧率,单张图片的话用处不大

pTime = 0
cTime = 0

读取图片,检测手部关键点,结果保存在 results 中,可以通过 help(results) 查看其属性

img = cv2.imread("1.jpg")
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = hands.process(imgRGB)

检测结果的三个属性的 help 介绍如下

 |  ----------------------------------------------------------------------|  Data and other attributes defined here:||  multi_hand_landmarks = [landmark {|    x: 0.692896|    y: 0.489765495|    z:...||  multi_hand_world_landmarks = [landmark {|    x: 0.000626816414|    y: 0.08...||  multi_handedness = [classification {|    index: 1|    score: 0.889409304|   ...

如果存在检测结果,遍历关键点,可视化出来

if results.multi_hand_landmarks:for handLms in results.multi_hand_landmarks:for id, lm in enumerate(handLms.landmark):#print(id,lm)h, w, c = img.shapecx, cy = int(lm.x *w), int(lm.y*h)#if id ==0:cv2.circle(img, (cx,cy), 3, (255,0,255), cv2.FILLED)mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)

统计时间,帧率显示在左上角

cTime = time.time()
fps = 1/(cTime-pTime)
pTime = cTimecv2.putText(img,str(int(fps)), (10,70), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,255), 3)

显示图片,保存结果,退出时候关闭所有窗口

cv2.imshow("Image", img)
cv2.imwrite("result.jpg", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

3、效果展示

输入图片

在这里插入图片描述

输出结果

在这里插入图片描述

输入图片

在这里插入图片描述

输出结果

在这里插入图片描述
输入图片

在这里插入图片描述

输出图片

在这里插入图片描述

输入图片

在这里插入图片描述

输出图片

在这里插入图片描述

4、完整代码

单张图片

import cv2
import mediapipe as mp
import timempHands = mp.solutions.hands
hands = mpHands.Hands(static_image_mode=False,max_num_hands=2,min_detection_confidence=0.5,min_tracking_confidence=0.5)
mpDraw = mp.solutions.drawing_utilspTime = 0
cTime = 0img = cv2.imread("1.jpg")
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
results = hands.process(imgRGB)
#print(results.multi_hand_landmarks)if results.multi_hand_landmarks:for handLms in results.multi_hand_landmarks:for id, lm in enumerate(handLms.landmark):#print(id,lm)h, w, c = img.shapecx, cy = int(lm.x *w), int(lm.y*h)#if id ==0:cv2.circle(img, (cx,cy), 3, (255,0,255), cv2.FILLED)mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)cTime = time.time()
fps = 1/(cTime-pTime)
pTime = cTimecv2.putText(img,str(int(fps)), (10,70), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,255), 3)cv2.imshow("Image", img)
cv2.imwrite("result.jpg", img)
cv2.waitKey(0)
cv2.destroyAllWindows()

视频

import cv2
import mediapipe as mp
import timecap = cv2.VideoCapture(0)mpHands = mp.solutions.hands
hands = mpHands.Hands(static_image_mode=False,max_num_hands=2,min_detection_confidence=0.5,min_tracking_confidence=0.5)
mpDraw = mp.solutions.drawing_utilspTime = 0
cTime = 0while True:success, img = cap.read()img = cv2.flip(img, 1)imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)results = hands.process(imgRGB)#print(results.multi_hand_landmarks)if results.multi_hand_landmarks:for handLms in results.multi_hand_landmarks:for id, lm in enumerate(handLms.landmark):#print(id,lm)h, w, c = img.shapecx, cy = int(lm.x *w), int(lm.y*h)#if id ==0:cv2.circle(img, (cx,cy), 3, (255,0,255), cv2.FILLED)mpDraw.draw_landmarks(img, handLms, mpHands.HAND_CONNECTIONS)cTime = time.time()fps = 1/(cTime-pTime)pTime = cTimecv2.putText(img,str(int(fps)), (10,70), cv2.FONT_HERSHEY_PLAIN, 3, (255,0,255), 3)cv2.imshow("Image", img)cv2.waitKey(1)

5、涉及到的库函数

mediapipe.solutions.hands.Hands 是 MediaPipe 框架中用于手部关键点检测的重要接口。

关键参数

static_image_mode:

  • 默认为 False,表示将输入图像视为视频流。在此模式下,接口会尝试在第一个输入图像中检测手,并在成功检测后进一步定位手的坐标。在随后的图像中,它会跟踪这些坐标,直到失去对任何一只手的跟踪。
  • 设置为 True 时,接口会在每个输入图像上运行手部检测,适用于处理一批静态的、可能不相关的图像。

max_num_hands:

  • 表示最多检测几只手,默认为 2。

min_detection_confidence:

  • 手部检测模型的最小置信值(0-1 之间),超过阈值则检测成功。默认为 0.5。

min_tracking_confidence:

  • 坐标跟踪模型的最小置信值(0-1 之间),用于将手部坐标视为成功跟踪。不成功则在下一个输入图像上自动调用手部检测。将其设置为更高的值可以提高解决方案的稳健性,但代价是更高的延迟。如果 static_image_mode 为 True,则忽略这个参数。默认为 0.5。

返回值

Handednessd

  • 表示检测到的手是左手还是右手

Landmarks

  • 手部关键点共有21个,每个关键点由x、y和z坐标组成。x和y坐标通过图像的宽度和高度进行了归一化,范围在[0.0, 1.0]之间。z坐标表示关键点的深度,手腕处的深度被定义为原点。数值越小,表示关键点离摄像机越近。z的大小与x的大小大致相同。

WorldLandmarks

  • 以世界坐标的形式呈现21个手部关键点。每个关键点由x、y和z组成,表示以米为单位的真实世界三维坐标,原点位于手的几何中心。
HandLandmarkerResult:Handedness:Categories #0:index        : 0score        : 0.98396categoryName : Left   # Left代表左手Landmarks:Landmark #0:x            : 0.638852y            : 0.671197z            : -3.41E-7Landmark #1:x            : 0.634599y            : 0.536441z            : -0.06984... (21 landmarks for a hand)WorldLandmarks:Landmark #0:x            : 0.067485y            : 0.031084z            : 0.055223Landmark #1:x            : 0.063209y            : -0.00382z            : 0.020920... (21 world landmarks for a hand)

6、参考

  • https://ai.google.dev/edge/mediapipe/solutions/vision/hand_landmarker/python
  • MediaPipe实现手指关键点检测及追踪,人脸识别及追踪
  • https://github.com/webdevpathiraja/Hand-Gesture-Sign-Detection-Project/tree/main
  • Mediapipe框架(一)人手关键点检测

更多有趣的代码示例,可参考【Programming】

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词