加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2020-12-15 10:07:51 所属栏目:大数据 来源:网络整理
导读:我需要用Pascal / Delphi / Lazarus写的逆透视变换.见下图: 我想我需要走过目标像素,然后计算源图像中的相应位置(避免四舍五入错误等). function redraw_3d_to_2d(sourcebitmap:tbitmap,sourceaspect:extended,point_a,point_b,point_c,point_d:tpoint,mega
我需要用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));

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读