如何在OpenCV中使用OpenPose获得单个身体部位的大小?

问题描述

我正在使用Virtual Dressing平台。我想从图像中获取一个人的尺寸。我已经实现了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],5],[2,3],[3,4],[5,6],[6,7],8],[8,9],[9,10],11],[11,12],[12,13],[0,14],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),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,255,255),thickness=-1,lineType=cv2.FILLED)
        cv2.putText(framecopy,"{}".format(i),cv2.FONT_HERShey_SIMPLEX,1,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],2)
        cv2.circle(frame,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) 

Here's the output

谁能告诉我如何前进?

解决方法

实际上,您的问题并不简单。

通常,您将有多种选择来执行此操作,我将仅向您描述int抽象步骤以及如何实现此目标。有些方法需要更多的工作量,有些则不够精确。到目前为止,我已经成功使用了变体A。

变体A)

设置:

您使用1倍相机,而您的人正好位于2D平面的前面。您的相机与2d表面(背景)的固定距离和角度应始终相同。我们必须假设人是平坦的,并使用针孔照相机概念。您可以执行以下处理步骤

处理:

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

StepA2)为您的人做一张照片,进行镜头矫正

StepA3)通过“打开姿势框架”计算“身体点”

StepA4)使用inverse homography使用来自步骤A1)的相机校准数据将点从“像素空间”投影到“真实世界”空间 现在计算以毫米/或厘米为单位的欧几里得距离(在校准xml文件中定义)。 此步骤假定我们将点投影在100%的平面2D曲面上,因为此处的z维度设置为零,否则计算要复杂得多,但也可以这样做。 我添加了small code example to my github account as example

变体B:

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

变体C:

设置:

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

步骤:

StepC1)看到一个良好的校准槽here

StepC2)使用3D重建进行距离计算。 Here is the detailed idea and some code

变体D:

使用3D扫描仪或Kinect系统(a paper which shows the kinect way way