2

我正在开发一个虚拟穿衣平台。我想从图像中获得一个人的测量值。我已经实现了 OpenPose 并且能够获得一个人的骨架但是我不知道如何获得单个身体部位的测量值?

这是使用 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) 

这是输出

谁能告诉我如何前进?

4

1 回答 1

2

实际上,您的问题并非微不足道。

通常,您将有多种选择,我将仅向您描述抽象的步骤,以及如何实现这一目标。有些方法工作量更大,有些方法不太精确。到目前为止,我成功地使用了变体 A。

变体 A)

设置:

您使用 1x 摄像头,您的人就在一个平面 2D 表面的正前方。您的相机应该始终与 2d 表面(背景)具有相同的固定距离和角度。我们必须假设人是平的并使用针孔相机的概念。您可以执行以下处理步骤

加工:

步骤 A1)通过打印的 2D 图案(棋盘或其他图案)进行相机校准。它的含义是您的图案在背景上始终尽可能平坦。在背景的不同点生成多个图像,并尝试覆盖整个可见空间。使用 camera_calibration 的 opencv 示例进行姿势估计(估计到相机的位置和距离),并使用镜头校正 链接到代码示例。您应该事先编辑 config xml 文件,定义您使用的模式以及您使用的以 mm 或 cm 为单位的正方形大小。

StepA2) 拍人像,进行镜头校正

StepA3) 通过 Open-Pose-Framework 计算“身体点”

StepA4)使用逆单应性,使用步骤 A1 中的相机校准数据将点从“像素空间”投影到“真实世界”空间)现在以 mm / 或 cm 为单位计算欧几里得距离(在校准 xml 文件中定义)。此步骤假设我们将点投影在 100% 平坦的 2D 表面上,因为我们的 z 维度在此处设置为零,否则计算要复杂得多,但也可以这样做。我在我的 github 帐户中添加了一个小代码示例作为示例

变体 B:

在图片中使用易于检测的已知几何形状的“对象”,该对象将大小确定为某种比较器。您还必须知道一些相机参数,例如焦距。我在这里找到了一个很好的分步教程,其中还包括一些数学背景。

变体 C:

设置:

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

脚步:

StepC1)在此处查看良好的校准走槽

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

变体 D:

使用 3D 扫描仪或 Kinect 系统(显示 kinect 方式的论文

于 2020-09-14T15:49:15.200 回答