如何将2D点反向投影到3D中?

时间:2020-03-05 18:56:58  来源:igfitidea点击:

我在屏幕空间中有4个2D点,​​我需要将它们反向投影回3D空间中。我知道这4个点中的每一个都是3D旋转的刚性矩形的一个角,并且知道矩形的大小。如何从中获得3D坐标?

我没有使用任何特定的API,并且没有现有的投影矩阵。我只是在寻找基本的数学来做到这一点。当然,没有足够的数据将单个2D点转换为3D而没有其他参考,但是我想像一下,如果我们有4个点,我们会知道它们在同一平面上都彼此成直角,并且我们知道它们之间的距离,那么我们应该能够从那里弄清楚。不幸的是我无法完全解决。

这可能属于摄影测量学的范畴,但是google搜索并没有带给我任何有用的信息。

解决方案

回答

假设这些点确实是矩形的一部分,我给出一个通用的想法:

找到两个最大距离的点:最有可能定义对角线的一个点(例外:特殊情况下,矩形与YZ平面几乎平行,留给学生)。称它们为A,C。计算BAD,BCD角度。与直角相比,这些可为我们提供3D空间中的方向。要了解z距离,我们需要将投影的边与已知的边相关联,然后基于3d投影方法(是1 / z?),我们将在正确的轨道上了解距离。

回答

如果没人回答,我回家时会拿出我的线性代数书。但是@ D G,并非所有矩阵都是可逆的。奇异矩阵是不可逆的(行列式= 0时)。实际上这将一直发生,因为投影矩阵必须具有0和1的特征值,并且必须是平方的(因为它是幂等的,所以p ^ 2 = p)。

一个简单的例子是[[0 1] [0 1]],因为行列式= 0,并且这是x = y线上的投影!

回答

我们在2D曲面上的投影具有无限多个3D矩形,这些矩形将投影为相同的2D形状。

这样考虑:我们有组成3D矩形的四个3D点。称它们为(x0,y0,z0),(x1,y1,z1),(x2,y2,z2)和(x3,y3,z3)。将这些点投影到x-y平面上时,将放下z坐标:(x0,y0),(x1,y1),(x2,y2),(x3,y3)。

现在,要投影回3D空间,需要对z0,..,z3进行反向工程。但是,任何a组z坐标(a)在点之间保持相同的x-y距离,b)保持矩形的形状都可以。因此,该(无限)集合的任何成员都将做:{(z0 + i,z1 + i,z2 + i,z3 + i)|我<R}。

编辑@Jarrett:假设我们解决了这个问题,最后在3D空间中得到一个矩形。现在,想象一下将矩形沿z轴上下滑动。那些无限数量的平移矩形都具有相同的x-y投影。我们怎么知道我们找到了"正确"的?

编辑2:好的,这是我对这个问题的评论-一种更直观的推理方法。

想象一下,在办公桌上方拿着一张纸。假装纸的每个角上都装有一个失重的激光指示器,该指示器向下指向桌子。纸张是3D对象,桌子上的激光指示器点是2D投影。

现在,我们如何仅看激光笔的点数就能知道纸离办公桌有多远?

你不能垂直向上和向下移动纸张。无论纸张的高度如何,激光笔仍会照在桌子上的相同位置上。

在反向投影中找到z坐标就像试图仅在桌子上基于激光指示器点找到纸张的高度一样。

回答

在二维空间中,将可以构建2个有效的矩形。不知道原始矩阵投影,就不会知道哪一个是正确的。与"盒子"问题相同:我们看到两个正方形,一个正方形在另一个正方形内,其中四个内部顶点分别连接到四个外部顶点。我们是从上到下还是自下而上查看一个框?

话虽如此,我们正在寻找一个矩阵变换T,其中...

{{x1,y1,z1},{x2,y2,z2},{x3,y3,z3},{x4,y4,z4}} x T = {{x1,y1},{x2,y2},{ x3,y3},{x4,y4}}

(4 x 3)x T =(4 x 2)

因此,T必须是(3 x 2)矩阵。因此,我们有6个未知数。

现在建立一个关于T的约束系统并使用Simplex求解。要构建约束,我们知道穿过前两个点的线必须与穿过后两个点的线平行。我们知道穿过点1和3的线必须与穿过点2和4的线平行。我们知道穿过1和2的线必须与穿过点2和3的线正交。我们知道长度1和2的线的长度必须等于3和4的线的长度。我们知道1和3的线的长度必须等于2和4的线的长度。

为了使此操作更加容易,我们需要了解矩形,因此我们知道所有边的长度。

那应该给我们很多约束来解决这个问题。

当然,要找回,可以找到T逆。

@Rob:是的,有无限数量的投影,但是没有无限数量的项目,这些点必须满足矩形的要求。

@nlucaroni:是的,只有在投影中有四个点时,这才可以解决。如果矩形仅投影到2个点(即矩形的平面与投影表面正交),则无法解决。

嗯...我应该回家写这个小宝石。这听起来很有趣。

更新:

  • 除非我们固定其中一个点,否则投影的数量是无限的。如果固定原始矩形的点,则有两个可能的原始矩形。

回答

从3D投影到2D时,我们会丢失信息。

在单点的简单情况下,反投影将为我们提供穿过3d空间的无限射线。

立体重建通常将从两个2d图像开始,然后再投影回3D。然后寻找产生的两条3D射线的交点。

投影可以采用不同的形式。正交或者透视。我猜我们正在假设正交投影?

在情况下,假设我们具有原始矩阵,则3D空间中将有4条射线。然后,我们将能够通过3d矩形尺寸来约束问题并尝试解决。

该解决方案将不是唯一的,因为围绕平行于2d投影平面的任一轴的旋转在方向上将是模棱两可的。换句话说,如果2d图像垂直于z轴,则围绕x轴顺时针或者逆时针旋转3d矩形将产生相同的图像。对于y轴也是如此。

在矩形平面平行于z轴的情况下,我们还有更多解决方案。

由于我们没有原始的投影矩阵,因此任何投影中都存在一个不确定的比例因子,这进一步引入了歧义。我们无法区分投影的缩放比例和z轴方向的3d平移。如果我们只对3d空间中4个点的相互之间的相对位置感兴趣,而不对2d投影的平面感兴趣,那么这不是问题。

从透视图的角度看,事情变得越来越难...

回答

如果我们知道形状是平面上的矩形,则可以极大地限制该问题。我们当然不能弄清楚"哪个"平面,因此可以选择它位于z = 0且角之一位于x = y = 0且边缘平行于x / y轴的平面上。

因此,3d中的点是{0,0,0},{w,0,0},{w,h,0}和{0,h,0}。我很确定不会找到绝对大小,因此只有比率w / h是相对的,所以这是一个未知数。

相对于此平面,相机必须在空间中的某个点cx,cy,cz处,并且必须指向nx,ny,nz方向(长度为1的矢量,因此其中之一是多余的),并且具有focus_length / image_width w的因数这些数字变成3x3投影矩阵。

这样一共有7个未知数:w / h,cx,cy,cz,nx,ny和w。

我们总共有8个已知值:4个x + y对。

这样就可以解决了。

下一步是使用Matlab或者Mathmatica。

回答

对于我的OpenGL引擎,以下片段将鼠标/屏幕坐标转换为3D世界坐标。阅读评论,以了解发生了什么。

/*   FUNCTION:        YCamera :: CalculateWorldCoordinates
     ARGUMENTS:       x         mouse x coordinate
                      y         mouse y coordinate
                      vec       where to store coordinates
     RETURN:          n/a
     DESCRIPTION:     Convert mouse coordinates into world coordinates
*/

`
void YCamera :: CalculateWorldCoordinates(float x,float y,YVector3 * vec)
{
// 开始
GLint视口[4];
GLdouble mvmatrix [16],projmatrix [16];

GLint real_y;
GLdouble mx, my, mz;

glGetIntegerv(GL_VIEWPORT, viewport);
glGetDoublev(GL_MODELVIEW_MATRIX, mvmatrix);
glGetDoublev(GL_PROJECTION_MATRIX, projmatrix);

real_y = viewport[3] - (GLint) y - 1;   // viewport[3] is height of window in pixels
gluUnProject((GLdouble) x, (GLdouble) real_y, 1.0, mvmatrix, projmatrix, viewport, &mx, &my, &mz);

/*  'mouse' is the point where mouse projection reaches FAR_PLANE.
    World coordinates is intersection of line(camera->mouse) with plane(z=0) (see LaMothe 306)

    Equation of line in 3D:
        (x-x0)/a = (y-y0)/b = (z-z0)/c      

    Intersection of line with plane:
        z = 0
        x-x0 = a(z-z0)/c  <=> x = x0+a(0-z0)/c  <=> x = x0 -a*z0/c
        y = y0 - b*z0/c

*/
double lx = fPosition.x - mx;
double ly = fPosition.y - my;
double lz = fPosition.z - mz;
double sum = lx*lx + ly*ly + lz*lz;
double normal = sqrt(sum);
double z0_c = fPosition.z / (lz/normal);

vec->x = (float) (fPosition.x - (lx/normal)*z0_c);
vec->y = (float) (fPosition.y - (ly/normal)*z0_c);
vec->z = 0.0f;

}
`

回答

http://library.wolfram.com/infocenter/Articles/2794/

http://campar.in.tum.de/Students/SepPoseEstimation

http://opencvlibrary.sourceforge.net/Posit可以工作,但是可以
可以发散或者循环。

回答

遵循Rons方法:如果知道如何旋转矩形,则可以找到z值。

诀窍是找到进行投影的投影矩阵。幸运的是,这样做是可能的,甚至是便宜的。相关数学可以在Paul Heckbert的论文"图像变形的投影映射"中找到。

http://pages.cs.wisc.edu/~dyer/cs766/readings/heckbert-proj.pdf

这样,我们可以恢复投影过程中丢失的每个顶点的同质部分。

现在我们仍然剩下四行而不是点(如罗恩所解释)。由于我们知道原始矩形的大小,因此不会丢失任何内容。现在,我们可以将Ron方法和2D方法中的数据插入线性方程式求解器,并求解z。我们可以通过这种方式获得每个顶点的确切z值。

注意:这之所以有效,是因为:

  • 原始形状是一个矩形
  • 我们知道3D空间中矩形的确切大小。

确实是一个特例。

希望能帮助到你,
尼尔斯

回答

D. DeMenthon设计了一种算法,可以在知道对象的模型时根据2D图像中的特征点计算对象的姿态(其在空间中的位置和方向)-这是确切问题:

We describe a method for finding the pose of an object from a single image. We assume that we can detect and match in the image four or more noncoplanar feature points of the object, and that we know their relative geometry on the object.

该算法称为Posit,并在其经典文章"代码行25行中基于模型的对象姿势"中进行了描述(可在其网站上的第4节中找到)。

文章的直接链接:http://www.cfar.umd.edu/~daniel/daniel_papersfordownload/Pose25Lines.pdf
OpenCV实施:http://opencv.willowgarage.com/wiki/Posit

这个想法是用缩放的正投影法反复逼近透视投影,直到收敛到准确的姿势为止。