如何使用 OpenCV 绘制 3D 坐标轴以进行人脸姿态估计?

Posted

技术标签:

【中文标题】如何使用 OpenCV 绘制 3D 坐标轴以进行人脸姿态估计?【英文标题】:How to draw 3D Coordinate Axes with OpenCV for face pose estimation? 【发布时间】:2015-07-24 07:21:30 【问题描述】:

假设我有面部欧拉角(俯仰、偏航、滚动)。如何绘制显示人脸姿势的 3D 坐标轴?

这是来自here的示例:

【问题讨论】:

为什么不直接从您的链接中获取代码? 我不想用OpenGL来绘制结果。 将 3D 轴创建为顶点/向量。对它们应用旋转。将它们投影到您的相机/图像平面 没有。阅读有关相机模型、计算机图形学、渲染管道、相机投影的信息。如果您想要简单的方法,请使用 OpenGL。如果没有,请学习并理解它是如何完成的(仅投影简单的线条不会太难)。 - opencv 有一些功能可以帮助您建立相机模型并转换您的顶点,但您必须了解您想要做什么以及如何实现它。 - en.wikipedia.org/wiki/3D_projection 按照@Micka 的建议去做。如果你不想使用 OpenGL,那你想要什么?你想使用 OpenCV 吗? 【参考方案1】:

对上面给出的代码的一些说明

def draw_axis(img, rotation_vec, t, K, scale=0.1, dist=None):
    """
    Draw a 6dof axis (XYZ -> RGB) in the given rotation and translation
    :param img - rgb numpy array
    :rotation_vec - euler rotations, numpy array of length 3,
                    use cv2.Rodrigues(R)[0] to convert from rotation matrix
    :t - 3d translation vector, in meters (dtype must be float)
    :K - intrinsic calibration matrix , 3x3
    :scale - factor to control the axis lengths
    :dist - optional distortion coefficients, numpy array of length 4. If None distortion is ignored.
    """
    img = img.astype(np.float32)
    dist = np.zeros(4, dtype=float) if dist is None else dist
    points = scale * np.float32([[1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0]]).reshape(-1, 3)
    axis_points, _ = cv2.projectPoints(points, rotation_vec, t, K, dist)
    img = cv2.line(img, tuple(axis_points[3].ravel()), tuple(axis_points[0].ravel()), (255, 0, 0), 3)
    img = cv2.line(img, tuple(axis_points[3].ravel()), tuple(axis_points[1].ravel()), (0, 255, 0), 3)
    img = cv2.line(img, tuple(axis_points[3].ravel()), tuple(axis_points[2].ravel()), (0, 0, 255), 3)
    return img

【讨论】:

【参考方案2】:

一个简单的例子:

def draw_axis(img, R, t, K):
    # unit is mm
    rotV, _ = cv2.Rodrigues(R)
    points = np.float32([[100, 0, 0], [0, 100, 0], [0, 0, 100], [0, 0, 0]]).reshape(-1, 3)
    axisPoints, _ = cv2.projectPoints(points, rotV, t, K, (0, 0, 0, 0))
    img = cv2.line(img, tuple(axisPoints[3].ravel()), tuple(axisPoints[0].ravel()), (255,0,0), 3)
    img = cv2.line(img, tuple(axisPoints[3].ravel()), tuple(axisPoints[1].ravel()), (0,255,0), 3)
    img = cv2.line(img, tuple(axisPoints[3].ravel()), tuple(axisPoints[2].ravel()), (0,0,255), 3)
    return img

【讨论】:

请问您的示例中的 R、t 和 K 是什么? @juerg cs.cmu.edu/~16385/s17/Slides/11.1_Camera_matrix.pdf 在第30页。它们是相机矩阵的分解 R 可以是任意 3d 旋转矩阵。【参考方案3】:

只要您有相机参数,这可以在纯 OpenCV 中完成。您应该能够创建对应于轴 x、y、z 的三个向量(基本上是点 [0,0,0] [1, 0, 0], [0, 1, 0], [0, 0, 1]您稍后将投影到图像平面中。您应该首先根据您的偏航/俯仰/滚动旋转这些点(例如通过将它们乘以旋转矩阵)。

要将 3D 点投影到图像平面,请使用 projectPoints 函数。它采用 3D 点、相机参数并生成 2D 图像点。获得图像点后,您可以简单地使用line 函数在投影中心点(3D 中的 [0,0,0])和轴点的每个生成投影之间绘制线。

【讨论】:

以上是关于如何使用 OpenCV 绘制 3D 坐标轴以进行人脸姿态估计?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 OpenCV 中计算点的 3D 坐标

绘制 3D 非正交坐标

对象跟踪openCV,问题,建议?

如何从 3d 对象文件中获取 3d 坐标。

opencv建立数学坐标系绘制函数曲线

opencv建立数学坐标系绘制函数曲线