OpenCV - 立体视觉的倾斜相机和三角测量地标

Posted

技术标签:

【中文标题】OpenCV - 立体视觉的倾斜相机和三角测量地标【英文标题】:OpenCV - Tilted camera and triangulation landmark for stereo vision 【发布时间】:2016-07-02 06:48:58 【问题描述】:

我正在使用立体系统,因此我试图通过三角测量获得一些点的世界坐标。

我的相机呈现一个角度,Z 轴方向(深度方向)不垂直于我的表面。这就是为什么当我观察平面时,我没有得到恒定的深度而是“线性”变化,对吗?我想要基线方向的深度......我如何重新投影?

我的投影数组和三角函数的一段代码:

#C1 and C2 are the cameras matrix (left and rig)
#R_0 and T_0 are the transformation between cameras
#Coord1 and Coord2 are the correspondant coordinates of left and right respectively
P1 = np.dot(C1,np.hstack((np.identity(3),np.zeros((3,1))))) 

P2 =np.dot(C2,np.hstack(((R_0),T_0)))

for i in range(Coord1.shape[0])
    z = cv2.triangulatePoints(P1, P2, Coord1[i,],Coord2[i,])

-------- 稍后编辑 -----------

感谢 scribbleink,所以我尝试应用您的建议。但我认为我有一个错误,因为它不能很好地工作,如下所示。并且点云似乎向图像边缘弯曲和弯曲。

U, S, Vt = linalg.svd(F)
V = Vt.T

#Right epipol
U[:,2]/U[2,2]

# The expected X-direction with C1 camera matri and C1[0,0] the focal length
vecteurX = np.array([(U[:,2]/U[2,2])[0],(U[:,2]/U[2,2])[1],C1[0,0]])
vecteurX_unit = vecteurX/np.sqrt(vecteurX[0]**2 + vecteurX[1]**2 + vecteurX[2]**2)


# The expected Y axis :
height = 2048
vecteurY = np.array([0, height -1, 0])
vecteurY_unit = vecteurY/np.sqrt(vecteurY[0]**2 + vecteurY[1]**2 + vecteurY[2]**2)


# The expected Z direction :
vecteurZ = np.cross(vecteurX,vecteurY)
vecteurZ_unit = vecteurZ/np.sqrt(vecteurZ[0]**2 + vecteurZ[1]**2 + vecteurZ[2]**2)

#Normal of the Z optical (the current Z direction)
Zopitcal = np.array([0,0,1])

cos_theta = np.arccos(np.dot(vecteurZ_unit, Zopitcal)/np.sqrt(vecteurZ_unit[0]**2 + vecteurZ_unit[1]**2 + vecteurZ_unit[2]**2)*np.sqrt(Zopitcal[0]**2 + Zopitcal[1]**2 + Zopitcal[2]**2))

sin_theta = (np.cross(vecteurZ_unit, Zopitcal))[1]

#Definition of the Rodrigues vector and use of cv2.Rodrigues to get rotation matrix
v1 = Zopitcal  
v2 = vecteurZ_unit 

v_rodrigues = v1*cos_theta + (np.cross(v2,v1))*sin_theta + v2*(np.cross(v2,v1))*(1. - cos_theta)
R = cv2.Rodrigues(v_rodrigues)[0]

【问题讨论】:

你能用投影矩阵来变换你的点吗? 我添加了补语 ;) 不知道有没有可能 应用 3D 旋转矩阵不应导致点弯曲。请在应用 R 之前绘制点并确保它们不是非平面的。 由于您的数据看起来不是平面的,因此很难测试。我建议先修复平面性。问题可能出在您建议的校准参数中,也可能出在您用于从视差到 3D 世界坐标的部分中(例如,请参阅this other post)。我没有足够的信息可以告诉。 【参考方案1】:

您预期的 z 方向对于重建方法是任意的。通常,您有一个旋转矩阵,可以从您想要的方向旋转左相机。您可以轻松构建该矩阵 R。然后您需要做的就是将重构的点乘以 R 的转置。

【讨论】:

我使用了 R_0,它是每个相机校准得到的旋转矩阵 1 和 2 的乘积,以便进行三角测量,但我不知道如何构建这个矩阵 R...我试图确定一个在平面试样的情况下,通过拟合平面来进行刚体运动,但效果不佳......【参考方案2】:

为了补充fireant 的回复,这里是一个候选解决方案,假设预期的 X 方向与连接两个摄像头投影中心的线重合。

    计算焦距 f_1 和 f_2(通过针孔模型校准)。 求解摄像机 2 的极点在摄像机 1 的框架中的位置。为此,您可以使用立体相机对的基本矩阵 (F) 或基本矩阵 (E)。具体来说,左右极点位于 F 的零空间中,因此您可以使用Singular Value Decomposition。有关可靠的理论参考,请参阅 Hartley 和 Zisserman,第二版,表 9.1“基本矩阵属性摘要”,第 246 页 (freely available PDF of the chapter)。 摄像机 1 的投影中心,即 (0, 0, 0) 和右极点的位置,即 (e_x, e_y, f_1) 共同定义了一条与连接摄像机中心的线对齐的光线。这可以用作预期的 X 方向。将此向量称为 v_x。 假设预期的 Y 轴在图像平面中朝下,即从 (0, 0, f_1) 到 (0, height-1, f_1),其中 f 是焦距。将此向量称为 v_y。 预期的 Z 方向现在是向量 v_x 和 v_y 的叉积。 使用预期的 Z 方向以及相机 1 的光轴(Z 轴),然后可以使用 this other *** post 中列出的方法从两个 3D 矢量计算旋转矩阵。

实用说明: 根据我的实际经验,如果不付出相当大的努力,期望平面对象与立体基线完全对齐是不可能的。需要进行一定程度的平面拟合和额外的旋转。

一次性努力: 这取决于您是否需要这样做一次,例如对于一次性校准,在这种情况下,只需实时进行此估计过程,然后旋转您的立体相机对,直到深度图方差最小化。然后锁定您的相机位置并祈祷以后不会有人撞到它。

重复性: 如果您需要将估计的深度图与随捕获的每个新帧变化的真正任意 Z 轴对齐,那么您应该考虑在平面估计方法上投入时间并使其更加稳健。

【讨论】:

感谢您的帮助,这很有趣!我会试试的:)

以上是关于OpenCV - 立体视觉的倾斜相机和三角测量地标的主要内容,如果未能解决你的问题,请参考以下文章

双目立体视觉

如何用 Matlab 立体计算机视觉测量运动物体的距离和质心?

如何测量相机与物体之间的距离

opencv三维重建深度怎么不随视场变化

如何测量立体图像中的距离?

带有 glm::frustum 闪烁的倾斜/离轴立体投影