目录
引言
1.过程简介
2. 代码结构
2.1 导入库
2.2 初始化模型
2.3 读取视频流或摄像头
2.4 初始化FPS计算
2.5 主循环
2.6 转换BGR图像为RGB图像
2.7 运行姿势检测模型和手部检测模型
2.8 绘制姿势关键点及连接线
2.9 检测手部关键点
2.10 判断手部与鼻子、嘴的相对位置
2.11 计算并显示FPS
2.12 显示结果
2.13 退出程序
2.14 释放资源
3. 实现思路
4. 注意事项
5. 总结
行业应用
代码实现
效果展示
引言
这份代码使用了 MediaPipe 库中的 Pose 模型和 Hands 模型,以及 OpenCV 库,用于实时监测摄像头捕捉到的视频中的姿势和手部动作。主要功能包括标记关键点、绘制姿势连接线以及通过手部与鼻子、嘴的相对位置判定实现了简单的动作监测。
1.过程简介
这段代码实现了使用MediaPipe库进行人体姿势和手部动作检测,并在摄像头视频流上展示检测结果和实时FPS。
首先,导入了需要的库,包括cv2和mediapipe。然后,通过mp_pose.Pose()和mp_hands.Hands()初始化了MediaPipe的Pose和Hands模型。
接下来,通过cap = cv2.VideoCapture(0)打开了摄像头,获取视频流。然后,通过循环读取每一帧的图像,直到视频结束。
在循环中,首先将BGR图像转换为RGB图像,然后分别使用pose.process()和hands.process()运行姿势和手部检测模型,获得检测结果。
接着,通过mp.solutions.drawing_utils.draw_landmarks()方法绘制姿势关键点和连接线。如果检测到手部关键点,遍历每个手部关键点,将关键点绘制为圆点。
在手部检测的过程中,同样检测了鼻尖和嘴巴的位置,判断手部和鼻尖、嘴巴的距离是否小于一定阈值,如果满足条件,则认为在摸鼻子或摸嘴巴。
在最后,计算FPS并显示在图像上,然后通过cv2.imshow()显示图像。同时,通过cv2.waitKey(1)判断是否按下ESC键,如果是则退出循环。
最后,释放摄像头资源并关闭所有窗口。
2. 代码结构
2.1 导入库
import cv2 import mediapipe as mp import time
导入 OpenCV 和 MediaPipe 库。
2.2 初始化模型
mp_pose = mp.solutions.pose mp_hands = mp.solutions.hands pose = mp_pose.Pose() hands = mp_hands.Hands()
初始化姿势检测模型和手部检测模型。
2.3 读取视频流或摄像头
cap = cv2.VideoCapture(0)
打开默认摄像头,获取视频流。
2.4 初始化FPS计算
fps_start_time = time.time() fps_frame_count = 0 fps = 0
记录开始时间和帧数,计算每秒帧数(FPS)。
2.5 主循环
while cap.isOpened(): ret, frame = cap.read() if not ret: break
主循环用于读取视频流的每一帧。
2.6 转换BGR图像为RGB图像
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
将每一帧从 BGR 转换为 RGB,以适应 MediaPipe 模型。
2.7 运行姿势检测模型和手部检测模型
pose_results = pose.process(rgb_frame) hand_results = hands.process(rgb_frame)
运行姿势检测模型和手部检测模型,获取检测结果。
2.8 绘制姿势关键点及连接线
if pose_results.pose_landmarks: mp.solutions.drawing_utils.draw_landmarks(frame, pose_results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
通过 mp.solutions.drawing_utils.draw_landmarks
绘制姿势关键点及连接线。
2.9 检测手部关键点
if hand_results.multi_hand_landmarks: for landmarks in hand_results.multi_hand_landmarks: # 处理手部关键点
对检测到的手部关键点进行处理。
2.10 判断手部与鼻子、嘴的相对位置
# 判断手是否接近鼻子
distance_to_nose = cv2.norm((nose_x, nose_y), (hand_x, hand_y))
if distance_to_nose < 10: # 调整阈值以适应你的实际情况
cv2.putText(frame, "Touching Nose", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 155, 155), 2,cv2.LINE_AA)# 判断手是否接近嘴巴
distance_to_mouth = cv2.norm((mouth_x, mouth_y), (hand_x, hand_y))
if distance_to_mouth < 20: # 调整阈值以适应你的实际情况
cv2.putText(frame, "Touching Mouth", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 155, 155), 2,cv2.LINE_AA)
# 判断手部和鼻尖位置关系 # 判断手部和嘴巴位置关系
通过相对位置判定手部与鼻子、嘴的关系。
2.11 计算并显示FPS
# 计算FPSfps_frame_count += 1if fps_frame_count >= 15:fps_end_time = time.time()fps = round(fps_frame_count / (fps_end_time - fps_start_time), 2)fps_frame_count = 0fps_start_time = time.time()# 显示FPScv2.putText(frame, f"FPS: {fps}", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)
# 计算并显示FPS
计算帧率,并在视频窗口上方显示。
2.12 显示结果
cv2.imshow('Pose and Hand Detection', frame)
使用 cv2.imshow
显示最终结果。
2.13 退出程序
if cv2.waitKey(1) & 0xFF == 27: # 按ESC键退出 break
通过按下 ESC 键退出程序。
2.14 释放资源
cap.release() cv2.destroyAllWindows()
释放摄像头资源,关闭所有窗口。
3. 实现思路
该代码首先通过 MediaPipe 库提供的 Pose 和 Hands 模型,获取姿势和手部的关键点。然后,通过 OpenCV 绘制姿势关键点和连接线,并在每一帧中检测手部的相对位置,判断是否进行了摸鼻子和摸嘴的动作。
4. 注意事项
- 使用 MediaPipe 提供的模型进行姿势和手部检测。
- 通过 OpenCV 绘制姿势关键点和连接线,提高可视化效果。
- 通过相对位置判定手部与鼻子、嘴的关系,实现了动作监测。
5. 总结
这份代码展示了如何结合 MediaPipe 和 OpenCV 库,实现实时的姿势和手部检测,并通过相对位置的判定,实现了简单的动作监测。代码结构清晰,易于理解和扩展。
行业应用
此模块可以用作汽车内部摄像头的部署,来实时检测驾驶员的驾驶专注度以达到警示驾驶员的目的。
代码实现
import cv2
import mediapipe as mp
import time# 初始化MediaPipe Pose模型和Hand模型
mp_pose = mp.solutions.pose
mp_hands = mp.solutions.hands
pose = mp_pose.Pose()
hands = mp_hands.Hands()# 读取视频流或摄像头
cap = cv2.VideoCapture(0) # 0表示默认摄像头# 初始化FPS计算
fps_start_time = time.time()
fps_frame_count = 0
fps = 0while cap.isOpened():ret, frame = cap.read()if not ret:break# 转换BGR图像为RGB图像rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)# 运行姿势估计模型pose_results = pose.process(rgb_frame)# 运行手部估计模型hand_results = hands.process(rgb_frame)# 绘制姿势关键点及连接线if pose_results.pose_landmarks:mp.solutions.drawing_utils.draw_landmarks(frame, pose_results.pose_landmarks, mp_pose.POSE_CONNECTIONS)# 检测手部关键点if hand_results.multi_hand_landmarks:for landmarks in hand_results.multi_hand_landmarks:for point in landmarks.landmark:x, y, _ = int(point.x * frame.shape[1]), int(point.y * frame.shape[0]), int(point.z * frame.shape[1] * 5)cv2.circle(frame, (x, y), 5, (155, 155, 0), -1)# 获取鼻尖位置if pose_results.pose_landmarks:nose_landmark = pose_results.pose_landmarks.landmark[mp_pose.PoseLandmark.NOSE]nose_x, nose_y = int(nose_landmark.x * frame.shape[1]), int(nose_landmark.y * frame.shape[0])# 获取嘴巴位置mouth_landmark = pose_results.pose_landmarks.landmark[int((mp_pose.PoseLandmark.MOUTH_LEFT + mp_pose.PoseLandmark.MOUTH_RIGHT) / 2)]mouth_x, mouth_y = int(mouth_landmark.x * frame.shape[1]), int(mouth_landmark.y * frame.shape[0])# 判断手部和鼻尖位置关系,如果距离小于一定阈值,则判定为摸鼻子for landmarks in hand_results.multi_hand_landmarks:for point in landmarks.landmark:hand_x, hand_y, _ = int(point.x * frame.shape[1]), int(point.y * frame.shape[0]), int(point.z * frame.shape[1] * 5)# 判断手是否接近鼻子distance_to_nose = cv2.norm((nose_x, nose_y), (hand_x, hand_y))if distance_to_nose < 10: # 调整阈值以适应你的实际情况cv2.putText(frame, "Touching Nose", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 155, 155), 2,cv2.LINE_AA)# 判断手是否接近嘴巴distance_to_mouth = cv2.norm((mouth_x, mouth_y), (hand_x, hand_y))if distance_to_mouth < 20: # 调整阈值以适应你的实际情况cv2.putText(frame, "Touching Mouth", (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 155, 155), 2,cv2.LINE_AA)# 计算FPSfps_frame_count += 1if fps_frame_count >= 15:fps_end_time = time.time()fps = round(fps_frame_count / (fps_end_time - fps_start_time), 2)fps_frame_count = 0fps_start_time = time.time()# 显示FPScv2.putText(frame, f"FPS: {fps}", (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2, cv2.LINE_AA)# 显示结果cv2.imshow('Pose and Hand Detection', frame)# 退出程序if cv2.waitKey(1) & 0xFF == 27: # 按ESC键退出break# 释放资源
cap.release()
cv2.destroyAllWindows()
其实我还想要加入眼睛的部分,但是我写的眼睛部分检测的代码有BUG,所以我就暂时没有加上去,等我研究研究啦~~~~
效果展示
ヾ( ̄▽ ̄)Bye~Bye~