一、安装配置openpose

参考这篇文章
在Windows上编译OpenPose Python Wrapper - 远处有泽细细说 (yuanze.wang)https://yuanze.wang/posts/build-openpose-python-api/

为了防止文章中用到的东西失效,也附上一份我的百度网盘,我的网盘中额外添加了一个pybind11的压缩包,我并不清楚这个是否是必要的,作者提了一嘴,但教程中未涉及。

链接:https://pan.baidu.com/s/17KfsYGyxUuqcoVYD0FGcKQ 
提取码:1odt 

简单说一下流程:需要提前准备:NVIDIA显卡驱动,CUDA 10.0,CMake,VisualStudio

1、下载OpenPose源代码,推荐下载并解压我百度网盘中的“openpose.tar.gz”以保持版本一致性。也可去官网自行下载最新版。

2、下载百度网盘中的"opencv_411_v14_15_2019_09_24.zip","caffe3rdparty_15_2019_03_14.zip",“caffe_15_2019_05_16.zip”到openpose\3rdparty\windows中,并解压到此处。(注意保留压缩包在此处,防止程序未检测到对应文件,重新下载。)

3、删除openpose\models文件夹,并下载百度网盘中的"models"文件夹进行替换。

4、下载并解压百度网盘中的"pybind11.zip",放在openpose\3rdparty文件夹下覆盖。(不知道这一步是否必须。)

5、打开CMake,设置源代码位置为你的openpose位置(如F:/openpose),并在该目录下新建build文件夹作为编译文件夹(如F:/openpose/build)点击Configure按钮,选择你安装的VS版本,并选择平台为x64,点击Finish即可。不出意外的话CMake会在最下面显示Configuring done。

6、勾选上方变量中的BUILD_PYTHON(请确保已经安装了64位Python),再次点击Configuring按钮。随后点击Genetate按钮,生成VS工程文件,并点击OpenProject来打开工程,并在解决方案配置中选择Release(在本地Windows调试器左边)。

7、右键点击pyopenpose项目,点击生成。看到生成成功的提示后,可以在openpose\build\python\openpose\Release目录中找到pyopenpose.cp38-win_amd64.pyd(文件名根据python版本可能不同)。

8、换个地方新建一个名字叫openpose的文件夹,将第7步中提到的pyopenpose.cp38-win_amd64.pyd复制到其中,再将openpose\build\python\openpose\__init__.py复制到其中,再将openpose\build\bin中的所有文件复制到其中,最后将openpose\build\x64\Release\openpose.dll复制到其中。至此,这个openpose便是可以被我们本机对应版本Python调用的OpenPose库了。

二、运行demo

将openpose\models文件夹复制到新建的openpose文件夹中,并在上一级目录新建openpose_demo.py,运行此文件即可演示Python对OpenPoseAPI的调用。

路径如下:

 

(图中其他Py文件,以及media等文件夹都是后续使用时自己创建的。)

openpose_demo.py里的东西如下:

import cv2
import sys
import timeit
import openpose.pyopenpose as op

params = dict()
params["model_folder"] = 'openpose\\models'
params["net_resolution"] = '128x192'
params["render_pose"] = '1'

opWrapper = op.WrapperPython()
opWrapper.configure(params)
opWrapper.start()

cap = cv2.VideoCapture(0)
print('Video device Initialized.')

frame_start_time = timeit.default_timer()
frame_cnt = 0

while True:  # Process Image
   datum = op.Datum()
   ret, img = cap.read()  # Read camera
   imageToProcess = img
   datum.cvInputData = imageToProcess
   opWrapper.emplaceAndPop([datum])

   # print("Body keypoints: \\n" + str(datum.poseKeypoints))
   cv2.imshow("Openpose Python - Press Q to Exit", datum.cvOutputData)

   frame_end_time = timeit.default_timer()
   if frame_end_time - frame_start_time > 1:
      print('fps:{}'.format(frame_cnt))
      frame_cnt = 0
      frame_start_time = frame_end_time

   frame_cnt = frame_cnt + 1

   if cv2.waitKey(1) & 0xFF == ord('q'):
      break

cap.release()
cv2.destroyAllWindows()
exit(0)
 

三、openpose使用简介 

3.1、参数

在openpose\include\openpose\flags.hpp中可以查阅完整参数及说明,现挑一些我觉得比较重要的翻译如下:

params["model_folder"] = "openpose/models/"#模型地址
params["video"] = "./media/help.mp4"#视频地址(不写默认使用前置摄像头)
params["net_resolution"] = '160x240'#分辨率,需要是16的倍数,降低这个参数可以以准确率为代价显著提升处理速度。
params["disable_multi_thread"] = True#稍微降低帧率以大大减少延迟,用于网络摄像头
params["frame_step"] = 2#隔几帧处理一张图片
params["process_real_time"] = False#保持视频原来的速度,如果处理速度过慢就会跳帧,过快就会减慢速度
params["disable_blending"] = False #如果为True,只显示骨骼关键点,背景为黑
params["model_pose"] = "BODY_25" #参数设置"BODY_25“表示使用25点的检测模式,CUDA版本中最快最准的模式。此外设置"COCO"使用18点的检测模式,设置"MPI"使用15点的检测模式,最不精确,但在CPU上最快。设置"MPI_4_layers"使用15点的检测模式,甚至比上一种更快,但不够准确。

经过测试,BODY_25是最快的。(使用GPU的话)

附上25点和18点的位置图:

 

 3.2、使用

初始化伪代码如下(完整代码在最后面):

import openpose.pyopenpose as op

parser = argparse.ArgumentParser()
args = parser.parse_known_args()
params = dict()
params["model_folder"] = "openpose/models/"#模型地址

...#设置参数

#初始化

opWrapper = op.WrapperPython()
opWrapper.configure(params)
opWrapper.start()

  cap = cv2.VideoCapture("./media/help.mp4")

while True:
        datum = op.Datum()

    ret, img = cap.read()

然后就可以开始使用了,在while语句中使用datum.cvInputData = img的形式对img进行骨骼关键点提取。
然后跟上一句opWrapper.emplaceAndPop([datum])

获取关键点的方式:key_points = datum.poseKeypoints[0]

key_points里即为每个关键点的信息,它的shape为(25,3),其中25代表25个关键点,3代表每个关键点的x坐标,y坐标和置信度(0-1之间的浮点数)

获取处理后图片的方式:frame = datum.cvOutputData

frame即为提取了关键点并绘制后的图片。

3.3、案例

目标:识别图像中人是否在双手挥手呼救,并与单手挥手和双手伸懒腰区分开。

思路:使用onepose提取骨骼关键点后,判断双手手臂上的关键点y坐标是否在肩膀上方,且x坐标和肩膀中心的关键点的距离是否在阈值内(挥手时手臂会贴近头部,即靠近肩膀中心,而伸懒腰多数为双手向两边展开)

代码:

import cv2
import sys
import timeit
#import openpose.pyopenpose as op
import os
import shutil
from sys import platform
import argparse

try:
    import openpose.pyopenpose as op
    # Flags

    parser = argparse.ArgumentParser()
    args = parser.parse_known_args()

    # Custom Params (refer to include/openpose/flags.hpp for more parameters)
    params = dict()
    params["model_folder"] = "openpose/models/"#模型地址
    params["video"] = "./media/help.mp4"#视频地址(不写默认使用前置摄像头)
    params["net_resolution"] = '160x240'#分辨率,需要是16的倍数
    params["model_pose"] = "BODY_25" #`BODY_25` (fastest for CUDA version, most accurate, and includes"
                                                        #" foot keypoints), `COCO` (18 keypoints), `MPI` (15 keypoints, least accurate model but"
                                                        #" fastest on CPU), `MPI_4_layers` (15 keypoints, even faster but less accurate)
    #params["disable_multi_thread"] = True#稍微降低帧率以大大减少延迟,用于网络摄像头
    params["frame_step"] = 2#隔几帧处理一张图片
    params["process_real_time"] = False#保持视频原来的速度,如果处理速度过慢就会跳帧,过快就会减慢速度

    params["face_detector"] = 0#脸部检测的模式
    params["disable_blending"] = False #如果为True,只显示骨骼关键点,背景为黑

    #初始化
    opWrapper = op.WrapperPython()
    opWrapper.configure(params)
    opWrapper.start()
    #获取视频信息
    cap = cv2.VideoCapture("./media/help.mp4")
    fps = cap.get(cv2.CAP_PROP_FPS)
    w = int(0.5 *cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    h = int(0.5 *cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    frame_start_time = timeit.default_timer()
    #运算中需要用到的一些东西
    frame_cnt = 0#计算FPS
    is_help_threshold = 100#呼救角度阈值
    is_help_num = 0#判断呼救累计值
    is_first_help = True#是否初次判断成呼救
    fourcc = cv2.VideoWriter_fourcc('m','p','4','v')
    # print(fourcc)
    # print(fps)
    # print(w)
    # print(h)
    writer = cv2.VideoWriter(r'./output/mp4/output.mp4',fourcc,fps,(w,h))

    while True:  # Process Image
        datum = op.Datum()
        ret, img = cap.read()  # Read camera

        imageToProcess = cv2.resize(img,(w,h))
        #imageToProcess = img
        datum.cvInputData = imageToProcess#提取关键点

        opWrapper.emplaceAndPop([datum])
        #print(type(datum.poseKeypoints))
        #print(datum.poseKeypoints.shape)
        key_points = datum.poseKeypoints[0]#key_points保存每个关键点。shape为25,3,25代表25个关键点,3代表每个关键点的XY坐标和置信度
        frame = datum.cvOutputData#获取提取骨骼之后的图片

        #判断是否为help的后处理,基本思路是手臂需要高于肩膀。且在一定角度范围内。
        if key_points[2][1] > key_points[3][1] and key_points[5][1] >key_points[6][1]:
            if abs(key_points[1][0] - key_points[3][0]) < is_help_threshold and abs(key_points[1][0] - key_points[6][0]) < is_help_threshold:
                if is_help_num <= 50:
                    if is_first_help and is_help_num >19 :
                        is_help_num = 50
                        is_first_help = False
                    is_help_num += 3
            else:
                if is_help_num < 20:
                    is_first_help = True
                    is_help_num = 0
                if is_help_num >= 0:
                    is_help_num -= 1


        else:
            if is_help_num < 20:
                is_first_help = True
                is_help_num = 0
            if is_help_num >= 0:
                is_help_num -= 2
        print('ishelpnum:',is_help_num)
        if is_help_num >= 20:
            cv2.putText(frame, f'help', (round(0.75 * frame.shape[1]), round(0.15 * frame.shape[0])),
                        cv2.FONT_ITALIC, 1, (16, 25, 238), 2, lineType=cv2.LINE_AA)
        # print("Body keypoints: \\n" + str(datum.poseKeypoints))

        #写入图片
        writer.write(frame)
        cv2.imshow("Openpose Python - Press Q to Exit", frame)
        frame_end_time = timeit.default_timer()
        if frame_end_time - frame_start_time > 1:
            print('fps:{}'.format(frame_cnt))
            frame_cnt = 0
            frame_start_time = frame_end_time
        frame_cnt = frame_cnt + 1

        if cv2.waitKey(1) & 0xFF == ord('1'):
            break
    cap.release()
    cv2.destroyAllWindows()
except Exception as e:
    print(e)
    sys.exit(-1)

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐