Ceres 给出的例子是解决 BAL 数据集中的问题。和前面的例子一样,第一步是定义一个 template functor 来计算重投影误差/残差。
BAL 问题中的每个残差都取决于一个三维点和一个相机,其中定义相机的九个参数是:三个旋转参数(罗德里格斯轴角向量)、三个平移参数、一个焦距参数和两个径向畸变参数。有关该摄像机模型的详细信息,请参阅 Bundler homepage and the BAL homepage。
structSnavelyReprojectionError {SnavelyReprojectionError(double observed_x,double observed_y):observed_x(observed_x),observed_y(observed_y) {}template <typenameT>booloperator()(constT*const camera,constT*const point,T* residuals) const { // camera[0,1,2] are the angle-axis rotation. T p[3]; ceres::AngleAxisRotatePoint(camera, point, p); // camera[3,4,5] are the translation.p[0] +=camera[3]; p[1] +=camera[4]; p[2] +=camera[5]; // Compute the center of distortion. The sign change comes from // the camera model that Noah Snavely's Bundler assumes, whereby // the camera coordinate system has a negative z axis. T xp =-p[0] /p[2]; T yp =-p[1] /p[2]; // Apply second and fourth order radial distortion.const T& l1 =camera[7];const T& l2 =camera[8]; T r2 = xp*xp + yp*yp; T distortion =1.0+ r2 * (l1 + l2 * r2); // Compute final projected point position.const T& focal =camera[6]; T predicted_x = focal * distortion * xp; T predicted_y = focal * distortion * yp; // The error is the difference between the predicted and observed position.residuals[0] = predicted_x -T(observed_x);residuals[1] = predicted_y -T(observed_y);returntrue; } // Factory to hide the construction of the CostFunction object from // the client code.static ceres::CostFunction*Create(constdouble observed_x,constdouble observed_y) {returnnew ceres::AutoDiffCostFunction<SnavelyReprojectionError,2,9,3> (observed_x, observed_y); }double observed_x;double observed_y;};
ceres::Problem problem;for (int i =0; i <bal_problem.num_observations(); ++i) { ceres::CostFunction* cost_function = SnavelyReprojectionError::Create(bal_problem.observations()[2* i +0],bal_problem.observations()[2* i +1]);problem.AddResidualBlock(cost_function,nullptr /* squared loss */,bal_problem.mutable_camera_for_observation(i),bal_problem.mutable_point_for_observation(i));}