OpenCV triangulatePoints() 得到负深度,我做错了什么?

问题描述

因此该设置给出了如下所示的坐标系,其中 z 轴指向屏幕外(朝向您),相机焦距为 270 像素,图像分辨率为 {{ 1}},那么我们在 3D 空间的某个地方有一个物体,两个无人机 640x480d1 在两个不同的视点进行两次观察,其中 d2 位于 d1物体对应的图像坐标为(6,3,2)(320,280)的坐标为d2(9.5,4.5,3)(160,408)标题为{{1} } 与 d1 轴的度数和 -20 的度数是 y 轴的 d2 度,目标是确定 +30 对象所在的位置,无人机悬停在 y 平面

Click Here for Image Illustration

给定信息,通过让(x,y,z)作为参考系,我们可以得到相机内在函数xy,变换是用d1轴旋转K = [[270,320],[0,270,240],1]]度为旋转轴和平移 +50,因此我的代码

z

这给你一个齐次坐标 t = [3.5,1.5,1],其中 import numpy as np import cv2 def pixel2cam(pt,K): u = (pt[0] - K[0][2]) / K[0][0] v = (pt[1] - K[1][2]) / K[1][1] return np.array([u,v],dtype=np.float32) def triangulate(points_1,points_2,K,R,t): cam_pts_1 = pixel2cam(points_1,K).reshape(2,1) cam_pts_2 = pixel2cam(points_2,1) T1 = np.array([[1,0],1,0]],dtype=np.float32) T2 = np.hstack((R,t)) X = cv2.triangulatePoints(T1,T2,cam_pts_1,cam_pts_2) X /= X[3] return X K = np.array([[270,1]],dtype=np.float32) # rotate +50 degrees along z axis R = np.array([[0.643,-0.766,[0.766,0.643,dtype=np.float32) t = np.array([[3.5],[1.5],[1]],dtype=np.float) pt_1 = (320,280) pt_2 = (160,408) X = triangulate(pt_1,pt_2,t) 是负数,所以我的问题是

  • 我在此处正确地表述了 X = [[-2.4155867],[ -5.1455526],[-12.032189],[1.]])z 吗?
  • 如果是,那么错误可能是由于此处使用的相机坐标系与 R 中的不同吗?

感谢任何帮助!

解决方法

我在您的代码中看到多个问题。我将尝试在下面的不同部分中一一检查它们。

OpenCV 点三角剖分

首先,OpenCV cv2.triangulatePoints() 将投影矩阵从世界坐标转换为像素坐标,以及图像上世界点的像素坐标。请参阅 cv2.triangulatePoints() documentation。您还可以在 this page 的“详细描述”部分阅读 OpenCV 投影背后的数学原理。

这是您的 triangulate() 函数的更正版本:

def triangulate(points_1,points_2,K,R,t):
    T1 = np.array([[1,0],[0,1,0]],dtype=np.float32)
    T2 = np.hstack((R,t))
    proj1 = np.matmul(K,T1)
    proj2 = np.matmul(K,T2)
    X = cv2.triangulatePoints(proj1,proj2,points_1,points_2)
    X /= X[3]
    return X

旋转矩阵

在 OpenCV 坐标系中,相机的 z 轴是光轴(参见 this answer 中的图表)。绕 z 轴旋转与您在问题中链接的图像不匹配,绕 y 轴旋转 -50 度似乎更正确。

您可以使用 cv2.Rodrigues() 重新计算旋转矩阵。请注意,此函数以弧度表示角度,请参阅 documentation

rotation_vector = np.array([0,-50 / 180 * np.pi,0])
R,_ = cv2.Rodrigues(rotation_vector)

单位

你说你的焦点是以像素为单位的。查看数据,我非常怀疑焦距和平移值是否一致,至少如果它们以像素表示的话。我看到两种可能性:

  • 数据是正确的,但您在写问题时误解了焦距的单位。在这种情况下,忘记了本节的其余部分;
  • 您问题中所述的单位是正确的,并且您正在尝试使用不一致的数据对点进行三角测量。

要解决此问题,请确保焦距和平移均以像素或相同的距离单位表示。您可以通过相机的像素间距进行从像素到距离单位的转换,并通过乘以像素间距来进行从距离单位到像素的转换。像素间距应写在您使用的相机型号的数据表中。

结果

应用上述三个修正后,我得到了一个 X 向量,它的 z 坐标为正。不过,我获得的值并没有多大意义,因为我不确定数据的正确值和单位。