opencv 获取摄像机Z轴和ArUco标记Z轴之间的Angular

qnyhuwrf  于 2023-11-22  发布在  Angular
关注(0)|答案(2)|浏览(117)

我感兴趣的是计算定义相机Z轴的矢量与ArUco标记Z轴之间的Angular 。
为此,我首先检测图像中的ArUco标记:

corners, ids, rvec, tvec = aruco_utils.get_aruco_marker_info(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), marker_length, camera_matrix, dist_coeffs)

字符串
我创建了转换矩阵来转换相机坐标系和标记坐标系之间的坐标:

M        = np.zeros((4,4))
M[:3,:3] = cv2.Rodrigues(rvec)[0]
M[:3,3]  = tvec[0].T
M[3,3]   = 1

marker_to_camera_matrix = np.matrix(M)
camera_to_marker_matrix = np.linalg.inv(marker_to_camera_matrix)


我将Z相机轴转换为标记坐标系:

coord_z = np.array([0,0,1, 1])
coord_z = np.dot(camera_to_marker_matrix, coord_z)


最后我计算了angle between,平移矢量和标记的Z轴:

camera_z_proj = np.array(coord_z)[0][:3]
camera_z_proj = camera_z_proj / np.linalg.norm(camera_z_proj)
marker_z_proj = np.array([0,0,1])

dot_product = np.dot(camera_z_proj, marker_z_proj)

# Calculate the angle in radians
angle_radians = np.arccos(dot_product)

# Convert the angle from radians to degrees
angle_degrees = np.degrees(angle_radians)


然而,这个解决方案不起作用,因为我为具有不同方向的不同标记计算了这个Angular ,最终结果是一个非常相似的Angular 。


的数据
在每一种情况下,即使我下载一个合成的ArUco标记(不是一个真实的照片),这个Angular 总是在70º左右。



有什么线索我做错了什么吗?
我希望找到相机坐标系的Z轴和ArUco坐标系的Z轴之间的Angular 。

z9smfwbn

z9smfwbn1#

你的问题是当你应该处理向量的时候,你处理了点。回顾你的代码,找出发生这种情况的地方。提示:任何你处理四维向量的地方。
两个Z轴之间的Angular 需要通过在标记空间中创建一个值为(0,0,1)的向量来计算,将其从标记帧转换到相机空间(至少应用旋转;平移对向量无关紧要),然后使用一点矩阵/线性代数(点积)计算其相对于向量(0,0,1)的Angular 。
可以通过首先使用Rodrigues()rvec计算旋转矩阵,然后将该矩阵与向量相乘来应用旋转。
这可以通过取旋转矩阵的第三列来简化,这是乘法的结果。
然后你可以用点积或叉积来计算这个Angular ,这两个向量已经是单位长度的了,这会使数学更简单。

wixjitnu

wixjitnu2#

我遇到的主要问题来自相机校准。它是使用普通棋盘完成的,这主要导致对ArUco标记的Z轴的错误估计。在使用ChArUco棋盘校准相机后,这种估计得到了改善。
最后,我计算标记轴(使用其旋转向量rvec)与类似相机标记(image_plane_vector)之间的Angular :

R = cv2.Rodrigues(rvec)[0]
pt = np.dot(R, image_plane_vector)
angle_radians, angle_degrees = angle_between_two_vectors(pt, image_plane_vector)

字符串
Angular 计算如下:

def angle_between_two_vectors(v1, v2):
    v1, v2 = np.array(v1), np.array(v2)
    if len(v1.shape) > 1: v1 = v1[0]
    if len(v2.shape) > 1: v2 = v2[0]
    v1, v2 = v1[:3], v2[:3]
    assert v1.shape == (3,) and v2.shape == (3,)
    v1 = v1 / np.linalg.norm(v1)  # Normalize the normal vector
    v2 = v2 / np.linalg.norm(v2)  # Normalize the normal vector
    dot_product = np.dot(v1, v2)
    angle_radians = np.arccos(dot_product)
    angle_degrees = np.degrees(angle_radians)
    return angle_radians, angle_degrees


下面是在新的相机校准后使用此代码进行计算的一些结果。文本描述符包括括号[ang_x, and_y, ang_z]每个轴(X,Y,Z)与标记的Angular (以度为单位)。它们与相机的类似Angular 。最终值对应于归一化到范围[0,90]º的Z角。
Image 1
Image 2
Image 3

相关问题