I want to implement a bundle adjustment in Ceres Solver. Here is my understanding of the implementation steps:
-
Define the Reprojection Error:
struct ReprojectionError { ReprojectionError(double observed_x, double observed_y, const cv::Mat& K) : observed_x(observed_x), observed_y(observed_y), K(K) {} template <typename T> bool operator()(const T* const extrinsics, const T* const point, T* residuals) const { // Unpack extrinsics const T* rotation = extrinsics; const T* translation = extrinsics + 3; // Project the 3D point to 2D T p[3]; ceres::AngleAxisRotatePoint(rotation, point, p); p[0] += translation[0]; p[1] += translation[1]; p[2] += translation[2]; // Apply the intrinsic matrix T xp = p[0] / p[2]; T yp = p[1] / p[2]; // Convert to image plane T u_proj_x = T(K.at<double>(0, 0)) * xp + T(K.at<double>(0, 2)); T u_proj_y = T(K.at<double>(1, 1)) * yp + T(K.at<double>(1, 2)); // Compute the residuals residuals[0] = u_proj_x - T(observed_x); residuals[1] = u_proj_y - T(observed_y); return true; } static ceres::CostFunction* Create(double observed_x, double observed_y, const cv::Mat& K) { return (new ceres::AutoDiffCostFunction<ReprojectionError, 2, 6, 3>( new ReprojectionError(observed_x, observed_y, K))); } double observed_x; double observed_y; cv::Mat K; };
-
Add Observations to the Problem:
ceres::Problem problem; for (const auto& observation : observations) { ceres::CostFunction* cost_function = ReprojectionError::Create(observation.x, observation.y, intrinsics[observation.camera_id]); problem.AddResidualBlock(cost_function, nullptr, extrinsics[observation.camera_id], points_3d[observation.tag_id]); }
-
Run the Solver:
ceres::Solver::Options options; options.linear_solver_type = ceres::DENSE_SCHUR; ceres::Solver::Summary summary; ceres::Solve(options, &problem, &summary); std::cout << summary.FullReport() << "n";
Am I correctly implementing the bundle adjustment correctly?