Question

Étant donné une image 2d d'un rectangle déformé par la perspective:

entrer image description ici

Je sais que la forme était à l'origine un rectangle, mais je ne sais pas sa taille d'origine.

Si je sais que les coordonnées de pixels des coins dans cette image, comment calculer les proportions d'origine, à savoir le quotient (largeur / hauteur) du rectangle?

(fond: l'objectif est de automatiquement undistort photos de documents rectangulaires, la détection de bord sera probablement fait avec transformation de Hough)

Mise à jour:

Il y a eu des discussions s'il est possible à tout pour déterminer la largeur: rapport hauteur avec les informations données. Ma naïve pensée est qu'il doit être possible, puisque je ne peux penser à aucun moyen de projeter par exemple un 1: 4 rectangle sur le quadrilatère représenté ci-dessus. Le rapport apparaît clairement proche de 1: 1, donc il devrait y avoir un moyen de déterminer mathématiquement. Je n'ai cependant pas de preuve pour cette au-delà de ma conjecture intuitive.

Je ne l'ai pas encore entièrement compris les arguments présentés ci-dessous, mais je pense qu'il doit y avoir une certaine hypothèse implicite que nous manque ici et qui est interprétée différemment.

Cependant, après des heures de recherche, je l'ai enfin trouvé des documents pertinents au problème. Je me bats pour comprendre les mathématiques utilisées là-bas, jusqu'à présent sans succès. En particulier, le premier document semble discuter exactement ce que je voulais faire, malheureusement sans exemples de code et mathématiques très dense.

  • Zhengyou Zhang, Li-Wei He, "l'analyse de tableau blanc et amélioration de l'image" http://research.microsoft.com/en -nous / um / personne / zhang / papiers / tr03-39.pdf p.11

      

    "En raison de la distorsion en perspective, l'image d'un rectangle semble être une quadrangulaire. Cependant, puisque nous savons qu'il est un rectangle dans l'espace, nous sommes en mesure d'estimer à la fois la distance focale et le rapport d'aspect du rectangle de l'appareil photo. «

  • ROBERT M. Haralick "Détermination Les paramètres de la caméra à partir de la projection en perspective d'un rectangle" http://portal.acm.org/citation.cfm?id=87146

      

    « nous montrons comment utiliser la projection en perspective 2D d'un rectangle de taille inconnue et la position dans l'espace 3D pour déterminer les paramètres d'angle de regard de la caméra par rapport aux plans du rectangle. »

Était-ce utile?

La solution

Voici ma tentative de répondre à ma question après avoir lu le document

Je manoeuvré les équations pour un certain temps dans SAGE, et est venu avec cette pseudo-code dans 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;

Mise à jour: voici comment ces équations où détermine:

Ce qui suit est le code SAGE . Il est accessible en ligne à l'adresse http://www.sagenb.org/home/pub/704/ . (Sage est vraiment utile dans la résolution des équations, et utilisable dans tout navigateur, check it out)

# 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())
              ) 

Les équations simplifiées de la c-code où déterminées par

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

Autres conseils

Mise à jour

Après avoir lu votre mise à jour, et en regardant la première référence (Whiteboard numérisation et amélioration de l'image), je vois où le point manquant est.

Les données d'entrée du problème est un quadruple (A, B, C, D), et au centre O de l'image projetée. Dans l'article, il correspond à l'hypothèse u0 = v0 = 0. L'ajout de ce point, le problème est assez limité pour obtenir le rapport d'aspect du rectangle.

Le problème est ensuite retraitée comme suit: Etant donné un quadruple (A, B, C, D) dans le plan Z = 0, pour E de la position des yeux (0,0, h), h> 0 et un plan 3D P de telle sorte que la projection (a, B, C, D) P est un rectangle.

Notez que P est déterminée par E: pour obtenir un parallélogramme, P doit contenir des parallèles à (UE) et (EV), où U = (AB) x (CD) et V = (AD) x (BC).

Expérimentalement, il semble que ce problème a généralement une solution unique, ce qui correspond à une valeur unique du rapport p / h du rectangle.

text alt text alt

Article précédent

Non, vous ne pouvez pas déterminer le rapport rectangle de la projection.

Dans le cas général, une quadruple (A, B, C, D) de quatre points non colinéaires de la Z = 0 plan est la projection de rectangles infiniment nombreuses, avec un nombre infini de rapports largeur / hauteur.

Considérons les deux points de fuite U, intersection de (AB) et (CD) et V, intersection de (AD) et (BC), et le point I, intersection des deux diagonales (AC) et (BD). Pour projeter comme ABCD, un parallélogramme du centre, je dois reposer sur un plan contenant la ligne parallèle à (UV) par le point I. Sur un tel plan, vous pouvez trouver de nombreux rectangles en saillie à ABCD, toutes avec un autre rapport W / h.

Voir ces deux images réalisées avec Cabri 3D. Dans les deux cas ABCD est inchangé (sur le plan Z = 0 gris), et le plan bleu contenant le rectangle ne change pas non plus. La ligne verte partiellement caché est la ligne (UV) et la ligne verte visible est parallèle et contient I.

text alt text alt

isnt Taille vraiment nécessaire, et ne sont proportions. Et sachant de quel côté est en hausse est un peu hors de propos étant donné qu'il utilise des photos / scans de documents. Je doute hes va balayer les côtés arrière d'entre eux.

« intersection Coin » est la méthode pour corriger la perspective. Cela pourrait être utile:

Comment dessiner une grille de perspective correcte en 2D

Sur la question de savoir pourquoi les résultats donnent h / w plutôt alors w / h: Je me demande si l'expression de l'équation 20 ci-dessus est correcte. Posté est:

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

Lorsque je tente d'exécuter ce avec OpenCV, je reçois une exception. Mais tout fonctionne correctement lorsque j'utilise l'équation suivante qui me ressemble plus à l'équation 20: Mais basé sur l'équation 20, on dirait qu'il devrait être:

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

Vous pouvez déterminer la largeur / hauteur par cette réponse Calcul rectangle coordonnées 3D avec Coordinate son ombre? . Supposons que votre rectangle tourner sur le point d'intersection en diagonale calculer la largeur et la hauteur. Mais lorsque vous modifiez la distance entre le plan d'ombre hypothèse au plan réel ombre proportionnelle du rectangle est la même avec une largeur / hauteur calculée!

il est impossible de connaître la largeur de ce rectangle sans connaître la distance de la « caméra ».

un petit rectangle de 5 centimètres vu la distance semble la même que celle d'un grand rectangle vu de mètres

Dessiner un triangle isocèle avec les deux points de fuite, et un troisième point au-dessous de l'horizon (qui est, sur le même côté de l'horizon que le rectangle est). Ce troisième point sera notre origine et les deux lignes aux points de fuite seront nos axes. Appelez la distance de l'origine à un point de fuite pi / 2. Maintenant étendre les côtés du rectangle des points de fuite aux axes, et marquer l'endroit où ils se croisent les axes. Choix d'un axe, mesurer les distances entre les deux marques à l'origine, transformer ces distances: x-> tan (x), et la différence sera la longueur « true » de ce côté. Faites la même chose pour l'autre axe. Prenez le rapport de ces deux longueurs et vous avez terminé.

Vous avez besoin plus d'informations, ce chiffre transformé pourrait venir de tout parallélogramme donné une perspective arbitraire.

Je suppose que vous devez faire une sorte de premier étalonnage.

Modifier pour ceux qui ont dit que je me trompais, va ici la preuve mathématique qu'il ya des combinaisons infinies de rectangles / caméras qui donnent à la même projection:

Afin de simplifier le problème (comme nous avons seulement besoin du rapport des côtés), supposons que notre rectangle est défini par les points suivants: R=[(0,0),(1,0),(1,r),(0,r)] (cette simplification est la même que la transformation de tout problème à un poste équivalent dans un affines l'espace).

Le polygone transformé est défini comme suit: T=[(tx0,ty0),(tx1,ty1),(tx2,ty2),(tx3,ty3)]

Il existe une matrice de transformation M = [[m00,m01,m02],[m10,m11,m12],[m20,m21,m22]] qui satisfait (Rxi,Ryi,1)*M=wi(txi,tyi,1)'

si nous élargissons l'équation ci-dessus pour les points,

pour R_0 nous obtenons: m02-tx0*w0 = m12-ty0*w0 = m22-w0 = 0

pour R_1 nous obtenons: m00-tx1*w1 = m10-ty1*w1 = m20+m22-w1 = 0

pour R_2 nous obtenons: m00+r*m01-tx2*w2 = m10+r*m11-ty2*w2 = m20+r*m21+m22-w2 = 0

et R_3 nous obtenons: m00+r*m01-tx3*w3 = m10+r*m11-ty3*w3 = m20 + r*m21 + m22 -w3 = 0

Jusqu'à présent, nous avons 12 équations, 14 variables inconnues (9 à partir de la matrice, 4 de la wi et 1 pour le rapport r) et le reste sont des valeurs connues (txi et tyi sont données).

Même si le système n'a pas été sous-spécifié, certaines inconnues sont multipliés entre eux (produits r et mi0) rendant le système non linéaire (vous pouvez le transformer en un système linéaire attribuant un nouveau nom à chaque produit, mais vous « ll finissent toujours avec 13 inconnues, et trois d'entre eux étant élargi à des solutions infinies).

Si vous pouvez trouver une faille dans le raisonnement ou les mathématiques, s'il vous plaît laissez-moi savoir.

Dropbox a un long article sur leur blog tech où ils décrivent comment ils ont résolu le problème de leur application du scanner.

https: //blogs.dropbox. com / technologie / 2016/08 / rapide document de rectification et d'amélioration /

  

Rectifier un document

     

Nous supposons que le document d'entrée est rectangulaire dans le monde physique, mais si elle ne fait pas face exactement la caméra, les angles résultant de l'image est un quadrilatère convexe général. Donc, pour satisfaire notre premier but, nous devons annuler la transformation géométrique appliquée par le processus de capture. Cette transformation dépend du point de vue de la caméra par rapport au document (ce sont les soi-disant paramètres extrinsèques), en plus des choses comme la distance focale de la caméra (les paramètres intrinsèques). Voici un diagramme du scénario de capture:

     

Pour annuler la transformation géométrique, il faut d'abord déterminer lesdits paramètres. Si nous supposons une caméra bien symétrique (pas d'astigmatisme, pas de biais, et ainsi de suite), les inconnues de ce modèle sont:

     
      
  • l'emplacement 3D de la caméra par rapport au document (3 degrés de liberté),
  •   
  • l'orientation 3D de la caméra par rapport au document (3 degrés de liberté),
  •   
  • les dimensions du document (2 degrés de liberté), et
  •   
  • la distance focale de la caméra (1 degré de liberté).
  •   
     

Du côté de la médaille, x et y coordonnées des quatre coins de documents détectés nous donne effectivement huit contraintes. Bien qu'il y ait des inconnues apparemment plus (9) que les contraintes (8), les inconnues ne sont pas entièrement libres variables on pourrait imaginer mise à l'échelle du document physiquement et en le plaçant loin de la caméra, pour obtenir une photo identique. Cette relation introduit une contrainte supplémentaire, nous avons donc un système entièrement contraint à résoudre. (Le système actuel d'équations nous résolvons implique quelques autres considérations, l'article pertinent Wikipédia donne un bon résumé: https : //en.wikipedia.org/wiki/Camera_resectioning)

     

Une fois que les paramètres ont été récupérés, nous pouvons annuler la transformation géométrique appliquée par le processus de capture pour obtenir une belle image rectangulaire. Cependant, cela est potentiellement un processus de temps: on regarderait, pour chaque pixel de sortie, la valeur du pixel d'entrée correspondante dans l'image source. Bien sûr, les GPU sont spécialement conçus pour des tâches comme celle-ci: rendre une texture dans un espace virtuel. Il existe une vue transformons, qui se trouve être l'inverse de la caméra transformons nous venons de régler pour -À que l'on peut rendre l'image d'entrée complète et obtenir le document rectifié. (Un moyen facile de voir est de constater qu'une fois que vous avez l'image d'entrée complète sur l'écran de votre téléphone, vous pouvez incliner et traduire le téléphone de telle sorte que la projection de la région de document sur l'écran apparaît vous rectiligne.)

     

Enfin, rappelons qu'il y avait une ambiguïté par rapport à l'échelle: nous ne pouvons pas dire si le document était un document de format lettre (8,5” x 11” ) ou un tableau d'affichage (17” x 22” ), pour exemple. Quelles devraient être les dimensions de l'image de sortie soit? Pour résoudre cette ambiguïté, on compte le nombre de pixels dans le quadrilatérale dans l'image d'entrée, et réglez la résolution de sortie pour correspondre à ce nombre de pixels. L'idée est que nous ne voulons pas suréchantillonner ou sous-échantillonner l'image trop.

Il semble y avoir encore une certaine confusion sur ce problème intéressant. Je veux donner une explication facile à suivre lorsque le problème peut et ne peut pas être résolu.

Contraintes et degrés de liberté

En général, lorsque nous sommes confrontés à un problème comme celui-ci la première chose à faire est d'évaluer le nombre de degrés inconnus de la liberté (DoFs) N, et le nombre d'équations indépendantes M que nous avons pour contraindre les DoFs inconnus. Il est impossible de résoudre le problème si N si M dépasse (ce qui signifie qu'il ya moins de contraintes que d'inconnues). Nous pouvons exclure tous les problèmes où cela est le cas comme étant sans solution. Si N ne dépasse pas M puis peut est possible de résoudre le problème avec une solution unique, mais ce n'est pas garantie (voir le deuxième au dernier paragraphe pour un exemple).

Prenons p 1, p 2, p 3 et p 4 pour désigner les positions de la 4 coins de la surface plane en coordonnées mondiales. Utilisons R et t pour la rotation 3D et la traduction qui transforme ces coordonnées de la caméra. Utilisons K pour indiquer la caméra 3x3 matrice intrinsèque. Nous ignorerons la distorsion de l'objectif pour l'instant. La position 2D de la i e coin à l'image de la caméra est donné par q i = f ( K ( Rp i + t )) où f est la fonction de projection f (x, y, z) = (x / z, y / z). En utilisant cette équation, nous savons que chaque coin dans l'image à nos inconnues nous donne deux équations (à savoir deux contraintes): l'un de la composante x q i et un de la composante y. Nous avons donc un total de 8 contraintes à travailler avec. Le nom officiel de ces contraintes sont les contraintes de reprojection .

Alors, quelles sont nos DoFs inconnus? Certes, R et t ne sont pas connus, parce que nous ne savons pas la pose de la caméra en coordonnées monde. Par conséquent, nous avons déjà 6 DoFs inconnus: 3 R (par exemple lacet, tangage et roulis) et 3 pour t . Par conséquent, il peut y avoir un maximum de deux inconnues dans les termes restants ( K , p 1, p 2, p 3, p 4).

Différents problèmes

Nous pouvons construire des problèmes différents selon le deux termes ( K , p 1, p 2 p 3, p 4) nous allons considérer comme inconnu. À ce stade, nous allons écrire K sous la forme habituelle: K = (fx, 0, cx, 0, Fy, cy; 0,0,1) où fx et fy sont les termes de distance focale (fx / fy est normalement appelé le rapport d'aspect de l'image) et (cx, cy) est le point principal (le centre de projection dans l'image).

Nous pourrions obtenir un problème en ayant fx et fy comme nos deux inconnues, et d'assumer (cx, cy, p 1, p 2 p 3, p 4) sont tous connus. En effet, ce problème très utilisé et est résolu dans la méthode d'étalonnage de la caméra de OpenCV, en utilisant des images d'une cible plane checkerboard. Il est utilisé pour obtenir une estimation initiale pour Fx et Fy, en supposant que le point principal est au centre de l'image (ce qui est une hypothèse très raisonnable pour la plupart des appareils photo).

Sinon, nous pouvons créer un autre problème en supposant fx = fy, ce qui est encore tout à fait raisonnable pour de nombreux appareils photo et assumer cette distance focale (notée f) est le que inconnu K . Par conséquent, nous avons encore une des inconnues de gauche à jouer avec (le rappel, nous pouvons avoir un maximum de deux inconnues). Donc, nous allons utiliser ceci en supposant que nous connaissons la forme du plan: comme un rectangle (qui était l'hypothèse d'origine dans la question). Par conséquent, nous pouvons définir les coins de la manière suivante: p 1 = (0,0,0), p = 2 (0, w, 0), P 3 = (h, 0,0) et p = 4 (h, w, 0), où h et w désigne la hauteur et la largeur du rectangle. Maintenant, parce que nous avons seulement 1 gauche inconnue, laissez-nous en ce que le ratio d'aspect de l'avion: x = w / h. Maintenant, la question est peut-on récupérer simultanément x, f, R et t des 8 contraintes de reprojection? La réponse il se trouve est oui! Et la solution est donnée dans le document de Zhang cité dans la question.

L'ambiguïté de l'échelle

On peut se demander si un autre problème peut être résolu: si nous supposons K est connu et les 2 inconnues sont h et w. Peuvent-ils être résolus à partir des équations de reprojection? La réponse est non, et parce qu'il ya une ambiguïté entre la taille de l'avion et la profondeur de l'avion à la caméra. Plus précisément, si nous escaladons les coins p i par s et échelle t par s, puis s annule dans les équations de reprojection. Par conséquent, l'échelle absolue du plan ne peut être recouvrée.

Il peut y avoir d'autres problèmes avec différentes combinaisons pour les DoFs inconnus, par exemple ayant R , t , l'un des composants du point principal et le plan "s largeur inconnues. Cependant il faut penser que les cas sont d'une utilité pratique. Néanmoins, je ne l'ai pas encore vu un ensemble systématique de solutions pour toutes les combinaisons utiles!

Plus de points

On pourrait penser que si nous devions ajouter des correspondances de points supplémentaires entre le plan et l'image, ou exploiter les bords du plan, on pourrait récupérer plus de 8 DoFs inconnus. Malheureusement, la réponse est non. En effet, ils n'ajoutent pas de contraintes indépendantes supplémentaires. La raison en est parce que les 4 coins décrivent complètement la transformation du plan à l'image. Ceci peut être vu en ajustant une matrice d'homographie en utilisant les quatre coins, qui peut alors déterminer les positions de tous les autres points sur le plan de l'image.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top