10

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

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

4

3 回答 3

11

a,b,c,d 是二维正方形的四个角。

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

alpha、beta、gamma、delta 是二维梯形的四个角。

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

H 是您要查找的 3x3 矩阵,也称为单应矩阵

    h1 h2 h3
H = h4 h5 h6
    h7 h8 h9

H 将 a、b、c、d 映射为 alpha、beta、gamma、delta,因此您有以下四个等式

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

假设您知道 a,b,c,d 和 alpha, beta, gamma, delta,您可以求解前四个方程组的九个未知数 h1、h2、h3、h4、h5、h6、h7、h8、h9。

在这里,我刚刚描述了该问题的“原始”解决方案,原则上可以工作;有关上述方法的详细说明,您可以查看例如此页面http://www.corrmap.com/features/homography_transformation.php他们放置的位置h9=1(因为H只能用 8 个参数表示)然后求解线性系统八个未知数的八个方程。您可以在Elan Dubrofsky的论文 Homography Estimation的第 2 节中找到类似的解释。

另一种解释是David Austin 在AMS 2013 年 3 月的Feature Column中使用 Projective Geometry to Correct a Camera

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

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

于 2011-07-02T08:01:46.230 回答
3

也许你可以使用四边形?在这里查看我的答案:

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

然后您将完全控制每个点,并且可以轻松制作任何四角形状。:)

于 2012-10-10T13:54:49.413 回答
0

具有最小依赖项的 Java 实现

对于那些知识和时间有限的人正在寻找快速而肮脏的解决方案,Wii-interact项目中有一个工作且非常可靠的 Java 实现。

转换位于 The Homography源文件中。它归结为构造和求解矩阵:

/**
* 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 Matrix Package

执照

  1. Wii 交互GNU GPL v3
  2. JAMA公共领域
于 2014-01-03T11:08:14.103 回答