Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download

All published worksheets from http://sagenb.org

Views: 168759
Image: ubuntu2004
# 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()) )
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) 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= 45.2097243131986 ; ratio= 0.634782539235867 calculated: f= 45.2097243132 ; 1/ratio= 0.634782539236 k2 = 1.4485486955 ; k3 = 1.10166293863
# unfinished: some attempts at researching reliability # by introducing gausian noise print ( f_(k2=k2_,k3=k3_)(s=1,u0=rand_u0,v0=rand_v0)( m1x=rand_m1hom[0]+gauss(0,2),m1y=rand_m1hom[1]+gauss(0,2), m2x=rand_m2hom[0]+gauss(0,2),m2y=rand_m2hom[1]+gauss(0,2), m3x=rand_m3hom[0]+gauss(0,2),m3y=rand_m3hom[1]+gauss(0,2), m4x=rand_m4hom[0]+gauss(0,2),m4y=rand_m4hom[1]+gauss(0,2), ), 1/whRatio(f=f_)(k2=k2_,k3=k3_)(s=1,u0=rand_u0,v0=rand_v0)( m1x=rand_m1hom[0]+gauss(0,2),m1y=rand_m1hom[1]+gauss(0,2), m2x=rand_m2hom[0]+gauss(0,2),m2y=rand_m2hom[1]+gauss(0,2), m3x=rand_m3hom[0]+gauss(0,2),m3y=rand_m3hom[1]+gauss(0,2), m4x=rand_m4hom[0]+gauss(0,2),m4y=rand_m4hom[1]+gauss(0,2), ) )
(NaN, NaN - NaN*I)