18

I'm working with a homography calculated by OpenCV. I currently use this homography to transform points using the function below. This function performs the task I require however I have no clue how it actually works.

Can anyone explain, line by line exactly, the logic/theory behind the last 3 lines of code, I understand that this transforms the point x,y but I'm unclear as to why this works:

Why are Z, px and py calculated in this way, what do the elements in h correspond to?

Your comments are greatly appreciated :)

double h[9];
homography = cvMat(3, 3, CV_64F, h);
CvMat ps1 = cvMat(MAX_CALIB_POINTS/2,2,CV_32FC1, points1);
CvMat ps2 = cvMat(MAX_CALIB_POINTS/2,2,CV_32FC1, points2);

cvFindHomography(&ps1, &ps2, &homography, 0);

...

// This is the part I don't fully understand
double x = 10.0;
double y = 10.0;
double Z = 1./(h[6]*x + h[7]*y + h[8]);
px = (int)((h[0]*x + h[1]*y + h[2])*Z);
py = (int)((h[3]*x + h[4]*y + h[5])*Z);
Angie Quijano
  • 3,308
  • 3
  • 20
  • 30
Jayson
  • 221
  • 1
  • 2
  • 6

2 Answers2

34

cvFindHomography() returns a matrix using homogenous coordinates:

Homogeneous coordinates are ubiquitous in computer graphics because they allow common operations such as translation, rotation, scaling and perspective projection to be implemented as matrix operations

What's happening in the code: The cartesian point p_origin_cartesian(x,y) is transformed to homogenous coordinates, then the 3x3 perspective transformation matrix h is applied and the result is converted back to cartesian coordinates p_transformed_cartesian(px,py).

UPDATE

In detail:

Convert p_origin_cartesian to p_origin_homogenous:

(x,y)  =>  (x,y,1)

Do perspective transformation:

p_transformed_homogenous = h * p_origin_homogenous =

(h0,h1,h2)    (x)   (h0*x + h1*y + h2)   (tx)   
(h3,h4,h5)  * (y) = (h3*x + h4*y + h5) = (ty) 
(h6,h7,h8)    (1)   (h6*x + h7*y + h8)   (tz)

Convert p_transformed_homogenous to p_transformed_cartesian:

(tx,ty,tz)  =>  (tx/tz, ty/tz) 

Your code translated:

px = tx/tz;
py = ty/tz;
Z  = 1/tz;
Angie Quijano
  • 3,308
  • 3
  • 20
  • 30
Ben
  • 4,037
  • 5
  • 29
  • 46
  • z is the 3rd coordinate in the 3-dimensional homogenous coordinates. Explaining how homogenous coordinates work would go too far here. But p_homogenous(x,y,z) corresponds to p_cartesian(x/z,y/z). – Ben Feb 14 '12 at 12:11
  • I just edited my answer, now it should be clear what happens in your code. – Ben Feb 14 '12 at 13:27
  • Ok, if it's tx/tz, why in the code is it tx*Z? Just answered my own question I think, tx*Z is the same as tx/tz? – Jayson Feb 14 '12 at 13:37
  • 1
    Yes. tx*Z = tx*(1/tz) = tx/tz ;) – Ben Feb 14 '12 at 13:53
4

OpenCV Python implementation following @Ben answer

p = np.array((x,y,1)).reshape((3,1))
temp_p = M.dot(p)
sum = np.sum(temp_p ,1)
px = int(round(sum[0]/sum[2]))
py = int(round(sum[1]/sum[2]))
flaviussn
  • 1,127
  • 1
  • 13
  • 29