pasar partir online jpg imagen full fotos crear convertir delphi math geometry pascal lazarus

delphi - partir - inkscape full



Redibujar imagen desde perspectiva 3d a 2d (2)

Necesito una transformada de perspectiva inversa escrita en Pascal / Delphi / Lazarus. Vea la siguiente imagen:

Creo que necesito recorrer los píxeles de destino y luego calcular la posición correspondiente en la imagen de origen (para evitar problemas con errores de redondeo, etc.).

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;

Necesito la fórmula real ... Entonces, una solución OpenGL no sería ideal ...



Nota: Hay una versión de esto con una composición matemática adecuada en Math SE.

Computando una transformación proyectiva.

Una perspectiva es un caso especial de una transformación proyectiva , que a su vez se define por cuatro puntos.

Paso 1: Comenzando con las 4 posiciones en la imagen de origen, llamadas (x1,y1) a (x4,y4) , resuelve el siguiente sistema de ecuaciones lineales :

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

Las columnas forman coordenadas homogéneas : una dimensión más, creadas agregando un 1 como la última entrada. En los pasos posteriores, los múltiplos de estos vectores se utilizarán para denotar los mismos puntos. Vea el último paso para ver un ejemplo de cómo convertirlos de nuevo en coordenadas bidimensionales.

Paso 2: Escale las columnas por los coeficientes que acaba de calcular:

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

Esta matriz asignará (1,0,0) a un múltiplo de (x1,y1,1) , (0,1,0) a un múltiplo de (x2,y2,1) , (0,0,1) a un múltiplo de (x3,y3,1) y (1,1,1) a (x4,y4,1) . Por lo tanto, asignará estos cuatro vectores especiales (llamados vectores de base en explicaciones posteriores) a las posiciones especificadas en la imagen.

Paso 3: Repita los pasos 1 y 2 para las posiciones correspondientes en la imagen de destino, para obtener una segunda matriz llamada B

Este es un mapa de vectores de base a posiciones de destino.

Paso 4: Invert B para obtener B⁻¹ .

B mapas B de los vectores base a las posiciones de destino, por lo que la matriz inversa se asigna en la dirección inversa.

Paso 5: Calcular la matriz combined C = A∙B⁻¹ .

B⁻¹ asigna desde posiciones de destino a vectores de base, mientras que A asigna desde allí a posiciones de origen. Así que la combinación asigna las posiciones de destino a las posiciones de origen.

Paso 6: Para cada píxel (x,y) de la imagen de destino, calcule el producto

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

Estas son las coordenadas homogéneas de tu punto transformado.

Paso 7: Calcule la posición en la imagen de origen de esta manera:

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

Esto se denomina deshomogenización del vector de coordenadas.

Todas estas matemáticas serían mucho más fáciles de leer y escribir si SO fuera compatible con MathJax ...

Elegir el tamaño de la imagen

El enfoque anterior supone que conoce la ubicación de sus esquinas en la imagen de destino. Para estos, debe conocer el ancho y el alto de esa imagen, que también está marcada con signos de interrogación en su código. Así que supongamos que la height de la imagen de salida es 1 , y el width sourceaspect . En ese caso, el área general también sería sourceaspect . Tienes que escalar esa área por un factor de pixelcount/sourceaspect de pixelcount/sourceaspect para lograr un área de pixelcount de pixelcount . Lo que significa que tienes que escalar cada longitud de borde por la raíz cuadrada de ese factor. Así que al final, tienes

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