本文主要是介绍【python】OpenCV—Single Human Pose Estimation,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
文章目录
- 1、Human Pose Estimation
- 2、模型介绍
- 3、基于图片的单人人体关键点检测
- 4、基于视频的单人人体关键点检测
- 5、左右校正
- 6、关键点平滑
- 7、涉及到的库函数
- scipy.signal.savgol_filter
- 8、参考
1、Human Pose Estimation
Human Pose Estimation,即人体姿态估计,是一种基于计算机视觉和深度学习的技术,用于自动检测和识别人体的姿态和动作。它可以在图像或视频中准确地确定人体各个关节的位置和运动。
一、定义与分类
- 定义:人体姿态估计是指图像或视频中人体关节的定位问题,也可表述为在所有关节姿势的空间中搜索特定姿势。
- 分类:
2D姿态估计:从RGB图像估计每个关节的2D坐标(x,y)。
3D姿态估计:从RGBD图像中估计每个关节的3D坐标(x,y,z)。
根据应用场景,还可分为单人姿态估计、多人姿态估计、人体姿态跟踪等。
二、技术原理
- 实现方式:人体姿态识别的实现通常基于深度学习模型,如卷积神经网络(CNN)和循环神经网络(RNN)。首先,通过训练模型使用大量标记的姿势数据,模型能够学习到人体各个关节的特征表示。然后,当输入一张图像或视频时,模型会对每个关节进行定位和跟踪,进而恢复出人体的姿态。
- 改进技术:为了提高模型的鲁棒性和准确性,研究人员还提出了一些改进技术,如引入上下文信息、多尺度特征融合、姿势关系建模等。
三、应用领域
- 健身和运动:帮助跟踪和纠正运动姿势,提供更高效、精确的训练指导。
- 医疗:用于康复治疗、姿势评估等方面。
- 安防:用于行为分析、异常检测等。
- 虚拟现实(VR)与增强现实(AR):创建更真实的互动体验。
- 健康管理:监控老年人的身体活动,预防跌倒风险等。
四、未来展望
- 随着深度学习和计算机视觉技术的不断发展,人体姿态估计技术将在更多领域发挥重要作用。未来,该技术有望进一步提高准确性和实时性,为人们的训练、康复、安全和生活提供更加有效的支持。同时,随着数据量的增加和计算能力的提升,人体姿态估计技术也将更加智能化和个性化,满足不同场景下的需求。
2、模型介绍
COCO 输出格式
- 鼻子- 0,脖子- 1,右肩- 2,右手肘- 3,右手腕- 4,左肩- 5,左肘- 6,左腕- 7,右髋部- 8,右膝- 9,右脚踝- 10,左臀部- 11,左膝- 12,左脚踝 - 13,右眼- 14,左眼- 15,右耳- 16,左耳- 17,背景-18
MPII 输出格式
- 头-0,颈-1,右肩-2,右手肘-3,右手腕-4,左肩-5,左肘-6,左腕-7,右髋部-8,右膝-9,右脚踝-10,左臀部-11,左膝-12,左脚踝-13,胸部-14,背景-15
COCO 输出格式的模型
MPII 格式模型
3、基于图片的单人人体关键点检测
import cv2
import time
import numpy as np
import argparseparser = argparse.ArgumentParser(description='Run keypoint detection')
parser.add_argument("--device", default="gpu", help="Device to inference on")
parser.add_argument("--image_file", default="1.jpg", help="Input image")args = parser.parse_args()MODE = "COCO"
# MODE = "MPI"if MODE is "COCO":protoFile = "pose/coco/pose_deploy_linevec.prototxt"weightsFile = "pose/coco/pose_iter_440000.caffemodel"nPoints = 18POSE_PAIRS = [ [1,0],[1,2],[1,5],[2,3],[3,4],[5,6],[6,7],[1,8],[8,9],[9,10],[1,11],[11,12],[12,13],[0,14],[0,15],[14,16],[15,17]]elif MODE is "MPI":protoFile = "pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt"weightsFile = "pose/mpi/pose_iter_160000.caffemodel"nPoints = 15POSE_PAIRS = [[0,1], [1,2], [2,3], [3,4], [1,5], [5,6], [6,7], [1,14], [14,8], [8,9], [9,10], [14,11], [11,12], [12,13] ]frame = cv2.imread(args.image_file)
frameCopy = np.copy(frame)
frameWidth = frame.shape[1]
frameHeight = frame.shape[0]
threshold = 0.1net = cv2.dnn.readNetFromCaffe(protoFile, weightsFile)if args.device == "cpu":net.setPreferableBackend(cv2.dnn.DNN_TARGET_CPU)print("Using CPU device")
elif args.device == "gpu":net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)print("Using GPU device")t = time.time()
# input image dimensions for the network
inWidth = 368
inHeight = 368
inpBlob = cv2.dnn.blobFromImage(frame, 1.0 / 255, (inWidth, inHeight),(0, 0, 0), swapRB=False, crop=False)net.setInput(inpBlob)output = net.forward()
print("time taken by network : {:.3f}".format(time.time() - t))H = output.shape[2]
W = output.shape[3]# Empty list to store the detected keypoints
points = []for i in range(nPoints):# confidence map of corresponding body's part.probMap = output[0, i, :, :]# Find global maxima of the probMap.minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)# Scale the point to fit on the original imagex = (frameWidth * point[0]) / Wy = (frameHeight * point[1]) / Hif prob > threshold : cv2.circle(frameCopy, (int(x), int(y)), 8, (0, 255, 255), thickness=-1, lineType=cv2.FILLED)cv2.putText(frameCopy, "{}".format(i), (int(x), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, lineType=cv2.LINE_AA)# Add the point to the list if the probability is greater than the thresholdpoints.append((int(x), int(y)))else :points.append(None)# Draw Skeleton
for pair in POSE_PAIRS:partA = pair[0]partB = pair[1]if points[partA] and points[partB]:cv2.line(frame, points[partA], points[partB], (0, 255, 255), 2)cv2.circle(frame, points[partA], 8, (0, 0, 255), thickness=-1, lineType=cv2.FILLED)cv2.imshow(MODE+'-Output-Keypoints', frameCopy)
cv2.imshow(MODE+'-Output-Skeleton', frame)cv2.imwrite(MODE+'-Output-Keypoints.jpg', frameCopy)
cv2.imwrite(MODE+'-Output-Skeleton.jpg', frame)print("Total time taken : {:.3f}".format(time.time() - t))cv2.waitKey(0)
输入图片
COCO 输出
关键点连起来
可以看出脸部关键点预测的不太准,特别是鼻子
MPII 输出格式
关键点连起来
脚踝还是有一点点瑕疵
再看一组例子
输入图片
COCO 输出格式
同样的,脸部关键点不太准,耳朵鼻子
MPII 格式输出
MPII 结果不错
4、基于视频的单人人体关键点检测
import cv2
import time
import numpy as np
import argparseparser = argparse.ArgumentParser(description='Run keypoint detection')
parser.add_argument("--device", default="gpu", help="Device to inference on")
parser.add_argument("--video_file", default="sample_video.mp4", help="Input Video")args = parser.parse_args()# MODE = "MPI"
MODE = "COCO"if MODE is "COCO":protoFile = "pose/coco/pose_deploy_linevec.prototxt"weightsFile = "pose/coco/pose_iter_440000.caffemodel"nPoints = 18POSE_PAIRS = [ [1,0],[1,2],[1,5],[2,3],[3,4],[5,6],[6,7],[1,8],[8,9],[9,10],[1,11],[11,12],[12,13],[0,14],[0,15],[14,16],[15,17]]elif MODE is "MPI" :protoFile = "pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt"weightsFile = "pose/mpi/pose_iter_160000.caffemodel"nPoints = 15POSE_PAIRS = [[0,1], [1,2], [2,3], [3,4], [1,5], [5,6], [6,7], [1,14], [14,8], [8,9], [9,10], [14,11], [11,12], [12,13] ]inWidth = 368
inHeight = 368
threshold = 0.1input_source = args.video_file
cap = cv2.VideoCapture(input_source)
hasFrame, frame = cap.read()vid_writer = cv2.VideoWriter(MODE+'-output.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 10, (frame.shape[1],frame.shape[0]))net = cv2.dnn.readNetFromCaffe(protoFile, weightsFile)
if args.device == "cpu":net.setPreferableBackend(cv2.dnn.DNN_TARGET_CPU)print("Using CPU device")
elif args.device == "gpu":net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)print("Using GPU device")while cv2.waitKey(1) < 0:t = time.time()hasFrame, frame = cap.read()frameCopy = np.copy(frame)if not hasFrame:cv2.waitKey()breakframeWidth = frame.shape[1]frameHeight = frame.shape[0]inpBlob = cv2.dnn.blobFromImage(frame, 1.0 / 255, (inWidth, inHeight),(0, 0, 0), swapRB=False, crop=False)net.setInput(inpBlob)output = net.forward()H = output.shape[2]W = output.shape[3]# Empty list to store the detected keypointspoints = []for i in range(nPoints):# confidence map of corresponding body's part.probMap = output[0, i, :, :]# Find global maxima of the probMap.minVal, prob, minLoc, point = cv2.minMaxLoc(probMap)# Scale the point to fit on the original imagex = (frameWidth * point[0]) / Wy = (frameHeight * point[1]) / Hif prob > threshold : cv2.circle(frameCopy, (int(x), int(y)), 8, (0, 255, 255), thickness=-1, lineType=cv2.FILLED)cv2.putText(frameCopy, "{}".format(i), (int(x), int(y)), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, lineType=cv2.LINE_AA)# Add the point to the list if the probability is greater than the thresholdpoints.append((int(x), int(y)))else :points.append(None)# Draw Skeletonfor pair in POSE_PAIRS:partA = pair[0]partB = pair[1]if points[partA] and points[partB]:cv2.line(frame, points[partA], points[partB], (0, 255, 255), 3, lineType=cv2.LINE_AA)cv2.circle(frame, points[partA], 8, (0, 0, 255), thickness=-1, lineType=cv2.FILLED)cv2.circle(frame, points[partB], 8, (0, 0, 255), thickness=-1, lineType=cv2.FILLED)cv2.putText(frame, "time taken = {:.2f} sec".format(time.time() - t), (50, 50), cv2.FONT_HERSHEY_COMPLEX, .8, (255, 50, 0), 2, lineType=cv2.LINE_AA)# cv2.putText(frame, "OpenPose using OpenCV", (50, 50), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 50, 0), 2, lineType=cv2.LINE_AA)# cv2.imshow('Output-Keypoints', frameCopy)cv2.imshow(MODE + '-Output-Skeleton', frame)vid_writer.write(frame)vid_writer.release()
COCO 格式输出
COCO-output
MPII 格式输出
MPI-output
手腕脚腕是难点,左右存在混淆,抖动比较明显
下面章节我们来优化缓解下上述问题,基于 MPII 格式的输出
5、左右校正
身体部分预测的关键点不合理时被交换,这样左边的部分就总是在左边(要确保人一直是对着屏幕前的我们的吧,背对着和正面切换这样的校正就没有意义了)
先把正常预测的结果保存下来,save_pose_data,py
检测结果保存在 workout.csv
中
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
"""
@File : save_pose_data.py.py
@Time : 2021/9/27 16:21
@Author : David
@Software: PyCharm
"""
import cv2, numpy as np, csv# https://github.com/opencv/opencv/blob/master/samples/dnn/openpose.py
outfile_path = 'workout.csv'protoFile = "./pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt"
weightsFile = "./pose/mpi/pose_iter_160000.caffemodel"
net = cv2.dnn.readNetFromCaffe(protoFile, weightsFile)data, input_width, input_height, threshold, frame_number = [], 368, 386, 0.1, 0input_source = "sample_video.mp4"
cap = cv2.VideoCapture(input_source)# use the previous location of the body part if the model is wrong
previous_x, previous_y = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0]while True:ret, img = cap.read()if not ret: break# get the image shapeimg_width, img_height = img.shape[1], img.shape[0]# get a blob from the imageinputBlob = cv2.dnn.blobFromImage(img, 1.0 / 255, (input_width, input_height), (0, 0, 0), swapRB=False, crop=False)# set the input and perform a forward passnet.setInput(inputBlob)output = net.forward()# get the output shapeoutput_width, output_height = output.shape[2], output.shape[3]# Empty list to store the detected keypointsx_data, y_data = [], []# Iterate through the body partsfor i in range(15):# find probability that point is correct_, prob, _, point = cv2.minMaxLoc(output[0, i, :, :])# Scale the point to fit on the original imagex, y = (img_width * point[0]) / output_width, (img_height * point[1]) / output_height# Is the point likely to be correct?if prob > threshold:x_data.append(x)y_data.append(y)xy = tuple(np.array([x, y], int))cv2.circle(img, xy, 5, (25, 0, 255), 5)# No? us the location in the previous frameelse:x_data.append(previous_x[i])y_data.append(previous_y[i])# add these points to the list of datadata.append(x_data + y_data)previous_x, previous_y = x_data, y_dataframe_number += 1# use this break statement to check your data before processing the whole video# if frame_number == 300: breakprint(frame_number)cv2.imshow('img', img)k = cv2.waitKey(1)if k == 27: break# write the data to a .csv file
import pandas as pddf = pd.DataFrame(data)
df.to_csv(outfile_path, index=False)
print('save complete')
读取模型预测的结果,进行左右校正,swap_body_parts.py
输出 swapped_body_parts.csv
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
"""
@File : swap_body_parts.py.py
@Time : 2021/9/27 16:52
@Author : David
@Software: PyCharm
"""
# swap_body_parts.py
import pandas as pd
import numpy as np
import cv2, os
import csvinput_source = "sample_video.mp4"
cap = cv2.VideoCapture(input_source)
frame_number = 0
font, scale, colorText, thick = cv2.FONT_HERSHEY_SIMPLEX, .5, (234, 234, 234), 1
size, color, thickness = 5, (255, 255, 255), 5
# get pose data - data is generated by open pose video
df = pd.read_csv('workout.csv')# there are 15 points in the skeleton
# 0 head
# 1 neck
# 2, 5 shoulders
# 3, 6 elbows
# 4, 7 hands
# 8, 11 hips
# 9, 12 knees
# 10, 13 ankles
# 14 torsodata = []
while cv2.waitKey(10) < 0 and frame_number < len(df.values) - 2:ret, img = cap.read()if not ret: breaktry:values = df.values[frame_number]except:breakvalues = np.array(values, int)points = []points.append((values[0], values[1]))points.append((values[2], values[3]))points.append((values[4], values[5]))points.append((values[6], values[7]))points.append((values[8], values[9]))points.append((values[10], values[11]))points.append((values[12], values[13]))points.append((values[14], values[15]))points.append((values[16], values[17]))points.append((values[18], values[19]))points.append((values[20], values[21]))points.append((values[22], values[23]))points.append((values[24], values[25]))points.append((values[26], values[27]))points.append((values[28], values[29]))# create a blank list to store the non-swapped poitnsnon_swap_points = []for i in range(15): non_swap_points.append((0, 0))# add the head, that point never changesnon_swap_points[0] = points[0]# add the neck, that point never changesnon_swap_points[1] = points[1]# add the torso, that never changesnon_swap_points[14] = points[14]# swap the left and right shoulders (2 and 5)if points[2][0] < points[5][0]:non_swap_points[2] = points[2]non_swap_points[5] = points[5]else:non_swap_points[2] = points[5]non_swap_points[5] = points[2]# swap the elbowsif points[3][0] < points[6][0]:non_swap_points[3] = points[3]non_swap_points[6] = points[6]else:non_swap_points[6] = points[3]non_swap_points[3] = points[6]# swap the handsif points[4][0] < points[7][0]:non_swap_points[4] = points[4]non_swap_points[7] = points[7]else:non_swap_points[7] = points[4]non_swap_points[4] = points[7]# swap the hipsif points[8][0] < points[11][0]:non_swap_points[11] = points[11]non_swap_points[8] = points[8]else:non_swap_points[8] = points[11]non_swap_points[11] = points[8]# swap the kneesif points[9][0] < points[12][0]:non_swap_points[9] = points[9]non_swap_points[12] = points[12]else:non_swap_points[12] = points[9]non_swap_points[9] = points[12]# swap the feetif points[10][0] < points[13][0]:non_swap_points[10] = points[10]non_swap_points[13] = points[13]else:non_swap_points[13] = points[10]non_swap_points[10] = points[13]for point in non_swap_points:cv2.circle(img, point, 3, (0, 0, 255), 3)cv2.putText(img, str(non_swap_points.index(point)), point, font, scale, colorText, thick, cv2.LINE_AA)cv2.imshow('Output-Skeleton', img)frame_number += 1data.append(non_swap_points)
cv2.destroyAllWindows()with open('swapped_body_parts.csv', 'w') as csvfile:fieldnames = []for i in range(30): fieldnames.append(str(i))writer = csv.DictWriter(csvfile, fieldnames=fieldnames)writer.writeheader()for trick in data:writer.writerow({'0': trick[0][0],'1': trick[0][1],'2': trick[1][0],'3': trick[1][1],'4': trick[2][0],'5': trick[2][1],'6': trick[3][0],'7': trick[3][1],'8': trick[4][0],'9': trick[4][1],'10': trick[5][0],'11': trick[5][1],'12': trick[6][0],'13': trick[6][1],'14': trick[7][0],'15': trick[7][1],'16': trick[8][0],'17': trick[8][1],'18': trick[9][0],'19': trick[9][1],'20': trick[10][0],'21': trick[10][1],'22': trick[11][0],'23': trick[11][1],'24': trick[12][0],'25': trick[12][1],'26': trick[13][0],'27': trick[13][1],'28': trick[14][0],'29': trick[14][1]})
结果会在下一小节展示
6、关键点平滑
在应用平滑算法之前,所有帧的姿态数据必须是已知的(我们保存在了workout.csv
之中)
#!/usr/bin/python3
# -*- encoding: utf-8 -*-
"""
@File : smooth_pose_data.py.py
@Time : 2021/9/27 16:15
@Author : David
@Software: PyCharm
"""
import pandas as pd
import numpy as np
import cv2
from scipy import signalcircle_color, line_color = (255, 255, 0), (0, 0, 255)
window_length, polyorder = 13, 2input_source = "sample_video.mp4"# Get pose data - data is generated by OpenPose
df = pd.read_csv('workout.csv')
# df = pd.read_csv('swapped_body_parts.csv')cap = cv2.VideoCapture(input_source)# get width of video
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))# get height of video
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
out = cv2.VideoWriter('smooth_pose.avi',cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'), 30, (frame_width, frame_height))
# There are 15 points in the skeleton
pairs = [[0, 1], # head[1, 2], [1, 5], # sholders[2, 3], [3, 4], [5, 6], [6, 7], # arms[1, 14], [14, 11], [14, 8], # hips[8, 9], [9, 10], [11, 12], [12, 13]] # legs# Smooth it out
for i in range(30):df[str(i)] = signal.savgol_filter(df[str(i)], window_length, polyorder)frame_number = 0
while True:print(frame_number)ret, img = cap.read() # 720, 576if not ret:break# img = np.zeros_like(img)values = np.array(df.values[frame_number], int)points, lateral_offset = [], 18points = list(zip(values[:15] + lateral_offset, values[15:]))cc = 0for point in points:cc += 90xy = tuple(np.array([point[0], point[1]], int))cv2.circle(img, xy, 5, (cc, cc, cc), 5)# Draw Skeletonfor pair in pairs:partA = pair[0]partB = pair[1]cv2.line(img, points[partA], points[partB], line_color, 3, lineType=cv2.LINE_AA)cv2.imshow('Output-Skeleton', img)out.write(img)k = cv2.waitKey(100)if k == 27: # Escbreakframe_number += 1
out.release()
cv2.destroyAllWindows()
我们仅平滑,不左右校正,看看结果
smooth pose direct
smooth_pose_data.py
平滑结果,可以看到结果丝滑了很多,抖动明显减少,不过大幅度动作关键点预测的还是不太准确,特别是手腕脚腕这些比较难的地方,而且也容易出现左右混淆
下面我们先左右校正,再平滑,输入 df = pd.read_csv('swapped_body_parts.csv')
smooth pose
感觉哪里有点问题,哈哈,比直接平滑效果变差了
7、涉及到的库函数
scipy.signal.savgol_filter
scipy.signal.savgol_filter
是 SciPy 库中用于数据平滑的一个函数,它实现了 Savitzky-Golay 滤波器。Savitzky-Golay 滤波器是一种在一维数据上应用的滤波技术,通过局域多项式最小二乘法拟合来平滑数据并去除噪声,同时保留信号的形状和变化信息。
函数签名
scipy.signal.savgol_filter(x, window_length, polyorder, deriv=0, delta=1.0, axis=-1, mode='interp', cval=0.0)
参数说明
- x (array_like): 要过滤的数据。如果 x 不是单精度或双精度浮点型数组,则会在过滤前被转换为 numpy.float64 类型。
- window_length (int): 滤波器窗口的长度(即系数的数量)。该值必须为正奇数,决定了平滑的范围。如果 mode 是 ‘interp’,则 window_length 必须小于或等于 x 的大小。
- polyorder (int): 用于拟合样本的多项式的阶数。该值必须小于 window_length。
- deriv (int, 可选): 要计算的导数的阶数。默认为 0,表示仅平滑数据而不进行微分。如果大于 0,则计算指定阶数的导数。
- delta (float, 可选): 样本间隔。当 deriv 大于 0 时使用。默认为 1.0。
- axis (int, 可选): 应用滤波器的轴。对于多维数组,该参数指定在哪个轴上应用滤波器。默认为 -1,即最后一个轴。
- mode (str, 可选): 用于处理边界的模式。可以是 ‘mirror’、‘constant’、‘nearest’、‘wrap’ 或 ‘interp’。默认为 ‘interp’。这些模式决定了在窗口移出数组边界时如何处理边界值。
‘mirror’: 通过镜像反射填充边界。
‘constant’: 使用 cval 指定的常量值填充边界。
‘nearest’: 使用最近的值填充边界。
‘wrap’: 通过环绕的方式填充边界。
‘interp’: 使用多项式插值填充边界。 - cval (scalar, 可选): 当 mode 为 ‘constant’ 时,用于填充边界的常量值。默认为 0.0。
返回值
- Y (ndarray): 过滤后的数据。
注意事项
- Savitzky-Golay 滤波器是一种局部多项式回归方法,它通过最小化窗口内数据的局部多项式拟合误差来平滑数据。
选择合适的 window_length 和 polyorder 是非常重要的,它们将直接影响平滑的效果和信号的保留程度。 - window_length 必须是奇数,以便窗口能够对称地围绕中心点。
- 在处理多维数据时,axis 参数允许用户指定在哪个维度上应用滤波器。
示例
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import savgol_filter # 创建示例数据
x = np.linspace(-4, 4, 500)
y = np.exp(-x**2) + np.random.normal(0, 0.05, x.shape) # 应用 Savitzky-Golay 滤波器
y_filtered = savgol_filter(y, window_length=51, polyorder=3) # 绘制原始数据和平滑后的数据
plt.plot(x, y, label='Noisy data')
plt.plot(x, y_filtered, label='Smoothed data', color='red')
plt.legend()
plt.show()
以上示例展示了如何使用 scipy.signal.savgol_filter 函数对带有噪声的数据进行平滑处理。
8、参考
参考学习来自以下链接
-
Code and model
链接:https://pan.baidu.com/s/1OoDWEc7bdwKbKBEqQ5oOdA
提取码:123a -
OpenCV进阶(5)基于OpenCV的深度学习人体姿态估计之单人篇
-
https://learnopencv.com/deep-learning-based-human-pose-estimation-using-opencv-cpp-python/
-
Cao Z, Simon T, Wei S E, et al. Realtime multi-person 2d pose estimation using part affinity fields[C]//Proceedings of the IEEE conference on computer vision and pattern recognition. 2017: 7291-7299.
https://arxiv.org/pdf/1611.08050 -
MPII Human Pose Dataset
http://human-pose.mpi-inf.mpg.de/ -
Human Pose Evaluator Dataset
https://www.robots.ox.ac.uk/~vgg/data/pose_evaluation/
这篇关于【python】OpenCV—Single Human Pose Estimation的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!