what nearest bilinear graphics pixel interpolation

graphics - bilinear - nearest interpolation



extraer una imagen cuadrilátera a un rectángulo (3)

ACTUALIZACIÓN DE BOUNTY

Siguiendo el enlace de Denis , esta es la forma de utilizar el código threeblindmiceandamonkey :

// the destination rect is our ''in'' quad int dw = 300, dh = 250; double in[4][4] = {{0,0},{dw,0},{dw,dh},{0,dh}}; // the quad in the source image is our ''out'' double out[4][5] = {{171,72},{331,93},{333,188},{177,210}}; double homo[3][6]; const int ret = mapQuadToQuad(in,out,homo); // homo can be used for calculating the x,y of any destination point // in the source, e.g. for(int i=0; i<4; i++) { double p1[3] = {out[i][0],out[i][7],1}; double p2[3]; transformMatrix(p1,p2,homo); p2[0] /= p2[2]; // x p2[1] /= p2[2]; // y printf("/t%2.2f/t%2.2f/n",p2[0],p2[1]); }

Esto proporciona una transformación para convertir puntos en el destino a la fuente; por supuesto, puedes hacerlo al revés, pero está ordenado poder hacer esto para la mezcla:

for(int y=0; y<dh; y++) { for(int x=0; x<dw; x++) { // calc the four corners in source for this // destination pixel, and mix

Para la mezcla, estoy usando supermuestreo con puntos aleatorios; funciona muy bien, incluso cuando hay una gran disparidad en el área de origen y destino

PREGUNTA DE ANTECEDENTES

En la imagen en la parte superior, el letrero en el costado de la camioneta no está de cara a la cámara. Quiero calcular, lo mejor que pueda con los píxeles que tengo, cómo se vería de frente.

Sé las coordenadas de la esquina del quad en la imagen, y el tamaño del rectángulo de destino.

Me imagino que esto es una especie de ciclo a través del eje xey haciendo una línea de Bresenham en ambas dimensiones a la vez con algún tipo de mezcla, ya que los píxeles en las imágenes de origen y destino se superponen. ¿Alguna mezcla subpíxel de algún tipo?

¿Qué enfoques existen y cómo se mezclan los píxeles?

¿Hay un enfoque estándar para esto?



Busque la "quad to quad" transform , por ejemplo, threeblindmiceandamonkey .
Una transformada 3x3 en coordenadas homogéneas 2d puede transformar cualquier 4 puntos (un quad) en cualquier otro quad; por el contrario, cualquier combinación de culata y taco, como las esquinas de su camión y un rectángulo objetivo, dan una transformación de 3 x 3.

Qt tiene quadToQuad y puede transformar pixmaps con él, pero supongo que no tienes Qt?
10Jun añadido: desde labs.trolltech.com/page/Graphics/Examples hay una buena demostración que quad-to-quads un mapa de píxeles a medida que mueve las esquinas:

Agregó 11Jun: @Will, aquí está translate.h en Python (¿cuál sabe un poco? "" "..." "" son comentarios de líneas múltiples).
perstrans() es la clave; Espero que tenga sentido, si no preguntes.

De todos modos, podría mapear los píxeles uno por uno, mapQuadToQuad (rect objetivo, quad original), pero sin la interpolación de píxeles se verá terrible; OpenCV lo hace todo.

#!/usr/bin/env python """ square <-> quad maps from http://threeblindmiceandamonkey.com/?p=16 matrix.h """ from __future__ import division import numpy as np __date__ = "2010-06-11 jun denis" def det2(a, b, c, d): return a*d - b*c def mapSquareToQuad( quad ): # [4][2] SQ = np.zeros((3,3)) px = quad[0,0] - quad[1,0] + quad[2,0] - quad[3,0] py = quad[0,1] - quad[1,1] + quad[2,1] - quad[3,1] if abs(px) < 1e-10 and abs(py) < 1e-10: SQ[0,0] = quad[1,0] - quad[0,0] SQ[1,0] = quad[2,0] - quad[1,0] SQ[2,0] = quad[0,0] SQ[0,1] = quad[1,1] - quad[0,1] SQ[1,1] = quad[2,1] - quad[1,1] SQ[2,1] = quad[0,1] SQ[0,2] = 0. SQ[1,2] = 0. SQ[2,2] = 1. return SQ else: dx1 = quad[1,0] - quad[2,0] dx2 = quad[3,0] - quad[2,0] dy1 = quad[1,1] - quad[2,1] dy2 = quad[3,1] - quad[2,1] det = det2(dx1,dx2, dy1,dy2) if det == 0.: return None SQ[0,2] = det2(px,dx2, py,dy2) / det SQ[1,2] = det2(dx1,px, dy1,py) / det SQ[2,2] = 1. SQ[0,0] = quad[1,0] - quad[0,0] + SQ[0,2]*quad[1,0] SQ[1,0] = quad[3,0] - quad[0,0] + SQ[1,2]*quad[3,0] SQ[2,0] = quad[0,0] SQ[0,1] = quad[1,1] - quad[0,1] + SQ[0,2]*quad[1,1] SQ[1,1] = quad[3,1] - quad[0,1] + SQ[1,2]*quad[3,1] SQ[2,1] = quad[0,1] return SQ #............................................................................... def mapQuadToSquare( quad ): return np.linalg.inv( mapSquareToQuad( quad )) def mapQuadToQuad( a, b ): return np.dot( mapQuadToSquare(a), mapSquareToQuad(b) ) def perstrans( X, t ): """ perspective transform X Nx2, t 3x3: [x0 y0 1] t = [a0 b0 w0] -> [a0/w0 b0/w0] [x1 y1 1] t = [a1 b1 w1] -> [a1/w1 b1/w1] ... """ x1 = np.vstack(( X.T, np.ones(len(X)) )) y = np.dot( t.T, x1 ) return (y[:-1] / y[-1]) .T #............................................................................... if __name__ == "__main__": np.set_printoptions( 2, threshold=100, suppress=True ) # .2f sq = np.array([[0,0], [1,0], [1,1], [0,1]]) quad = np.array([[171, 72], [331, 93], [333, 188], [177, 210]]) print "quad:", quad print "square to quad:", perstrans( sq, mapSquareToQuad(quad) ) print "quad to square:", perstrans( quad, mapQuadToSquare(quad) ) dw, dh = 300, 250 rect = np.array([[0, 0], [dw, 0], [dw, dh], [0, dh]]) quadquad = mapQuadToQuad( quad, rect ) print "quad to quad transform:", quadquad print "quad to rect:", perstrans( quad, quadquad ) """ quad: [[171 72] [331 93] [333 188] [177 210]] square to quad: [[ 171. 72.] [ 331. 93.] [ 333. 188.] [ 177. 210.]] quad to square: [[-0. 0.] [ 1. 0.] [ 1. 1.] [ 0. 1.]] quad to quad transform: [[ 1.29 -0.23 -0. ] [ -0.06 1.79 -0. ] [-217.24 -88.54 1.34]] quad to rect: [[ 0. 0.] [ 300. 0.] [ 300. 250.] [ 0. 250.]] """


Lo que quieres se llama rectificación plana, y no es tan simple, me temo. Lo que tiene que hacer es recuperar la homografía que asigna esta vista oblicua del lado de la furgoneta a la vista frontal. Photoshop / etc. tiene herramientas para hacer esto por usted dado algunos puntos de control; si quieres implementarlo por ti mismo, tendrás que empezar a profundizar en la visión por computadora.

Editar - OK, aquí tienes: un script de Python para hacer el warping, usando la biblioteca OpenCV que tiene funciones convenientes para calcular la homografía y deformar la imagen por ti:

import cv def warpImage(image, corners, target): mat = cv.CreateMat(3, 3, cv.CV_32F) cv.GetPerspectiveTransform(corners, target, mat) out = cv.CreateMat(height, width, cv.CV_8UC3) cv.WarpPerspective(image, out, mat, cv.CV_INTER_CUBIC) return out if __name__ == ''__main__'': width, height = 400, 250 corners = [(171,72),(331,93),(333,188),(177,210)] target = [(0,0),(width,0),(width,height),(0,height)] image = cv.LoadImageM(''fries.jpg'') out = warpImage(image, corners, target) cv.SaveImage(''fries_warped.jpg'', out)

Y el resultado:

OpenCV también tiene enlaces C y C ++, o puede usar EmguCV para un contenedor .NET; la API es bastante uniforme en todos los idiomas, por lo que puedes replicar esto en el idioma que más te guste.