射影变换 [英] Projective transformation

查看:142
本文介绍了射影变换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定两个图像缓冲区(假设它是一个尺寸宽度*高度的整数数组,每个元素都有一个颜色值),如何将由四边形定义的区域从一个图像缓冲区映射到另一个(总是正方形)的图像缓冲?我引导了解这被称为投影转换。



我也在寻找一个通用的(不是语言或库特定的)方法来做到这一点,这样它就可以合理地应用于任何语言,而不依赖于为我完成所有工作的魔法函数X。 例如:我写了一个使用处理库(processing.org)从Java摄像头捕获视频的简短Java程序。在初始校准步骤中,捕获的视频直接输出到窗口中。然后,用户点击四个点来定义将要转换的视频区域,然后在程序的后续操作过程中将其映射到方形窗口。如果用户点击定义在相机输出中以一定角度可见的门的角的四个点,则该转换将导致随后的视频将门的变换图像映射到窗口的整个区域,虽然有些失真。

解决方案

使用线性代数比所有几何体要容易得多!此外,你不需要使用正弦,余弦等,所以你可以存储每个数字作为一个有理分数,并得到确切的数字结果,如果你需要它。



你想要的是从旧的(x,y)坐标到你的新的(x',y')坐标的映射。你可以用矩阵来做。您需要找到2乘4的投影矩阵P,以使旧坐标的P乘以新的坐标。我们假设您将线条映射到线条(而不是直线到抛物线)。因为你有一个投影(平行线不平行)和平移(滑动),你也需要一个因子(xy)和(1)。绘制为矩阵:

$ $ p $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ b [efgh] [x * y] [y']
[1]

您需要知道一个通​​过h以解决这些方程:

  a * x_0 + b * y_0 + c * x_0 * y_0 + d = i_0 
a * x_1 + b * y_1 + c * x_1 * y_1 + d = i_1
a * x_2 + b * y_2 + c * x_2 * y_2 + d = i_2
a * x_3 + b * y_3 + c * x_3 * y_3 + d = i_3

e * x_0 + f * y_0 + g * x_0 * y_0 + h = j_0
e * x_1 + f * y_1 + g * x_1 * y_1 + h = j_1
e * x_2 + f * y_2 + g * x_2 * y_2 + h = j_2
e * x_3 + f * y_3 + g * x_3 * y_3 + h = j_3

再次,您可以使用线性代数:
$ b $

  [x_0 y_0 x_0 * y_0 1] [ae] [i_0 j_0] 
[x_1 y_1 x_1 * y_1 1] * [bf] = [i_1 j_1]
[x_2 y_2 x_2 * y_2 1] [cg] [i_2 j_2]
[x_3 y_3 x_3 * y_3 1] [dh] [i_3 j_3]

插入角的x_n,y_n,i_n,j_n。 (角落效果最好,因为如果你从用户点击中选择点数,它们相距很远就可以减少错误)。取4×4矩阵的逆矩阵,并将它乘以等式的右边。该矩阵的转置是P.您应该能够找到函数来计算矩阵逆并在线乘法。

您可能会遇到以下错误:

>


  • 计算时,记得检查零除。这表明你的矩阵不可逆。如果您尝试将一个(x,y)坐标映射到两个不同点,则可能会发生这种情况。如果您编写自己的矩阵数学,请记住矩阵通常是指定的行,列(垂直,水平)和屏幕图形是x,y(水平,垂直)。您一定会在第一次遇到问题。


Given two image buffers (assume it's an array of ints of size width * height, with each element a color value), how can I map an area defined by a quadrilateral from one image buffer into the other (always square) image buffer? I'm led to understand this is called "projective transformation".

I'm also looking for a general (not language- or library-specific) way of doing this, such that it could be reasonably applied in any language without relying on "magic function X that does all the work for me".

An example: I've written a short program in Java using the Processing library (processing.org) that captures video from a camera. During an initial "calibrating" step, the captured video is output directly into a window. The user then clicks on four points to define an area of the video that will be transformed, then mapped into the square window during subsequent operation of the program. If the user were to click on the four points defining the corners of a door visible at an angle in the camera's output, then this transformation would cause the subsequent video to map the transformed image of the door to the entire area of the window, albeit somewhat distorted.

解决方案

Using linear algebra is much easier than all that geometry! Plus you won't need to use sine, cosine, etc, so you can store each number as a rational fraction and get the exact numerical result if you need it.

What you want is a mapping from your old (x,y) co-ordinates to your new (x',y') co-ordinates. You can do it with matrices. You need to find the 2-by-4 projection matrix P such that P times the old coordinates equals the new co-ordinates. We'll assume that you're mapping lines to lines (not, for instance, straight lines to parabolas). Because you have a projection (parallel lines don't stay parallel) and translation (sliding), you need a factor of (xy) and (1), too. Drawn as matrices:

          [x  ]
[a b c d]*[y  ] = [x']
[e f g h] [x*y]   [y']
          [1  ]

You need to know a through h so solve these equations:

a*x_0 + b*y_0 + c*x_0*y_0 + d = i_0
a*x_1 + b*y_1 + c*x_1*y_1 + d = i_1
a*x_2 + b*y_2 + c*x_2*y_2 + d = i_2
a*x_3 + b*y_3 + c*x_3*y_3 + d = i_3

e*x_0 + f*y_0 + g*x_0*y_0 + h = j_0
e*x_1 + f*y_1 + g*x_1*y_1 + h = j_1
e*x_2 + f*y_2 + g*x_2*y_2 + h = j_2
e*x_3 + f*y_3 + g*x_3*y_3 + h = j_3

Again, you can use linear algebra:

[x_0 y_0 x_0*y_0 1]   [a e]   [i_0 j_0]
[x_1 y_1 x_1*y_1 1] * [b f] = [i_1 j_1]
[x_2 y_2 x_2*y_2 1]   [c g]   [i_2 j_2]
[x_3 y_3 x_3*y_3 1]   [d h]   [i_3 j_3]

Plug in your corners for x_n,y_n,i_n,j_n. (Corners work best because they are far apart to decrease the error if you're picking the points from, say, user-clicks.) Take the inverse of the 4x4 matrix and multiply it by the right side of the equation. The transpose of that matrix is P. You should be able to find functions to compute a matrix inverse and multiply online.

Where you'll probably have bugs:

  • When computing, remember to check for division by zero. That's a sign that your matrix is not invertible. That might happen if you try to map one (x,y) co-ordinate to two different points.
  • If you write your own matrix math, remember that matrices are usually specified row,column (vertical,horizontal) and screen graphics are x,y (horizontal,vertical). You're bound to get something wrong the first time.

这篇关于射影变换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆