我正在尝试编写一个函数,当给定两个摄像头时,它们的旋转,平移矩阵,焦点以及每个摄像头的点坐标将能够将该点三角剖分到3D空间中。基本上,给出所有需要的外部/内部值
我熟悉一般的想法:以某种方式创建两条射线并找到满足最小二乘问题的最接近点,但是,我不知道如何将给定信息转化为一系列方程式。 3D中的坐标点。
答案 0 :(得分:1)
我的旅程迟到了几年。我遇到了完全相同的问题,发现有几个人在问同样的问题,但从未找到足够简单的答案让我理解在这里为未来的人。
最后我还会给你一些代码示例,让你在 python 中做你想做的事情,所以坚持下去。
我的手写笔记的一些屏幕截图,其中解释了整个过程。 Page 1. Page 2. Page 3.
这是我开头的等式,可以在 https://docs.opencv.org/master/d9/d0c/group__calib3d.html
中找到一旦您在现实世界中为两个相机选择了相同的原点,您将拥有其中两个具有相同 X、Y、Z 值的方程。
抱歉,下一部分您已经有了,但其他人可能还没有做到这一点:
首先,您需要校准您的相机,这将为您提供每台相机的相机矩阵和失真(内在属性)。 https://docs.opencv.org/master/dc/dbb/tutorial_py_calibration.html
您只需要这两个并且可以转储 rvecs 和 tvecs,因为这会在您设置相机时发生变化。
一旦你选择了你的真实世界坐标系,你就可以使用 cv2.solvePnP 来获得旋转和平移向量。为此,您需要一组真实世界的点以及它们在每个相机的相机中的相应坐标。我的诀窍是我编写了一些代码来显示该领域的图像,然后我会传入点数。然后我会点击图像上的位置并创建一个映射。这个位的代码有点长,所以除非有要求,否则我不会在这里分享。
cv2.solvePnP
将为您提供旋转矩阵的向量,因此您需要使用以下行将其转换为 3x3 矩阵:
`R, jac = cv2.Rodrigues(rvec)`
现在回到最初的问题:
每个相机都有 3x3 相机矩阵。每个相机都有 3x3 旋转矩阵。每个相机都有 3x1 的平移向量。您有一些 (u, v)
坐标,用于确定每个相机中感兴趣对象的位置。数学在笔记的图像中有更多的解释。
import numpy as np
def get_xyz(camera1_coords, camera1_M, camera1_R, camera1_T, camera2_coords, camera2_M, camera2_R, camera2_T):
# Get the two key equations from camera1
camera1_u, camera1_v = camera1_coords
# Put the rotation and translation side by side and then multiply with camera matrix
camera1_P = camera1_M.dot(np.column_stack((camera1_R,camera1_T)))
# Get the two linearly independent equation referenced in the notes
camera1_vect1 = camera1_v*camera1_P[2,:]-camera1_P[1,:]
camera1_vect2 = camera1_P[0,:] - camera1_u*camera1_P[2,:]
# Get the two key equations from camera2
camera2_u, camera2_v = camera2_coords
# Put the rotation and translation side by side and then multiply with camera matrix
camera2_P = right_M.dot(np.column_stack((camera2_R,camera2_T)))
# Get the two linearly independent equation referenced in the notes
camera2_vect1 = camera2_v*camera2_P[2,:]-camera2_P[1,:]
camera2_vect2 = camera2_P[0,:] - camera2_u*camera2_P[2,:]
# Stack the 4 rows to create one 4x3 matrix
full_matrix = np.row_stack((camera1_vect1, camera1_vect2, camera2_vect1, camera2_vect2))
# The first three columns make up A and the last column is b
A = full_matrix[:, :3]
b = full_matrix[:, 3].reshape((4, 1))
# Solve overdetermined system. Note b in the wikipedia article is -b here.
# https://en.wikipedia.org/wiki/Overdetermined_system
soln = np.linalg.inv(A.T.dot(A)).dot(A.T).dot(-b)
return soln
答案 1 :(得分:0)
假设您有两个摄像机-摄像机1和摄像机2。
对于每个摄像机j = 1、2,您将得到:
中心hj
之间的距离Oj
,(“焦点”是正确的术语吗?基本上是相机从其观看屏幕的点Oj
)和相机的屏幕。相机的坐标系以Oj
为中心,Oj--->x
和Oj--->y
轴与屏幕平行,而Oj--->z
轴与屏幕垂直。
3 x 3旋转矩阵Uj
和3 x 1平移矢量Tj
将相对于相机j(请参见点1)的系统的笛卡尔3D坐标转换为世界坐标,即相对于描述3D世界中所有点的第三坐标系的坐标。
在摄像机j的屏幕上,该屏幕是平行于平面Oj-x-y
且与原点hj
相距Oj
的平面,您具有2D坐标(假设仅点pj
的x,y坐标,其中两个点p1
和p2
实际上是同一点P
的投影图像,位于3D,分别到摄像机1和2的屏幕上。通过在点Oj
和点P
之间绘制3D线并将点pj
定义为该线与相机j的屏幕的唯一交点,可以得到投影。相机j的3D坐标系中的屏幕方程为z = hj
,因此点pj
相对于相机j的3D坐标系的坐标看起来像pj = (xj, yj, hj)
,因此2D屏幕坐标只是pj = (xj, yj)
。
输入:为您提供2D点p1 = (x1, y1), p2 = (x2, y2)
,twp摄像机的焦距h1, h2
,两个3 x 3旋转矩阵U1
和{{ 1}},两个转换3 x 1矢量列U2
和T1
。
输出:世界坐标系中P点的坐标T2
。
一种避免这种情况的简单方法是避免以下情况的算法:避免同质坐标和投影矩阵(也可以或多或少地等效):
表格P = (x0, y0, z0)
和Q1 = [x1; y1; h1]
,它们被解释为3 x 1矢量列;
变换Q2 = [x2; y2; h2]
和P1 = U1*Q1 + T1
,其中P2 = U1*Q2 + T1
是矩阵乘法,这里是3 x 3矩阵乘以3 x 1列,给定3 x 1列;
形成*
和X = T1 + t1*(P1 - T1)
行;
来自前面步骤3的两条线在一个公共点(即点X = T2 + t2*(P2 - T2)
)处相交,或者它们是斜线,即它们不相交但不平行(不共面)。
如果线是斜线,请在第一行上找到唯一点P
,在第二行上找到唯一点X1
,以使向量X2
垂直两条线都垂直,即X2 - X1
垂直于矢量X2 - X1
和P1 - T1
。这两个点X1和X2是两条线上的最接近点。然后,可以将点P2 - T2
作为线段P = (X1 + X2)/2
的中点。
通常,两条线应该彼此非常靠近,因此两个点X1和X2应该彼此非常靠近。