回答
老实说,我不知道该怎么形容数学的透视失真。您可以尝试搜索相关文献(例如Google Scholar)。另请参阅OpenGL文档glFrustum
。
EDIT:有趣的是,从版本8,数学具有ImagePerspectiveTransformation
。在相关部分,它说:
对于一个3×3的矩阵
m
,ImagePerspectiveTransformation[image,m]
适用LinearFractionalTransform[m]
图像。
这是一个变换的是,对于一些a
(矩阵),b
(矢量),c
(矢量)和d
(标量),变换矢量r
到(a.r+b)/(c.r+d)
。在2D情况下,这给homogeneous matrix:
a_11 a_12 b_1
a_21 a_22 b_2
c_1 c_2 d
要应用变换,您可以通过扩展与z=1
列向量乘以这个矩阵,然后取结果的前两个元素和第三将它们划分:
{{a11, a12, b1}, {a21, a22, b2}, {c1, c2, d}}.{{x}, {y}, {1}} // #[[
1 ;; 2, All]]/#[[3, 1]] & // First /@ # &
其给出:
{(b1 + a11 x + a12 y)/(d + c1 x + c2 y),
(b2 + a21 x + a22 y)/(d + c1 x + c2 y)}
随着例如:
a = {{0.9, 0.1}, {0.3, 0.9}}
b = {0, -0.1}
c = {0, 0.1}
d = 1
你得到这样的转换:
im = Import["/home/cataphract/Downloads/so_q.png"];
orfun = BSplineFunction[ImageData[im], SplineDegree -> 1];
(*transf=TransformationFunction[{{0.9, 0.1, 0.}, {0.3,
0.9, -0.1}, {0., 0.1, 1.}}] -- let's expand this:*)
transf = {(0.9 x + 0.1 y)/(1.+ 0.1 y), (-0.1 + 0.3 x + 0.9 y)/(
1. + 0.1 y)} /. {x -> #[[1]], y -> #[[2]]} &;
ParametricPlot[transf[{x, y}], {x, 0, 1}, {y, 0, 1},
ColorFunction -> (orfun[1 - #4, #3] &),
Mesh -> None,
FrameTicks -> None,
Axes -> False,
ImageSize -> 200,
PlotRange -> All,
Frame -> False
]
一旦你有一个图,描述了点方面最终图像的点的位置在原图像,它只是为新图像中的每个点找到它的值。
还有一个额外的困难。由于图像是离散的,即具有像素而不是连续值,所以必须使其连续。
假设你有一个转换,使图像的大小加倍。在最终图像中计算点{x,y}
的函数将在原始中查找点{x/2, y/2}
。这一点不存在,因为图像是离散的。所以你必须插入这一点。有几种可能的策略。
在本数学实例中,我做一个简单的二维旋转,并使用度-1样条函数进行内插:
im = Import["d:\\users\\cataphract\\desktop\\img.png"]
orfun = BSplineFunction[ImageData[im], SplineDegree -> 1];
transf = Function[{coord}, RotationMatrix[20. Degree].coord];
ParametricPlot[transf[{x, y}], {x, 0, 1}, {y, 0, 1},
ColorFunction -> (orfun[1 - #4, #3] &), Mesh -> None,
FrameTicks -> None, Axes -> None, ImageSize -> 200,
PlotRange -> {{-0.5, 1}, {0, 1.5}}]
这给出:
PHP:
对于插值,谷歌为“B样条”。其余如下。
首先为原始图像选择一个参考,例如图像是200x200,像素(1,1)贴图(0,0)和像素(200,200)映射到(1,1)。
然后,您必须猜测应用转换时最终图像的着陆点。这取决于转换,你可以例如将它应用到图像的角落或只是猜测。假设你考虑像(我)那样映射到(-.5,0)和(1,1.5)之间,并且你的最终图像也应该是200x200。然后:
$sizex = 200;
$sizey = 200;
$x = array("min"=>-.5, "max" => 1);
$y = array("min"=>0, "max" => 1.5);
// keep $sizex/$sizey == $rangex/$rangey
$rangex = $x["max"] - $x["min"];
$rangey = $y["max"] - $y["min"];
for ($xp = 1; $xp <= $sizex; $xp++) {
for ($yp = 1; $yp <= $sizey; $yp++) {
$value = transf(
(($xp-1)/($sizex-1)) * $rangex + $x["min"],
(($yp-1)/($sizey-1)) * $rangey + $y["min"]);
/* $value should be in the form array(r, g, b), for instance */
}
}
有趣的,但似乎并没有被PHP代码(是吗?) – 2010-08-22 04:23:05
@马克不,不是这样的。这是Mathematica。在PHP中,您必须自己实现样条线并使用两个循环(嵌套)来构建参数图。但原则是一样的。 – Artefacto 2010-08-22 04:25:53
你将如何使用循环将其实现到PHP中? – 2010-08-22 04:27:51
- 1. 透视转换
- 2. CSS透视转换
- 3. 转换列使用数据透视
- 4. 使用CATransform3D透视的折纸转换
- 5. Python - 从旋转角度对OpenCV进行透视变换
- 6. 使用Android OpenCV进行图像透视变换
- 7. 转换为alpha使用PHP GD
- 8. EaselJS透视图像转换
- 9. 透视图/转换矩阵
- 10. GD透明PNG
- 11. 使用Java进行视频转码/转换
- 12. 用OpenCv进行透视检测
- 13. 如何使用GD对PHP结果图像进行着色使用GD
- 14. 转换透视表数据帧
- 15. 如何特别转换透视原点?
- 16. 转换数据帧(数据透视)
- 17. 透视投影 - 如何转换坐标
- 18. 曲线透视:将3D转换为2D
- 19. mysql将结果转换为使用php的数据透视表
- 20. 使用Python进行IP地址转换
- 21. 使用xslt 1.0进行时间转换
- 22. 使用ResourceDictionary进行图像转换
- 23. 使用父节点进行XSLT转换
- 24. 使用XSLT进行XML转换
- 25. 使用scss进行多重转换
- 26. 使用Python 2.7进行类型转换
- 27. 使用Spark进行字符串转换
- 28. 使用XSLT2进行XML转换分组
- 29. 使用Aspose进行HTML到PDF转换
- 30. 使用openweathermap API进行温度转换
这已经回答了[这里] [1]。 [1]:http://stackoverflow.com/a/2536847/577306 – Jarrod 2012-07-22 20:20:15