Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV: measuring distance between two balls in millimeters - how to improve accuracy

Tags:

opencv

I also posted this topic in the Q&A forum at opencv.org but I don't know how many experts from here are reading this forum - so forgive me that I'm also trying it here.

I'm currently learning OpenCV and my current task is to measure the distance between two balls which are lying on a plate. My next step is to compare several cameras and resolutions to get a feeling how important resolution, noise, distortion etc. is and how heavy these parameters affect the accuracy. If the community is interested in the results I'm happy to share the results when they are ready! The camera is placed above the plate using a wide-angle lens. The width and height of the plate (1500 x 700 mm) and the radius of the balls (40 mm) are known.

My steps so far:

  1. camera calibration
  2. undistorting the image (the distortion is high due to the wide-angle lens)
  3. findHomography: I use the corner points of the plate as input (4 points in pixels in the undistorted image) and the corner points in millimeters (starting with 0,0 in the lower left corner, up to 1500,700 in the upper right corner)
  4. using HoughCircles to find the balls in the undistorted image
  5. applying perspectiveTransform on the circle center points => circle center points now exist in millimeters
  6. calculation the distance of the two center points: d = sqrt((x1-x2)^2+(y1-y2)^2)

The results: an error of around 4 mm at a distance of 300 mm, an error of around 25 mm at a distance of 1000 mm But if I measure are rectangle which is printed on the plate the error is smaller than 0.2 mm, so I guess the calibration and undistortion is working good.

I thought about this and figured out three possible reasons:

  1. findHomography was applied to points lying directly on the plate whereas the center points of the balls should be measured in the equatorial height => how can I change the result of findHomography to change this, i.e. to "move" the plane? The radius in mm is known.
  2. the error increases with increasing distance of the ball to the optical center because the camera will not see the ball from the top, so the center point in the 2D projection of the image is not the same as in the 3D world - I will we projected further to the borders of the image. => are there any geometrical operations which I can apply on the found center to correct the value?
  3. during undistortion there's probably a loss of information, because I produce a new undistorted image and go back to pixel accuracy although I have many floating point values in the distortion matrix. Shall I search for the balls in the distorted image and tranform only the center points with the distortion matrix? But I don't know what's the code for this task.

I hope someone can help me to improve this and I hope this topic is interesting for other OpenCV-starters.

Thanks and best regards!

like image 375
efdev1234 Avatar asked May 04 '13 20:05

efdev1234


People also ask

Which is the most accurate method for measuring distance?

Answer: LINEAR SCALE IS THE MOST ACCURATE METHOD OF MEASURING DISTANCE ON MAP.

How do you measure accurate distance?

Digital tape measures are accurate for both short distances and long distances up to 300 feet. They are also portable and easy to use. However, there are limitations as well. Laser tape measures should only be used indoors, and they only work if there is a solid endpoint for them to reflect a beam against.

How do you measure the distance between two objects?

Measuring Distance Between Two Points To measure is to determine how far apart two geometric objects are. The most common way to measure distance is with a ruler. Inch-rulers are usually divided up by eighth-inch (or 0.125 in) segments. Centimeter rulers are divided up by tenth-centimeter (or 0.1 cm) segments.


1 Answers

Here are some thoughts to help you along... By no means "the answer", though.

First a simple one. If you have calibrated your image in mm at a particular plane that is distance D away, then points that are r closer will appear larger than they are. To get from measured coordinates to actual coordinates, you use

Actual = measured * (D-r)/D

So since the centers of the spheres are radius r above the plane, the above formula should answer part 1 of your question.

Regarding the second question: if you think about it, the center of the sphere that you see should be in the right place "in the plane of the center of the sphere", even though you look at it from an angle. Draw yourself a picture to convince yourself this is so.

Third question: if you find the coordinates of the spheres in the distorted image, you should be able to transform them to the corrected image using perspectiveTransform. This may improve accuracy a little bit - but I am surprised at the size of errors you see. How large is a single pixel at the largest distance (1000mm)?

EDIT

You asked about elliptical projections etc. Basically, if you think of the optical center of the camera as a light source, and look at the shadow of the ball onto the plane as your "2D image", you can draw a picture of the rays that just hit the sides of the ball, and determine the different angles:

enter image description here

It is easy to see that P (the mid point of A and B) is not the same as C (the projection of the center of the sphere). A bit more trig will show you that the error C - (A+B)/2 increases with x and decreases with D. If you know A and B you can calculate the correct position of C (given D) from:

C = D * tan( (atan(B/D) + atan(A/D)) / 2 )

The error becomes larger as D is smaller and/or x is larger. Note D is the perpendicular (shortest) distance from the lens to the object plane.

This only works if the camera is acting like a "true lens" - in other words, there is no pincushion distortion, and a rectangle in the image plane maps into a rectangle on the sensor. The above combined with your own idea to fit in the uncorrected ('pixel') space, then transform the centers found with perspectiveTransform, ought to get you all the way there.

See what you can do with that!

like image 69
Floris Avatar answered Oct 19 '22 06:10

Floris