OpenCV和Mediapipe实现摸嘴或鼻检测

目录

引言

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

    # 计算FPS
    fps_frame_count += 1
    if fps_frame_count >= 15:
        fps_end_time = time.time()
        fps = round(fps_frame_count / (fps_end_time - fps_start_time), 2)
        fps_frame_count = 0
        fps_start_time = time.time()

    # 显示FPS
    cv2.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 = 0

while 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)

    # 计算FPS
    fps_frame_count += 1
    if fps_frame_count >= 15:
        fps_end_time = time.time()
        fps = round(fps_frame_count / (fps_end_time - fps_start_time), 2)
        fps_frame_count = 0
        fps_start_time = time.time()

    # 显示FPS
    cv2.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~

  • 25
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
使用OpenCVmediapipe库可以实现动作识别,具体步骤如下: 1. 安装OpenCVmediapipe库,可以使用pip命令进行安装。 2. 使用OpenCV读取视频或者摄像头的实时画面。 3. 使用mediapipe库中的姿势估计模型,对人体姿势进行估计。 4. 根据姿势估计结果,提取关键点信息,例如手臂、腿部等关键点的位置和角度。 5. 根据关键点信息,设计算法进行动作识别,例如可以使用机器学习算法进行分类识别。 6. 根据识别结果,进行相应的处理,例如输出识别结果或者触发相应的动作。 下面是一个简单的示例代码,可以实现对视频中人体动作的识别: ```python import cv2 import mediapipe as mp # 初始化mediapipe库中的姿势估计模型 mp_pose = mp.solutions.pose.Pose() # 打开摄像头 cap = cv2.VideoCapture(0) while True: # 读取摄像头画面 ret, frame = cap.read() # 将画面转换为灰度图像 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 使用mediapipe库中的姿势估计模型,对人体姿势进行估计 results = mp_pose.process(gray) # 提取关键点信息 if results.pose_landmarks: # 获取左手腕关键点的位置 left_wrist_x = results.pose_landmarks.landmark[mp.solutions.pose.PoseLandmark.LEFT_WRIST].x left_wrist_y = results.pose_landmarks.landmark[mp.solutions.pose.PoseLandmark.LEFT_WRIST].y # 获取右手腕关键点的位置 right_wrist_x = results.pose_landmarks.landmark[mp.solutions.pose.PoseLandmark.RIGHT_WRIST].x right_wrist_y = results.pose_landmarks.landmark[mp.solutions.pose.PoseLandmark.RIGHT_WRIST].y # 判断手臂是否向上伸展 if left_wrist_y < results.pose_landmarks.landmark[mp.solutions.pose.PoseLandmark.LEFT_ELBOW].y and right_wrist_y < results.pose_landmarks.landmark[mp.solutions.pose.PoseLandmark.RIGHT_ELBOW].y: print("手臂向上伸展") # 显示画面 cv2.imshow('frame', frame) # 按下q键退出程序 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放摄像头 cap.release() # 关闭窗口 cv2.destroyAllWindows

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WenJGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值