|
|
|
@ -1,6 +1,6 @@
|
|
|
|
#include "Arith_BATask.h"
|
|
|
|
#include "Arith_BATask.h"
|
|
|
|
#define GLOG_USE_GLOG_EXPORT
|
|
|
|
|
|
|
|
#include "ceres/ceres.h"
|
|
|
|
#include "ceres/ceres.h"
|
|
|
|
|
|
|
|
#include <ceres/rotation.h>
|
|
|
|
#include "Arith_GeoSolver.h"
|
|
|
|
#include "Arith_GeoSolver.h"
|
|
|
|
#include "math.h"
|
|
|
|
#include "math.h"
|
|
|
|
#include "Arith_Utils.h"
|
|
|
|
#include "Arith_Utils.h"
|
|
|
|
@ -120,6 +120,103 @@ private:
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SE3群优化
|
|
|
|
|
|
|
|
struct SE3Residual
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
SE3Residual(cv::KeyPoint keypoint_i, cv::KeyPoint keypoint_j,cv::Mat _K, double _fEvHeight)
|
|
|
|
|
|
|
|
: keypoint_i_(keypoint_i), keypoint_j_(keypoint_j),K(_K),EvHeight(_fEvHeight)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int a = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
|
|
|
|
bool operator()(const T* const se3_i, const T* const se3_j, T* residual) const
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// 左图投影到物方
|
|
|
|
|
|
|
|
// T ptL[3] = {T(keypoint_i_.pt.x), T(keypoint_i_.pt.y)}; // 原始点
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 深度矩阵
|
|
|
|
|
|
|
|
Eigen::Matrix<T, 3, 3> 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);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// K-1
|
|
|
|
|
|
|
|
Eigen::Matrix<T, 3, 3> K_1;
|
|
|
|
|
|
|
|
Eigen::Matrix<T, 3, 3> K_inv;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
double fx = K.at<double>(0, 0);
|
|
|
|
|
|
|
|
double fy = K.at<double>(1, 1);
|
|
|
|
|
|
|
|
double cx = K.at<double>(0, 2);
|
|
|
|
|
|
|
|
double cy = K.at<double>(1, 2);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
K_1 << T(fx), T(0), T(cx),
|
|
|
|
|
|
|
|
T(0), T(fy), T(cy),
|
|
|
|
|
|
|
|
T(0), T(0), T(1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
K_inv << T(1) / T(fx), T(0), -T(cx) / T(fx),
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 投影也可以用这个
|
|
|
|
|
|
|
|
//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;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
// 恢复尺度
|
|
|
|
|
|
|
|
T GeoX = result[0] / result[2];
|
|
|
|
|
|
|
|
T GeoY = result[1] / result[2];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 平移,获得地理坐标
|
|
|
|
|
|
|
|
GeoX += se3_i[3];
|
|
|
|
|
|
|
|
GeoY += se3_i[4];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 正算,投影到右图
|
|
|
|
|
|
|
|
GeoX += -se3_j[3];
|
|
|
|
|
|
|
|
GeoY += -se3_j[4];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
T rvec_j[3] = { se3_j[0], se3_j[1], se3_j[2] };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Eigen::Matrix<T, 3, 1> pGeoR(GeoX, GeoY, T(EvHeight));
|
|
|
|
|
|
|
|
Eigen::Matrix<T, 3, 1> 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];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 计算重投影误差
|
|
|
|
|
|
|
|
residual[0] = uR - T(keypoint_j_.pt.x);
|
|
|
|
|
|
|
|
residual[1] = vR - T(keypoint_j_.pt.y);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
const cv::KeyPoint keypoint_i_; // 第 i 帧图像中的特征点
|
|
|
|
|
|
|
|
const cv::KeyPoint keypoint_j_; // 第 j 帧图像中的特征点
|
|
|
|
|
|
|
|
cv::Mat_<double> K; //内参
|
|
|
|
|
|
|
|
double EvHeight;//高差,用于三角化
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BA_Task::BA_Task(FileCache<FrameCache>* cache)
|
|
|
|
BA_Task::BA_Task(FileCache<FrameCache>* cache)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -144,6 +241,11 @@ void BA_Task::InitTask()
|
|
|
|
_FeaPtVec.clear();
|
|
|
|
_FeaPtVec.clear();
|
|
|
|
_FeaDespVec.clear();
|
|
|
|
_FeaDespVec.clear();
|
|
|
|
_paraVec.clear();
|
|
|
|
_paraVec.clear();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_origRtK.clear();
|
|
|
|
|
|
|
|
_currRtK.clear();
|
|
|
|
|
|
|
|
_origse3.clear();
|
|
|
|
|
|
|
|
_currse3.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -168,8 +270,20 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
h_list[i] = (double*)_currMatrix[i].data;
|
|
|
|
h_list[i] = (double*)_currMatrix[i].data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 整合为6D参数
|
|
|
|
|
|
|
|
std::vector<double*> se3_list(_currse3.size());
|
|
|
|
|
|
|
|
for (int i = 0; i < _currse3.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
se3_list[i] = (double*)_currse3[i].data;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constK = cv::Mat(3, 3, CV_64FC1, ((double*)_origRtK[0].data) + 12);
|
|
|
|
|
|
|
|
|
|
|
|
// 创建 Ceres 问题
|
|
|
|
// 创建 Ceres 问题
|
|
|
|
ceres::Problem problem;
|
|
|
|
ceres::Problem problemH;
|
|
|
|
|
|
|
|
ceres::Problem problemSE3;
|
|
|
|
|
|
|
|
|
|
|
|
// 添加残差块
|
|
|
|
// 添加残差块
|
|
|
|
int nParaCnt = 0;//参数组数
|
|
|
|
int nParaCnt = 0;//参数组数
|
|
|
|
@ -221,11 +335,18 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
cv::Mat Hi0 = _origMatrix[i];
|
|
|
|
cv::Mat Hi0 = _origMatrix[i];
|
|
|
|
cv::Mat Hj0 = _origMatrix[j];
|
|
|
|
cv::Mat Hj0 = _origMatrix[j];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef OPT_H
|
|
|
|
ceres::CostFunction* cost_function =
|
|
|
|
ceres::CostFunction* cost_function =
|
|
|
|
new ceres::AutoDiffCostFunction<HomographyResidual, 8, 8, 8>(
|
|
|
|
new ceres::AutoDiffCostFunction<HomographyResidual, 8, 8, 8>(
|
|
|
|
new HomographyResidual(keypoint_i, keypoint_j, Hi0, Hj0));
|
|
|
|
new HomographyResidual(keypoint_i, keypoint_j, Hi0, Hj0));
|
|
|
|
problem.AddResidualBlock(cost_function, scale_loss, h_list[i], h_list[j]);
|
|
|
|
problemH.AddResidualBlock(cost_function, scale_loss, h_list[i], h_list[j]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
ceres::CostFunction* cost_function =
|
|
|
|
|
|
|
|
new ceres::AutoDiffCostFunction<SE3Residual,2,6,6>(
|
|
|
|
|
|
|
|
new SE3Residual(keypoint_i, keypoint_j, constK, constHeight));
|
|
|
|
|
|
|
|
problemSE3.AddResidualBlock(cost_function, scale_loss, se3_list[i],se3_list[j]);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -236,32 +357,55 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
|
|
|
|
|
|
|
|
// 配置求解器
|
|
|
|
// 配置求解器
|
|
|
|
ceres::Solver::Options options;
|
|
|
|
ceres::Solver::Options options;
|
|
|
|
options.max_num_iterations = 2; // 增加最大迭代次数
|
|
|
|
options.max_num_iterations = 6; // 增加最大迭代次数
|
|
|
|
options.function_tolerance = 1e-5; // 设置更严格的函数值容忍度
|
|
|
|
options.function_tolerance = 1e-5; // 设置更严格的函数值容忍度
|
|
|
|
options.gradient_tolerance = 1e-5; // 设置更严格的梯度容忍度
|
|
|
|
options.gradient_tolerance = 1e-5; // 设置更严格的梯度容忍度
|
|
|
|
options.parameter_tolerance = 1e-5; // 设置更严格的参数容忍度
|
|
|
|
options.parameter_tolerance = 1e-5; // 设置更严格的参数容忍度
|
|
|
|
options.minimizer_progress_to_stdout = true;
|
|
|
|
options.minimizer_progress_to_stdout = true;
|
|
|
|
//options.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY; // 使用稀疏求解器
|
|
|
|
//options.linear_solver_type = ceres::SPARSE_NORMAL_CHOLESKY; // 使用稀疏求解器
|
|
|
|
options.num_threads = 1; // 使用多线程
|
|
|
|
options.num_threads = 8; // 使用多线程
|
|
|
|
|
|
|
|
|
|
|
|
ceres::Solver::Summary summary;
|
|
|
|
ceres::Solver::Summary summary;
|
|
|
|
|
|
|
|
|
|
|
|
// 求解
|
|
|
|
// 求解
|
|
|
|
ceres::Solve(options, &problem, &summary);
|
|
|
|
#ifdef OPT_H
|
|
|
|
|
|
|
|
ceres::Solve(options, &problemH, &summary);
|
|
|
|
|
|
|
|
#else
|
|
|
|
|
|
|
|
ceres::Solve(options, &problemSE3, &summary);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//for (int i = 0; i < _origse3.size(); i++)
|
|
|
|
|
|
|
|
//{
|
|
|
|
|
|
|
|
// std::cout << "------------" << std::endl;
|
|
|
|
|
|
|
|
// std::cout << _origse3[i] << std::endl;
|
|
|
|
|
|
|
|
// std::cout << _currse3[i] << std::endl;
|
|
|
|
|
|
|
|
// std::cout << "------------" << std::endl;
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
//for (int i = 0; i < _currMatrix.size(); i++)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 输出结果
|
|
|
|
|
|
|
|
std::cout << summary.FullReport() << std::endl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef OPT_H
|
|
|
|
|
|
|
|
// 将优化se3写入H
|
|
|
|
|
|
|
|
updateSe3();
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//for (int i = 0; i < _origMatrix.size(); i++)
|
|
|
|
//{
|
|
|
|
//{
|
|
|
|
// std::cout << "------------" << std::endl;
|
|
|
|
// std::cout << "------------" << std::endl;
|
|
|
|
// std::cout << _origMatrix[i] << std::endl;
|
|
|
|
// std::cout << _origMatrix[i] << std::endl;
|
|
|
|
// std::cout << _currMatrix[i] << std::endl;
|
|
|
|
// std::cout << _currMatrix[i] << std::endl;
|
|
|
|
// std::cout << "------------" << std::endl;
|
|
|
|
// std::cout << "------------" << std::endl;
|
|
|
|
//}
|
|
|
|
//}
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
// 输出结果
|
|
|
|
|
|
|
|
std::cout << summary.BriefReport() << std::endl;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 写入缓存
|
|
|
|
// 优化后H写入文件缓存
|
|
|
|
writeFrameInfo();
|
|
|
|
writeFrameInfo();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -284,6 +428,8 @@ bool BA_Task::updateCacheH(KeyType Key, cv::Mat H)
|
|
|
|
int BA_Task::readFrameInfo(vector<KeyType> frameInd)
|
|
|
|
int BA_Task::readFrameInfo(vector<KeyType> frameInd)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto _t_frame_cache = std::make_shared<FrameCache>();
|
|
|
|
auto _t_frame_cache = std::make_shared<FrameCache>();
|
|
|
|
|
|
|
|
_cache->get(frameInd[0], _t_frame_cache);
|
|
|
|
|
|
|
|
constHeight = _t_frame_cache->_para.nEvHeight;
|
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < frameInd.size(); i++)
|
|
|
|
for (size_t i = 0; i < frameInd.size(); i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -293,6 +439,8 @@ int BA_Task::readFrameInfo(vector<KeyType> frameInd)
|
|
|
|
// 记录key
|
|
|
|
// 记录key
|
|
|
|
_frameInd.push_back(key);
|
|
|
|
_frameInd.push_back(key);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 注意Mat 浅拷贝陷阱!!!!!!
|
|
|
|
|
|
|
|
|
|
|
|
// 特征点
|
|
|
|
// 特征点
|
|
|
|
vector<cv::KeyPoint> keypoints(_t_frame_cache->_pt, _t_frame_cache->_pt + _t_frame_cache->ptNum);
|
|
|
|
vector<cv::KeyPoint> keypoints(_t_frame_cache->_pt, _t_frame_cache->_pt + _t_frame_cache->ptNum);
|
|
|
|
_FeaPtVec.push_back(keypoints);
|
|
|
|
_FeaPtVec.push_back(keypoints);
|
|
|
|
@ -308,6 +456,14 @@ int BA_Task::readFrameInfo(vector<KeyType> frameInd)
|
|
|
|
_currMatrix.push_back(H.clone());
|
|
|
|
_currMatrix.push_back(H.clone());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 初始SE3
|
|
|
|
|
|
|
|
_origRtK.push_back(cv::Mat(21, 1, CV_64F, _t_frame_cache->RtK).clone());
|
|
|
|
|
|
|
|
_currRtK.push_back(cv::Mat(21, 1, CV_64F, _t_frame_cache->RtK).clone());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_origse3.push_back(cv::Mat(6, 1, CV_64F, _t_frame_cache->se3).clone());
|
|
|
|
|
|
|
|
_currse3.push_back(cv::Mat(6, 1, CV_64F, _t_frame_cache->se3).clone());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 缓存包围多边形
|
|
|
|
// 缓存包围多边形
|
|
|
|
_polygon.push_back(warpRectWithH(H, cv::Size(_t_frame_cache->_frame_info.u32Width, _t_frame_cache->_frame_info.u32Height)));
|
|
|
|
_polygon.push_back(warpRectWithH(H, cv::Size(_t_frame_cache->_frame_info.u32Width, _t_frame_cache->_frame_info.u32Height)));
|
|
|
|
|
|
|
|
|
|
|
|
@ -323,6 +479,15 @@ int BA_Task::readFrameInfo(vector<KeyType> frameInd)
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <Arith_GeoSolver.h>
|
|
|
|
|
|
|
|
void BA_Task::updateSe3()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (size_t i = 0; i < _origse3.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
_currMatrix[i] = Transe3ToH((double*)_origse3[i].data, constK, constHeight);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int BA_Task::writeFrameInfo()
|
|
|
|
int BA_Task::writeFrameInfo()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < _currMatrix.size(); i++)
|
|
|
|
for (size_t i = 0; i < _currMatrix.size(); i++)
|
|
|
|
|