【发布时间】:2011-09-03 17:07:06
【问题描述】:
我知道将正方形转换为梯形是一种线性变换,可以使用射影矩阵来完成,但我在弄清楚如何构造矩阵时遇到了一些麻烦。
使用投影矩阵进行平移、缩放、旋转和剪切非常简单。是否有一个简单的投影矩阵可以将正方形转换为梯形?
【问题讨论】:
标签: matrix transform linear-algebra projection perspective
我知道将正方形转换为梯形是一种线性变换,可以使用射影矩阵来完成,但我在弄清楚如何构造矩阵时遇到了一些麻烦。
使用投影矩阵进行平移、缩放、旋转和剪切非常简单。是否有一个简单的投影矩阵可以将正方形转换为梯形?
【问题讨论】:
标签: matrix transform linear-algebra projection perspective
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 个参数表示),然后求解八个未知数的八个方程的线性系统.你可以在论文Homography Estimation by Elan Dubrofsky的第2节找到类似的解释。
另一种解释是大卫·奥斯汀在2013 March issue of Feature Column from the AMS 中使用投影几何校正相机。
上述方法及其缺点在 Richard Hartley 和 Andrew Zissermann 第二版计算机视觉中的多视图几何的第 4 章“估计 - 2D 投影变换”中进行了描述,他们在其中还描述了不同的更好的算法;您可以查看此链接http://www.cse.iitd.ac.in/~suban/vision/geometry/node24.html,它似乎遵循同一本书。
您可以在Computer Vision: Models, Learning, and Inference by Simon J.D. Prince 一书的第 15.1.4 节“射影变换模型”中找到对单应性的另一种解释。算法算法 15.4:投影变换(单应性)的最大似然学习在他的Algorithms booklet 中进行了概述:该问题通过非线性最小化来解决。
【讨论】:
H,你通常会从a 到alpha,具有非线性函数; a=[x1,y1,1]alpha=[X1,Y1,1] 其中X1=(x1*h1+y1*h2+h3)/(x1*h7+y1*h8+h9) 和Y1=(x1*h4+y1*h5+h6)/(x1*h7+y1*h8+h9)
【讨论】:
对于那些知识和时间有限的人正在寻找快速而肮脏的解决方案,Wii-interact 项目中有一个工作且非常可靠的 Java 实现。
转换位于The Homography source file。归结为构造和求解矩阵:
/**
* 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
【讨论】: