- ceres::Problem problem 生成一個非線性最小二乘problem
2. struct/class costFunctor{
代價函數,用以計算jacobin矩陣
template<typename t> bool operator(){}
}
3.probelm.AddResidualBlock(new AutoDiffCostFunction<costFunctor,1,1,1>(new costFunctor())); 生成jacobin
4.Solver::Options 非線性最小二乘求解時的選項,如疊代次數,矩陣分解方法等
5.Solver::Summary summary
6.Solve(options,&problem,&summary)
總體來說,ceres庫就像是一個黑盒,隻需要把測量值和觀測值輸入代價函數中,即可自動求解jacobin矩陣,并進行非線性最小二乘疊代。
//1.構造代價函數
// Templated pinhole camera model for used with Ceres. The camera is
// parameterized using 9 parameters: 3 for rotation, 3 for translation, 1 for
// focal length and 2 for radial distortion. The principal point is not modeled
// (i.e. it is assumed be located at the image center).
struct SnavelyReprojectionError {
SnavelyReprojectionError(double observed_x, double observed_y)
: observed_x(observed_x), observed_y(observed_y) {}
template <typename T>
bool operator()(const T* const camera,
const T* 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 - observed_x;
residuals[1] = predicted_y - observed_y;
return true;
}
//該代價函數實作了重投影過程。
//2.構造代價函數的偏導數
// Factory to hide the construction of the CostFunction object from
// the client code.
//對構造生成的代價函數求偏導
static ceres::CostFunction* Create(const double observed_x,
const double observed_y) {
return (new ceres::AutoDiffCostFunction<SnavelyReprojectionError, 2, 9, 3>(
new SnavelyReprojectionError(observed_x, observed_y)));
}
double observed_x;
double observed_y;
};
3.在構造好代價函數的偏導數後,利用solve求解非線性最小二乘
// Create residuals for each observation in the bundle adjustment problem. The
// parameters for cameras and points are added automatically.
//讀取檔案中的相機參數和三維點,按照costFunction計算梯度
ceres::Problem problem;
for (int i = 0; i < bal_problem.num_observations(); ++i) {
// Each Residual block takes a point and a camera as input and outputs a 2
// dimensional residual. Internally, the cost function stores the observed
// image location and compares the reprojection against the observation.
ceres::CostFunction* cost_function =
SnavelyReprojectionError::Create(observations[2 * i + 0],
observations[2 * i + 1]);
problem.AddResidualBlock(cost_function,
NULL ,
bal_problem.mutable_camera_for_observation(i),
bal_problem.mutable_point_for_observation(i));
}
// Make Ceres automatically detect the bundle structure. Note that the
// standard solver, SPARSE_NORMAL_CHOLESKY, also works fine but it is slower
// for standard bundle adjustment problems.
ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_SCHUR;
options.minimizer_progress_to_stdout = true;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
std::cout << summary.FullReport() << "\n";
結論:
目前對ceres的了解隻到達整體架構的程度,但是對于
1)其内部如何求偏導
2)選用何種非線性最小二乘算法
等具體的内部如何實作還不清晰。
清晰一發:
對于一個BA問題,如有p個相機,q個三維點。變量向量x有如下的塊結構:
x = [y1,...,yp,z1,...,zq].
其中,y對應相機參數,相機參數塊個數c=6/9
z對應三維點參數,參數個數s=3
對于BA問題,求解的是 JTJ * X = b
針對JTJ=H
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLyQTNxMTNwcTM1ADOwkTMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
H矩陣又可以寫成上述形式,其中B是一個pc*pc的塊稀疏矩陣
C是一個qs*qs的塊對焦矩陣
E是一個pc*qs的塊稀疏矩陣
上述線性方程求解可寫成:
對上述系數矩陣進行高斯消元,可以得到C是一個塊對角矩陣,并且每個塊也是對焦矩陣。是以,求解C的逆是非常簡單,并且運算代價非常小的。是以,利用C矩陣這一特性,可以消去Δz。
,将其帶入分塊矩陣第一行,可得,
則最終就簡化成,隻需要計算pc*pc大小的系數矩陣塊的線性方程組了。而且在一般情況下,相機數量p是遠小于三維點數量q的。
還有兩處不了解:
為什麼三維點對應的矩陣塊C是塊對角的?
回答上頭的問題:
BA中正規方程的稀疏性分析
這裡以一個例子進行說明:
如圖所示,以兩個相機和六個三維點的對應作為樣例,說明BA的稀疏性,首先列寫jacobin矩陣J,并計算JTJ,可以看出,對應相機元素的矩陣塊,是塊對角矩陣,對應三維點元素的矩陣塊,也是塊對角矩陣,對三維點的元素的塊進行高斯消元,可以得到一個3x3的對角矩陣,是以,整個三維點元素對應的分塊矩陣就是一個對角矩陣,是以在求解時,可以直接求倒數得到矩陣塊的逆。