|
|
|
|
@ -19,6 +19,8 @@ using namespace ceres;
|
|
|
|
|
#define STABLE_Y3 1080
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//// H投影残差:将左图投影到右图,最小化同名点全景图上的投影误差。
|
|
|
|
|
//// 问题:缺少尺度约束,H矩阵优化后失去正交性 优点:形式简单
|
|
|
|
|
struct HomographyResidual
|
|
|
|
|
@ -106,8 +108,8 @@ private:
|
|
|
|
|
// 问题:不是真正三角化,无深度优化。 优点:有尺度约束,标准做法,可对21个参数优化。
|
|
|
|
|
struct SE3Residual
|
|
|
|
|
{
|
|
|
|
|
SE3Residual(cv::KeyPoint keypoint_i, cv::KeyPoint keypoint_j,cv::Mat _K, double _fEvHeight_i, double _fEvHeight_j)
|
|
|
|
|
: keypoint_i_(keypoint_i), keypoint_j_(keypoint_j),K(_K),EvHeight_i(_fEvHeight_i), EvHeight_j(_fEvHeight_j)
|
|
|
|
|
SE3Residual(cv::KeyPoint keypoint_i, cv::KeyPoint keypoint_j,cv::Mat _K, double _fEvHeight_i, double _fEvHeight_j, const cv::Mat H1, const cv::Mat H2)
|
|
|
|
|
: keypoint_i_(keypoint_i), keypoint_j_(keypoint_j),K(_K),EvHeight_i(_fEvHeight_i), EvHeight_j(_fEvHeight_j), Hi0_(H1), Hj0_(H2)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
@ -115,18 +117,20 @@ struct SE3Residual
|
|
|
|
|
template <typename T>
|
|
|
|
|
bool operator()(const T* const se3_i, const T* const se3_j, T* residual) const
|
|
|
|
|
{
|
|
|
|
|
typedef Eigen::Matrix<T, 3, 1> EPoint;
|
|
|
|
|
typedef Eigen::Matrix<T, 3, 3> EMat;
|
|
|
|
|
// 左图投影到物方
|
|
|
|
|
// T ptL[3] = {T(keypoint_i_.pt.x), T(keypoint_i_.pt.y)}; // 原始点
|
|
|
|
|
|
|
|
|
|
// 深度矩阵
|
|
|
|
|
Eigen::Matrix<T, 3, 3> M_het_inv;
|
|
|
|
|
EMat M_het_inv;
|
|
|
|
|
M_het_inv << T(1), T(0), T(0),
|
|
|
|
|
T(0), T(1), T(0),
|
|
|
|
|
T(0), T(0), T(1.0 / EvHeight_i);
|
|
|
|
|
|
|
|
|
|
// K-1
|
|
|
|
|
Eigen::Matrix<T, 3, 3> K_1;
|
|
|
|
|
Eigen::Matrix<T, 3, 3> K_inv;
|
|
|
|
|
EMat K_1;
|
|
|
|
|
EMat K_inv;
|
|
|
|
|
|
|
|
|
|
double fx = K.at<double>(0, 0);
|
|
|
|
|
double fy = K.at<double>(1, 1);
|
|
|
|
|
@ -141,17 +145,18 @@ struct SE3Residual
|
|
|
|
|
T(0), T(1) / T(fy), -T(cy) / T(fy),
|
|
|
|
|
T(0), T(0), T(1);
|
|
|
|
|
|
|
|
|
|
Eigen::Matrix<T, 3, 1> ptL(T(keypoint_i_.pt.x), T(keypoint_i_.pt.y), T(1.0));
|
|
|
|
|
EPoint ptL(T(keypoint_i_.pt.x), T(keypoint_i_.pt.y), T(1.0));
|
|
|
|
|
EPoint ptR(T(keypoint_j_.pt.x), T(keypoint_j_.pt.y), T(1.0));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 投影也可以用这个
|
|
|
|
|
//cv::Point2f warpPL = warpPointWithse3((const double*)se3_i, (const double)EvHeight, K, ptL);
|
|
|
|
|
Eigen::Matrix<T, 3, 1> pt = K_inv * ptL;
|
|
|
|
|
Eigen::Matrix<T, 3, 1> LeftRota;
|
|
|
|
|
EPoint pt = K_inv * ptL;
|
|
|
|
|
EPoint LeftRota;
|
|
|
|
|
|
|
|
|
|
T rvec_i[3] = { -se3_i[0], -se3_i[1], -se3_i[2] };
|
|
|
|
|
ceres::AngleAxisRotatePoint(rvec_i, pt.data(), LeftRota.data());
|
|
|
|
|
Eigen::Matrix<T, 3, 1> result = M_het_inv * LeftRota;
|
|
|
|
|
EPoint result = M_het_inv * LeftRota;
|
|
|
|
|
// 恢复尺度
|
|
|
|
|
T GeoX = result[0] / result[2];
|
|
|
|
|
T GeoY = result[1] / result[2];
|
|
|
|
|
@ -168,22 +173,20 @@ struct SE3Residual
|
|
|
|
|
|
|
|
|
|
T rvec_j[3] = { se3_j[0], se3_j[1], se3_j[2] };
|
|
|
|
|
|
|
|
|
|
Eigen::Matrix<T, 3, 1> pGeoR(GeoX, GeoY, GeoZ);
|
|
|
|
|
Eigen::Matrix<T, 3, 1> RightRota;
|
|
|
|
|
EPoint pGeoR(GeoX, GeoY, GeoZ);
|
|
|
|
|
EPoint RightRota;
|
|
|
|
|
|
|
|
|
|
ceres::AngleAxisRotatePoint(rvec_j, pGeoR.data(), RightRota.data());
|
|
|
|
|
|
|
|
|
|
// 投影到右图像方
|
|
|
|
|
Eigen::Matrix<T, 3, 1> pUVR = K_1* RightRota;
|
|
|
|
|
|
|
|
|
|
// 压缩尺度
|
|
|
|
|
T uR = pUVR[0] / pUVR[2];
|
|
|
|
|
T vR = pUVR[1] / pUVR[2];
|
|
|
|
|
EPoint pUVR = K_1* RightRota;
|
|
|
|
|
|
|
|
|
|
EPoint pUVR_1 = pUVR / pUVR[2];
|
|
|
|
|
|
|
|
|
|
// 计算重投影误差
|
|
|
|
|
residual[0] = uR - T(keypoint_j_.pt.x);
|
|
|
|
|
residual[1] = vR - T(keypoint_j_.pt.y);
|
|
|
|
|
residual[0] = (pUVR_1 - ptR).squaredNorm();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -195,6 +198,9 @@ private:
|
|
|
|
|
cv::Mat_<double> K; //内参
|
|
|
|
|
double EvHeight_i;//高差,用于三角化
|
|
|
|
|
double EvHeight_j;//高差,用于三角化
|
|
|
|
|
|
|
|
|
|
const cv::Mat Hi0_;//初始定位H,用于坐标控制
|
|
|
|
|
const cv::Mat Hj0_;//初始定位H,用于坐标控制
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -332,8 +338,8 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map, std::unordered_ma
|
|
|
|
|
|
|
|
|
|
#ifdef OPT_SE3
|
|
|
|
|
ceres::CostFunction* cost_function =
|
|
|
|
|
new ceres::AutoDiffCostFunction<SE3Residual,2,6,6>(
|
|
|
|
|
new SE3Residual(keypoint_i, keypoint_j, constK, _depth[i], _depth[j]));
|
|
|
|
|
new ceres::AutoDiffCostFunction<SE3Residual,1,6,6>(
|
|
|
|
|
new SE3Residual(keypoint_i, keypoint_j, constK, _depth[i], _depth[j], Hi0, Hj0));
|
|
|
|
|
problemSE3.AddResidualBlock(cost_function, scale_loss, se3list[i], se3list[j]);
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|