• 3D视觉——2.人体姿态估计(Pose Estimation)入门——OpenPose含安装、编译、使用(单帧、实时视频)


    本章博客就是对OpenPose工具包进行开发;我呕心沥血(笑哭),经历重重困难,想放弃了很多次(因为openpose的编译实在是太麻烦了)但是后来还是成功了,各位点个赞吧!这个真的太麻烦了。

    按照单帧图像和实时视频的顺序述写,其中单帧是使用的Pytorch编程只是调用OpenPose的模型;实时视频中使用Python调用OpenPose的包,所以必须得安装OpenPose,并对其进行编译,最后再使用。


    首先从github上,下载CMU提供的源码下来:

    https://github.com/CMU-Perceptual-Computing-Lab/openposehttps://github.com/CMU-Perceptual-Computing-Lab/openpose


    项目结构

    1. OpenPose-Demo-Pytorch-master
    2. |
    3. |----images----|----pose.jpg
    4. |----bin(编译之后,从源码拷贝下来的,单帧不看这个)
    5. |----x64(编译之后,从源码拷贝下来的,单帧不看这个)
    6. |----Release(编译之后,从源码拷贝下来的,单帧不看这个)
    7. |----models----|----pose----|----body_25----|----pose_deploy.prototxt
    8. | | |----pose_iter_584000.caffemodel
    9. | |----coco----|----pose_deploy_linevec.prototxt
    10. | | |----pose_iter_440000.caffemodel
    11. |----video----|----1.mp4
    12. |----config.py
    13. |----predict.py(单帧)
    14. |----Demo.py(实时视频)

    关键点详解

    关键点25(model\pose\body_25\pose_iter_584000.caffemodel or pose_deploy.prototxt)如下图1. 所示,关键点18(model\pose\coco\pose_iter_440000.caffemodel or pose_deploy_linevec.prototxt)如下图2.所示。

    下载模型,可在CMU的github上下载,上面提供了,就不再提供。

    步骤:

    1. git clone https://github.com/CMU-Perceptual-Computing-Lab/openpose.git
    2. or
    3. downloads .zip
    4. cd openpose-master/models
    5. bash getModels.sh (Linux)
    6. 双击 getModels.bat (Windows)
    7. 下载 pose_iter_584000.caffemodel
    8. pose_iter_440000.caffemodel
    9. ...(只用这两个,将其放置在我们项目的models\pose\下)

     图1.

    1. {0, “Nose”},
    2. {1, “Neck”},
    3. {2, “RShoulder”},
    4. {3, “RElbow”},
    5. {4, “RWrist”},
    6. {5, “LShoulder”},
    7. {6, “LElbow”},
    8. {7, “LWrist”},
    9. {8, “MidHip”},
    10. {9, “RHip”},
    11. {10, “RKnee”},
    12. {11, “RAnkle”},
    13. {12, “LHip”},
    14. {13, “LKnee”},
    15. {14, “LAnkle”},
    16. {15, “REye”},
    17. {16, “LEye”},
    18. {17, “REar”},
    19. {18, “LEar”},
    20. {19, “LBigToe”},
    21. {20, “LSmallToe”},
    22. {21, “LHeel”},
    23. {22, “RBigToe”},
    24. {23, “RSmallToe”},
    25. {24, “RHeel”}

     图2.

    1. {"Nose": 0,
    2. "Neck": 1,
    3. "RShoulder": 2,
    4. "RElbow": 3,
    5. "LShoulder": 5,
    6. "LElbow": 6,
    7. "LWrist": 7,
    8. "RHip": 8,
    9. "RKnee": 9,
    10. "RAnkle": 10,
    11. "LHip": 11,
    12. "LKnee": 12,
    13. "LAnkle": 13,
    14. "REye": 14,
    15. "LEye": 15,
    16. "REar": 16,
    17. "LEar": 17,
    18. "Background": 18}

    1.单帧代码

    对于单帧将之前的源码下载下来,并将模型权重拷贝(进入源码的models里面双击getModels.bat下载这些权重)到我们自己的项目,就是将models中.prototxt与.caffemodel拷走;之后我们对模型进行推理,其步骤主要为:

    • 首先,读取模型与推理所需要的图像,在进行推理获取结果
    • 其次,关键点检测,再利用PAFs,找到有些关键点对
    • 最后,将点对组合成正确的人体骨骼图

    配置文件

    config.py

    1. prototxt_25 = "models/pose/body_25/pose_deploy.prototxt"
    2. caffemodel_25 = "models/pose/body_25/pose_iter_584000.caffemodel"
    3. point_name_25 = ['None', 'Neck', 'RShoulder',
    4. 'RElbow', 'RWrist', 'LShoulder',
    5. 'LElbow', 'LWrist', 'MidHip',
    6. 'RHip', 'RKnee', 'RAnkle',
    7. 'LHip', 'LKnee', 'LAnkle',
    8. 'REye', 'LEye', 'REar',
    9. 'LEar', 'LBigToe', 'LSmallToe',
    10. 'LHeel', 'RBigToe', 'RSmallToe',
    11. 'RHeel']
    12. point_pairs_25 = [[1, 8], [1, 2], [1, 5], [2, 3], [3, 4], [5, 6],
    13. [6, 7], [8, 9], [9, 10], [10, 11], [8, 12], [12, 13],
    14. [13, 14], [1, 0], [0, 15], [15, 17], [0, 16], [16, 18],
    15. [2, 17], [5, 18], [14, 19], [19, 20], [14, 21], [11, 22],
    16. [22, 23], [11, 24]]
    17. map_idx_25 = [[26, 27], [40, 41], [48, 49], [42, 43], [44, 45], [50, 51],
    18. [52, 53], [32, 33], [28, 29], [30, 31], [34, 35], [36, 37],
    19. [38, 39], [56, 57], [58, 59], [62, 63], [60, 61], [64, 65],
    20. [46, 47], [54, 55], [66, 67], [68, 69], [70, 71], [72, 73],
    21. [74, 75], [76, 77]]
    22. colors_25 = [[255, 0, 0], [255, 85, 0], [255, 170, 0],
    23. [255, 255, 0], [170, 255, 0], [85, 255, 0],
    24. [0, 255, 0], [0, 255, 85], [0, 255, 170],
    25. [0, 255, 255], [0, 170, 255], [0, 85, 255],
    26. [0, 0, 255], [85, 0, 255], [170, 0, 255],
    27. [255, 0, 255], [255, 0, 170], [255, 0, 85],
    28. [255, 170, 85], [255, 170, 170], [255, 170, 255],
    29. [255, 85, 85], [255, 85, 170], [255, 85, 255],
    30. [170, 170, 170]]
    31. prototxt_18 = "./models/coco/pose_deploy_linevec.prototxt"
    32. caffemodel_18 = "./models/coco/pose_iter_440000.caffemodel"
    33. point_names_18 = ['Nose', 'Neck',
    34. 'R-Sho', 'R-Elb', 'R-Wr',
    35. 'L-Sho', 'L-Elb', 'L-Wr',
    36. 'R-Hip', 'R-Knee', 'R-Ank',
    37. 'L-Hip', 'L-Knee', 'L-Ank',
    38. 'R-Eye', 'L-Eye', 'R-Ear', 'L-Ear']
    39. point_pairs_18 = [[1, 2], [1, 5], [2, 3], [3, 4], [5, 6], [6, 7],
    40. [1, 8], [8, 9], [9, 10], [1, 11], [11, 12], [12, 13],
    41. [1, 0], [0, 14], [14, 16], [0, 15], [15, 17],
    42. [2, 17], [5, 16]]
    43. map_idx_18 = [[31, 32], [39, 40], [33, 34], [35, 36], [41, 42], [43, 44],
    44. [19, 20], [21, 22], [23, 24], [25, 26], [27, 28], [29, 30],
    45. [47, 48], [49, 50], [53, 54], [51, 52], [55, 56],
    46. [37, 38], [45, 46]]
    47. colors_18 = [[0, 100, 255], [0, 100, 255], [0, 255, 255],
    48. [0, 100, 255], [0, 255, 255], [0, 100, 255],
    49. [0, 255, 0], [255, 200, 100], [255, 0, 255],
    50. [0, 255, 0], [255, 200, 100], [255, 0, 255],
    51. [0, 0, 255], [255, 0, 0], [200, 200, 0],
    52. [255, 0, 0], [200, 200, 0], [0, 0, 0]]

    OpenPose

    predict.py(核心)

    1. import cv2
    2. import time
    3. import numpy as np
    4. import matplotlib.pyplot as plt
    5. from config import *
    6. class general_mulitpose_model(object):
    7. # 初始化 Pose keypoint_num: 25 or 18
    8. def __init__(self, keypoint_num):
    9. # 加载openpose模型
    10. def get_model(self):
    11. # 获取关键点
    12. def getKeypoints(self, probMap, threshold=0.1):
    13. # 获取有效点对
    14. def getValidPairs(self, output, detected_keypoints, width, height):
    15. # 连接有效点对,获取完整的人体骨骼图
    16. def getPersonwiseKeypoints(self, valid_pairs, invalid_pairs, keypoints_list):
    17. # 关键点连接后的可视化
    18. def vis_pose(self, img_file, personwiseKeypoints, keypoints_list):
    19. # 预测(推理)关键点
    20. def predict(self, imgfile):

    初始化

    1. def __init__(self, keypoint_num):
    2. self.point_names = point_name_25 if keypoint_num == 25 else point_names_18
    3. self.point_pairs = point_pairs_25 if keypoint_num == 25 else point_pairs_18
    4. self.map_idx = map_idx_25 if keypoint_num == 25 else map_idx_18
    5. self.colors = colors_25 if keypoint_num == 25 else colors_18
    6. self.num_points = 25 if keypoint_num == 25 else 18
    7. self.prototxt = prototxt_25 if keypoint_num == 25 else prototxt_18
    8. self.caffemodel = caffemodel_25 if keypoint_num == 25 else caffemodel_18
    9. self.pose_net = self.get_model()

    获取关键点

    1. def getKeypoints(self, probMap, threshold=0.1):
    2. mapSmooth = cv2.GaussianBlur(probMap, (3, 3), 0, 0)
    3. mapMask = np.uint8(mapSmooth > threshold)
    4. keypoints = []
    5. # find the blobs
    6. contours, hierarchy = cv2.findContours(mapMask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    7. for cnt in contours:
    8. blobMask = np.zeros(mapMask.shape)
    9. blobMask = cv2.fillConvexPoly(blobMask, cnt, 1)
    10. maskedProbMap = mapSmooth * blobMask
    11. _, maxVal, _, maxLoc = cv2.minMaxLoc(maskedProbMap)
    12. keypoints.append(maxLoc + (probMap[maxLoc[1], maxLoc[0]],))
    13. return keypoints

    获取有效点对

    1. def getValidPairs(self, output, detected_keypoints, width, height):
    2. valid_pairs = []
    3. invalid_pairs = []
    4. n_interp_samples = 15
    5. paf_score_th = 0.1
    6. conf_th = 0.7
    7. for k in range(len(self.map_idx)):
    8. # A -> B constitute a limb
    9. pafA = output[0, self.map_idx[k][0], :, :]
    10. pafB = output[0, self.map_idx[k][1], :, :]
    11. pafA = cv2.resize(pafA, (width, height))
    12. pafB = cv2.resize(pafB, (width, height))
    13. candA = detected_keypoints[self.point_pairs[k][0]]
    14. candB = detected_keypoints[self.point_pairs[k][1]]
    15. nA = len(candA)
    16. nB = len(candB)
    17. if (nA != 0 and nB != 0):
    18. valid_pair = np.zeros((0, 3))
    19. for i in range(nA):
    20. max_j = -1
    21. maxScore = -1
    22. found = 0
    23. for j in range(nB):
    24. # Find d_ij
    25. d_ij = np.subtract(candB[j][:2], candA[i][:2])
    26. norm = np.linalg.norm(d_ij)
    27. if norm:
    28. d_ij = d_ij / norm
    29. else:
    30. continue
    31. # Find p(u)
    32. interp_coord = list(
    33. zip(np.linspace(candA[i][0], candB[j][0], num=n_interp_samples),
    34. np.linspace(candA[i][1], candB[j][1], num=n_interp_samples)))
    35. # Find L(p(u))
    36. paf_interp = []
    37. for k in range(len(interp_coord)):
    38. paf_interp.append([pafA[int(round(interp_coord[k][1])), int(round(interp_coord[k][0]))],
    39. pafB[int(round(interp_coord[k][1])), int(round(interp_coord[k][0]))]])
    40. # Find E
    41. paf_scores = np.dot(paf_interp, d_ij)
    42. avg_paf_score = sum(paf_scores) / len(paf_scores)
    43. # check if the connection is valid
    44. # If the fraction of interpolated vectors aligned with PAF is higher then threshold -> Valid Pair
    45. if (len(np.where(paf_scores > paf_score_th)[0]) / n_interp_samples) > conf_th:
    46. if avg_paf_score > maxScore:
    47. max_j = j
    48. maxScore = avg_paf_score
    49. found = 1
    50. # Append the connection to the list
    51. if found:
    52. valid_pair = np.append(valid_pair, [[candA[i][3], candB[max_j][3], maxScore]], axis=0)
    53. # Append the detected connections to the global list
    54. valid_pairs.append(valid_pair)
    55. else: # If no keypoints are detected
    56. print("No Connection : k = {}".format(k))
    57. invalid_pairs.append(k)
    58. valid_pairs.append([])
    59. return valid_pairs, invalid_pairs

    连接有效点对,获取完整的人体骨骼图

    1. def getPersonwiseKeypoints(self, valid_pairs, invalid_pairs, keypoints_list):
    2. personwiseKeypoints = -1 * np.ones((0, self.num_points + 1))
    3. for k in range(len(self.map_idx)):
    4. if k not in invalid_pairs:
    5. partAs = valid_pairs[k][:, 0]
    6. partBs = valid_pairs[k][:, 1]
    7. indexA, indexB = np.array(self.point_pairs[k])
    8. for i in range(len(valid_pairs[k])):
    9. found = 0
    10. person_idx = -1
    11. for j in range(len(personwiseKeypoints)):
    12. if personwiseKeypoints[j][indexA] == partAs[i]:
    13. person_idx = j
    14. found = 1
    15. break
    16. if found:
    17. personwiseKeypoints[person_idx][indexB] = partBs[i]
    18. personwiseKeypoints[person_idx][-1] += keypoints_list[partBs[i].astype(int), 2] + \
    19. valid_pairs[k][i][2]
    20. elif not found and k < self.num_points - 1:
    21. row = -1 * np.ones(self.num_points + 1)
    22. row[indexA] = partAs[i]
    23. row[indexB] = partBs[i]
    24. row[-1] = sum(keypoints_list[valid_pairs[k][i, :2].astype(int), 2]) + \
    25. valid_pairs[k][i][2]
    26. personwiseKeypoints = np.vstack([personwiseKeypoints, row])
    27. return personwiseKeypoints

    关键点连接后的可视化

    1. def vis_pose(self, img_file, personwiseKeypoints, keypoints_list):
    2. img = cv2.imread(img_file)
    3. for i in range(self.num_points - 1):
    4. for n in range(len(personwiseKeypoints)):
    5. index = personwiseKeypoints[n][np.array(self.point_pairs[i])]
    6. if -1 in index:
    7. continue
    8. B = np.int32(keypoints_list[index.astype(int), 0])
    9. A = np.int32(keypoints_list[index.astype(int), 1])
    10. cv2.line(img, (B[0], A[0]), (B[1], A[1]), self.colors[i], 3, cv2.LINE_AA)
    11. plt.figure()
    12. plt.imshow(img[:, :, ::-1])
    13. plt.title('Results')
    14. plt.axis("off")
    15. plt.show()

    预测(推理)关键点

    import cv2 显示

    因为原始图像尺寸太大了,所以我resize了一下。

    1. def vis_pose(self, img_file, personwiseKeypoints, keypoints_list):
    2. img = cv2.imread(img_file)
    3. for i in range(self.num_points - 1):
    4. for n in range(len(personwiseKeypoints)):
    5. index = personwiseKeypoints[n][np.array(self.point_pairs[i])]
    6. if -1 in index:
    7. continue
    8. B = np.int32(keypoints_list[index.astype(int), 0])
    9. A = np.int32(keypoints_list[index.astype(int), 1])
    10. cv2.line(img, (B[0], A[0]), (B[1], A[1]), self.colors[i], 3, cv2.LINE_AA)
    11. img = cv2.resize(img, (480, 640))
    12. cv2.imshow("Results", img)
    13. cv2.waitKey(0)
    14. cv2.destroyAllWindows()

    import matplotlib.pyplot as plt 显示

    1. def predict(self, imgfile):
    2. img = cv2.imread(imgfile)
    3. height, width, _ = img.shape
    4. net_height = 368
    5. net_width = int((net_height / height) * width)
    6. start = time.time()
    7. in_blob = cv2.dnn.blobFromImage(
    8. img, 1.0 / 255, (net_width, net_height), (0, 0, 0), swapRB=False, crop=False)
    9. self.pose_net.setInput(in_blob)
    10. output = self.pose_net.forward()
    11. print("[INFO]Time Taken in Forward pass: {} ".format(time.time() - start))
    12. detected_keypoints = []
    13. keypoints_list = np.zeros((0, 3))
    14. keypoint_id = 0
    15. threshold = 0.1
    16. for part in range(self.num_points):
    17. probMap = output[0, part, :, :]
    18. probMap = cv2.resize(probMap, (width, height))
    19. keypoints = self.getKeypoints(probMap, threshold)
    20. print("Keypoints - {} : {}".format(self.point_names[part], keypoints))
    21. keypoint_with_id = []
    22. for i in range(len(keypoints)):
    23. keypoint_with_id.append(keypoints[i] + (keypoint_id,))
    24. keypoints_list = np.vstack([keypoints_list, keypoints[i]])
    25. keypoint_id += 1
    26. detected_keypoints.append(keypoint_with_id)
    27. valid_paris, invalid_pairs = self.getValidPairs(output, detected_keypoints, width, height)
    28. personwiseKeypoints = self.getPersonwiseKeypoints(valid_paris, invalid_pairs, keypoints_list)
    29. self.vis_pose(imgfile, personwiseKeypoints, keypoints_list)

    main.py

    1. if __name__ == '__main__':
    2. gmm = general_mulitpose_model(25)
    3. personwiseKeypoints, keypoints_list = gmm.predict("images/pose.jpg")

    完整代码

    1. import cv2
    2. import time
    3. import math
    4. import numpy as np
    5. from config import *
    6. class general_mulitpose_model(object):
    7. def __init__(self, keypoint_num):
    8. self.point_names = point_name_25 if keypoint_num == 25 else point_names_18
    9. self.point_pairs = point_pairs_25 if keypoint_num == 25 else point_pairs_18
    10. self.map_idx = map_idx_25 if keypoint_num == 25 else map_idx_18
    11. self.colors = colors_25 if keypoint_num == 25 else colors_18
    12. self.num_points = 25 if keypoint_num == 25 else 18
    13. self.prototxt = prototxt_25 if keypoint_num == 25 else prototxt_18
    14. self.caffemodel = caffemodel_25 if keypoint_num == 25 else caffemodel_18
    15. self.pose_net = self.get_model()
    16. def get_model(self):
    17. coco_net = cv2.dnn.readNetFromCaffe(self.prototxt, self.caffemodel)
    18. return coco_net
    19. def predict(self, imgfile):
    20. start = time.time()
    21. img = cv2.imread(imgfile)
    22. height, width, _ = img.shape
    23. net_height = 368
    24. net_width = int((net_height / height) * width)
    25. start = time.time()
    26. in_blob = cv2.dnn.blobFromImage(
    27. img, 1.0 / 255, (net_width, net_height), (0, 0, 0), swapRB=False, crop=False)
    28. self.pose_net.setInput(in_blob)
    29. output = self.pose_net.forward()
    30. print("[INFO]Time Taken in Forward pass: {} ".format(time.time() - start))
    31. detected_keypoints = []
    32. keypoints_list = np.zeros((0, 3))
    33. keypoint_id = 0
    34. threshold = 0.1
    35. for part in range(self.num_points):
    36. probMap = output[0, part, :, :]
    37. probMap = cv2.resize(probMap, (width, height))
    38. keypoints = self.getKeypoints(probMap, threshold)
    39. print("Keypoints - {} : {}".format(self.point_names[part], keypoints))
    40. keypoint_with_id = []
    41. for i in range(len(keypoints)):
    42. keypoint_with_id.append(keypoints[i] + (keypoint_id,))
    43. keypoints_list = np.vstack([keypoints_list, keypoints[i]])
    44. keypoint_id += 1
    45. detected_keypoints.append(keypoint_with_id)
    46. valid_paris, invalid_pairs = self.getValidPairs(output, detected_keypoints, width, height)
    47. personwiseKeypoints = self.getPersonwiseKeypoints(valid_paris, invalid_pairs, keypoints_list)
    48. img = self.vis_pose(imgfile, personwiseKeypoints, keypoints_list)
    49. FPS = math.ceil(1 / (time.time() - start))
    50. img = cv2.putText(img, "FPS" + str(int(FPS)), (25, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 3)
    51. return img
    52. def getKeypoints(self, probMap, threshold=0.1):
    53. mapSmooth = cv2.GaussianBlur(probMap, (3, 3), 0, 0)
    54. mapMask = np.uint8(mapSmooth > threshold)
    55. keypoints = []
    56. # find the blobs
    57. _, contours, hierarchy = cv2.findContours(mapMask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    58. for cnt in contours:
    59. blobMask = np.zeros(mapMask.shape)
    60. blobMask = cv2.fillConvexPoly(blobMask, cnt, 1)
    61. maskedProbMap = mapSmooth * blobMask
    62. _, maxVal, _, maxLoc = cv2.minMaxLoc(maskedProbMap)
    63. keypoints.append(maxLoc + (probMap[maxLoc[1], maxLoc[0]],))
    64. return keypoints
    65. def getValidPairs(self, output, detected_keypoints, width, height):
    66. valid_pairs = []
    67. invalid_pairs = []
    68. n_interp_samples = 15
    69. paf_score_th = 0.1
    70. conf_th = 0.7
    71. for k in range(len(self.map_idx)):
    72. # A -> B constitute a limb
    73. pafA = output[0, self.map_idx[k][0], :, :]
    74. pafB = output[0, self.map_idx[k][1], :, :]
    75. pafA = cv2.resize(pafA, (width, height))
    76. pafB = cv2.resize(pafB, (width, height))
    77. candA = detected_keypoints[self.point_pairs[k][0]]
    78. candB = detected_keypoints[self.point_pairs[k][1]]
    79. nA = len(candA)
    80. nB = len(candB)
    81. if (nA != 0 and nB != 0):
    82. valid_pair = np.zeros((0, 3))
    83. for i in range(nA):
    84. max_j = -1
    85. maxScore = -1
    86. found = 0
    87. for j in range(nB):
    88. # Find d_ij
    89. d_ij = np.subtract(candB[j][:2], candA[i][:2])
    90. norm = np.linalg.norm(d_ij)
    91. if norm:
    92. d_ij = d_ij / norm
    93. else:
    94. continue
    95. # Find p(u)
    96. interp_coord = list(
    97. zip(np.linspace(candA[i][0], candB[j][0], num=n_interp_samples),
    98. np.linspace(candA[i][1], candB[j][1], num=n_interp_samples)))
    99. # Find L(p(u))
    100. paf_interp = []
    101. for k in range(len(interp_coord)):
    102. paf_interp.append([pafA[int(round(interp_coord[k][1])), int(round(interp_coord[k][0]))],
    103. pafB[int(round(interp_coord[k][1])), int(round(interp_coord[k][0]))]])
    104. # Find E
    105. paf_scores = np.dot(paf_interp, d_ij)
    106. avg_paf_score = sum(paf_scores) / len(paf_scores)
    107. # check if the connection is valid
    108. # If the fraction of interpolated vectors aligned with PAF is higher then threshold -> Valid Pair
    109. if (len(np.where(paf_scores > paf_score_th)[0]) / n_interp_samples) > conf_th:
    110. if avg_paf_score > maxScore:
    111. max_j = j
    112. maxScore = avg_paf_score
    113. found = 1
    114. # Append the connection to the list
    115. if found:
    116. valid_pair = np.append(valid_pair, [[candA[i][3], candB[max_j][3], maxScore]], axis=0)
    117. # Append the detected connections to the global list
    118. valid_pairs.append(valid_pair)
    119. else: # If no keypoints are detected
    120. print("No Connection : k = {}".format(k))
    121. invalid_pairs.append(k)
    122. valid_pairs.append([])
    123. return valid_pairs, invalid_pairs
    124. def getPersonwiseKeypoints(self, valid_pairs, invalid_pairs, keypoints_list):
    125. personwiseKeypoints = -1 * np.ones((0, self.num_points + 1))
    126. for k in range(len(self.map_idx)):
    127. if k not in invalid_pairs:
    128. partAs = valid_pairs[k][:, 0]
    129. partBs = valid_pairs[k][:, 1]
    130. indexA, indexB = np.array(self.point_pairs[k])
    131. for i in range(len(valid_pairs[k])):
    132. found = 0
    133. person_idx = -1
    134. for j in range(len(personwiseKeypoints)):
    135. if personwiseKeypoints[j][indexA] == partAs[i]:
    136. person_idx = j
    137. found = 1
    138. break
    139. if found:
    140. personwiseKeypoints[person_idx][indexB] = partBs[i]
    141. personwiseKeypoints[person_idx][-1] += keypoints_list[partBs[i].astype(int), 2] + \
    142. valid_pairs[k][i][2]
    143. elif not found and k < self.num_points - 1:
    144. row = -1 * np.ones(self.num_points + 1)
    145. row[indexA] = partAs[i]
    146. row[indexB] = partBs[i]
    147. row[-1] = sum(keypoints_list[valid_pairs[k][i, :2].astype(int), 2]) + \
    148. valid_pairs[k][i][2]
    149. personwiseKeypoints = np.vstack([personwiseKeypoints, row])
    150. return personwiseKeypoints
    151. def vis_pose(self, img_file, personwiseKeypoints, keypoints_list):
    152. img = cv2.imread(img_file)
    153. for i in range(self.num_points - 1):
    154. for n in range(len(personwiseKeypoints)):
    155. index = personwiseKeypoints[n][np.array(self.point_pairs[i])]
    156. if -1 in index:
    157. continue
    158. B = np.int32(keypoints_list[index.astype(int), 0])
    159. A = np.int32(keypoints_list[index.astype(int), 1])
    160. cv2.line(img, (B[0], A[0]), (B[1], A[1]), self.colors[i], 3, cv2.LINE_AA)
    161. img = cv2.resize(img, (480, 640))
    162. return img
    163. if __name__ == '__main__':
    164. gmm = general_mulitpose_model(25)
    165. img = gmm.predict("images/pose.jpg")
    166. cv2.imshow("frame", img)
    167. cv2.waitKey(0)
    168. cv2.destroyAllWindows()

    运行结果

    cv2显示

    plt 显示


    2.实时视频

    因为之前都只是调用了openpose的模型并没有真正使用源码,所以现在真正使用,并且编译一下,其步骤为:

    1)配置文件3rdparty\windows

    将之前github上下载好的项目,找到位置打开,如我的位置:

    D:\PycharmProject\openpose-master

    进入"3rdparty",找到windows,双击四个.bat文件

    1. D:\PycharmProject\openpose-master\3rdparty\windows
    2. getCaffe.bat
    3. getCaffe3rdparty.bat
    4. getFreeglut.bat
    5. getOpenCV.bat

     

     2)配置文件3rdparty\caffe or pybind11

    进入官网的"3rdparty",找到caffe or pybind11

     将其git clone https://github.com/CMU-Perceptual-Computing-Lab/caffe.git 或者 下载.zip文件, 放到你文件所在的位置如:

    'D:\PycharmProject\openpose-master\3rdparty\caffe'

    将其git clone https://github.com/pybind/pybind11.git 或者 下载.zip文件,放到你文件所在的位置如:'D:\PycharmProject\openpose-master\3rdparty\pybind11'

    如图

    3)模型下载(之前已经介绍过了)

    1. cd openpose-master/models
    2. bash getModels.sh (Linux)
    3. 双击 getModels.bat (Windows)
    4. 下载 pose_iter_584000.caffemodel
    5. pose_iter_440000.caffemodel
    6. ...(还有hand,face的模型)

    4)Cmake编译

    首先下载cmake-gui:

    https://cmake.org/download/https://cmake.org/download/windows就下载.msi版本的

    之后就是将openpose-master编译

    第三行的build是自己取的名字,可以直接build或者其他build_CPU

     点击Add Entry,输入自己的Python路径,再点击OK!

     之后,点击“Configure“

    配置vs,你的vs要和你电脑的版本一样,可在 控制面板-> 程序 中查看

     完成之后,再点BUILD_PYTHON,DOWNLOAD_BODY_25_MODEL,DOWNLOAD_BODY_COCO_MODEL,DOWNLOAD_BODY_MPI_MODEL(hand,face也如果有用也选吧!)

     

    “GPU_MODE”选中“CPU_ONLY”,不选"USE_CUDNN";你也可以选择"CUDA",那之后必须选择“USE_CUDNN”

     点击“Configure”,等全部完成之后,点击“Generate”

    5)编译工程

    找到openpose-master/build/OpenPose.sln使用vs 2017打开,输入(release x64版本)点击绿色倒三角符号,等待结果

     如果成功这是下面这种状态,并且视频摄像头打开,openpose开始识别人体姿态与人!

     之后右键点击pyopenpose,设为启动项目

     之后结合,官网给的代码,仿照"openpose-master\build\examples\tutorial_api_python\01_body_from_image.py"来导入pyopenpose

    把官网给的openpose-master\build\bin 与 openpose-master\x64拷贝到自己的项目里面去

    把openpose-master\build\python\openpose\Release 导入自己的项目

    再把openpose-master\models中的 hand 和 face 还有 pose 导入自己的项目中去 


    代码

    尝试导入openpose,查看是否成功

    1. import os
    2. import sys
    3. from sys import platform
    4. BASE_DIR = os.path.dirname(os.path.realpath(__file__))
    5. if platform == 'win32':
    6. lib_dir = 'Release'
    7. bin_dir = 'bin'
    8. x64_dir = 'x64'
    9. lib_path = os.path.join(BASE_DIR, lib_dir)
    10. bin_path = os.path.join(BASE_DIR, bin_dir)
    11. x64_path = os.path.join(BASE_DIR, x64_dir)
    12. sys.path.append(lib_path)
    13. os.environ['PATH'] += ';' + bin_path + ';' + x64_path + '\Release;'
    14. try:
    15. import pyopenpose as op
    16. print("successful, import pyopenpose!")
    17. except ImportError as e:
    18. print("fail to import pyopenpose!")
    19. raise e
    20. else:
    21. print(f"当前电脑环境:\n{platform}\n")
    22. sys.exit(-1)

     查看结果


    实时视频核心代码

    1. # 处理数据
    2. datum = op.Datum()
    3. # 开始openpose
    4. opWrapper = op.WrapperPython()
    5. # 配置参数
    6. params = dict()
    7. params["model_folder"] = BASE_DIR + "\models"
    8. params["model_pose"] = "BODY_25"
    9. params["number_people_max"] = 3
    10. params["disable_blending"] = False
    11. # 导入参数
    12. opWrapper.configure(params)
    13. opWrapper.start()
    14. ...

    1. ...
    2. # 处理图像
    3. # 输入图像frame打入datum.cvInputData
    4. datum.cvInputData = frame
    5. # 处理输入图像
    6. opWrapper.emplaceAndPop(op.VectorDatum([datum]))
    7. # 输出图像为opframe
    8. opframe = datum.cvOutputData
    9. ....

     完整代码

    1. import os
    2. import time
    3. import cv2
    4. import sys
    5. from tqdm import tqdm
    6. from sys import platform
    7. BASE_DIR = os.path.dirname(os.path.realpath(__file__))
    8. if platform == 'win32':
    9. lib_dir = 'Release'
    10. bin_dir = 'bin'
    11. x64_dir = 'x64'
    12. lib_path = os.path.join(BASE_DIR, lib_dir)
    13. bin_path = os.path.join(BASE_DIR, bin_dir)
    14. x64_path = os.path.join(BASE_DIR, x64_dir)
    15. sys.path.append(lib_path)
    16. os.environ['PATH'] += ';' + bin_path + ';' + x64_path + '\Release;'
    17. try:
    18. import pyopenpose as op
    19. print("successful, import pyopenpose!")
    20. except ImportError as e:
    21. print("fail to import pyopenpose!")
    22. raise e
    23. else:
    24. print(f"当前电脑环境:\n{platform}\n")
    25. sys.exit(-1)
    26. def out_video(input):
    27. datum = op.Datum()
    28. opWrapper = op.WrapperPython()
    29. params = dict()
    30. params["model_folder"] = BASE_DIR + "\models"
    31. params["model_pose"] = "BODY_25"
    32. params["number_people_max"] = 3
    33. params["disable_blending"] = False
    34. opWrapper.configure(params)
    35. opWrapper.start()
    36. file = input.split("/")[-1]
    37. output = "video/out-optim-" + file
    38. print("It will start processing video: {}".format(input))
    39. cap = cv2.VideoCapture(input)
    40. frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    41. frame_size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
    42. # create VideoWriter,VideoWriter_fourcc is video decode
    43. fourcc = cv2.VideoWriter_fourcc('D', 'I', 'V', 'X')
    44. fps = cap.get(cv2.CAP_PROP_FPS)
    45. out = cv2.VideoWriter(output, fourcc, fps, frame_size)
    46. # the progress bar
    47. with tqdm(range(frame_count)) as pbar:
    48. while cap.isOpened():
    49. start = time.time()
    50. success, frame = cap.read()
    51. if success:
    52. datum.cvInputData = frame
    53. opWrapper.emplaceAndPop(op.VectorDatum([datum]))
    54. opframe = datum.cvOutputData
    55. FPS = 1 / (time.time() - start)
    56. opframe = cv2.putText(opframe, "FPS" + str(int(FPS)), (25, 50), cv2.FONT_HERSHEY_SIMPLEX, 1,
    57. (0, 255, 0), 3)
    58. out.write(opframe)
    59. pbar.update(1)
    60. else:
    61. break
    62. pbar.close()
    63. cv2.destroyAllWindows()
    64. out.release()
    65. cap.release()
    66. print("{} finished!".format(output))
    67. if __name__ == "__main__":
    68. video_dir = "video/2.avi"
    69. out_video(video_dir)

    运行结果

    OpenPose运行结果

    效果比之前的MediaPipe好很多


    参考:

    工程实现 || 基于opencv使用openpose完成人体姿态估计https://blog.csdn.net/magic_ll/article/details/108451560?spm=1001.2014.3001.5506openpose从安装到实战全攻略!(win10)https://zhuanlan.zhihu.com/p/500651669

  • 相关阅读:
    二叉搜索树的实现
    Data-free NAS
    ES6中Promise用法(封装Ajax)
    节假日和汉语拼音接口
    通过uboot命令开启核隔离
    AJAX概念
    【ASP.NET Core】标记帮助器——替换元素名称
    【毕业设计】基于javaEE+SSH+SQL Server的学生信息管理系统设计与实现(毕业论文+程序源码)——学生信息管理系统
    给女生说一些关于软件测试职场的一些真实的建议~
    金蝶云星空企业版v8.0内网穿透配置详解:实现便捷的异地远程访问
  • 原文地址:https://blog.csdn.net/XiaoyYidiaodiao/article/details/125565738