手势识别是计算机视觉领域中的重要方向,通过对摄像机采集的手部相关的图像序列进行分析处理,进而识别其中的手势,手势被识别后用户就可以通过手势来控制设备或者与设备交互。完整的手势识别一般有手的检测和姿态估计、手部跟踪和手势识别等。
import cv2
import mediapipe as mp
# 初始化 MediaPipe 手部模型
mp_hands = mp.solutions.hands
hands = mp_hands.Hands()
# 初始化视频流
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
# 转换为 RGB
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 获取手部关键点
results = hands.process(rgb_frame)
# 如果检测到手部
if results.multi_hand_landmarks:
for landmarks in results.multi_hand_landmarks:
# 绘制手部关键点
mp.solutions.drawing_utils.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)
# 显示图像
cv2.imshow('Hand Detection', frame)
# 按 'q' 键退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放资源
cap.release()
cv2.destroyAllWindows()
这段代码是一个简单的手部检测应用程序,使用了 OpenCV 和 MediaPipe 库来实时检测和绘制手部关键点。下面是对代码的详细解释:
import cv2
import mediapipe as mp
cv2
是 OpenCV 的 Python 接口库,用于图像处理和计算机视觉任务。mediapipe
是 Google 提供的一个跨平台框架,用于实现高效的计算机视觉任务,这里用它来做手部关键点检测。mp_hands = mp.solutions.hands
hands = mp_hands.Hands()
mp_hands
是 MediaPipe 提供的手部检测模块。通过 mp.solutions.hands
访问。hands = mp_hands.Hands()
创建了一个 Hands
对象,用于进行手部检测。它会自动处理图像中的手部检测、手部关键点识别和跟踪。cap = cv2.VideoCapture(0)
cv2.VideoCapture(0)
打开了计算机的默认摄像头(0
表示第一个摄像头)。返回的 cap
对象用于读取视频流。while True:
ret, frame = cap.read()
if not ret:
break
cap.read()
从摄像头读取一帧图像并返回两个值:ret
和 frame
。ret
是布尔值,表示图像是否成功读取,frame
是当前帧的图像。ret
为 False
,则说明读取图像失败,程序退出循环。rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
cv2.cvtColor
将图像从 BGR 转换为 RGB。results = hands.process(rgb_frame)
hands.process(rgb_frame)
将 RGB 图像传递给 MediaPipe 的 Hands
模型进行处理。results
包含了检测到的手部信息,包括手部关键点的位置。如果图像中没有手部,results.multi_hand_landmarks
会是空的。if results.multi_hand_landmarks:
for landmarks in results.multi_hand_landmarks:
mp.solutions.drawing_utils.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)
results.multi_hand_landmarks
是一个包含所有检测到的手的关键点位置的列表。如果检测到手部,它会返回一个非空列表。landmarks
是每个手部的关键点集合,每个关键点是一个 (x, y, z)
坐标。mp.solutions.drawing_utils.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)
将每个手的关键点绘制到 frame
图像上,并且连接关键点,形成手的骨架结构。mp_hands.HAND_CONNECTIONS
用于连接不同的关键点。cv2.imshow('Hand Detection', frame)
cv2.imshow
显示处理后的图像(frame
)。窗口的标题是 ‘Hand Detection’。if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.waitKey(1)
等待键盘输入,1
表示等待 1 毫秒。返回值是按下键的 ASCII 码。q
键,ord('q')
的值与 cv2.waitKey(1)
返回值相等,程序就会退出循环,停止视频流。cap.release()
cv2.destroyAllWindows()
cap.release()
释放摄像头资源。cv2.destroyAllWindows()
关闭所有 OpenCV 显示的窗口。要进行手关键点估计,可以使用 MediaPipe 库来进行高效的手部检测,结合 OpenCV 来进行图像处理和显示。这里将展示一个基于 MediaPipe 手部模型的手关键点估计的完整代码。
MediaPipe 提供了一个预训练的模型来检测手部的 21 个关键点,包括手指关节和手掌部位。我们将使用 MediaPipe 提供的 Hands
模块来检测手部关键点。
import cv2
import mediapipe as mp
# 初始化 MediaPipe 手部检测模型
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(min_detection_confidence=0.7, min_tracking_confidence=0.5)
mp_drawing = mp.solutions.drawing_utils
# 打开摄像头
cap = cv2.VideoCapture(0)
while True:
# 读取每一帧图像
ret, frame = cap.read()
if not ret:
print("无法获取视频帧")
break
# 将图像转换为 RGB 格式,MediaPipe 需要 RGB 输入
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
# 获取手部关键点检测结果
results = hands.process(rgb_frame)
# 如果检测到手部
if results.multi_hand_landmarks:
for landmarks in results.multi_hand_landmarks:
# 绘制手部关键点和连接线
mp_drawing.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)
# 获取并显示每个关键点的坐标
for idx, landmark in enumerate(landmarks.landmark):
h, w, c = frame.shape
cx, cy = int(landmark.x * w), int(landmark.y * h)
cv2.putText(frame, str(idx), (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1, cv2.LINE_AA)
cv2.circle(frame, (cx, cy), 5, (0, 0, 255), -1) # 绘制红色的关键点
# 显示图像
cv2.imshow('Hand Keypoint Estimation', frame)
# 按 'q' 键退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放摄像头资源并关闭窗口
cap.release()
cv2.destroyAllWindows()
初始化 MediaPipe 手部模型:
mp.solutions.hands.Hands()
创建手部检测模型,min_detection_confidence=0.7
和 min_tracking_confidence=0.5
表示最低的检测和追踪置信度阈值,适用于动态环境中。打开摄像头:
cv2.VideoCapture(0)
打开计算机的默认摄像头,并获取实时视频流。图像转换:
cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
将图像转换为 RGB 格式。处理图像并获取手部关键点:
hands.process(rgb_frame)
用于处理图像并检测手部关键点。results
对象包含手部信息,如果检测到手部,results.multi_hand_landmarks
将返回手部的 21 个关键点的位置。绘制关键点和连接线:
mp_drawing.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)
绘制手的 21 个关键点以及它们之间的连接线(即手指的骨架)。landmarks.landmark
包含了每个关键点的 (x, y, z)
坐标,其中 x
和 y
是图像中的像素坐标,z
是深度信息(在 3D 空间中的位置,但对于 2D 图像可忽略)。显示关键点坐标:
cv2.putText
在图像上显示关键点的索引。cv2.circle
用来在图像上绘制关键点位置。显示视频流:
cv2.imshow()
来显示处理过的每一帧图像,展示检测到的手部关键点。退出条件:
q
键退出程序并释放摄像头资源。MediaPipe 的 Hands
模型检测手部的 21 个关键点,索引如下(从 0 到 20):
YOLO(You Only Look Once)是一个非常强大的目标检测算法,特别适用于实时应用。它将目标检测任务转化为一个回归问题,能够快速且准确地检测图像中的目标物体。虽然 YOLO 本身并没有直接针对手部关键点估计的功能,但可以用它来检测手部区域,然后结合其他模型(比如 MediaPipe 或深度学习的关键点检测模型)来进行手关键点估计。
import cv2
import torch
import mediapipe as mp
# 初始化 MediaPipe 手部检测模型
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(min_detection_confidence=0.7, min_tracking_confidence=0.5)
mp_drawing = mp.solutions.drawing_utils
# 加载 YOLOv5 模型(选择合适的模型大小)
model = torch.hub.load('ultralytics/yolov5', 'yolov5s') # 'yolov5s' 是一个小型的 YOLOv5 模型
# 打开摄像头
cap = cv2.VideoCapture(0)
while True:
# 读取每一帧图像
ret, frame = cap.read()
if not ret:
print("无法获取视频帧")
break
# 使用 YOLOv5 检测图像中的物体(包括手部)
results = model(frame) # 检测结果,包括边界框、标签、置信度等
# 提取 YOLOv5 检测到的手部(通常手部被标记为 0 或其他标签,依赖于训练数据)
# 获取所有检测到的物体的边界框
hands_detections = results.xyxy[0] # 获取检测结果,xyxy 形式 [x_min, y_min, x_max, y_max, confidence, class]
for detection in hands_detections:
if detection[5] == 0: # 类别 0 代表手部(具体根据训练数据集而定)
x_min, y_min, x_max, y_max = map(int, detection[:4])
# 在图像上绘制手部边界框
cv2.rectangle(frame, (x_min, y_min), (x_max, y_max), (255, 0, 0), 2)
# 提取手部区域并进行手部关键点估计
hand_region = frame[y_min:y_max, x_min:x_max]
rgb_hand_region = cv2.cvtColor(hand_region, cv2.COLOR_BGR2RGB)
# 使用 MediaPipe 估计手部关键点
hand_results = hands.process(rgb_hand_region)
# 如果检测到手部关键点
if hand_results.multi_hand_landmarks:
for landmarks in hand_results.multi_hand_landmarks:
# 绘制手部关键点和连接线
mp_drawing.draw_landmarks(frame, landmarks, mp_hands.HAND_CONNECTIONS)
for idx, landmark in enumerate(landmarks.landmark):
h, w, c = frame.shape
cx, cy = int(landmark.x * w), int(landmark.y * h)
cv2.putText(frame, str(idx), (cx, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1, cv2.LINE_AA)
cv2.circle(frame, (cx, cy), 5, (0, 0, 255), -1) # 绘制红色的关键点
# 显示图像
cv2.imshow('Hand Detection and Keypoint Estimation', frame)
# 按 'q' 键退出
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放摄像头资源并关闭窗口
cap.release()
cv2.destroyAllWindows()
torch.hub.load('ultralytics/yolov5', 'yolov5s')
载入 YOLOv5 模型,yolov5s
是一个小型的 YOLOv5 模型,适合实时应用。可以根据需求选择 yolov5m
或 yolov5l
(更大的模型,精度更高但速度较慢)。cv2.VideoCapture(0)
打开摄像头并读取每一帧图像。model(frame)
进行图像检测,返回一个 results
对象,其中包含检测到的边界框、类别标签、置信度等信息。hands.process(rgb_hand_region)
进行手部关键点估计,返回手部的关键点信息。mp_drawing.draw_landmarks()
绘制手部的 21 个关键点和连接线。q
键退出程序。