Kas*_* DK 17 delphi math geometry pascal lazarus
我需要用Pascal/Delphi/Lazarus编写的逆透视变换.见下图:

我想我需要遍历目标像素,然后计算源图像中的相应位置(以避免舍入错误等问题).
function redraw_3d_to_2d(sourcebitmap:tbitmap, sourceaspect:extended, point_a, point_b, point_c, point_d:tpoint, megapixelcount:integer):tbitmap;
var
destinationbitmap:tbitmap;
x,y,sx,sy:integer;
begin
destinationbitmap:=tbitmap.create;
destinationbitmap.width=megapixelcount*sourceaspect*???; // I dont how to calculate this
destinationbitmap.height=megapixelcount*sourceaspect*???; // I dont how to calculate this
for x:=0 to destinationbitmap.width-1 do
for y:=0 to destinationbitmap.height-1 do
begin
sx:=??;
sy:=??;
destinationbitmap.canvas.pixels[x,y]=sourcebitmap.canvas.pixels[sx,sy];
end;
result:=destinationbitmap;
end;
Run Code Online (Sandbox Code Playgroud)
我需要真正的公式......所以OpenGL解决方案并不理想......
MvG*_*MvG 20
注意:有一个版本的这对数学SE适当的数学排版.
步骤1:从源图像中的4个位置开始,(x1,y1)通过命名(x4,y4),您可以求解以下线性方程组:
[x1 x2 x3] [?] [x4]
[y1 y2 y3]?[?] = [y4]
[ 1 1 1] [?] [ 1]
Run Code Online (Sandbox Code Playgroud)
colums形成同质坐标:一个维度更多,通过添加a 1作为最后一个条目创建.在随后的步骤中,这些矢量的倍数将用于表示相同的点.有关如何将这些转换为二维坐标的示例,请参见最后一步.
第2步:按刚刚计算的系数缩放列:
[??x1 ??x2 ??x3]
A = [??y1 ??y2 ??y3]
[? ? ? ]
Run Code Online (Sandbox Code Playgroud)
该矩阵将映射(1,0,0)到的倍数(x1,y1,1),(0,1,0)以的倍数(x2,y2,1),(0,0,1)以的倍数(x3,y3,1)和(1,1,1)到(x4,y4,1).因此,它会将这四个特殊向量(在后续解释中称为基向向量)映射到图像中的指定位置.
步骤3:对目标图像中的相应位置重复步骤1和2,以获得第二个称为矩阵的矩阵B.
这是从基础向量到目标位置的映射.
第4步: 反转 B获取B?¹.
B 从基矢量到目标位置的映射,因此逆矩阵以相反的方向映射.
第5步:计算组合矩阵C = A?B?¹.
B?¹从目的地位置到基础向量的A映射,同时从那里到源位置的映射.因此,组合将目的地位置映射到源位置.
步骤6:对于(x,y)目标图像的每个像素,计算产品
[x'] [x]
[y'] = C?[y]
[z'] [1]
Run Code Online (Sandbox Code Playgroud)
这些是变换点的同质坐标.
第7步:计算源图像中的位置,如下所示:
sx = x'/z'
sy = y'/z'
Run Code Online (Sandbox Code Playgroud)
这被称为坐标向量的非均匀化.
如果SO 支持MathJax,所有这些数学将更容易读写 ... ☹
上述方法假定您知道目标图像中角落的位置.对于这些,您必须知道该图像的宽度和高度,在您的代码中也会用问号标记.因此,让我们假设height你的输出图像的人1,和width人sourceaspect.在这种情况下,整个区域sourceaspect也是如此.你必须按比例缩放该区域,pixelcount/sourceaspect以达到一个区域pixelcount.这意味着您必须按照该因子的平方根缩放每个边长.所以最后,你有
pixelcount = 1000000.*megapixelcount;
width = round(sqrt(pixelcount*sourceaspect));
height = round(sqrt(pixelcount/sourceaspect));
Run Code Online (Sandbox Code Playgroud)