回答
老實說,我不知道該怎麼形容數學的透視失真。您可以嘗試搜索相關文獻(例如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. 如何使用cv :: warpPerspective進行透視轉換?
- 2. 透視轉換
- 3. JSSOR禁用轉換透視
- 4. CSS透視轉換
- 5. 使用CATransform3D透視的摺紙轉換
- 6. 轉換列使用數據透視
- 7. Mysql的轉換列,以行(透視表)
- 8. Python - 從旋轉角度對OpenCV進行透視變換
- 9. 使用Android OpenCV進行圖像透視變換
- 10. 透視變換+在iOS中使用OpenCV進行裁剪
- 11. 轉換爲alpha使用PHP GD
- 12. SQL - 轉換行而不使用數據透視等
- 13. 使用node_xslt進行轉換
- 14. 使用Raphael.js進行轉換
- 15. 透視圖/轉換矩陣
- 16. 將ORorte轉換爲透視
- 17. EaselJS透視圖像轉換
- 18. GD透明PNG
- 19. 轉化使用逆透視
- 20. 使用Java進行視頻轉碼/轉換
- 21. 應用透視無變換旋轉
- 22. 如何使用GD對PHP結果圖像進行着色使用GD
- 23. 用OpenCv進行透視檢測
- 24. 如何使用ffmpeg在php中進行視頻轉換?
- 25. 使用FFmpeg進行視頻旋轉
- 26. 使用jQuery進行懸停轉換
- 27. 使用xslt 1.0進行時間轉換
- 28. 使用SQL進行表格轉換
- 29. 使用numeric_std進行類型轉換
- 30. 使用XSLT進行XML到CSV轉換
這已經回答了[這裏] [1]。 [1]:http://stackoverflow.com/a/2536847/577306 – Jarrod 2012-07-22 20:20:15