为了将3D点投影到图像平面,请使用projectPoints函数。它使用3D点、相机参数并生成2D图像点。一旦您获得了图像点,您只需使用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, yaw, pitch, roll, tdx=None, tdy=None, size = 100):
pitch = pitch * np.pi / 180
yaw = -(yaw * np.pi / 180)
roll = roll * np.pi / 180
if tdx != None and tdy != None:
tdx = tdx
tdy = tdy
else:
height, width = img.shape[:2]
tdx = width / 2
tdy = height / 2
# X-Axis pointing to right. drawn in red
x1 = size * (math.cos(yaw) * math.cos(roll)) + tdx
y1 = size * (math.cos(pitch) * math.sin(roll) + math.cos(roll) * math.sin(pitch) * math.sin(yaw)) + tdy
# Y-Axis | drawn in green
# v
x2 = size * (-math.cos(yaw) * math.sin(roll)) + tdx
y2 = size * (math.cos(pitch) * math.cos(roll) - math.sin(pitch) * math.sin(yaw) * math.sin(roll)) + tdy
# Z-Axis (out of the screen) drawn in blue
x3 = size * (math.sin(yaw)) + tdx
y3 = size * (-math.cos(yaw) * math.sin(pitch)) + tdy
cv2.line(img, (int(tdx), int(tdy)), (int(x1),int(y1)),(0,0,255),3)
cv2.line(img, (int(tdx), int(tdy)), (int(x2),int(y2)),(0,255,0),3)
cv2.line(img, (int(tdx), int(tdy)), (int(x3),int(y3)),(255,0,0),3)
return img
也可以使用OpenCV函数drawFrameAxes来实现此功能。
scale = 0.1
img = cv2.drawFrameAxes(img, K, distortion, rotation_vec, translation_vec, scale)
上面给出的代码有些需要澄清的地方
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