mediapipe实现实时动作检测【python版本】

mediapipe实现实时动作检测

  • 前言
    • 安装opencv-python
    • 安装mediapipe
    • 可能遇到的错误
    • 先来实现单张图片的人体关键点检测检测
    • 实现视频实时动作检测

前言

MediaPipe为直播和流媒体提供跨平台、可定制的机器学习(MachineLearning) 解决方案。利用mediapipe和python可以实现以下功能:

  1. MediaPipe Face Detection 人脸检测
  2. MediaPipe Face Mesh 人脸三维关键点(468个)检测
  3. MediaPipe Hands 手部关键点检测
  4. MediaPipe Holistic 人体识别
  5. MediaPipe Objectron 物体识别
  6. MediaPipe Pose 人体动作姿态识别
  7. MediaPipe Selfie Segmentation 自拍分割

本文代码运行环境:win10,python3.7,pycharm,mediapipe 0.8.10,
涉及到的Python库为:opencv-python,mediapipe,matplotlib

安装opencv-python

在python中使用pip install指令安装库很简单,由于包比较大所以使用豆瓣源安装

pip install opencv-python -i https://pypi.douban.com/simple/

调用opencv相关函数时导入的包为:

import cv2 as cv

对于使用pycharm导入cv2之后没有代码提示的问题,可以参考此文章
解决Opencv / cv2没有代码提示的问题

安装mediapipe

pip install mediapipe -i https://pypi.douban.com/simple/

可能遇到的错误

  1. 包的版本问题
    mediapipe实现实时动作检测【python版本】_第1张图片
    报错是因为protobuf这个包的版本太高了导致不兼容,卸载重装低版本的就行
 pip uninstall protobuf
pip install protobuf==3.19.0
  1. 第一次运行mediapipe代码可能需要下载模型
    第一次运行mediapipe 代码的时候 有时候会下载模型,但是有时候因为网络问题,可能下载不下来,报错:
Downloading model to D:\anaconda\envs\virtual_mediapipe\lib\site-packages\mediapipe/modules/pose_landmark/pose_landmark_heavy.tflite

TimeoutError: [WinError 10060] 由于连接方在一段时间后没有正确答复或连接的主机没有反应,连 接尝试失败。
[ WARN:0] global C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-_xlv4eex\opencv\modules\videoio\src\cap_msmf.cpp (438) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback

可以去github或gitee上下载对应的包

https://gitee.com/mirrors/mediapipe/tree/master/mediapipe/modules/pose_landmark
输出信息中写了 他会把需要的包下载到什么文件夹:

Downloading model to D:\anaconda\envs\virtual_mediapipe\lib\site-packages\mediapipe/modules/pose_landmark/pose_landmark_heavy.tflite
比如这个模型:pose_landmark_heavy.tflite
mediapipe实现实时动作检测【python版本】_第2张图片
把对应文件下载下来后复制粘贴到这个文件夹就解决了
mediapipe实现实时动作检测【python版本】_第3张图片
接下来就可以愉快的使用mediapipe了

先来实现单张图片的人体关键点检测检测

import cv2 as cv
import mediapipe as mp
import matplotlib.pyplot as plt


# 定义可视化图像函数
def look_img(img):
    # opencv读入图像格式为BGR,matplotlib可视化格式为RGB,因此需要将BGR转为RGB
    img_rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB)
    plt.imshow(img_rgb)
    plt.show()


# 导入solution
mp_pose = mp.solutions.pose

# 导入绘图函数
mp_drawing = mp.solutions.drawing_utils

# 导入模型
pose = mp_pose.Pose(static_image_mode=True,         # 是静态图片还是连续视频帧
                    model_complexity=2,             # 选择人体姿态关键点检测模型,0性能差但快,2性能好但慢,1介于两者之间
                    smooth_landmarks=True,          # 是否平滑关键点
                    enable_segmentation=True,       # 是否人体抠图
                    min_detection_confidence=0.5,   # 置信度阈值
                    min_tracking_confidence=0.5     # 追踪阈值
                    )

# 读入图像
img = cv.imread('2.png')
# BGR转RGB
img_RGB = cv.cvtColor(img, cv.COLOR_BGR2RGB)
# 将图像输入模型,获取预测结果
results = pose.process(img_RGB)

# 可视化结果
mp_drawing.draw_landmarks(img, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
look_img(img)

# 在三维真实物理坐标系中以米为单位可视化人体关键点
mp_drawing.plot_landmarks(results.pose_world_landmarks, mp_pose.POSE_CONNECTIONS)

原图是这样的
mediapipe实现实时动作检测【python版本】_第4张图片
经过关键点识别之后是这样的
mediapipe实现实时动作检测【python版本】_第5张图片
三维人体图像是这样的,由于第三个维度是预测出来的,所以有时候不是很准确。
mediapipe实现实时动作检测【python版本】_第6张图片

实现视频实时动作检测

会了单张图像检测后,视频检测就非常简单了。
视频就是由连续的一帧一帧图像组成的,摄像头实时获取的视频也不例外,只需要调用cv2(opencv)里的视频捕捉函数一帧一帧读取图像就可以了。

import cv2 as cv
import mediapipe as mp


# 导入solution
mp_pose = mp.solutions.pose
# 导入绘图函数
mp_drawing = mp.solutions.drawing_utils

# 导入模型
pose = mp_pose.Pose(static_image_mode=True,  # 是静态图片还是连续视频帧
                    model_complexity=2,  # 选择人体姿态关键点检测模型,0性能差但快,2性能好但慢,1介于两者之间
                    smooth_landmarks=True,  # 是否平滑关键点
                    enable_segmentation=True,  # 是否人体抠图
                    min_detection_confidence=0.5,  # 置信度阈值
                    min_tracking_confidence=0.5  # 追踪阈值
                    )


# 处理单帧的函数
def process_frame(img):
    img_rgb = cv.cvtColor(img, cv.COLOR_BGR2RGB)
    results = pose.process(img_rgb)

    mp_drawing.draw_landmarks(img, results.pose_landmarks, mp_pose.POSE_CONNECTIONS)
    return img


# 读取视频帧的函数
def process_cap(cap, gap):
    while cap.isOpened():
        # 读视频帧
        ret, frame = cap.read()
        if ret:  # 判断是否读取成功
            # 如果读取成功则处理该帧
            frame = process_frame(frame)
            # 展示处理后的三通道图像
            cv.imshow('video', frame)
            # 按键盘的esc或者q退出
            if cv.waitKey(gap) in [ord('q'), 27]:
                break
        else:
            # print('error!')
            break

    # 关闭摄像头
    cap.release()
    # 关闭图像窗口
    cv.destroyAllWindows()


# 从摄像头实时检测
def detect_camera():
    # 创建窗口
    cv.namedWindow('video', cv.WINDOW_NORMAL)
    # 调用摄像头获取画面  0是windows系统下默认的摄像头,1是Mac系统
    cap = cv.VideoCapture(0)

    process_cap(cap, 1)


# 从本地导入视频检测
def detect_video(path):
    # 创建窗口
    cv.namedWindow('video', cv.WINDOW_NORMAL)

    # 从本地读取视频
    cap = cv.VideoCapture(path)
    # 获取原视频帧率
    fps = cap.get(cv.CAP_PROP_FPS)
    # 获取原视频窗口大小
    width = int(cap.get(cv.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv.CAP_PROP_FRAME_HEIGHT))
    # print(fps)
    # 视频两帧之间的播放间隔,单位为毫秒
    gap = int(1000 / fps)
    cv.resizeWindow('video',width,height)
    process_cap(cap, gap)


if __name__ == '__main__':
    while True:
        menu = int(input('请选择检测模式:1. 打开摄像头检测\t2. 从本地导入视频检测\t3. 退出\n'))
        if menu == 1:
            detect_camera()
            break
        elif menu == 2:
            path = input('请输入视频路径(例如:D:\\download\\abc.mp4):\n')
            detect_video(path)
            break
        elif menu == 3:
            break
        else:
            print("输入错误,请重新输入!")
            continue

你可能感兴趣的:(python,opencv,计算机视觉)