我想我需要走过目标像素,然后计算源图像中的相应位置(避免四舍五入错误等).
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解决方案不会是理想的…
解决方法
计算投影变革
一个透视是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));