OpenCV OpenPose 手部关键点识别
从 HuggingFace 下载模型文件 models_hand_pose_deploy.prototxt
和 pose_iter_102000.caffemodel
,然后放到同一目录下。
可参考官方 GitHub 来安装 OpenPose。本示例未使用 OpenPose 库,仅使用 OpenCV 和 OpenPose 官方提供的模型文件。
py
import time
import cv2
import numpy as np
proto_file = "models_hand_pose_deploy.prototxt"
weights_file = "pose_iter_102000.caffemodel"
n_points = 22
POSE_PAIRS = [
[0, 1],
[1, 2],
[2, 3],
[3, 4],
[0, 5],
[5, 6],
[6, 7],
[7, 8],
[0, 9],
[9, 10],
[10, 11],
[11, 12],
[0, 13],
[13, 14],
[14, 15],
[15, 16],
[0, 17],
[17, 18],
[18, 19],
[19, 20],
]
threshold = 0.2
cap = cv2.VideoCapture(0)
has_frame, frame = cap.read()
frame_width = frame.shape[1]
frame_height = frame.shape[0]
aspect_ratio = frame_width / frame_height
in_height = 368
in_width = int(((aspect_ratio * in_height) * 8) // 8)
net = cv2.dnn.readNetFromCaffe(proto_file, weights_file)
k = 0
while cap.isOpened():
k += 1
t = time.time()
has_frame, frame = cap.read()
frame_copy = np.copy(frame)
if not has_frame:
cv2.waitKey()
break
inp_blob = cv2.dnn.blobFromImage(
frame, 1.0 / 255, (in_width, in_height), (0, 0, 0), swapRB=False, crop=False
)
net.setInput(inp_blob)
output = net.forward()
print("forward = {}".format(time.time() - t), end=", ")
points = []
for i in range(n_points):
prob_map = output[0, i, :, :]
prob_map = cv2.resize(prob_map, (frame_width, frame_height))
min_val, prob, min_loc, point = cv2.minMaxLoc(prob_map)
if prob > threshold:
cv2.circle(
frame_copy,
(int(point[0]), int(point[1])),
6,
(0, 255, 255),
thickness=-1,
lineType=cv2.FILLED,
)
cv2.putText(
frame_copy,
"{}".format(i),
(int(point[0]), int(point[1])),
cv2.FONT_HERSHEY_SIMPLEX,
0.8,
(0, 0, 255),
2,
lineType=cv2.LINE_AA,
)
points.append((int(point[0]), int(point[1])))
else:
points.append(None)
for pair in POSE_PAIRS:
part_a = pair[0]
part_b = pair[1]
if points[part_a] and points[part_b]:
cv2.line(
frame,
points[part_a],
points[part_b],
(0, 255, 255),
2,
lineType=cv2.LINE_AA,
)
cv2.circle(
frame, points[part_a], 5, (0, 0, 255), thickness=-1, lineType=cv2.FILLED
)
cv2.circle(
frame, points[part_b], 5, (0, 0, 255), thickness=-1, lineType=cv2.FILLED
)
cv2.imshow("webcam", frame)
print("total = {}".format(time.time() - t))
key = cv2.waitKey(1)
if key == 27:
break
cap.release()
cv2.destroyAllWindows()