【问题标题】:How do I reverse-project 2D points into 3D?如何将 2D 点反向投影到 3D?
【发布时间】:2010-09-09 17:18:11
【问题描述】:

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

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

这可能属于摄影测量的范畴,但谷歌搜索并没有让我找到任何有用的信息。

【问题讨论】:

  • 如果我没记错的话,你可以有两个 3D 坐标选项。
  • 这个问题虽然不清楚,但暗示着透视(所以z距离越大,投影越小)
  • 您好 Joshua,我也遇到了很多问题。你有没有找到一个令人满意的解决方案?谢谢,T
  • 还没有西奥。我正在从事的项目有点被搁置了,但我最终需要弄清楚这一点。我正在考虑开始赏金。
  • 嗨,Joshua,你好运了吗?如果您愿意,我非常希望看到解决它的代码! :D

标签: 3d geometry 2d photogrammetry reverseprojection


【解决方案1】:

对于我的 OpenGL 引擎,以下片段会将鼠标/屏幕坐标转换为 3D 世界坐标。阅读评论以了解正在发生的事情的实际描述。

/* 功能:YCamera :: 计算世界坐标 参数:x 鼠标 x 坐标 y 鼠标 y 坐标 vec 在哪里存储坐标 返回:不适用 描述:将鼠标坐标转换为世界坐标 */
void YCamera :: CalculateWorldCoordinates(float x, float y, YVector3 *vec)
{
    //  START
    GLint viewport[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;
}

【讨论】:

    【解决方案2】:

    是的,Monte Carlo 有效,但我为这个问题找到了更好的解决方案。此代码完美运行(并使用 OpenCV):

    Cv2.CalibrateCamera(new List<List<Point3f>>() { points3d }, new List<List<Point2f>>() { points2d }, new Size(height, width), cameraMatrix, distCoefs, out rvecs, out tvecs, CalibrationFlags.ZeroTangentDist | CalibrationFlags.FixK1 | CalibrationFlags.FixK2 | CalibrationFlags.FixK3);
    

    此函数获取已知的 3d 和 2d 点、屏幕大小并返回旋转 (rvecs[0])、平移 (tvecs[0]) 和相机的内在值矩阵。这就是你需要的一切。

    【讨论】:

    • OpenCV 也有 FindHomography() 方法,效果也很好。
    【解决方案3】:

    感谢@Vegard 的出色回答。我稍微清理了一下代码:

    import pandas as pd
    import numpy as np
    
    class Point2:
        def __init__(self,x,y):
            self.x = x
            self.y = y
    
    class Point3:
        def __init__(self,x,y,z):
            self.x = x
            self.y = y
            self.z = z
    
    # Known 2D coordinates of our rectangle
    i0 = Point2(318, 247)
    i1 = Point2(326, 312)
    i2 = Point2(418, 241)
    i3 = Point2(452, 303)
    
    # 3D coordinates corresponding to i0, i1, i2, i3
    r0 = Point3(0, 0, 0)
    r1 = Point3(0, 0, 1)
    r2 = Point3(1, 0, 0)
    r3 = Point3(1, 0, 1)
    
    mat = [
        [1, 0, 0, 0],
        [0, 1, 0, 0],
        [0, 0, 1, 0],
        [0, 0, 0, 1],
    ]
    
    def project(p, mat):
        #print mat
        x = mat[0][0] * p.x + mat[0][1] * p.y + mat[0][2] * p.z + mat[0][3] * 1
        y = mat[1][0] * p.x + mat[1][1] * p.y + mat[1][2] * p.z + mat[1][3] * 1
        w = mat[3][0] * p.x + mat[3][1] * p.y + mat[3][2] * p.z + mat[3][3] * 1
        return Point2(720 * (x / w + 1) / 2., 576 - 576 * (y / w + 1) / 2.)
    
    # The squared distance between two points a and b
    def norm2(a, b):
        dx = b.x - a.x
        dy = b.y - a.y
        return dx * dx + dy * dy
    
    def evaluate(mat): 
        c0 = project(r0, mat)
        c1 = project(r1, mat)
        c2 = project(r2, mat)
        c3 = project(r3, mat)
        return norm2(i0, c0) + norm2(i1, c1) + norm2(i2, c2) + norm2(i3, c3)    
    
    def perturb(mat, amount):
        from copy import deepcopy
        from random import randrange, uniform
        mat2 = deepcopy(mat)
        mat2[randrange(4)][randrange(4)] += uniform(-amount, amount)
        return mat2
    
    def approximate(mat, amount, n=1000):
        est = evaluate(mat)
        for i in xrange(n):
            mat2 = perturb(mat, amount)
            est2 = evaluate(mat2)
            if est2 < est:
                mat = mat2
                est = est2
    
        return mat, est
    
    for i in xrange(1000):
        mat,est = approximate(mat, 1)
        print mat
        print est
    

    .1 的近似调用对我不起作用,所以我把它拿出来了。我也跑了一段时间,最后我检查它是在

    [[0.7576315397559887, 0, 0.11439449272592839, -0.314856490473439], 
    [0.06440497208710227, 1, -0.5607502645413118, 0.38338196981556827], 
    [0, 0, 1, 0], 
    [0.05421620936883742, 0, -0.5673977598434641, 2.693116299312736]]
    

    有大约 0.02 的误差。

    【讨论】:

      【解决方案4】:

      好的,我来这里是为了寻找答案,但没有找到简单明了的东西,所以我继续做了愚蠢但有效(且相对简单)的事情:蒙特卡洛优化。

      简单地说,算法如下:随机扰动你的投影矩阵,直到它将你已知的 3D 坐标投影到你已知的 2D 坐标。

      这是托马斯坦克引擎的静态照片:

      假设我们使用 GIMP 在地平面上找到我们认为是正方形的二维坐标(是否真的是正方形取决于您对深度的判断):

      我在 2D 图像中得到四个点:(318, 247)(326, 312)(418, 241)(452, 303)

      按照惯例,我们说这些点应该对应于 3D 点:(0, 0, 0)(0, 0, 1)(1, 0, 0)(1, 0, 1)。也就是说,y=0 平面上的一个单位正方形。

      将这些 3D 坐标中的每一个投影到 2D 中是通过将 4D 向量 [x, y, z, 1] 与 4x4 投影矩阵相乘,然后将 x 和 y 分量除以 z 来实际获得透视校正来完成的。这或多或少是gluProject() 所做的,除了gluProject() 还考虑了当前视口并考虑了单独的模型视图矩阵(我们可以假设模型视图矩阵是单位矩阵)。查看 gluProject() 文档非常方便,因为我实际上想要一个适用于 OpenGL 的解决方案,但要注意文档中缺少公式中的 z 除法。

      请记住,算法是从一些投影矩阵开始并随机扰动它,直到它给出我们想要的投影。所以我们要做的是投影四个 3D 点中的每一个,看看我们离我们想要的 2D 点有多近。如果我们的随机扰动导致投影的 2D 点更接近我们在上面标记的点,那么我们保留该矩阵作为对我们最初(或之前)猜测的改进。

      让我们定义我们的观点:

      # Known 2D coordinates of our rectangle
      i0 = Point2(318, 247)
      i1 = Point2(326, 312)
      i2 = Point2(418, 241)
      i3 = Point2(452, 303)
      
      # 3D coordinates corresponding to i0, i1, i2, i3
      r0 = Point3(0, 0, 0)
      r1 = Point3(0, 0, 1)
      r2 = Point3(1, 0, 0)
      r3 = Point3(1, 0, 1)
      

      我们需要从一些矩阵开始,单位矩阵似乎是一个自然的选择:

      mat = [
          [1, 0, 0, 0],
          [0, 1, 0, 0],
          [0, 0, 1, 0],
          [0, 0, 0, 1],
      ]
      

      我们需要实际实现投影(基本上是矩阵乘法):

      def project(p, mat):
          x = mat[0][0] * p.x + mat[0][1] * p.y + mat[0][2] * p.z + mat[0][3] * 1
          y = mat[1][0] * p.x + mat[1][1] * p.y + mat[1][2] * p.z + mat[1][3] * 1
          w = mat[3][0] * p.x + mat[3][1] * p.y + mat[3][2] * p.z + mat[3][3] * 1
          return Point(720 * (x / w + 1) / 2., 576 - 576 * (y / w + 1) / 2.)
      

      这基本上是gluProject() 所做的,720 和 576 分别是图像的宽度和高度(即视口),我们从 576 中减去以计算我们从顶部开始计算 y 坐标的事实,而OpenGL 通常从底部开始计算它们。你会注意到我们没有计算 z,那是因为我们在这里并不需要它(尽管它可以很方便地确保它在 OpenGL 用于深度缓冲区的范围内)。

      现在我们需要一个函数来评估我们与正确解决方案的距离。该函数返回的值是我们将用来检查一个矩阵是否优于另一个矩阵的值。我选择按距离平方和,即:

      # The squared distance between two points a and b
      def norm2(a, b):
          dx = b.x - a.x
          dy = b.y - a.y
          return dx * dx + dy * dy
      
      def evaluate(mat): 
          c0 = project(r0, mat)
          c1 = project(r1, mat)
          c2 = project(r2, mat)
          c3 = project(r3, mat)
          return norm2(i0, c0) + norm2(i1, c1) + norm2(i2, c2) + norm2(i3, c3)
      

      为了扰动矩阵,我们只需在某个范围内随机选取一个元素进行扰动:

      def perturb(amount):
          from copy import deepcopy
          from random import randrange, uniform
          mat2 = deepcopy(mat)
          mat2[randrange(4)][randrange(4)] += uniform(-amount, amount)
      

      (值得注意的是,我们的project() 函数实际上根本不使用mat[2],因为我们不计算z,并且因为我们所有的y 坐标都是0,所以mat[*][1] 的值也无关紧要。我们可以利用这个事实,并且永远不要试图扰乱这些值,这会带来一点加速,但这留作练习......)

      为方便起见,让我们添加一个函数,通过反复调用perturb() 对我们迄今为止发现的最佳矩阵进行大量近似:

      def approximate(mat, amount, n=100000):
          est = evaluate(mat)
      
          for i in xrange(n):
              mat2 = perturb(mat, amount)
              est2 = evaluate(mat2)
              if est2 < est:
                  mat = mat2
                  est = est2
      
          return mat, est
      

      现在剩下要做的就是运行它...:

      for i in xrange(100):
          mat = approximate(mat, 1)
          mat = approximate(mat, .1)
      

      我发现这已经给出了一个相当准确的答案。跑了一会儿,发现的矩阵是:

      [
          [1.0836000765696232,  0,  0.16272110011060575, -0.44811064935115597],
          [0.09339193527789781, 1, -0.7990570384334473,   0.539087345090207  ],
          [0,                   0,  1,                    0                  ],
          [0.06700844759602216, 0, -0.8333379578853196,   3.875290562060915  ],
      ]
      

      错误约为2.6e-5。 (请注意,我们所说的未在计算中使用的元素实际上并没有从我们的初始矩阵中改变;那是因为改变这些条目不会改变评估的结果,所以改变永远不会继续。)

      我们可以使用glLoadMatrix() 将矩阵传递到OpenGL(但记得先转置它,并记得用单位矩阵加载你的模型视图矩阵):

      def transpose(m):
          return [
              [m[0][0], m[1][0], m[2][0], m[3][0]],
              [m[0][1], m[1][1], m[2][1], m[3][1]],
              [m[0][2], m[1][2], m[2][2], m[3][2]],
              [m[0][3], m[1][3], m[2][3], m[3][3]],
          ]
      
      glLoadMatrixf(transpose(mat))
      

      现在我们可以例如沿 z 轴平移以获得沿轨道的不同位置:

      glTranslate(0, 0, frame)
      frame = frame + 1
      
      glBegin(GL_QUADS)
      glVertex3f(0, 0, 0)
      glVertex3f(0, 0, 1)
      glVertex3f(1, 0, 1)
      glVertex3f(1, 0, 0)
      glEnd()
      

      从数学的角度来看,这肯定不是很优雅;你没有得到一个封闭形式的方程,你可以将你的数字插入并得到一个直接(和准确)的答案。但是,它确实允许您添加额外的约束,而不必担心使方程式复杂化;例如,如果我们也想合并高度,我们可以使用房子的那个角落并说(在我们的评估函数中)从地面到屋顶的距离应该是某某,然后再次运行该算法。所以,是的,这是一种蛮力,但很有效,而且效果很好。

      【讨论】:

      • 令人印象深刻的可视化效果!
      • 只是给将找到此问题/答案的人的说明。在计算机视觉中,这个问题被称为Perspective-n-Point (PnP)。计算机视觉库(OpenCVMatlab 等)可能具有此功能。使用随机方法(蒙特卡洛)可能有效,但文献中已经存在一些解决此类问题的方法。
      【解决方案5】:

      这是基于标记的增强现实的经典问题。

      您有一个方形标记(二维条码),并且您想在找到标记的四个边缘后找到它的姿势(相对于相机的平移和旋转)。 Overview-Picture

      我不知道该领域的最新贡献,但至少在某种程度上(2009 年)RPP 应该优于上面提到的 POSIT(并且确实是一个经典的方法) 请查看链接,它们也提供了来源。

      (PS - 我知道这是一个有点老的话题,但无论如何,这篇文章可能对某人有帮助)

      【讨论】:

      • 感谢您的回答!这可能是一个古老的问题,但它从未得到令人满意的回答。我会看看那些链接。
      【解决方案6】:

      D. DeMenthon 设计了一种算法,在知道对象模型的情况下,根据 2D 图像中的特征点计算对象的姿势(其在空间中的位置和方向) -- this是你的确切问题

      我们描述了一种从单个图像中找到对象姿势的方法。我们假设我们可以在图像中检测和匹配对象的四个或更多非共面特征点,并且我们知道它们在对象上的相对几何形状。

      该算法被称为 Posit,在经典文章“25 行代码中基于模型的对象姿势”(可在its website,第 4 节)中进行了描述。

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

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

      【讨论】:

        【解决方案7】:

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

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

        【讨论】:

          【解决方案8】:

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

          诀窍是找到进行投影的投影矩阵。幸运的是,这是可能的,而且成本很低。相关数学可以在 Paul Heckbert 的论文“Projective Mappings for Image Warping”中找到。

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

          通过这种方式,您可以恢复在投影期间丢失的每个顶点的同质部分。

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

          注意:这只是因为:

          1. 原来的形状是一个矩形
          2. 您知道矩形在 3D 空间中的确切大小。

          真的是特例。

          希望对你有帮助, 尼尔斯

          【讨论】:

            【解决方案9】:

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

            话虽如此,您正在寻找一个矩阵变换 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-inverse。

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

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

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

            更新:

            1. 除非您修复其中一个点,否则会有无数个投影。如果您固定原始矩形的点,则有两个可能的原始矩形。

            【讨论】:

            • @"嗯...我应该回家写这个小宝石。这听起来很有趣。"如果您这样做了,我将不胜感激! :-)
            • 我想请人解释一个给定的矩形(比如一张票)——我的眼睛稳定,它和票之间有一个透明玻璃——它可以有无限的地方,而它的角投影到玻璃上完全相同的 4 个点。请。
            • 你听起来好像和 Jarrett 很亲近!我不认为你真的相信有无限的预测。我的意思是如果你在你面前举起一张纸,在 3d 空间中只有一个位置和方向你可以拿着它,它看起来完全一样(忽略翻转/旋转纸)。此外,如果你闭上眼睛,我在你面前举起一张纸,当你睁开眼睛时,你可以很好地推断出这张纸在 3d 空间中的位置,只需将世界视为 2d 图像并知道纸张的大小。那么数学肯定也能做到吗?
            • 澄清一下,“忽略翻转/旋转纸张”是指忽略您刚刚将矩形纸张旋转 180 度的重复案例。
            【解决方案10】:

            如果您知道该形状是平面中的矩形,则可以大大进一步限制该问题。您当然无法确定“哪个”平面,因此您可以选择它位于 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 的向量,因此其中一个是多余的),并且具有w 的焦点长度/图像宽度因子。这些数字变成了一个 3x3 的投影矩阵。

            这给出了总共 7 个未知数:w/h、cx、cy、cz、nx、ny 和 w。

            你总共有 8 个已知:4 个 x+y 对。

            这样就可以解决了。

            下一步是使用 Matlab 或 Mathmatica。

            【讨论】:

              【解决方案11】:

              当您从 3D 投影到 2D 时,您会丢失信息。

              在单点的简单情况下,逆投影将为您提供穿过 3d 空间的无限光线。

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

              投影可以采取不同的形式。正交或透视。我猜你是在假设正交投影?

              在您的情况下,假设您拥有原始矩阵,您将在 3D 空间中拥有 4 条光线。然后,您将能够通过 3d 矩形尺寸限制问题并尝试解决。

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

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

              由于您没有原始投影矩阵,因此任何投影中都存在任意比例因子会引入更多歧义。您无法区分投影中的缩放和沿 z 轴方向的 3d 平移。如果您只对 3d 空间中 4 个点彼此相关而不是 2d 投影平面的相对位置感兴趣,这不是问题。

              在透视投影中,事情变得更加困难......

              【讨论】:

                【解决方案12】:

                您在 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 进行逆向工程。但是任何一组 z 坐标 a)在点之间保持相同的 x-y 距离,并且 b)保持矩形的形状都可以。所以,这个(无限)集合的任何成员都可以:{(z0+i, z1+i, z2+i, z3+i) |我

                编辑@Jarrett:想象一下你解决了这个问题并最终在 3D 空间中生成了一个矩形。现在,想象一下在 z 轴上上下滑动该矩形。那些无限量的平移矩形都具有相同的 x-y 投影。你怎么知道你找到了“正确的”?

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

                想象在您的办公桌上方放一张纸。假设纸的每个角落都附有一个无重量的激光笔,指向桌子。纸是3D物体,桌上的激光笔点是2D投影。

                现在,您如何通过查看激光笔点来判断纸张离桌面有多高?

                你不能。上下移动纸张。无论纸张的高度如何,激光笔仍会照在桌子上的同一点上。

                在反向投影中查找 z 坐标就像试图仅根据桌面上的激光指针点来查找纸张的高度。

                【讨论】:

                • 是的,但我在问题中表示我也知道矩形的大小。应该只有一组 Z 坐标,其中所有 4 个点的距离都合适。在 z 轴上上下滑动会产生更大或更小的多边形。
                • 不,多边形的大小相同。在办公桌上方放一张纸。想象一下纸的角落一直延伸到桌面的位置。现在,上下移动纸张。这些点在所有这些位置都击中了桌子上的同一个点,但纸张的大小保持不变。
                • Rob,你完全忽略了透视的可能性。出于某种原因,您只考虑正交投影。
                • 确实如此。正交情况只是无限投影集中的一种情况。最重要的是,它是最不可能的(视点必须离您投影到的平面无限远)。 -1.
                【解决方案13】:

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

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

                【讨论】:

                  猜你喜欢
                  • 2010-09-12
                  • 2012-09-03
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-09-04
                  • 2019-06-08
                  • 2023-03-08
                  • 1970-01-01
                  相关资源
                  最近更新 更多