【问题标题】:Transform quadrilateral into a rectangle?把四边形变成长方形?
【发布时间】:2010-07-06 21:46:21
【问题描述】:

我的场景由一个任意四边形组成。我需要能够将该四边形转换为矩形。每个四边形都在 2d 坐标中,因此它们有 4 个顶点 (x_i, y_i)

转换需要有一个逆,因为这个想法是在操纵矩形后回到原来的四边形。

执行此操作的最简单方法是什么?我听说这叫做透视变换,但我发现了一些小线索,让我觉得这很容易做到。

【问题讨论】:

  • 这是实现此目的的另一种方法:stackoverflow.com/questions/9470493/… 如果这有帮助,请告诉我。
  • @MonsieurDart 那个问题/答案是 IOS 特定的
  • 确实!我的评论仅适用于 iOS。

标签: opengl computer-vision linear-algebra graphics


【解决方案1】:

您知道所需矩形的尺寸是多少吗?如果是这种情况,您可以使用透视变换将任何凸四边形映射到具有可逆变换的矩形。您所要做的就是获得4个对应点(在四边形和矩形之间),例如,(X1,Y1),(X2,Y2), (X3,Y3), (X4,Y4) 对应于四边形和对应的 (x1,y1), (x2,y 2), (x3,y3), (x4,y4)对于矩形。然后将其代入Borealid's 链接中的最后一个等式,就可以设置了:

上述方程的解(其中n = 4)将为您提供可逆透视变换矩阵的元素(a,b,c,d,e,...,h),

这将允许您将矩形上的点转换为四边形上的点。对于反向变换,只需反转变换矩阵。

还请注意,一旦获得变换坐标的向量 [XW YW W]T,您需要对其进行归一化,使 W = 1。即,您的最终答案是 [XW/W YW /W W/W]T 等于 [X Y 1]T,即期望的答案。

【讨论】:

  • 非常好的答案,谢谢。这是完全正确的。我不知道我是否应该把它作为一个新问题,但是,在这里:当我获得透视变换矩阵时,有没有办法将此矩阵应用于 OpenGL 上下文?我试着做glPushMatrix()然后glMultMatrixf(perspectiveTransformationInverse)然后尝试画我的四边形,然后glPopMatrix()。但是这种方法不起作用,您会建议我做什么?
  • 由于我没有使用过OpenGL,我真的不能推荐任何东西。但是要转换所有点,您只需将其与转换矩阵相乘并对其进行归一化即可。
  • 我明白,但如果我想在转换后的四边形(矩形)内画一些点怎么办。是否可以这样做,然后对这些点应用相同的逆变换,以将它们带入原始的非矩形四边形???或者转换不适用于这些点?谢谢
  • Here's this thing 在 Java/Processing 中实现
  • 感谢您的链接!这对于平滑纹理四边形非常有用。这些图像从现在开始的页面变为 403,但在回程机器上有一个版本:web.archive.org/web/20100327214143/http://alumni.media.mit.edu/…
【解决方案2】:

并非所有四边形都是矩形。由于这个原因,从四边形到矩形没有可逆的变换;存在比矩形更多的四边形,因此您无法生成从四边形到矩形的可逆映射。

但是,您可以为特定的四边形生成可逆变换。正如您推测的那样,它是关于旋转透视图,使四边形“出现”为新坐标空间中的矩形。请参阅 http://alumni.media.mit.edu/~cwren/interpolator/ ,其中包含此问题的 Matlab 源代码。

【讨论】:

    【解决方案3】:

    此解决方案使用 JAI (Java Advance Image) API 所有的魔法都在 QuadToQuad 方法中。这是代码示例。

    try
         {
          BufferedImage img = UtilImageIO.loadImage(picName);
          ParameterBlock params = new ParameterBlock();
          params.addSource(img); //source is the input image
            int w = img.getWidth(); //Set to the original width of the image
            int h = img.getHeight(); //Set to the original height of image
            Point tl = new Point(x,y); //The new top left corner
            Point tr = new Point((x1,y1); //The new top right corner
            Point bl = new Point(x2,y2); //The new bottom left corner
            Point br = new Point(x3,y3); //The new bottom right corner
            PerspectiveTransform p = PerspectiveTransform.getQuadToQuad(0,0, 0, h, w, h, w, 0, tl.x, tl.y, bl.x, bl.y, br.x, br.y, tr.x, tr.y).createInverse();
            WarpPerspective wa = new WarpPerspective(p);
            params.add(wa);
            params.add(Interpolation.getInstance(Interpolation.INTERP_BICUBIC)); //Change the interpolation if you need more speed
            RenderedOp dest = JAI.create("warp", params); //dest is now the output
            File outputfile = new File(picName);
            ImageIO.write(dest, "jpg", outputfile); 
    
        }
        catch(Exception e){}
    

    希望对您有所帮助。 :)

    【讨论】:

      猜你喜欢
      • 2010-12-23
      • 1970-01-01
      • 1970-01-01
      • 2017-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多