Pregunta

Dada una imagen 2D de un rectángulo distorsionado por la perspectiva:

introducir descripción de la imagen aquí

Sé que la forma era originalmente un rectángulo, pero no sé su tamaño original.

Si conozco las coordenadas en píxeles de las esquinas de la imagen, ¿cómo puedo calcular las proporciones originales, es decir, el cociente (ancho / alto) del rectángulo?

(fondo: el objetivo es automáticamente undistort fotos de documentos rectangulares, detección de bordes, probablemente se hace con transformada de Hough)

UPDATE:

Ha habido cierto debate sobre si es posible en absoluto para determinar el ancho: relación de altura con la información dada. Mi pensamiento era ingenua de que debe ser posible, ya que se me ocurre ninguna manera de proyectar por ejemplo, un 1: 4 rectángulo en el cuadrángulo ha representado anteriormente. La relación aparece claramente cercana a 1: 1, por lo que debe ser una forma de determinar matemáticamente. Tengo sin embargo, ninguna prueba de esto más allá de mi conjetura intuitiva.

Todavía no he entendido completamente los argumentos presentados más adelante, pero creo que tiene que haber alguna suposición implícita de que nos falta aquí y que se interpreta de manera diferente.

Sin embargo, después de horas de búsqueda, he encontrado finalmente algunos documentos relevantes para el problema. Estoy luchando para entender las matemáticas utilizadas en ese país, hasta ahora sin éxito. En particular, el primer documento parece discutir exactamente lo que quería hacer, por desgracia, sin ejemplos de código y matemáticas muy denso.

  • Zhengyou Zhang, Li-Wei, "la exploración Pizarra y mejora de la imagen" http://research.microsoft.com/en -us / um / personas / Zhang / documentos / tr03-39.pdf p.11

      

    "A causa de la distorsión de la perspectiva, la imagen de un rectángulo parece ser un cuadrilátero. Sin embargo, ya que sabemos que es un rectángulo en el espacio, somos capaces de estimar tanto la longitud focal de la cámara y la relación de aspecto del rectángulo. "

  • ROBERT M. Haralick "Determinación de parámetros de la cámara a partir de la proyección en perspectiva de un rectángulo" http://portal.acm.org/citation.cfm?id=87146

      

    "mostramos cómo utilizar la proyección en perspectiva 2D de un rectángulo del tamaño y la posición desconocida en el espacio 3D para determinar los parámetros de ángulo de visión de la cámara en relación con los planes del rectángulo."

¿Fue útil?

Solución

Aquí está mi intento de responder a mi pregunta después de leer el periódico

manipulé las ecuaciones por algún tiempo en SAGE, y se acercó con esta pseudo-código en C-style:


// in case it matters: licensed under GPLv2 or later
// legend:
// sqr(x)  = x*x
// sqrt(x) = square root of x

// let m1x,m1y ... m4x,m4y be the (x,y) pixel coordinates
// of the 4 corners of the detected quadrangle
// i.e. (m1x, m1y) are the cordinates of the first corner, 
// (m2x, m2y) of the second corner and so on.
// let u0, v0 be the pixel coordinates of the principal point of the image
// for a normal camera this will be the center of the image, 
// i.e. u0=IMAGEWIDTH/2; v0 =IMAGEHEIGHT/2
// This assumption does not hold if the image has been cropped asymmetrically

// first, transform the image so the principal point is at (0,0)
// this makes the following equations much easier
m1x = m1x - u0;
m1y = m1y - v0;
m2x = m2x - u0;
m2y = m2y - v0;
m3x = m3x - u0;
m3y = m3y - v0;
m4x = m4x - u0;
m4y = m4y - v0;


// temporary variables k2, k3
double k2 = ((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y - m1y*m4x) /
            ((m2y - m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x) ;

double k3 = ((m1y - m4y)*m2x - (m1x - m4x)*m2y + m1x*m4y - m1y*m4x) / 
            ((m3y - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y - m3y*m4x) ;

// f_squared is the focal length of the camera, squared
// if k2==1 OR k3==1 then this equation is not solvable
// if the focal length is known, then this equation is not needed
// in that case assign f_squared= sqr(focal_length)
double f_squared = 
    -((k3*m3y - m1y)*(k2*m2y - m1y) + (k3*m3x - m1x)*(k2*m2x - m1x)) / 
                      ((k3 - 1)*(k2 - 1)) ;

//The width/height ratio of the original rectangle
double whRatio = sqrt( 
    (sqr(k2 - 1) + sqr(k2*m2y - m1y)/f_squared + sqr(k2*m2x - m1x)/f_squared) /
    (sqr(k3 - 1) + sqr(k3*m3y - m1y)/f_squared + sqr(k3*m3x - m1x)/f_squared) 
) ;

// if k2==1 AND k3==1, then the focal length equation is not solvable 
// but the focal length is not needed to calculate the ratio.
// I am still trying to figure out under which circumstances k2 and k3 become 1
// but it seems to be when the rectangle is not distorted by perspective, 
// i.e. viewed straight on. Then the equation is obvious:
if (k2==1 && k3==1) whRatio = sqrt( 
    (sqr(m2y-m1y) + sqr(m2x-m1x)) / 
    (sqr(m3y-m1y) + sqr(m3x-m1x))


// After testing, I found that the above equations 
// actually give the height/width ratio of the rectangle, 
// not the width/height ratio. 
// If someone can find the error that caused this, 
// I would be most grateful.
// until then:
whRatio = 1/whRatio;

Actualización: aquí es cómo estas ecuaciones, donde determinaron:

El siguiente es el código en SAGE . Se puede acceder en línea en http://www.sagenb.org/home/pub/704/ . (Sage es muy útil en la resolución de ecuaciones, y utilizable en cualquier navegador, comprobar que funciona)

# CALCULATING THE ASPECT RATIO OF A RECTANGLE DISTORTED BY PERSPECTIVE

#
# BIBLIOGRAPHY:
# [zhang-single]: "Single-View Geometry of A Rectangle 
#  With Application to Whiteboard Image Rectification"
#  by Zhenggyou Zhang
#  http://research.microsoft.com/users/zhang/Papers/WhiteboardRectification.pdf

# pixel coordinates of the 4 corners of the quadrangle (m1, m2, m3, m4)
# see [zhang-single] figure 1
m1x = var('m1x')
m1y = var('m1y')
m2x = var('m2x')
m2y = var('m2y')
m3x = var('m3x')
m3y = var('m3y')
m4x = var('m4x')
m4y = var('m4y')

# pixel coordinates of the principal point of the image
# for a normal camera this will be the center of the image, 
# i.e. u0=IMAGEWIDTH/2; v0 =IMAGEHEIGHT/2
# This assumption does not hold if the image has been cropped asymmetrically
u0 = var('u0')
v0 = var('v0')

# pixel aspect ratio; for a normal camera pixels are square, so s=1
s = var('s')

# homogenous coordinates of the quadrangle
m1 = vector ([m1x,m1y,1])
m2 = vector ([m2x,m2y,1])
m3 = vector ([m3x,m3y,1])
m4 = vector ([m4x,m4y,1])


# the following equations are later used in calculating the the focal length 
# and the rectangle's aspect ratio.
# temporary variables: k2, k3, n2, n3

# see [zhang-single] Equation 11, 12
k2_ = m1.cross_product(m4).dot_product(m3) / m2.cross_product(m4).dot_product(m3)
k3_ = m1.cross_product(m4).dot_product(m2) / m3.cross_product(m4).dot_product(m2)
k2 = var('k2')
k3 = var('k3')

# see [zhang-single] Equation 14,16
n2 = k2 * m2 - m1
n3 = k3 * m3 - m1


# the focal length of the camera.
f = var('f')
# see [zhang-single] Equation 21
f_ = sqrt(
         -1 / (
          n2[2]*n3[2]*s^2
         ) * (
          (
           n2[0]*n3[0] - (n2[0]*n3[2]+n2[2]*n3[0])*u0 + n2[2]*n3[2]*u0^2
          )*s^2 + (
           n2[1]*n3[1] - (n2[1]*n3[2]+n2[2]*n3[1])*v0 + n2[2]*n3[2]*v0^2
          ) 
         ) 
        )


# standard pinhole camera matrix
# see [zhang-single] Equation 1
A = matrix([[f,0,u0],[0,s*f,v0],[0,0,1]])


#the width/height ratio of the original rectangle
# see [zhang-single] Equation 20
whRatio = sqrt (
               (n2*A.transpose()^(-1) * A^(-1)*n2.transpose()) / 
               (n3*A.transpose()^(-1) * A^(-1)*n3.transpose())
              ) 

Las ecuaciones simplificadas de la c-código donde determinados por

print "simplified equations, assuming u0=0, v0=0, s=1"
print "k2 := ", k2_
print "k3 := ", k3_
print "f  := ", f_(u0=0,v0=0,s=1)
print "whRatio := ", whRatio(u0=0,v0=0,s=1)

    simplified equations, assuming u0=0, v0=0, s=1
    k2 :=  ((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y - m1y*m4x)/((m2y
    - m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x)
    k3 :=  ((m1y - m4y)*m2x - (m1x - m4x)*m2y + m1x*m4y - m1y*m4x)/((m3y
    - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y - m3y*m4x)
    f  :=  sqrt(-((k3*m3y - m1y)*(k2*m2y - m1y) + (k3*m3x - m1x)*(k2*m2x
    - m1x))/((k3 - 1)*(k2 - 1)))
    whRatio :=  sqrt(((k2 - 1)^2 + (k2*m2y - m1y)^2/f^2 + (k2*m2x -
    m1x)^2/f^2)/((k3 - 1)^2 + (k3*m3y - m1y)^2/f^2 + (k3*m3x -
    m1x)^2/f^2))

print "Everything in one equation:"
print "whRatio := ", whRatio(f=f_)(k2=k2_,k3=k3_)(u0=0,v0=0,s=1)

    Everything in one equation:
    whRatio :=  sqrt(((((m1y - m4y)*m2x - (m1x - m4x)*m2y + m1x*m4y -
    m1y*m4x)/((m3y - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y - m3y*m4x) -
    1)*(((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y - m1y*m4x)/((m2y -
    m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x) - 1)*(((m1y -
    m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y - m1y*m4x)*m2y/((m2y - m4y)*m3x
    - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x) - m1y)^2/((((m1y - m4y)*m2x -
    (m1x - m4x)*m2y + m1x*m4y - m1y*m4x)*m3y/((m3y - m4y)*m2x - (m3x -
    m4x)*m2y + m3x*m4y - m3y*m4x) - m1y)*(((m1y - m4y)*m3x - (m1x -
    m4x)*m3y + m1x*m4y - m1y*m4x)*m2y/((m2y - m4y)*m3x - (m2x - m4x)*m3y
    + m2x*m4y - m2y*m4x) - m1y) + (((m1y - m4y)*m2x - (m1x - m4x)*m2y +
    m1x*m4y - m1y*m4x)*m3x/((m3y - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y
    - m3y*m4x) - m1x)*(((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y -
    m1y*m4x)*m2x/((m2y - m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x)
    - m1x)) + (((m1y - m4y)*m2x - (m1x - m4x)*m2y + m1x*m4y -
    m1y*m4x)/((m3y - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y - m3y*m4x) -
    1)*(((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y - m1y*m4x)/((m2y -
    m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x) - 1)*(((m1y -
    m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y - m1y*m4x)*m2x/((m2y - m4y)*m3x
    - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x) - m1x)^2/((((m1y - m4y)*m2x -
    (m1x - m4x)*m2y + m1x*m4y - m1y*m4x)*m3y/((m3y - m4y)*m2x - (m3x -
    m4x)*m2y + m3x*m4y - m3y*m4x) - m1y)*(((m1y - m4y)*m3x - (m1x -
    m4x)*m3y + m1x*m4y - m1y*m4x)*m2y/((m2y - m4y)*m3x - (m2x - m4x)*m3y
    + m2x*m4y - m2y*m4x) - m1y) + (((m1y - m4y)*m2x - (m1x - m4x)*m2y +
    m1x*m4y - m1y*m4x)*m3x/((m3y - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y
    - m3y*m4x) - m1x)*(((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y -
    m1y*m4x)*m2x/((m2y - m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x)
    - m1x)) - (((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y -
    m1y*m4x)/((m2y - m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x) -
    1)^2)/((((m1y - m4y)*m2x - (m1x - m4x)*m2y + m1x*m4y -
    m1y*m4x)/((m3y - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y - m3y*m4x) -
    1)*(((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y - m1y*m4x)/((m2y -
    m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x) - 1)*(((m1y -
    m4y)*m2x - (m1x - m4x)*m2y + m1x*m4y - m1y*m4x)*m3y/((m3y - m4y)*m2x
    - (m3x - m4x)*m2y + m3x*m4y - m3y*m4x) - m1y)^2/((((m1y - m4y)*m2x -
    (m1x - m4x)*m2y + m1x*m4y - m1y*m4x)*m3y/((m3y - m4y)*m2x - (m3x -
    m4x)*m2y + m3x*m4y - m3y*m4x) - m1y)*(((m1y - m4y)*m3x - (m1x -
    m4x)*m3y + m1x*m4y - m1y*m4x)*m2y/((m2y - m4y)*m3x - (m2x - m4x)*m3y
    + m2x*m4y - m2y*m4x) - m1y) + (((m1y - m4y)*m2x - (m1x - m4x)*m2y +
    m1x*m4y - m1y*m4x)*m3x/((m3y - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y
    - m3y*m4x) - m1x)*(((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y -
    m1y*m4x)*m2x/((m2y - m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x)
    - m1x)) + (((m1y - m4y)*m2x - (m1x - m4x)*m2y + m1x*m4y -
    m1y*m4x)/((m3y - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y - m3y*m4x) -
    1)*(((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y - m1y*m4x)/((m2y -
    m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x) - 1)*(((m1y -
    m4y)*m2x - (m1x - m4x)*m2y + m1x*m4y - m1y*m4x)*m3x/((m3y - m4y)*m2x
    - (m3x - m4x)*m2y + m3x*m4y - m3y*m4x) - m1x)^2/((((m1y - m4y)*m2x -
    (m1x - m4x)*m2y + m1x*m4y - m1y*m4x)*m3y/((m3y - m4y)*m2x - (m3x -
    m4x)*m2y + m3x*m4y - m3y*m4x) - m1y)*(((m1y - m4y)*m3x - (m1x -
    m4x)*m3y + m1x*m4y - m1y*m4x)*m2y/((m2y - m4y)*m3x - (m2x - m4x)*m3y
    + m2x*m4y - m2y*m4x) - m1y) + (((m1y - m4y)*m2x - (m1x - m4x)*m2y +
    m1x*m4y - m1y*m4x)*m3x/((m3y - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y
    - m3y*m4x) - m1x)*(((m1y - m4y)*m3x - (m1x - m4x)*m3y + m1x*m4y -
    m1y*m4x)*m2x/((m2y - m4y)*m3x - (m2x - m4x)*m3y + m2x*m4y - m2y*m4x)
    - m1x)) - (((m1y - m4y)*m2x - (m1x - m4x)*m2y + m1x*m4y -
    m1y*m4x)/((m3y - m4y)*m2x - (m3x - m4x)*m2y + m3x*m4y - m3y*m4x) -
    1)^2))


# some testing:
# - choose a random rectangle, 
# - project it onto a random plane,
# - insert the corners in the above equations,
# - check if the aspect ratio is correct.

from sage.plot.plot3d.transform import rotate_arbitrary

#redundandly random rotation matrix
rand_rotMatrix = \
           rotate_arbitrary((uniform(-5,5),uniform(-5,5),uniform(-5,5)),uniform(-5,5)) *\
           rotate_arbitrary((uniform(-5,5),uniform(-5,5),uniform(-5,5)),uniform(-5,5)) *\
           rotate_arbitrary((uniform(-5,5),uniform(-5,5),uniform(-5,5)),uniform(-5,5))

#random translation vector
rand_transVector = vector((uniform(-10,10),uniform(-10,10),uniform(-10,10))).transpose()

#random rectangle parameters
rand_width =uniform(0.1,10)
rand_height=uniform(0.1,10)
rand_left  =uniform(-10,10)
rand_top   =uniform(-10,10)

#random focal length and principal point
rand_f  = uniform(0.1,100)
rand_u0 = uniform(-100,100)
rand_v0 = uniform(-100,100)

# homogenous standard pinhole projection, see [zhang-single] Equation 1
hom_projection = A * rand_rotMatrix.augment(rand_transVector)

# construct a random rectangle in the plane z=0, then project it randomly 
rand_m1hom = hom_projection*vector((rand_left           ,rand_top            ,0,1)).transpose()
rand_m2hom = hom_projection*vector((rand_left           ,rand_top+rand_height,0,1)).transpose()
rand_m3hom = hom_projection*vector((rand_left+rand_width,rand_top            ,0,1)).transpose()
rand_m4hom = hom_projection*vector((rand_left+rand_width,rand_top+rand_height,0,1)).transpose()

#change type from 1x3 matrix to vector
rand_m1hom = rand_m1hom.column(0)
rand_m2hom = rand_m2hom.column(0)
rand_m3hom = rand_m3hom.column(0)
rand_m4hom = rand_m4hom.column(0)

#normalize
rand_m1hom = rand_m1hom/rand_m1hom[2]
rand_m2hom = rand_m2hom/rand_m2hom[2]
rand_m3hom = rand_m3hom/rand_m3hom[2]
rand_m4hom = rand_m4hom/rand_m4hom[2]

#substitute random values for f, u0, v0
rand_m1hom = rand_m1hom(f=rand_f,s=1,u0=rand_u0,v0=rand_v0)
rand_m2hom = rand_m2hom(f=rand_f,s=1,u0=rand_u0,v0=rand_v0)
rand_m3hom = rand_m3hom(f=rand_f,s=1,u0=rand_u0,v0=rand_v0)
rand_m4hom = rand_m4hom(f=rand_f,s=1,u0=rand_u0,v0=rand_v0)

# printing the randomly choosen values
print "ground truth: f=", rand_f, "; ratio=", rand_width/rand_height

# substitute all the variables in the equations:
print "calculated: f= ",\
f_(k2=k2_,k3=k3_)(s=1,u0=rand_u0,v0=rand_v0)(
  m1x=rand_m1hom[0],m1y=rand_m1hom[1],
  m2x=rand_m2hom[0],m2y=rand_m2hom[1],
  m3x=rand_m3hom[0],m3y=rand_m3hom[1],
  m4x=rand_m4hom[0],m4y=rand_m4hom[1],
),"; 1/ratio=", \
1/whRatio(f=f_)(k2=k2_,k3=k3_)(s=1,u0=rand_u0,v0=rand_v0)(
  m1x=rand_m1hom[0],m1y=rand_m1hom[1],
  m2x=rand_m2hom[0],m2y=rand_m2hom[1],
  m3x=rand_m3hom[0],m3y=rand_m3hom[1],
  m4x=rand_m4hom[0],m4y=rand_m4hom[1],
)

print "k2 = ", k2_(
  m1x=rand_m1hom[0],m1y=rand_m1hom[1],
  m2x=rand_m2hom[0],m2y=rand_m2hom[1],
  m3x=rand_m3hom[0],m3y=rand_m3hom[1],
  m4x=rand_m4hom[0],m4y=rand_m4hom[1],
), "; k3 = ", k3_(
  m1x=rand_m1hom[0],m1y=rand_m1hom[1],
  m2x=rand_m2hom[0],m2y=rand_m2hom[1],
  m3x=rand_m3hom[0],m3y=rand_m3hom[1],
  m4x=rand_m4hom[0],m4y=rand_m4hom[1],
)

# ATTENTION: testing revealed, that the whRatio 
# is actually the height/width ratio, 
# not the width/height ratio
# This contradicts [zhang-single]
# if anyone can find the error that caused this, I'd be grateful

    ground truth: f= 72.1045134124554 ; ratio= 3.46538779959142
    calculated: f=  72.1045134125 ; 1/ratio= 3.46538779959
    k2 =  0.99114614987 ; k3 =  1.57376280159

Otros consejos

Actualizar

Después de leer su actualización, y mirando a la primera referencia (exploración Pizarra y mejora de la imagen), no veo dónde está el punto que falta es.

Los datos de entrada del problema es una cuádruple (A, B, C, D), y el centro O de la imagen proyectada. En el artículo, que corresponde a la suposición de u0 = v0 = 0. La adición de este punto, el problema se vuelve limitado suficiente para obtener la relación de aspecto del rectángulo.

El problema se actualiza entonces como sigue: Dado un cuádruple (A, B, C, D) en el plano z = 0, encontrar la posición del ojo E (0,0, h), h> 0 y un plano 3D P tal que la proyección de (a, B, C, D) en P es un rectángulo.

Tenga en cuenta que P se determina por E: para obtener un paralelogramo, P debe contener paralelos a (UE) y (EV), donde U = (AB) x (CD) y V = (AD) x (BC).

Experimentalmente, parece que este problema tiene en una solución única en general, que corresponde a un valor único de la relación w / h del rectángulo.

text alt text alt

Cargo anterior

No, no se puede determinar la relación de rectángulo de la proyección.

En el caso general, una cuádruple (A, B, C, D) de cuatro puntos no colineales del plano z = 0 es la proyección de un número infinito de rectángulos, con un número infinito de relaciones de anchura / altura.

Considere los dos puntos de fuga U, de intersección de (AB) y (CD) y V, de intersección de (AD) y (BC), y el punto I, intersección de las dos diagonales (AC) y (BD). Para proyectar como ABCD, un paralelogramo del centro Debo estar en un plano que contiene la línea paralela a (UV) a través del punto I. En una de esas avión, puede encontrar muchos rectángulos que se proyectan hacia ABCD, todo ello con un diferente / w relación h.

Vea estas dos imágenes realizadas con Cabri 3D. En los dos casos ABCD es sin cambios (en el gris plano z = 0), y el plano azul que contiene el rectángulo no se cambia tampoco. La línea verde parcialmente oculta es la línea (UV) y la línea verde visible es paralela a la misma y contiene I.

text alt text alt

Tamaño isnt realmente necesario, y tampoco lo son las proporciones. Y sabiendo que el lado está arriba es una especie de irrelevante teniendo en cuenta que está usando fotos / imágenes escaneadas de documentos. Dudo hes que van a escanear las caras posteriores de los mismos.

"Corner intersección" es el método para corregir la perspectiva. Esto puede ser de ayuda:

cómo dibujar una cuadrícula en perspectiva correcta en 2D

Sobre la cuestión de por qué los resultados dan h / w en lugar de w / h: Me pregunto si la expresión de la Ecuación 20 anterior es correcta. Publicado es:

       whRatio = sqrt (
            (n2*A.transpose()^(-1) * A^(-1)*n2.transpose()) / 
            (n3*A.transpose()^(-1) * A^(-1)*n3.transpose())
           ) 

Cuando intento ejecutar que, con OpenCV, consigo una excepción. Pero todo funciona correctamente cuando se utiliza la siguiente ecuación, que a mí se parece más a la Ecuación 20: Pero en base a la Ecuación 20, se ve como tiene que ser:

        whRatio = sqrt (
            (n2.transpose()*A.transpose()^(-1) * A^(-1)*n2) /
            (n3.transpose()*A.transpose()^(-1) * A^(-1)*n3)
           )

Se puede determinar el ancho / alto por esta respuesta Cálculo rectángulo de coordenadas 3D coordinar con su sombra? . Suponga que su rectángulo rote en el punto de intersección diagonal calcularlo anchura y altura. Pero cuando se cambia la distancia entre el plano supuesto de sombra al plano sombra real proporcional del rectángulo es lo mismo con calculada anchura / altura!

es imposible conocer el ancho de este rectángulo sin saber la distancia de la 'cámara'.

un pequeño rectángulo visto de 5 centímetros de distancia se ve igual que un enorme rectángulo como se ve desde metros

Dibuje un triángulo rectángulo isósceles con esos dos puntos de fuga y un tercer punto por debajo del horizonte (es decir, en el mismo lado del horizonte como el rectángulo es). Ese tercer punto será nuestro origen y las dos líneas a los puntos de fuga serán nuestros ejes. Llame a la distancia desde el origen a un punto de fuga pi / 2. Ahora extender los lados del rectángulo desde los puntos de fuga a los ejes, y marcar el lugar donde se cruzan los ejes. Escoja un eje, medir las distancias de las dos marcas al origen, transformar esas distancias: x-> tan (x), y la diferencia será la longitud "verdadero" de ese lado. Haga lo mismo para el otro eje. Tome la relación entre esos dos longitudes y ya está.

Es necesario obtener más información, que figura transformada podría venir de cualquier paralelogramo dado una perspectiva arbitraria.

Así que supongo que tiene que hacer algún tipo de calibración en primer lugar.

Editar para los que dije que estaba equivocado, aquí va la prueba matemática de que hay infinitas combinaciones de rectángulos / cámaras que producen a la misma proyección:

Con el fin de simplificar el problema (ya que sólo necesitamos la relación de los lados) vamos a suponer que nuestra rectángulo se define por los siguientes puntos: R=[(0,0),(1,0),(1,r),(0,r)] (esta simplificación es la misma que la transformación de cualquier problema a un equivalente en un afín espacio).

El polígono transformado se define como: T=[(tx0,ty0),(tx1,ty1),(tx2,ty2),(tx3,ty3)]

Existe una M = [[m00,m01,m02],[m10,m11,m12],[m20,m21,m22]] matriz de transformación que satisface (Rxi,Ryi,1)*M=wi(txi,tyi,1)'

si ampliamos la ecuación anterior para los puntos,

para R_0 obtenemos: m02-tx0*w0 = m12-ty0*w0 = m22-w0 = 0

para R_1 obtenemos: m00-tx1*w1 = m10-ty1*w1 = m20+m22-w1 = 0

para R_2 obtenemos: m00+r*m01-tx2*w2 = m10+r*m11-ty2*w2 = m20+r*m21+m22-w2 = 0

y para R_3 obtenemos: m00+r*m01-tx3*w3 = m10+r*m11-ty3*w3 = m20 + r*m21 + m22 -w3 = 0

Hasta ahora tenemos 12 ecuaciones, 14 variables desconocidas (9 de la matriz, 4 de la wi, y 1 para la relación r) y los valores resto son conocidos (txi y tyi se dan).

Incluso si el sistema no se underspecified, algunas de las incógnitas se multiplican entre sí (r y mi0 productos) haciendo que el sistema no lineal (que podría transformarlo a un sistema lineal de asignar un nuevo nombre a cada producto, pero 'll finales todavía con 13 incógnitas, y 3 de ellos está ampliando a infinitas soluciones).

Si se puede encontrar cualquier falla en el razonamiento o las matemáticas, por favor hágamelo saber.

Dropbox tiene un extenso artículo en su blog de tecnología en el que describen cómo resolvieron el problema para su aplicación escáner.

https: //blogs.dropbox. com / tecnología / 2016/08 / fast-documento de rectificación y de realce /

  

La rectificación de un documento

     

Se supone que el documento de entrada es rectangular en el mundo físico, pero si no se enfrenta exactamente la cámara, los ángulos resultantes en la imagen a ser un cuadrilátero convexo general. Así que para satisfacer nuestro primer objetivo, debemos deshacer el geométrica transformada aplicada por el proceso de captura. Esta transformación depende del punto de vista de la cámara en relación con el documento (estos son los llamados parámetros extrínsecos), además de cosas como la longitud focal de la cámara (los parámetros intrínsecos). Aquí está un diagrama del escenario de captura:

     

Con el fin de deshacer la transformación geométrica, primero debemos determinar dichos parámetros. Si suponemos una cámara muy bien simétrica (sin astigmatismo, sin inclinación, etc.), las incógnitas en este modelo son:

     
      
  • la ubicación 3D de la cámara con respecto al documento (3 grados de libertad),
  •   
  • la orientación 3D de la cámara con respecto al documento (3 grados de libertad),
  •   
  • las dimensiones del documento (2 grados de libertad), y
  •   
  • la longitud focal de la cámara (1 grado de libertad).
  •   
     

Por otro lado, los ejes x e y las coordenadas de las cuatro esquinas de documentos detectados nos da efectivamente ocho limitaciones. Si bien no son aparentemente más incógnitas (9) de las limitaciones (8), las incógnitas no son del todo libre de las variables y uno podría imaginar escalar el documento física y colocándolo más lejos de la cámara, para obtener una foto idéntica. Esta relación impone una restricción adicional, por lo que tenemos un sistema totalmente limitada a resolver. (El actual sistema de ecuaciones que resolvemos implica algunas otras consideraciones, el artículo pertinente de Wikipedia da un buen resumen: https : //en.wikipedia.org/wiki/Camera_resectioning )

     

Una vez que se han recuperado los parámetros, podemos deshacer el geométrica transformada aplicada por el proceso de captura para obtener una imagen rectangular agradable. Sin embargo, esto es potencialmente un proceso que consume tiempo: uno podría mirar hacia arriba, para cada píxel de salida, el valor del píxel de entrada correspondiente en la imagen de origen. Por supuesto, las GPU están diseñados específicamente para este tipo de tareas: Representación de una textura en un espacio virtual. Existe una vista transformamos-que pasa a ser la inversa de la cámara transformamos que acabamos de resolver para! -Con la que uno puede hacer que la imagen de entrada completa y obtener el documento rectificado. (Una manera fácil de ver esto es tener en cuenta que una vez que tenga la imagen de entrada completa en la pantalla de su teléfono, puede inclinar y traducir el teléfono de tal forma que la proyección de la región documento en la pantalla aparece rectilínea en su caso.)

     

Por último, hay que recordar que hubo una ambigüedad con respecto a la escala: no podemos decir si el documento es un documento de tamaño carta o una cartulina (8,5” x 11” ) (17” x 22” ), por ejemplo. ¿Cuáles deberían ser las dimensiones de la imagen de salida? Para resolver esta ambigüedad, se cuenta el número de píxeles en el cuadrilátero la imagen de entrada y establezca la resolución de salida como para que coincida con este número de píxeles. La idea es que no queremos que la frecuencia de procesamiento o disminuir la resolución de la imagen demasiado.

Parece que todavía hay cierta confusión en este interesante problema. Quiero dar una explicación fácil de seguimiento para cuando el problema se puede y no se puede resolver.

Restricciones y grados de libertad

Normalmente, cuando nos encontramos con un problema como este la primera cosa que hacer es evaluar el número de grados desconocidos de libertad (DoFs) N, y el número de ecuaciones independientes M que tenemos para limitar los DoFs desconocidos. Es imposible resolver el problema si N si es superior a M (lo que significa que hay menos restricciones que incógnitas). Podemos descartar todos los problemas que esto sea el caso de ser imposible de resolver. Si N no sea superior a M, entonces puede será posible resolver el problema con una solución única, pero esto no está garantizado (ver el penúltimo párrafo para un ejemplo).

Vamos a usar p 1, p 2, p 3 y p 4 para denotar las posiciones de la 4 esquinas de la superficie plana en coordenadas mundiales. Vamos a usar R y t a ser la rotación 3D y la traducción que transforma estos a las coordenadas de la cámara. Vamos a usar K para denotar la matriz intrínseca cámara de 3x3. Vamos a ignorar la distorsión del objetivo por ahora. La posición en 2D de la i º esquina en la imagen de la cámara viene dada por q i = f ( K ( Rp i + t )) donde f es la función de proyección f (x, y, z) = (x / z, y / z). Usando esta ecuación sabemos que cada esquina de la imagen nos da dos ecuaciones (es decir, dos limitaciones) en nuestras incógnitas: uno de la componente x q I y uno de la componente y. Así que tenemos un total de 8 limitaciones para trabajar. El nombre oficial de estas limitaciones son los limitaciones de reproyección .

¿Cuáles son nuestras DoFs desconocidos? Ciertamente R y t son desconocidos, debido a que no conocemos la pose de la cámara en coordenadas del mundo. Por lo tanto tenemos ya 6 DoFs desconocidos: 3 para R (por ejemplo, de guiñada, cabeceo y balanceo) y 3 para t . Por lo tanto no puede haber un máximo de dos incógnitas en los términos restantes ( K , p 1, p 2, p 3, p 4).

Diferentes problemas

Podemos construir diferentes problemas dependiendo de que dos términos en ( K , p 1, p 2, p 3, p 4) que deberá considerar como desconocido. En este punto vamos a escribir a cabo K en la forma habitual: K = (fx, 0, cx; 0, fy, cy; 0,0,1) donde fx y fy son los términos de distancia focal (fx / fy normalmente se denomina relación de aspecto de la imagen) y (cx, cy) es el punto principal (el centro de la proyección en la imagen).

Podemos obtener un problema haciendo que fx y fy como nuestros dos incógnitas, y asumir (cx, cy, p 1, p 2, p 3, p 4) son todos conocidos. De hecho este mismo problema se utiliza y se resuelve dentro método de calibración de la cámara de OpenCV, el uso de imágenes de un objetivo plano de tablero de ajedrez. Esto se utiliza para obtener una estimación inicial para fx y fy, suponiendo que el punto principal se encuentra en el centro de la imagen (que es una suposición muy razonable para la mayoría de las cámaras).

Alternativamente podemos crear un problema diferente, asumiendo fx = fy, que de nuevo es bastante razonable para muchas cámaras, y asumir esta longitud focal (denotado como f) es la solamente desconocido en K . Por lo tanto todavía tenemos uno incógnitas que quedan para jugar con (recordemos que podemos tener un máximo de dos incógnitas). Así que vamos a utilizar esta suponiendo que conocemos la forma del avión: como un rectángulo (que era la suposición original en la pregunta). Por lo tanto podemos definir las esquinas como sigue: p 1 = (0,0,0), p 2 = (0, w, 0), P 3 = (h, 0,0) y p 4 = (h, w, 0), donde h y w indica la altura y la anchura del rectángulo. Ahora, porque sólo tenemos 1 izquierda desconocido, vamos a establecer esto como la relación de aspecto del avión: x = w / h. Ahora la pregunta es si podemos recuperar simultáneamente x, f, R y t de las limitaciones de reproyección 8? La respuesta resulta que es sí! Y la solución se da en el artículo de Zhang citado en la pregunta.

La ambigüedad escala

Uno puede preguntarse si otro problema puede ser resuelto: si suponemos K es conocido y los 2 incógnitas son h y w. Pueden ser resueltos a partir de las ecuaciones de reproyección? La respuesta es no, y se debe a que hay una ambigüedad entre el tamaño del avión y la profundidad del avión a la cámara. Específicamente, si la escala de la esquinas p i por s y la escala t por s, entonces s cancela en las ecuaciones de reproyección. Por lo tanto la escala absoluta del plano no es recuperable.

Puede haber otros problemas con diferentes combinaciones para los DoFs desconocidos, por ejemplo que tiene R , t , uno de los componentes punto principal y el plano "s ancho como incógnitas. sin embargo hay que pensar en qué casos son de uso práctico. sin embargo todavía no he visto un conjunto sistemático de soluciones para todas las combinaciones útiles!

Más puntos

Podríamos pensar que si tuviéramos que añadir correspondencias de puntos adicionales entre el plano y la imagen, o explotar los bordes del plano, se pueden recuperar más de 8 DoFs desconocidos. Lamentablemente, la respuesta es no. Esto se debe a que no añaden ninguna restricción adicionales independientes. La razón se debe a las 4 esquinas describen completamente la transformación del plano de la imagen. Esto se puede ver mediante la instalación de una matriz de homografía usando las cuatro esquinas, que puede determinar las posiciones de todos los demás puntos en el plano de la imagen.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top