使用 GD 进行透视变换
如何在图像上应用透视变换 仅使用 PHP GD 库?
我不想使用别人制作的功能我想了解发生了什么
How can I apply a perspective transformation on an image
using only the PHP GD library?
I don't want to use a function someone else made I want to UNDERSTAND what's going on
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
老实说,我不知道如何从数学上描述透视变形。您可以尝试搜索相关文献(例如 Google Scholar)。另请参阅 OpenGL 文档,
glFrustum
< /a>.编辑:有趣的是,从版本 8 开始,Mathematica 有一个 <代码>ImagePerspectiveTransformation。在相关部分,它说:
对于某些
a
(矩阵)、b
(向量)、c
(向量)和d
,这是一种变换code>(标量),将向量r
转换为(a.r+b)/(c.r+d)
。在 2D 情况下,这给出了 齐次矩阵:要应用变换,请乘以该矩阵通过用
z=1
扩展的列向量,然后将结果的前两个元素除以第三个: 得到:
通过示例:
您将得到以下转换:
一旦你有了一张用原始图像中的点来描述最终图像的点的位置的地图,它就只是一个找到新图像中每个点的值的问题。
还有一个额外的困难。由于图像是离散的,即具有像素而不是连续值,因此必须使其连续。
假设您有一个将图像大小加倍的转换。用于计算最终图像中的点
{x,y}
的函数将在原始图像中查找点{x/2, y/2}
。这一点不存在,因为图像是离散的。所以你必须对这一点进行插值。为此有几种可能的策略。在此 Mathematica 示例中,我执行简单的 2D 旋转并使用 1 度样条函数进行插值:
这给出:
PHP:
对于插值,请在 google 上搜索“B-spline”。其余部分如下。
首先选择原始图像的参考,假设图像为 200x200,则像素 (1,1) 映射 (0,0),像素 (200,200) 映射到 (1,1)。
然后你必须猜测应用变换时最终图像将落在哪里。这取决于变换,您可以将其应用于图像的角点或只是猜测。
假设您像我一样考虑 (-.5,0) 和 (1, 1.5) 之间的映射,并且您的最终图像也应该是 200x200。然后:
I honestly don't know how to describe mathematically a perspective distortion. You could try searching the literature for that (e.g. Google Scholar). See also in the OpenGL documentation,
glFrustum
.EDIT: Interestingly, starting with version 8, Mathematica has a
ImagePerspectiveTransformation
. In the relevant part, it says:This is a transformation that, for some
a
(matrix),b
(vector),c
(vector) andd
(scalar), transforms the vectorr
to(a.r+b)/(c.r+d)
. In a 2D situation, this gives the homogeneous matrix:To apply the transformation, you multiply this matrix by the column vector extended with
z=1
and then take the first two elements of the result and divide them by the third:which gives:
With the example:
You get this transformation:
Once you have a map that describes the position of a point of the final image in terms of a point in the original image, it's just a matter of finding its value for each of the points in the new image.
There's one additional difficulty. Since an image is discrete, i.e., has pixels instead of continuous values, you have to make it continuous.
Say you have a transformation that doubles the size of an image. The function to calculate a point
{x,y}
in the final image will look for point{x/2, y/2}
in the original. This point doesn't exist, because images are discrete. So you have to interpolate this point. There are several possible strategies for this.In this Mathematica example, I do a simple 2D rotation and use a degree-1 spline function to interpolate:
This gives:
PHP:
For the interpolation, google for "B-spline". The rest is as follows.
First choose a referential for the original image, say if the image is 200x200, pixel (1,1) maps (0,0) and pixel (200,200) maps to (1,1).
Then you have to guess where your final image will land when the transformation is applied. This depends on the transformation, you can e.g. apply it to the corners of the image or just guess.
Say you consider the mapped between (-.5,0) and (1, 1.5) like I did and that your final image should be 200x200 also. Then: