delphi – 从3d透视图将图像重绘为2d

前端之家收集整理的这篇文章主要介绍了delphi – 从3d透视图将图像重绘为2d前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我需要用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;

我需要真正的公式…所以一个OpenGL解决方案不会是理想的…

解决方法

注意:在数学SE上有适合数学排版的 a version of this.

计算投影变革

一个透视是projective transformation的一个特殊情况,反过来又被四点定义.

步骤1:从源图像中的4个位置(名称为(x1,y1)到(x4,y4))开始,解决以下system of linear equations

[x1 x2 x3] [λ]   [x4]
[y1 y2 y3]∙[μ] = [y4]
[ 1  1  1] [τ]   [ 1]

列为homogenous coordinates:一维更多,通过添加1作为最后一个条目创建.在随后的步骤中,这些向量的倍数将用于表示相同的点.有关如何将它们转回二维坐标的示例,请参阅最后一步.

步骤2:按照刚刚计算的系数缩放列:

[λ∙x1 μ∙x2 τ∙x3]
A = [λ∙y1 μ∙y2 τ∙y3]
    [λ    μ    τ   ]

该矩阵将(1,0)映射到(x1,y1,1),(0,1,0)的倍数为(x2,y2,1)的倍数,(x3,y3,1)和(1,1)至(x4,y4,1)的倍数.因此,它将映射这四个特殊向量(在随后的说明中称为基本向量)到图像中的指定位置.

步骤3:对目标图像中的相应位置重复步骤1和2,以获得称为B的第二个矩阵.

这是从基础向量到目标位置的地图.

步骤4:Invert B得到B -1.

B从基矢量映射到目标位置,因此逆矩阵沿相反方向映射.

步骤5:计算combined矩阵C = A∙B -1.

B – 1从目标位置映射到基向量,而A映射到源位置.因此,组合将目标位置映射到源位置.

步骤6:对于目标图像的每个像素(x,y),计算产品

[x']     [x]
[y'] = C∙[y]
[z']     [1]

这些是您转换点的均匀坐标.

步骤7:计算源图像中的位置,如下所示:

sx = x'/z'
sy = y'/z'

这被称为坐标矢量的去谐波.

所有这些数学将是so much easier to read and write如果SO是support MathJax …☹

选择图像大小

上面的aproach假设你知道你的角落在目的地图像中的位置.对于这些,您必须知道该图像的宽度和高度,它也由您的代码中的问号标记.所以我们假定输出图像的高度为1,宽度为sourceaspect.在这种情况下,整体面积也是源源不绝的.您必须以pixelcount / sourceaspect为因子来缩放该区域,以达到像素数的一个区域.这意味着您必须按照该因子的平方根来缩放每个边长.所以到最后,你有

pixelcount = 1000000.*megapixelcount;
width  = round(sqrt(pixelcount*sourceaspect));
height = round(sqrt(pixelcount/sourceaspect));

猜你在找的Delphi相关文章