0

Rosanswers logo

I'm trying to determine the distance between two object by using two cameras (OCV 2.3.1, MSVC++, Win7) but can't calculate the object's objectPoints. I think this is because the image points aren't being rectified before their disparity is calculated.

I. WHAT I DO FIRST Step 1. Calibrate each camera by itself

int numSquares = numCornersHor * numCornersVer;
Size board_sz = Size(numCornersHor, numCornersVer);

Mat cameraMatrix = Mat(3, 3, CV_32FC1); Mat distCoeffs;

vector<Mat> rvecs, tvecs;

cameraMatrix.ptr<float>(0)[0] = 1; cameraMatrix.ptr<float>(1)[1] = 1;

calibrateCamera(object_points, image_points, image.size(), cameraMatrix, distCoeffs, rvecs, tvecs);

Step 2. Calibrate the cameras to together.
int numCornersHor = 4; int numCornersVer = 3; const float squareSize = 1.75;

Size imageSize = Size(numCornersHor, numCornersVer);
   int numSquares = numCornersHor * numCornersVer;

for(int i = 0; i < pairs; i++ ) { for( int j = 0; j < imageSize.height; j++ ) { for( int k = 0; k < imageSize.width; k++ ) { objectPoints[i].push_back(Point3f(jsquareSize, ksquareSize, 0)); } } }

Mat R, T, E, F;

rms = stereoCalibrate(
objectPoints, imagePoints[0], imagePoints[1], cameraMatrix[0], distCoeffs[0], cameraMatrix[1], distCoeffs[1], imageSize, R, T, E, F, TermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 100, 1e-5), CV_CALIB_FIX_ASPECT_RATIO + CV_CALIB_ZERO_TANGENT_DIST + CV_CALIB_SAME_FOCAL_LENGTH + CV_CALIB_RATIONAL_MODEL + CV_CALIB_FIX_K3 + CV_CALIB_FIX_K4 + CV_CALIB_FIX_K5 );

Step 3. Create the rectification data stereoRectify( cameraMatrix[0], cameraMatrix[1], distCoeffs[0], distCoeffs[1], imageSize, R, T, RC1, RC2, //RC1: Rotation matrix Camera 1 PC1, PC2, Q, CALIB_ZERO_DISPARITY, 1,
imageSize);

II. WHAT I BELIEVE Goal: I'm trying undistort and rectify the image points of one object in the image from camera 1 and the image from camera 2 (I do this process twice: once while the clay pigeon's on the launcher and once one frame before the clay pigeon disintegrates)

Method: I believe that I don't need to use initUndistortRectifyMap then Remap but can instead just use undistortPoints. I think undistortPoints undistorts the points of interest and rectifies them.

III. WHAT I DO SECOND You can ignore this if my beliefs aren't correct.

undistortPoints(launcherC1, launcherC1Undistorted, cameraMatrixC1, distCoeffsC1, R1, P1);   
undistortPoints(launcherC2, launcherC2Undistorted, cameraMatrixC2, distCoeffsC2, R2, P2);

undistortPoints(clayPigeonC1, clayPigeonC1Undistorted, cameraMatrix1, distCoeffs1, R1, P1); undistortPoints(clayPigeonC2, clayPigeonC2Undistorted, cameraMatrix2, distCoeffs2, R2, P2);

The input and output arrays for undistortPoints (launcherC1, launcherC1Undistorted, ... clayPigeonC2, clayPigeonC2Undistorted) are vectors of Point2f objects.

IV. DISCREPANCY BETWEEN BELIEF AND REALITY After all undistortPoints functions are run,

  1. launcherC1Undisorted.y does not equal launcherC2Undistorted.y
  2. clayPigeonC1Undistorted.y does not equal clayPigeonC2Undistorted.y.
    They are up to 30% different.

V. QUESTIONS Q1: In addition to undistorting them does undistortPoints also rectify points? Q1.1_yes. Are the values of y supposed to be equal after rectification? Q1.1.1_yes Can you tell from the code I've included what I'm doing wrong so that they don't? Q1_no If undistortPoints doesn't rectify the points then how do I rectify them?

Thank you for any assistance. Charles++


Originally posted by Cherry 3.14 on ROS Answers with karma: 41 on 2012-05-04

Post score: 1

1 Answers1

0

Rosanswers logo

Hi Charles,

Your question doesn't have much to do with ROS, maybe you should ask it on an OpenCV forum, but as long as you made the effort to post it so nicely let my try to answer it.

As far as I know undistortPoints do not rectify the points. The correct approach would be to call initUndistortRectifyMap and then use Remap.

If instead of remapping the whole image what you need is to undistort and rectify only some image points, then what you can do is use manually the maps (mapx and mapy) generated by initUndistortRectifyMap. Something like this (assuming that point1 is a point on the original image):

undistortedRectifiedPoint.x = mapx[point1.x, point1.y]
undistortedRectifiedPoint.y = mapy[point1.x, point1.y]

I hope this helps.

Best regards, Martin.


Originally posted by Martin Peris with karma: 5625 on 2012-05-10

This answer was ACCEPTED on the original site

Post score: 1


Original comments

Comment by Cherry 3.14 on 2012-05-15:
I can't read mapx & mapy. I try Mat mapxC1; mapxC1.create(sizeImage,1); initUndistortRectifyMap(cameraMatrix1, distCoeffs1, R1, camMat1UndistRect, sizeImage, 0, /* ???*/ mapxC1, mapyC1);

Comment by Cherry 3.14 on 2012-05-15:
vector point1Cam1UndistortedRectified; point1Cam1UndistortedRectified.at(0).x = mapxC1[PointC1x, PointC1y]; point1Cam1UndistortedRectified.at(0).y = mapxC1[PointC1x, PointC1y]; but MSVC++ says not operator "[]" matches these operands right after mapxC1 in the last two lines. Know why?

Comment by Martin Peris on 2012-05-15:
Hi CharlesM, Actually the syntax "mapxC1[PointC1x, PointC1y]" is not correct, sorry I misled you with my pseudo-code. How about mapxC1.at(PointC1x,PointC1y)?

Comment by Martin Peris on 2012-05-15:
You can find more info on how to access OpenCV matrices efficiently here: http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#howtoscanimagesopencv

Comment by Cherry 3.14 on 2012-05-16:
Hi Martin, Thank you so much for your help! I know I'll reach the answer being assisted by an OCV expert. You told me how to put exactly the data I want into maps but now I'm frustrated since I still can't get that data. I tried your suggestion and link. Results:

Comment by Cherry 3.14 on 2012-05-16:
1.) MSVC++ says about mapxC1.at(PointC1x,PointC1y) that no overloaded functn matches argumnt list and that there are too many args in functn call.
2.) I don't know OCV or C++ well enough to make enough sense of the link you sent to get at a map's data

Comment by Cherry 3.14 on 2012-05-16:
What I've done: PointC1x & PointC1y are floats that are the x & y of Keypoint objects in an image that's been cvtColor( ... CV_RGB2GRAY)

Q.) Am I even creating the Mat for the map correctly mapxC1.create(sizeImage,1); ? Charles Mennell

Comment by Martin Peris on 2012-05-16:
The problem is that the parameters PointC1x and PointC1y should be integers (remember, after all, you are accessing data stored in the computer's memory which can only be indexed using integer numbers). Try: mapxC1.at(static_cast(PointC1x), static_cast(PointC1y))

Comment by Martin Peris on 2012-05-16:
The correct way to create mapxC1 would be: mapxC1.create(sizeImage, CV_16UC1). You want it to be a single channel matrix of 16 bit unsigned integers

Comment by Cherry 3.14 on 2012-05-19:
Thank you squared, Martin, The values held at the pixel represented by and x and a y pixel can be floats, right, just not the pixel (since a pixel is just 1 pixel at a location defined by two integers: row and column number)?

Comment by Cherry 3.14 on 2012-05-19:
Does a single channel matrix mean that for each row & column matrix location there is one object, in this case a16 bit unsigned integer?

Comment by Cherry 3.14 on 2012-05-19:
Tried mapxC1.at(s. After 1st . MSVC says "no OL func matches arg list" & it undrlines 2nd arg & says too many arguments. Why does VC say this when as I'm typing the args it says arg options are "const_Tp & at<_Tp> (cv::Point pt) const or in the () could be things like int i0, i1 or just i0=0? ...

Comment by Cherry 3.14 on 2012-05-19:
... I don't understand the _Tp, &, or <> but I do understand a Point and integer and MSVC has complained when I've sent it just a Point, and when it's sent two ints or just one