正方形到梯形



我知道将正方形转换为梯形是一种线性变换,可以使用投影矩阵来完成,但我在弄清楚如何构造矩阵时遇到了一些困难。

使用投影矩阵来平移、缩放、旋转和剪切是很简单的。有没有一个简单的投影矩阵可以将正方形转换为梯形?

a、b、c、d是2D正方形的四个角。

a、 b,c,d用齐次坐标表示,因此它们是3x1矩阵。

alpha、beta、gamma和delta是2D梯形的四个角。

alpha、beta、gamma、delta用齐次坐标表示,因此它们是3x1矩阵。

H是你正在寻找的3x3矩阵,它也被称为单应性

    h1 h2 h3
H = h4 h5 h6
    h7 h8 h9

H将a、b、c、d映射为α、β、γ、δ,因此您有以下四个等式

alpha=H*a
beta=H*b
gamma=H*c
delta=H*d

假设你知道a、b、c、d和阿尔法、贝塔、伽马、德尔塔,你就可以求解前面的四个方程组的九个未知数h1、h2、h3、h4、h5、h6、h7、h8、h9。

在这里,我刚刚描述了这个问题的"原始"解决方案,原则上是可行的;有关上面提到的方法的详细解释,您可以看到例如本页http://www.corrmap.com/features/homography_transformation.php其中他们放置h9=1(因为H可以仅用8个参数来表示),然后在8个未知数中求解8个方程的线性系统。你可以在Elan Dubrovsky的论文同态估计的第2节中找到类似的解释。

另一种解释是David Austin在2013年3月号的AMS特征专栏中发表的《使用投影几何校正相机》。

Richard Hartley和Andrew Zissermann的计算机视觉中的多视图几何第二版中的第4章"估计-2D投影变换"描述了上述方法及其缺点,他们还描述了不同且更好的算法;你可以查看这个链接http://www.cse.iitd.ac.in/~suban/vision/geometry/nod24.html,它似乎遵循了同一本书。

你可以在Simon J.D.Prince的《计算机视觉:模型、学习和推理》一书的第15.1.4节"投影变换模型"中找到对单应性的另一种解释。算法算法15.4:投影变换(单应性)的最大似然学习在他的《算法》小册子中概述:该问题通过非线性最小化来解决。

也许你可以使用四边形?请点击此处查看我的答案:

https://stackoverflow.com/a/12820877/202451

然后你就可以完全控制每一点,并且可以轻松地做出任何四角形状。:)

具有最小依赖关系的Java实现

对于那些知识和时间有限的人来说,寻找一个快速而肮脏的解决方案,Wii交互项目中有一个有效且相当可靠的Java实现。

该信息在同源性源文件中。它可以归结为构造和求解矩阵:

/**
* Please note that Dr. John Zelle assisted us in developing the code to
* handle the matrices involved in solving for the homography mapping.
* 
**/
Matrix A = new Matrix(new double[][]{
                {x1, y1, 1, 0,  0,  0, -xp1*x1, -xp1*y1},
                {0,  0,  0, x1, y1, 1, -yp1*x1, -yp1*y1},
                {x2, y2, 1, 0,  0,  0, -xp2*x2, -xp2*y2},
                {0,  0,  0, x2, y2, 1, -yp2*x2, -yp2*y2},
                {x3, y3, 1, 0,  0,  0, -xp3*x3, -xp3*y3},
                {0,  0,  0, x3, y3, 1, -yp3*x3, -yp3*y3},
                {x4, y4, 1, 0,  0,  0, -xp4*x4, -xp4*y4},
                {0,  0,  0, x4, y4, 1, -yp4*x4, -yp4*y4}
        });
        Matrix XP = new Matrix(new double[][]
                          {{xp1}, {yp1}, {xp2}, {yp2}, {xp3}, {yp3}, {xp4}, {yp4}});
        Matrix P = A.solve(XP);
        transformation = new Matrix(new double[][]{
                {P.get(0, 0), P.get(1, 0), P.get(2,0)},
                {P.get(3, 0), P.get(4, 0), P.get(5,0)},
                {P.get(6, 0), P.get(7, 0), 1}
        });

用法:以下方法做最后的转换:

public Point2D.Double transform(Point2D.Double point) {
    Matrix p = new Matrix(new double[][]{{point.getX()}, {point.getY()}, {1}});
    Matrix result = transformation.times(p);
    double z = result.get(2, 0);
    return new Point2D.Double(result.get(0, 0) / z, result.get(1, 0) / z);
}

Matrix类依赖关系来自JAMA:Java矩阵包

许可证

  1. Wii交互GNU GPL v3
  2. JAMA公共域

相关内容

  • 没有找到相关文章

最新更新