cpp verison of StereoRectify is wrong (Bug #1338)
Description
Back when ROS was using cv 2.0, there was that pesky bug somewhere in calibration that caused incorrect calibration. So, I wrote my own offline stereo calibration program that used cv 2.1 and got good results. Over the last week, I've been trying to calibrate a new camera and getting horrible results (the final rectified images I see after calling steroRectify, initUndistortMap, and remap were basically zooming in on very small parts of the two images.
After a while, I noticed that the P1, P2 returned were fishy looking, so instead of using those, I set P1 and P2 to the intrinsic matrices and calulated new rectification matricies (R1,R2) directly from the fundamental matrix (Hartley's method). This gave good results.
I also then ran the offline 'calibrate from tar' script in ROS calibrate_camera package, which does EXACTLY the same process of stereo calibration, but using Python. Here, I get out good quality rectification and projection matrices from stereoRectify. In short, cv 2.2 (and 2.3) stereorectify gives proper results in Python, but incorrect results in C++. I tested this by giving the two the exact same images, verifying that stereorectify is getting the same intrinsic and extrinsic parameters.
Associated revisions
Merge pull request #1338 from asmorkalov:android_tegra_detector
History
Updated by Patrick Beeson over 13 years ago
Here is some code where if you run stereoRectify on same intrinsics/extrinsics from stereoCalibrate(), when get weird P1 and P2, but if you calcualte them using stereoRectifyUncalibrated they work (but the fx/fy in the two projection matricies are no longer equal, which isn't the best -- I know some code just looks at fx/fy in one of the two matrices and assumes they are equal).
1Mat R1, R2, P1, P2, Q;
2Rect validRoir2;
3
4stereoRectify(cameraMatrixr0, distCoeffsr0,
5 cameraMatrixr1, distCoeffsr1,
6 imageSize, R, T, R1, R2, P1, P2, Q,
7 0, imageSize, &validRoir0, &validRoir1, CV_CALIB_ZERO_DISPARITY);
8
9 Mat rmapr2r2;
10// IF BY CALIBRATED (BOUGUET'S METHOD)
11 if( useCalibrated )
12 {
13 // we already computed everything
14
15 //BUT P1 and P2 have REALLY large numbers and are correct.
16
17 }
18// OR ELSE HARTLEY'S METHOD
19 else
20 // use intrinsic parameters of each camera, but
21 // compute the rectification transformation directly
22 // from the fundamental matrix
23 {
24 vector<Point2f> allimgptr2;
25 for( k = 0; k < 2; k++ )
26 {
27 for( i = 0; i < nimages; i++ )
28 std::copy(imagePoints[k][i].begin(), imagePoints[k][i].end(), back_inserter(allimgpt[k]));
29 }
30 F = findFundamentalMat(Mat(allimgptr0), Mat(allimgptr1), FM_8POINT, 0, 0);
31 Mat H1, H2;
32 stereoRectifyUncalibrated(Mat(allimgptr0), Mat(allimgptr1), F, imageSize, H1, H2, 3);
33
34 R1 = cameraMatrixr0.inv()*H1*cameraMatrixr0;
35 R2 = cameraMatrixr1.inv()*H2*cameraMatrixr1;
36 P1 = Mat::zeros(3, 4, CV_64F);
37 P2 = Mat::zeros(3, 4, CV_64F);
38
39 for (uint i=0;i<3;i++)
40 for (uint j=0;j<3;j++) {
41 P1.at<double>(i,j) = cameraMatrixr0.at<double>(i,j);
42 P2.at<double>(i,j) = cameraMatrixr1.at<double>(i,j);
43 }
44 P2.at<double>(0,3) = P2.at<double>(0,0)*T.at<double>(0,0);
45
46 // P1 and P2 are now good but P1(0,0) != P2(0,0) (same for
47 // (1,1)) would like them to be the same.
48
49 }
Updated by Patrick Beeson over 13 years ago
I now believe the issue was with stereoCalibrate converging to a bad set of parameters on occasion.
- Status changed from Open to Done
- (deleted custom field) set to invalid
Updated by Andrey Kamaev almost 13 years ago
- Status changed from Done to Cancelled
- Target version set to 2.4.0