基于OpenPose的人体姿态检测

基于OpenPose的⼈体姿态检测
⼀、概述
OpenPose最开始由卡内基梅隆⼤学提出,其主要基于先后发表的⼏篇⽂章中提出的模型中进⾏实现
CVPR 2016: Convolutional Pose Machine(CPM)
CVPR2017 : realtime multi-person pose estimation
CVPR2017 : Hand Keypoint Detection in Single Images using Multiview Bootstrapping
但运⾏计算量⾮常⼤,通常得在GPU上运⾏,并且帧率较低(低于5fps),在此后也陆续出现了⼀些改进版
改进版主要在模型上进⾏了⼀些改进或裁剪,另外移动端(如各种尬舞app) 为能够跑通OpenPose,在改⽹络结构的同时,对算法本⾝也进⾏了优化,减少了计算量,但与此同时准确性也有相应地降低。
⼆、简化版OpenPose实现代码
代码来源GitHub:非你莫属20120101
其代码较为简单,模型(较⼩:7.8M)已经训练好在graph_opt.pb⽂件中,其中全部实现代码在openpose.py⽂件中,下⾯是实现代码及测试效果
# To use Inference Engine backend, specify location of plugins:
# export LD_LIBRARY_PATH=/opt/intel/deeplearning_deploymenttoolkit/deployment_tools/external/mklml_lnx/lib:$LD_LIBRARY_PATH
import cv2 as cv
import numpy as np
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--input',help='Path to image or video. Skip to capture frames from camera')
parser.add_argument('--thr', default=0.2,type=float,help='Threshold value for pose parts heat map')
parser.add_argument('--width', default=368,type=int,help='Resize input to specific width.')
parser.add_argument('--height', default=368,type=int,help='Resize input to specific height.')
args = parser.parse_args()
BODY_PARTS ={"Nose":0,"Neck":1,"RShoulder":2,"RElbow":3,"RWrist":4,
"LShoulder":5,"LElbow":6,"LWrist":7,"RHip":8,"RKnee":9,
"RAnkle":10,"LHip":11,"LKnee":12,"LAnkle":13,"REye":14,
"LEye":15,"REar":16,"LEar":17,"Background":18}
POSE_PAIRS =[["Neck","RShoulder"],["Neck","LShoulder"],["RShoulder","RElbow"],
["RElbow","RWrist"],["LShoulder","LElbow"],["LElbow","LWrist"],
["Neck","RHip"],["RHip","RKnee"],["RKnee","RAnkle"],["Neck","LHip"],
["LHip","LKnee"],["LKnee","LAnkle"],["Neck","Nose"],["Nose","REye"],
["REye","REar"],["Nose","LEye"],["LEye","LEar"]]
inWidth = args.width
inHeight = args.height
net = adNetFromTensorflow("graph_opt.pb")
cap = cv.VideoCapture(args.input if args.input else0)
while cv.waitKey(1)<0:
hasFrame, frame = ad()
if not hasFrame:
cv.waitKey()
break
frameWidth = frame.shape[1]
frameHeight = frame.shape[0]
小学数学课堂教学的有效性
net.setInput(cv.dnn.blobFromImage(frame,1.0,(inWidth, inHeight),(127.5,127.5,127.5), swapRB=True, crop=False))    out = net.forward()
out = out[:,:19,:,:]# MobileNet output [1, 57, -1, -1], we only need the first 19 elements
assert(len(BODY_PARTS)== out.shape[1])
points =[]
for i in range(len(BODY_PARTS)):
# Slice heatmap of corresponging body's part.
heatMap = out[0, i,:,:]
# Originally, we try to find all the local maximums. To simplify a sample
# we just find a global one. However only a single pose at the same time
# could be detected this way.
_, conf, _, point = cv.minMaxLoc(heatMap)
x =(frameWidth * point[0])/ out.shape[3]
y =(frameHeight * point[1])/ out.shape[2]
# Add a point if it's confidence is higher than threshold.
points.append((int(x),int(y))if conf > args.thr else None)
for pair in POSE_PAIRS:
partFrom = pair[0]
partTo = pair[1]
assert(partFrom in BODY_PARTS)
assert(partTo in BODY_PARTS)
idFrom = BODY_PARTS[partFrom]
idTo = BODY_PARTS[partTo]
if points[idFrom]and points[idTo]:
cv.line(frame, points[idFrom], points[idTo],(0,255,0),3)
cv.ellipse(frame, points[idFrom],(3,3),0,0,360,(0,0,255), cv.FILLED)
cv.ellipse(frame, points[idTo],(3,3),0,0,360,(0,0,255), cv.FILLED)
t, _ = PerfProfile()
freq = cv.getTickFrequency()/1000
cv.putText(frame,'%.2fms'%(t / freq),(10,20), cv.FONT_HERSHEY_SIMPLEX,0.5,(0,0,0))
cv.imshow('OpenPose using OpenCV', frame)
检测效果如下:
下⾯两张图中体现出单⼈且姿态展开时较好的检测效果:
下⾯两张图中体现出多⼈或特殊姿态时较差的检测效果(如乱连接或者遗漏关键点等):
从左上⾓显⽰的处理时间可看到,处理较慢,基本⼀张图⽚需耗时0.5S
三、较复杂版OpenPose实现代码
代码来源GitHub:
其代码⽐起前⾯这个更复杂⼀些,模型(更⼤:200M)已经训练好在可⾃⾏下载,但在外⽹不易下载,因此也可在百度云下载:其中全部实现代码在demo_camera.py⽂件中,下⾯是修改了⼀点点代码,采取读⼊图⽚的⽅式进⾏了测试:
import argparse
import cv2
import math
import time
import numpy as np
import util
from config_reader import config_reader
from scipy.ndimage.filters import gaussian_filter
from model import get_testing_model
tic=0
# find connection in the specified sequence, center 29 is in the position 15
limbSeq =[[2,3],[2,6],[3,4],[4,5],[6,7],[7,8],[2,9],[9,10], \
[10,11],[2,12],[12,13],[13,14],[2,1],[1,15],[15,17], \
[1,16],[16,18],[3,17],[6,18]]
# the middle joints heatmap correpondence
mapIdx =[[31,32],[39,40],[33,34],[35,36],[41,42],[43,44],[19,20],[21,22], \
[23,24],[25,26],[27,28],[29,30],[47,48],[49,50],[53,54],[51,52], \
[55,56],[37,38],[45,46]]
# visualize
colors =[[255,0,0],[255,85,0],[255,170,0],[255,255,0],[170,255,0],[85,255,0],
[0,255,0], \
[0,255,85],[0,255,170],[0,255,255],[0,170,255],[0,85,255],[0,0,255],
[85,0,255], \
谢之光[170,0,255],[255,0,255],[255,0,170],[255,0,85]]
def process(input_image, params, model_params):
oriImg = cv2.imread(input_image)# B,G,R order
multiplier =[x * model_params['boxsize']/ oriImg.shape[0]for x in params['scale_search']]
heatmap_avg = np.zeros((oriImg.shape[0], oriImg.shape[1],19))
paf_avg = np.zeros((oriImg.shape[0], oriImg.shape[1],38))
最是寻常梦
#for m in range(len(multiplier)):
for m in range(1):
scale = multiplier[m]
imageToTest = size(oriImg,(0,0), fx=scale, fy=scale, interpolation=cv2.INTER_CUBIC)
imageToTest_padded, pad = util.padRightDownCorner(imageToTest, model_params['stride'],
model_params['padValue'])
input_img = np.transpose(np.float32(imageToTest_padded[:,:,:,np.newaxis]),(3,0,1,2))# required shape (1, width, height, channels)        output_blobs = model.predict(input_img)
# extract outputs, resize, and remove padding
heatmap = np.squeeze(output_blobs[1])# output 1 is heatmaps
heatmap = size(heatmap,(0,0), fx=model_params['stride'], fy=model_params['stride'],
interpolation=cv2.INTER_CUBIC)
heatmap = heatmap[:imageToTest_padded.shape[0]- pad[2],:imageToTest_padded.shape[1]- pad[3],
:]
heatmap = size(heatmap,(oriImg.shape[1], oriImg.shape[0]), interpolation=cv2.INTER_CUBIC)
paf = np.squeeze(output_blobs[0])# output 0 is PAFs
paf = size(paf,(0,0), fx=model_params['stride'], fy=model_params['stride'],
interpolation=cv2.INTER_CUBIC)
paf = paf[:imageToTest_padded.shape[0]- pad[2],:imageToTest_padded.shape[1]- pad[3],:]
paf = size(paf,(oriImg.shape[1], oriImg.shape[0]), interpolation=cv2.INTER_CUBIC)
heatmap_avg = heatmap_avg + heatmap /len(multiplier)
paf_avg = paf_avg + paf /len(multiplier)
all_peaks =[]
peak_counter =0
prinfTick(1)
for part in range(18):红河学院学报
map_ori = heatmap_avg[:,:, part]
map= gaussian_filter(map_ori, sigma=3)
map_left = np.zeros(map.shape)
map_left[1:,:]=map[:-1,:]
map_right = np.zeros(map.shape)
map_right[:-1,:]=map[1:,:]
map_up = np.zeros(map.shape)
map_up[:,1:]=map[:,:-1]
map_down = np.zeros(map.shape)
map_down[:,:-1]=map[:,1:]
peaks_binary = np.duce(
(map>= map_left,map>= map_right,map>= map_up,map>= map_down,map> params['thre1']))        peaks =list(o(peaks_binary)[1], np.nonzero(peaks_binary)[0]))# note reverse
peaks_with_score =[x +(map_ori[x[1], x[0]],)for x in peaks]
id=range(peak_counter, peak_counter +len(peaks))
peaks_with_score_and_id =[peaks_with_score[i]+(id[i],)for i in range(len(id))]
all_peaks.append(peaks_with_score_and_id)
peak_counter +=len(peaks)
connection_all =[]
special_k =[]
mid_num =10
prinfTick(2)
for k in range(len(mapIdx)):
score_mid = paf_avg[:,:,[x -19for x in mapIdx[k]]]
candA = all_peaks[limbSeq[k][0]-1]
candB = all_peaks[limbSeq[k][1]-1]
nA =len(candA)
nB =len(candB)
indexA, indexB = limbSeq[k]
if(nA !=0and nB !=0):
connection_candidate =[]
招贴设计论文for i in range(nA):
for j in range(nB):
vec = np.subtract(candB[j][:2], candA[i][:2])
norm = math.sqrt(vec[0]* vec[0]+ vec[1]* vec[1])
# failure case when 2 body parts overlaps
if norm ==0:
continue
vec = np.divide(vec, norm)
startend =list(zip(np.linspace(candA[i][0], candB[j][0], num=mid_num), \
np.linspace(candA[i][1], candB[j][1], num=mid_num)))
vec_x = np.array(
[score_mid[int(round(startend[I][1])),int(round(startend[I][0])),0] \
for I in range(len(startend))])
vec_y = np.array(
[score_mid[int(round(startend[I][1])),int(round(startend[I][0])),1] \
for I in range(len(startend))])
score_midpts = np.multiply(vec_x, vec[0])+ np.multiply(vec_y, vec[1])
score_with_dist_prior =sum(score_midpts)/len(score_midpts)+min(
0.5* oriImg.shape[0]/ norm -1,0)
criterion1 =o(score_midpts > params['thre2'])[0])>0.8*len(
score_midpts)

本文发布于:2024-09-22 18:21:20,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/85576.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:代码   实现   效果   处理   裁剪
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议