论文:Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields 提取码:1u2n
论文理解参考博客: https://blog.csdn.net/w275840140/article/details/89393626 https://blog.csdn.net/wwwhp/article/details/88782851
轻量级openpose模型完成项目地址(模型7M,精度偏低): 百度云地址:https://pan.baidu.com/s/1tpZPeRSup2SNsgOJR0CWUA 提取码:6f5u
代码:
import cv2 import numpy as np import argparse import time 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 = 368 inHeight = 368 thr = 0.2 net = cv2.dnn.readNetFromTensorflow("graph_opt.pb") def video_detect(): fps = 0.0 cap = cv2.VideoCapture(0) while True: t1 = time.time() ret, frame = cap.read() frameWidth = frame.shape[1] frameHeight = frame.shape[0] net.setInput(cv2.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 = cv2.minMaxLoc(heatMap) x = (frameWidth * point[0]) / out.shape[3] y = (frameHeight * point[1]) / out.shape[2] points.append((int(x), int(y)) if conf > 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]: #cv2.line() #第一个参数 img:要划的线所在的图像; # 第二个参数 pt1:直线起点 第三个参数 pt2:直线终点 # 第四个参数 color:直线的颜色 第五个参数 thickness=1:线条粗细 cv2.line(frame, points[idFrom], points[idTo], (0, 255, 0), 3) # cv2.ellipse()画椭圆 cv2.ellipse(frame, points[idFrom], (3, 3), 0, 0, 360, (0, 0, 255), cv2.FILLED) cv2.ellipse(frame, points[idTo], (3, 3), 0, 0, 360, (0, 0, 255), cv2.FILLED) fps = (fps + (1. / (time.time() - t1))) / 2 # print("fps= %.2f" % (fps)) frame = cv2.putText(frame, "fps= %.2f" % (fps), (0, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) cv2.imshow("video", frame) c = cv2.waitKey(1) & 0xff if c == 27: cap.release() break def img_detect(image): t1 = time.time() img = cv2.imread(image) imgWidth = img.shape[1] imgHeight = img.shape[0] net.setInput(cv2.dnn.blobFromImage(img, 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, :, :] _, conf, _, point = cv2.minMaxLoc(heatMap) x = (imgWidth * point[0]) / out.shape[3] y = (imgHeight * point[1]) / out.shape[2] points.append((int(x), int(y)) if conf > 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]: cv2.line(img, points[idFrom], points[idTo], (0, 255, 0), 3) cv2.ellipse(img, points[idFrom], (3, 3), 0, 0, 360, (0, 0, 255), cv2.FILLED) cv2.ellipse(img, points[idTo], (3, 3), 0, 0, 360, (0, 0, 255), cv2.FILLED) fps = time.time() - t1 frame = cv2.putText(img, "time= %.2fs" % (fps), (0, 40), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) cv2.imshow('img',img) cv2.waitKey(0) if __name__ == '__main__': # 视频检测 video_detect() # # 图片检测 # img_detect('qin.jpeg')效果图:
基于keras框架openpose姿态检测(190M,精度高)
百度云链接:https://pan.baidu.com/s/1-fqumQWZnz5h4KmW9-Msog 提取码:ety0 复制这段内容后打开百度网盘手机App,操作更方便哦–来自百度网盘超级会员V1的分享
主干模型:VGG19
from keras.models import Model from keras.layers.merge import Concatenate from keras.layers import Activation, Input, Lambda from keras.layers.convolutional import Conv2D from keras.layers.pooling import MaxPooling2D from keras.layers.merge import Multiply from keras.regularizers import l2 from keras.initializers import random_normal,constant def relu(x): return Activation('relu')(x) def conv(x, nf, ks, name, weight_decay): kernel_reg = l2(weight_decay[0]) if weight_decay else None bias_reg = l2(weight_decay[1]) if weight_decay else None x = Conv2D(nf, (ks, ks), padding='same', name=name, kernel_regularizer=kernel_reg, bias_regularizer=bias_reg, kernel_initializer=random_normal(stddev=0.01), bias_initializer=constant(0.0))(x) return x def pooling(x, ks, st, name): x = MaxPooling2D((ks, ks), strides=(st, st), name=name)(x) return x def vgg_block(x, weight_decay): # Block 1 x = conv(x, 64, 3, "conv1_1", (weight_decay, 0)) x = relu(x) x = conv(x, 64, 3, "conv1_2", (weight_decay, 0)) x = relu(x) x = pooling(x, 2, 2, "pool1_1") # Block 2 x = conv(x, 128, 3, "conv2_1", (weight_decay, 0)) x = relu(x) x = conv(x, 128, 3, "conv2_2", (weight_decay, 0)) x = relu(x) x = pooling(x, 2, 2, "pool2_1") # Block 3 x = conv(x, 256, 3, "conv3_1", (weight_decay, 0)) x = relu(x) x = conv(x, 256, 3, "conv3_2", (weight_decay, 0)) x = relu(x) x = conv(x, 256, 3, "conv3_3", (weight_decay, 0)) x = relu(x) x = conv(x, 256, 3, "conv3_4", (weight_decay, 0)) x = relu(x) x = pooling(x, 2, 2, "pool3_1") # Block 4 x = conv(x, 512, 3, "conv4_1", (weight_decay, 0)) x = relu(x) x = conv(x, 512, 3, "conv4_2", (weight_decay, 0)) x = relu(x) # Additional non vgg layers x = conv(x, 256, 3, "conv4_3_CPM", (weight_decay, 0)) x = relu(x) x = conv(x, 128, 3, "conv4_4_CPM", (weight_decay, 0)) x = relu(x) return x def stage1_block(x, num_p, branch, weight_decay): # Block 1 x = conv(x, 128, 3, "Mconv1_stage1_L%d" % branch, (weight_decay, 0)) x = relu(x) x = conv(x, 128, 3, "Mconv2_stage1_L%d" % branch, (weight_decay, 0)) x = relu(x) x = conv(x, 128, 3, "Mconv3_stage1_L%d" % branch, (weight_decay, 0)) x = relu(x) x = conv(x, 512, 1, "Mconv4_stage1_L%d" % branch, (weight_decay, 0)) x = relu(x) x = conv(x, num_p, 1, "Mconv5_stage1_L%d" % branch, (weight_decay, 0)) return x def stageT_block(x, num_p, stage, branch, weight_decay): # Block 1 x = conv(x, 128, 7, "Mconv1_stage%d_L%d" % (stage, branch), (weight_decay, 0)) x = relu(x) x = conv(x, 128, 7, "Mconv2_stage%d_L%d" % (stage, branch), (weight_decay, 0)) x = relu(x) x = conv(x, 128, 7, "Mconv3_stage%d_L%d" % (stage, branch), (weight_decay, 0)) x = relu(x) x = conv(x, 128, 7, "Mconv4_stage%d_L%d" % (stage, branch), (weight_decay, 0)) x = relu(x) x = conv(x, 128, 7, "Mconv5_stage%d_L%d" % (stage, branch), (weight_decay, 0)) x = relu(x) x = conv(x, 128, 1, "Mconv6_stage%d_L%d" % (stage, branch), (weight_decay, 0)) x = relu(x) x = conv(x, num_p, 1, "Mconv7_stage%d_L%d" % (stage, branch), (weight_decay, 0)) return x def apply_mask(x, mask1, mask2, num_p, stage, branch): w_name = "weight_stage%d_L%d" % (stage, branch) if num_p == 38: w = Multiply(name=w_name)([x, mask1]) # vec_weight else: w = Multiply(name=w_name)([x, mask2]) # vec_heat return w def get_training_model(weight_decay): stages = 6 np_branch1 = 38 np_branch2 = 19 img_input_shape = (None, None, 3) vec_input_shape = (None, None, 38) heat_input_shape = (None, None, 19) inputs = [] outputs = [] img_input = Input(shape=img_input_shape) vec_weight_input = Input(shape=vec_input_shape) heat_weight_input = Input(shape=heat_input_shape) inputs.append(img_input) inputs.append(vec_weight_input) inputs.append(heat_weight_input) img_normalized = Lambda(lambda x: x / 256 - 0.5)(img_input) # [-0.5, 0.5] # VGG stage0_out = vgg_block(img_normalized, weight_decay) # stage 1 - branch 1 (PAF) stage1_branch1_out = stage1_block(stage0_out, np_branch1, 1, weight_decay) w1 = apply_mask(stage1_branch1_out, vec_weight_input, heat_weight_input, np_branch1, 1, 1) # stage 1 - branch 2 (confidence maps) stage1_branch2_out = stage1_block(stage0_out, np_branch2, 2, weight_decay) w2 = apply_mask(stage1_branch2_out, vec_weight_input, heat_weight_input, np_branch2, 1, 2) x = Concatenate()([stage1_branch1_out, stage1_branch2_out, stage0_out]) outputs.append(w1) outputs.append(w2) # stage sn >= 2 for sn in range(2, stages + 1): # stage SN - branch 1 (PAF) stageT_branch1_out = stageT_block(x, np_branch1, sn, 1, weight_decay) w1 = apply_mask(stageT_branch1_out, vec_weight_input, heat_weight_input, np_branch1, sn, 1) # stage SN - branch 2 (confidence maps) stageT_branch2_out = stageT_block(x, np_branch2, sn, 2, weight_decay) w2 = apply_mask(stageT_branch2_out, vec_weight_input, heat_weight_input, np_branch2, sn, 2) outputs.append(w1) outputs.append(w2) if (sn < stages): x = Concatenate()([stageT_branch1_out, stageT_branch2_out, stage0_out]) model = Model(inputs=inputs, outputs=outputs) return model def get_testing_model(): stages = 6 np_branch1 = 38 np_branch2 = 19 img_input_shape = (None, None, 3) img_input = Input(shape=img_input_shape) img_normalized = Lambda(lambda x: x / 256 - 0.5)(img_input) # [-0.5, 0.5] # VGG stage0_out = vgg_block(img_normalized, None) # stage 1 - branch 1 (PAF) stage1_branch1_out = stage1_block(stage0_out, np_branch1, 1, None) # stage 1 - branch 2 (confidence maps) stage1_branch2_out = stage1_block(stage0_out, np_branch2, 2, None) x = Concatenate()([stage1_branch1_out, stage1_branch2_out, stage0_out]) # stage t >= 2 stageT_branch1_out = None stageT_branch2_out = None for sn in range(2, stages + 1): stageT_branch1_out = stageT_block(x, np_branch1, sn, 1, None) stageT_branch2_out = stageT_block(x, np_branch2, sn, 2, None) if (sn < stages): x = Concatenate()([stageT_branch1_out, stageT_branch2_out, stage0_out]) model = Model(inputs=[img_input], outputs=[stageT_branch1_out, stageT_branch2_out]) return model检测结果: