【python】OpenCV—Single Human Pose Estimation

2024-08-25 01:52

本文主要是介绍【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的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1104214

相关文章

基于Python实现一个图片拆分工具

《基于Python实现一个图片拆分工具》这篇文章主要为大家详细介绍了如何基于Python实现一个图片拆分工具,可以根据需要的行数和列数进行拆分,感兴趣的小伙伴可以跟随小编一起学习一下... 简单介绍先自己选择输入的图片,默认是输出到项目文件夹中,可以自己选择其他的文件夹,选择需要拆分的行数和列数,可以通过

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

Python中将嵌套列表扁平化的多种实现方法

《Python中将嵌套列表扁平化的多种实现方法》在Python编程中,我们常常会遇到需要将嵌套列表(即列表中包含列表)转换为一个一维的扁平列表的需求,本文将给大家介绍了多种实现这一目标的方法,需要的朋... 目录python中将嵌套列表扁平化的方法技术背景实现步骤1. 使用嵌套列表推导式2. 使用itert

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Python使用pip工具实现包自动更新的多种方法

《Python使用pip工具实现包自动更新的多种方法》本文深入探讨了使用Python的pip工具实现包自动更新的各种方法和技术,我们将从基础概念开始,逐步介绍手动更新方法、自动化脚本编写、结合CI/C... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

Conda与Python venv虚拟环境的区别与使用方法详解

《Conda与Pythonvenv虚拟环境的区别与使用方法详解》随着Python社区的成长,虚拟环境的概念和技术也在不断发展,:本文主要介绍Conda与Pythonvenv虚拟环境的区别与使用... 目录前言一、Conda 与 python venv 的核心区别1. Conda 的特点2. Python v

Python使用python-can实现合并BLF文件

《Python使用python-can实现合并BLF文件》python-can库是Python生态中专注于CAN总线通信与数据处理的强大工具,本文将使用python-can为BLF文件合并提供高效灵活... 目录一、python-can 库:CAN 数据处理的利器二、BLF 文件合并核心代码解析1. 基础合

Python使用OpenCV实现获取视频时长的小工具

《Python使用OpenCV实现获取视频时长的小工具》在处理视频数据时,获取视频的时长是一项常见且基础的需求,本文将详细介绍如何使用Python和OpenCV获取视频时长,并对每一行代码进行深入解析... 目录一、代码实现二、代码解析1. 导入 OpenCV 库2. 定义获取视频时长的函数3. 打开视频文

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文