如何使用 OpenCV 绘制 3D 坐标轴进行人脸姿势估计?
How to draw 3D Coordinate Axes with OpenCV for face pose estimation?
假设我有面部欧拉角(俯仰、偏航、滚动)。如何绘制显示面部姿势的3D坐标轴?
这是来自 here 的示例:
这可以在纯 OpenCV 中完成,只要您有相机参数。您应该能够创建对应于轴 x、y、z 的三个向量(基本上点 [0,0,0] [1, 0, 0], [0, 1, 0], [0, 0, 1] 哪个您稍后将投影到图像平面中。您应该首先根据 yaw/pitch/roll 旋转这些点(例如,将它们乘以旋转矩阵)。
为了将 3D 点投影到图像平面,请使用 projectPoints function. It takes 3D points, camera parameters and generates 2D image points. Once you have the image points, you can simply use the line 函数在投影的中心点(3D 中的 [0,0,0])和每个生成的投影之间画线轴点。
一个简单的例子:
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
上面给出的代码的一些说明
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
假设我有面部欧拉角(俯仰、偏航、滚动)。如何绘制显示面部姿势的3D坐标轴?
这是来自 here 的示例:
这可以在纯 OpenCV 中完成,只要您有相机参数。您应该能够创建对应于轴 x、y、z 的三个向量(基本上点 [0,0,0] [1, 0, 0], [0, 1, 0], [0, 0, 1] 哪个您稍后将投影到图像平面中。您应该首先根据 yaw/pitch/roll 旋转这些点(例如,将它们乘以旋转矩阵)。
为了将 3D 点投影到图像平面,请使用 projectPoints function. It takes 3D points, camera parameters and generates 2D image points. Once you have the image points, you can simply use the line 函数在投影的中心点(3D 中的 [0,0,0])和每个生成的投影之间画线轴点。
一个简单的例子:
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
上面给出的代码的一些说明
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