如何在 OpenCV 中使用 OpenPose 获取单个 body 部分的大小?

How to get the size of individual body parts using OpenPose in OpenCV?

我正在开发虚拟着装平台。我想从图像中获取一个人的尺寸。我已经实现了 OpenPose 并且能够获得一个人的骨架但是我不知道如何获得单个 body 部分的测量值?

下面是使用OpenPose、OpenCV获取Skeleton的代码

get_skeleton_op.py

import cv2 
import time
import numpy as np


protoFile = "pose/coco/pose_deploy_linevec.prototxt"
weightsFile = "pose/coco/pose_iter_440000.caffemodel"
nPoints = 18
POSE_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]]


frame = cv2.imread("./fatguy.jpg")
frameCopy = np.copy(frame)
frameWidth = frame.shape[1]
frameHeight = frame.shape[0]
threshold = 0.1 

net = cv2.dnn.readNetFromCaffe(protoFile, weightsFile)

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(output)
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 image
    x = (frameWidth * point[0]) / W 
    y = (frameHeight * point[1]) / H 

    if 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 threshold
        points.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('Output-Keypoints', frameCopy)
cv2.imshow('Output-Skeleton', frame)


cv2.imwrite('Output-Keypoints.jpg', frameCopy)
cv2.imwrite('Output-Skeleton.jpg', frame)

print("Total time taken : {:.3f}".format(time.time() - t)) 

cv2.waitKey(0) 

谁能告诉我如何前进?

其实你的问题不简单。

一般来说,您会有多种选择,我将只向您描述抽象步骤,您如何实现这一点。有些方法的工作量更大,有些则不太精确。到目前为止,我已成功使用变体 A。

变体 A)

设置:

你使用 1x 相机,你的人直接在平面 2D 表面前面。您的相机与 2d 表面(背景)的距离和角度应始终相同。我们必须假设人是平的,并使用针孔相机的概念。您可以进行以下处理步骤

处理中:

步骤 A1) 通过打印的 2D 图案(棋盘或其他..)做一个 camera calibration 重要的是你的图案在你的背景上总是尽可能平坦。在背景的不同点上生成多个图像,并尝试覆盖完整的可见区域 space。 使用 camera_calibration 的 opencv 示例进行姿势估计(估计到相机的位置和距离)和镜头校正 link to code example。 您应该事先编辑配置 xml 文件,定义您使用的图案以及您使用的平方尺寸(以毫米或厘米为单位)。

StepA2) 拍摄人物照片,进行镜头校正

StepA3) 通过Open-Pose-Framework

计算“body-points”

StepA4) 使用 inverse homography 将你的点从“像素 space” 投影到“真实世界” space 使用你的 camera-calibration 步骤中的数据A1) 现在以 mm / 或 cm 为单位计算欧氏距离(在校准 xml 文件中定义)。 此步骤假设我们将点投影到 100% 的平面二维表面上,因为我们的 z-dimension 在这里设置为零,否则计算要复杂得多,但也可以这样做。 我添加了一个small code example to my github account as example

变体 B:

在你的图片中使用一个易于检测的已知几何形状的“对象”,它决定了某种比较器的大小。您还必须知道一些相机参数,例如焦距。我找到了一个 good step-by-step tutorial here,其中还包括一些数学背景。

变体 C:

设置:

使用 2 个或更多相机和 3D 重建。这可能会导致更高的准确性。而且这个人现在可以站在你相机领域的任何地方。

步骤:

StepC1) 看校准好walk-troughhere

StepC2) 使用3D重建进行距离计算。 这是 详细的想法和一些代码

变体 D:

使用 3D 扫描仪或 Kinect-System(a paper which shows the kinect way way )