Calculate X Y in mm with known Z

Hi all,

I am using the fisheye camera to measure X, Y dimensions with the known Z as can be demonstrated in the image.

The fisheye camera is calibrated by putting the checkboard on the table. After calibration, I have camera matrix, distortion, rotation vector, and translation vector. Z dimension is took from translation vector [ a,b, Z].
Note: the checkboard is 6 x 8 and for each square: 20mm x 20mm

Now, I would like to measure the X ,Y dimension in the mm unit of Point A but I have wrong result.
I used undisortPoint() with the input is: uncalibrated image point(u,v) from fisheyecamera. Then, I used this equation to calculate X ,Y dimension in the mm unit

  • u = f_{x} * X / Z
  • v = f_{y} * Y / Z

However, the result of Point A(X, Y) is wrong.

My question is:

  1. undisortPoint() returns the point in optical Point coordinate or image coordinate?
  2. Is there any problem with my process that affects my X Y result?

Thank you very much.
I really apologize for my terrible English. Please forgive me.

undistorPoint() converts distorted image coordinates to undistorted image coordinates. If you use f as your z-cooridnate you will have a 3-D point in the camera coordinates (in units of pixels).

It looks like part of the problem is that you aren’t accounting for the rotation and translation of the camera in table coordinates. If you compute your camera position in world coords and the vector corresponding to your image point also in world coords you can compute a ray/plane intersection with your world plane.

I think something like:

cv::Mat R;
cv::Rodrigues(rvec,R);
cv::Mat cameraCoordsOfImagePoint = cv::Mat(3,1);  // load this with Ux, Uy, F
cv::Mat worldTrans = -R.inv() * tvec;
cv::Mat worldVec = R.inv() * cameraCoordsOfImagePoint;

// the image ray in world space is:  worldTrans + t * worldVec  - you want to know where 
// this intersects your world plane

// plane equation Ax + By + Cz + D = 0
cv::Mat planeNormal(3,1)  // this gets set up with A,B,C of your plane equation

// tIntesrsect is the value of t (in the ray equation above) when the ray intersects the plane
double tIntersect  = (D - worldCoordsOfNodalPoint.dot(planeNormal)) / worldVec.dot(planeNormal);

// To find your world point you just use tIntersect in the ray equation above:
 worldPoint = worldTrans + tIntersect * worldVec



I’ve used something like this in the past to do what (I think) you are trying to do. The “code” above probably won’t compile or work as is, but if you understand the basic idea you should be able to get it to work.

1 Like

Thank you for your reply, it is pretty clear for me. I will try it and post what I have done soon