Quantcast
Channel: OpenCV Q&A Forum - RSS feed
Viewing all articles
Browse latest Browse all 41027

I am getting less calibration error with simpler models. How, and am I doing it wrong?

$
0
0
Crosspost at SO: http://stackoverflow.com/questions/31292266/opencv-3-0-calibration-not-fitting-as-expected I'm getting results I don't expect when I use OpenCV 3.0 calibrateCamera. Here is my algorithm: 1. Load in 30 image points 2. Load in 30 corresponding world points (coplanar in this case) 3. Use points to calibrate the camera, just for un-distorting 4. Un-distort the image points, but don't use the intrinsics (coplanar world points, so intrinsics are dodgy) 5. Use the undistorted points to find a homography, transforming to world points (can do this because they are all coplanar) 6. Use the homography and perspective transform to map the undistorted points to the world space 7. Compare the original world points to the mapped points The points I have are noisy and only a small section of the image. There are 30 coplanar points from a single view so I can't get camera intrinsics, but should be able to get distortion coefficients and a homography to create a fronto-parallel view. As expected, the error varies depending on the calibration flags. However, it varies opposite to what I expected. If I allow all variables to adjust, I would expect error to come down. I am not saying I expect a better model; I actually expect over-fitting, but that should still reduce error given my test set is also my learning set. What I see though is that the fewer variables I use, the lower my error. The best result is with a straight homography. The code doesn't appear to have bugs; I've used "better" points and it works perfectly. I want to emphasize that the solution here can't be to use better points or perform a better calibration; the whole point of the exercise is to see how the various calibration models respond to different qualities of calibration data. The scenarios I'm looking at often have distorted lenses and only a few points in a single region to calibrate on. Any ideas? I've included code here. The different models are achieved by commenting out lines as indicated. // Load image points std::vector im_points; im_points.push_back(cv::Point2f(1206, 1454)); im_points.push_back(cv::Point2f(1245, 1443)); im_points.push_back(cv::Point2f(1284, 1429)); im_points.push_back(cv::Point2f(1315, 1456)); im_points.push_back(cv::Point2f(1352, 1443)); im_points.push_back(cv::Point2f(1383, 1431)); im_points.push_back(cv::Point2f(1431, 1458)); im_points.push_back(cv::Point2f(1463, 1445)); im_points.push_back(cv::Point2f(1489, 1432)); im_points.push_back(cv::Point2f(1550, 1461)); im_points.push_back(cv::Point2f(1574, 1447)); im_points.push_back(cv::Point2f(1597, 1434)); im_points.push_back(cv::Point2f(1673, 1463)); im_points.push_back(cv::Point2f(1691, 1449)); im_points.push_back(cv::Point2f(1708, 1436)); im_points.push_back(cv::Point2f(1798, 1464)); im_points.push_back(cv::Point2f(1809, 1451)); im_points.push_back(cv::Point2f(1819, 1438)); im_points.push_back(cv::Point2f(1925, 1467)); im_points.push_back(cv::Point2f(1929, 1454)); im_points.push_back(cv::Point2f(1935, 1440)); im_points.push_back(cv::Point2f(2054, 1470)); im_points.push_back(cv::Point2f(2052, 1456)); im_points.push_back(cv::Point2f(2051, 1443)); im_points.push_back(cv::Point2f(2182, 1474)); im_points.push_back(cv::Point2f(2171, 1459)); im_points.push_back(cv::Point2f(2164, 1446)); im_points.push_back(cv::Point2f(2306, 1474)); im_points.push_back(cv::Point2f(2292, 1462)); im_points.push_back(cv::Point2f(2278, 1449)); // Create corresponding world / object points std::vector world_points; for (int i = 0; i < 30; i++) { world_points.push_back(cv::Point3f(5 * (i / 3), 4 * (i % 3), 0.0f)); } // Perform calibration // Flags are set out so they can be commented out and "freed" easily int calibration_flags = 0 | cv::CALIB_FIX_K1 | cv::CALIB_FIX_K2 | cv::CALIB_FIX_K3 | cv::CALIB_FIX_K4 | cv::CALIB_FIX_K5 | cv::CALIB_FIX_K6 | cv::CALIB_ZERO_TANGENT_DIST | 0; // Initialise matrix cv::Mat intrinsic_matrix = cv::Mat(3, 3, CV_64F); intrinsic_matrix.ptr(0)[0] = 1; intrinsic_matrix.ptr(1)[1] = 1; cv::Mat distortion_coeffs = cv::Mat::zeros(5, 1, CV_64F); // Rotation and translation vectors std::vector undistort_rvecs; std::vector undistort_tvecs; // Wrap in an outer vector for calibration std::vector>im_points_v(1, im_points); std::vector>w_points_v(1, world_points); // Calibrate; only 1 plane, so intrinsics can't be trusted cv::Size image_size(4000, 3000); calibrateCamera(w_points_v, im_points_v, image_size, intrinsic_matrix, distortion_coeffs, undistort_rvecs, undistort_tvecs, calibration_flags); // Undistort im_points std::vector ud_points; cv::undistortPoints(im_points, ud_points, intrinsic_matrix, distortion_coeffs); // ud_points have been "unintrinsiced", but we don't know the intrinsics, so reverse that double fx = intrinsic_matrix.at(0, 0); double fy = intrinsic_matrix.at(1, 1); double cx = intrinsic_matrix.at(0, 2); double cy = intrinsic_matrix.at(1, 2); for (std::vector::iterator iter = ud_points.begin(); iter != ud_points.end(); iter++) { iter->x = iter->x * fx + cx; iter->y = iter->y * fy + cy; } // Find a homography mapping the undistorted points to the known world points, ground plane cv::Mat homography = cv::findHomography(ud_points, world_points); // Transform the undistorted image points to the world points (2d only, but z is constant) std::vector estimated_world_points; std::cout << "homography" << homography << std::endl; cv::perspectiveTransform(ud_points, estimated_world_points, homography); // Work out error double sum_sq_error = 0; for (int i = 0; i < 30; i++) { double err_x = estimated_world_points.at(i).x - world_points.at(i).x; double err_y = estimated_world_points.at(i).y - world_points.at(i).y; sum_sq_error += err_x*err_x + err_y*err_y; } std::cout << "Sum squared error is: " << sum_sq_error << std::endl;

Viewing all articles
Browse latest Browse all 41027

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>