|
|
|
@ -7,6 +7,8 @@
|
|
|
|
using namespace ceres;
|
|
|
|
using namespace ceres;
|
|
|
|
#include "Logger.h"
|
|
|
|
#include "Logger.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define STABLE_X1 320
|
|
|
|
#define STABLE_X1 320
|
|
|
|
#define STABLE_Y1 256
|
|
|
|
#define STABLE_Y1 256
|
|
|
|
|
|
|
|
|
|
|
|
@ -17,8 +19,8 @@ using namespace ceres;
|
|
|
|
#define STABLE_Y3 1080
|
|
|
|
#define STABLE_Y3 1080
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// H投影残差:将左右图全都投影到全景图,最小化同名点全景图上的投影误差。
|
|
|
|
//// H投影残差:将左图投影到右图,最小化同名点全景图上的投影误差。
|
|
|
|
// 问题:缺少尺度约束,H矩阵优化后失去正交性 优点:形式简单
|
|
|
|
//// 问题:缺少尺度约束,H矩阵优化后失去正交性 优点:形式简单
|
|
|
|
struct HomographyResidual
|
|
|
|
struct HomographyResidual
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
@ -27,42 +29,32 @@ struct HomographyResidual
|
|
|
|
{
|
|
|
|
{
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
template <typename T>
|
|
|
|
bool operator()(const T* const h_i, const T* const h_j, T* residual) const
|
|
|
|
bool operator()(const T* const h_i, const T* const h_j, T* residual) const
|
|
|
|
{
|
|
|
|
{
|
|
|
|
// 残差计算逻辑
|
|
|
|
typedef Eigen::Matrix<T, 3, 1> EPoint;
|
|
|
|
T H_i[9] = { h_i[0], h_i[1], h_i[2],
|
|
|
|
typedef Eigen::Matrix<T, 3, 3> EMat;
|
|
|
|
h_i[3], h_i[4], h_i[5],
|
|
|
|
|
|
|
|
h_i[6], h_i[7], T(1.0) };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
T H_j[9] = { h_j[0], h_j[1], h_j[2],
|
|
|
|
EMat Mat_H_i;
|
|
|
|
h_j[3], h_j[4], h_j[5],
|
|
|
|
Mat_H_i << T(h_i[0]), T(h_i[1]), T(h_i[2]),
|
|
|
|
h_j[6], h_j[7], T(1.0) };
|
|
|
|
T(h_i[3]), T(h_i[4]), T(h_i[5]),
|
|
|
|
|
|
|
|
T(h_i[6]), T(h_i[7]), T(1.0);
|
|
|
|
|
|
|
|
|
|
|
|
T p_i[3] = { T(keypoint_i_.pt.x), T(keypoint_i_.pt.y), T(1.0) };
|
|
|
|
EMat Mat_H_j;
|
|
|
|
T p_j[3] = { T(keypoint_j_.pt.x), T(keypoint_j_.pt.y), T(1.0) };
|
|
|
|
Mat_H_j << T(h_j[0]), T(h_j[1]), T(h_j[2]),
|
|
|
|
|
|
|
|
T(h_j[3]), T(h_j[4]), T(h_j[5]),
|
|
|
|
|
|
|
|
T(h_j[6]), T(h_j[7]), T(1.0);
|
|
|
|
|
|
|
|
|
|
|
|
T P_i[3] = { T(0), T(0), T(0) };
|
|
|
|
EPoint p_i(T(keypoint_i_.pt.x), T(keypoint_i_.pt.y), T(1.0));
|
|
|
|
T P_j[3] = { T(0), T(0), T(0) };
|
|
|
|
EPoint p_j(T(keypoint_j_.pt.x), T(keypoint_j_.pt.y), T(1.0));
|
|
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < 3; row++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (int col = 0; col < 3; col++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
P_i[row] += H_i[row * 3 + col] * p_i[col];
|
|
|
|
|
|
|
|
P_j[row] += H_j[row * 3 + col] * p_j[col];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
P_i[0] /= P_i[2];
|
|
|
|
EPoint warp_i = Mat_H_i * p_i;
|
|
|
|
P_i[1] /= P_i[2];
|
|
|
|
EPoint img_j = Mat_H_j.inverse() * warp_i;
|
|
|
|
P_j[0] /= P_j[2];
|
|
|
|
EPoint img_j_1 = img_j / img_j[2];
|
|
|
|
P_j[1] /= P_j[2];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 1.添加重投影误差
|
|
|
|
// 计算残差向量
|
|
|
|
residual[0] = P_i[0] - P_j[0];
|
|
|
|
residual[0] = (img_j_1 - p_j).squaredNorm();
|
|
|
|
residual[1] = P_i[1] - P_j[1];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 2. 不动点位置约束
|
|
|
|
// 2. 不动点位置约束
|
|
|
|
@ -70,42 +62,28 @@ struct HomographyResidual
|
|
|
|
cv::Point2f pS2 = warpPointWithH(Hi0_, cv::Point2f(STABLE_X2, STABLE_Y2));
|
|
|
|
cv::Point2f pS2 = warpPointWithH(Hi0_, cv::Point2f(STABLE_X2, STABLE_Y2));
|
|
|
|
cv::Point2f pS3 = warpPointWithH(Hi0_, cv::Point2f(STABLE_X3, STABLE_Y3));
|
|
|
|
cv::Point2f pS3 = warpPointWithH(Hi0_, cv::Point2f(STABLE_X3, STABLE_Y3));
|
|
|
|
|
|
|
|
|
|
|
|
T p_1[3] = { T(STABLE_X1), T(STABLE_Y1), T(1.0) };
|
|
|
|
EPoint pS1_E{ (T)pS1.x,(T)pS1.y ,T(1.0) };
|
|
|
|
T p_2[3] = { T(STABLE_X2), T(STABLE_Y2), T(1.0) };
|
|
|
|
EPoint pS2_E{ (T)pS2.x,(T)pS2.y,T(1.0) };
|
|
|
|
T p_3[3] = { T(STABLE_X3), T(STABLE_Y3), T(1.0) };
|
|
|
|
EPoint pS3_E{ (T)pS3.x,(T)pS3.y ,T(1.0) };
|
|
|
|
|
|
|
|
|
|
|
|
T P_r1[3] = { T(0), T(0), T(0) };
|
|
|
|
|
|
|
|
T P_r2[3] = { T(0), T(0), T(0) };
|
|
|
|
|
|
|
|
T P_r3[3] = { T(0), T(0), T(0) };
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int row = 0; row < 3; row++)
|
|
|
|
EPoint p_1{ T(STABLE_X1), T(STABLE_Y1), T(1.0) };
|
|
|
|
{
|
|
|
|
EPoint p_2{ T(STABLE_X2), T(STABLE_Y2), T(1.0) };
|
|
|
|
for (int col = 0; col < 3; col++)
|
|
|
|
EPoint p_3{ T(STABLE_X3), T(STABLE_Y3), T(1.0) };
|
|
|
|
{
|
|
|
|
|
|
|
|
P_r1[row] += H_i[row * 3 + col] * p_1[col];
|
|
|
|
|
|
|
|
P_r2[row] += H_i[row * 3 + col] * p_2[col];
|
|
|
|
|
|
|
|
P_r3[row] += H_i[row * 3 + col] * p_3[col];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
P_r1[0] /= P_r1[2];
|
|
|
|
|
|
|
|
P_r1[1] /= P_r1[2];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
P_r2[0] /= P_r2[2];
|
|
|
|
EPoint P_r1 = Mat_H_i * p_1;
|
|
|
|
P_r2[1] /= P_r2[2];
|
|
|
|
EPoint P_r2 = Mat_H_i * p_2;
|
|
|
|
|
|
|
|
EPoint P_r3 = Mat_H_i * p_3;
|
|
|
|
|
|
|
|
|
|
|
|
P_r3[0] /= P_r3[2];
|
|
|
|
P_r1 /= P_r1[2];
|
|
|
|
P_r3[1] /= P_r3[2];
|
|
|
|
P_r2 /= P_r2[2];
|
|
|
|
|
|
|
|
P_r3 /= P_r3[2];
|
|
|
|
|
|
|
|
|
|
|
|
// 约束中心点投影位置不变
|
|
|
|
|
|
|
|
residual[2] = (P_r1[0] - (T)pS1.x);
|
|
|
|
|
|
|
|
residual[3] = P_r1[1] - (T)pS1.y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
residual[4] = (P_r2[0] - (T)pS2.x);
|
|
|
|
// 约束投影位置不变
|
|
|
|
residual[5] = P_r2[1] - (T)pS2.y;
|
|
|
|
residual[2] = (P_r1 - pS1_E).squaredNorm();
|
|
|
|
|
|
|
|
residual[3] = (P_r2 - pS2_E).squaredNorm();
|
|
|
|
residual[6] = (P_r3[0] - (T)pS3.x);
|
|
|
|
residual[4] = (P_r3 - pS3_E).squaredNorm();
|
|
|
|
residual[7] = P_r3[1] - (T)pS3.y;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
@ -121,13 +99,15 @@ private:
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// SE3群优化
|
|
|
|
// SE3群优化
|
|
|
|
// SE3群优化残差:将左图三角化后投影到右图,最小化相对投影误差
|
|
|
|
// SE3群优化残差:将左图三角化后投影到右图,最小化相对投影误差
|
|
|
|
// 问题:不是真正三角化,无深度优化。 优点:有尺度约束,标准做法,可对21个参数优化。
|
|
|
|
// 问题:不是真正三角化,无深度优化。 优点:有尺度约束,标准做法,可对21个参数优化。
|
|
|
|
struct SE3Residual
|
|
|
|
struct SE3Residual
|
|
|
|
{
|
|
|
|
{
|
|
|
|
SE3Residual(cv::KeyPoint keypoint_i, cv::KeyPoint keypoint_j,cv::Mat _K, double _fEvHeight)
|
|
|
|
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(_fEvHeight)
|
|
|
|
: keypoint_i_(keypoint_i), keypoint_j_(keypoint_j),K(_K),EvHeight_i(_fEvHeight_i), EvHeight_j(_fEvHeight_j)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -138,12 +118,11 @@ struct SE3Residual
|
|
|
|
// 左图投影到物方
|
|
|
|
// 左图投影到物方
|
|
|
|
// T ptL[3] = {T(keypoint_i_.pt.x), T(keypoint_i_.pt.y)}; // 原始点
|
|
|
|
// T ptL[3] = {T(keypoint_i_.pt.x), T(keypoint_i_.pt.y)}; // 原始点
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 深度矩阵
|
|
|
|
// 深度矩阵
|
|
|
|
Eigen::Matrix<T, 3, 3> M_het_inv;
|
|
|
|
Eigen::Matrix<T, 3, 3> M_het_inv;
|
|
|
|
M_het_inv << T(1), T(0), T(0),
|
|
|
|
M_het_inv << T(1), T(0), T(0),
|
|
|
|
T(0), T(1), T(0),
|
|
|
|
T(0), T(1), T(0),
|
|
|
|
T(0), T(0), T(1.0 / EvHeight);
|
|
|
|
T(0), T(0), T(1.0 / EvHeight_i);
|
|
|
|
|
|
|
|
|
|
|
|
// K-1
|
|
|
|
// K-1
|
|
|
|
Eigen::Matrix<T, 3, 3> K_1;
|
|
|
|
Eigen::Matrix<T, 3, 3> K_1;
|
|
|
|
@ -176,18 +155,20 @@ struct SE3Residual
|
|
|
|
// 恢复尺度
|
|
|
|
// 恢复尺度
|
|
|
|
T GeoX = result[0] / result[2];
|
|
|
|
T GeoX = result[0] / result[2];
|
|
|
|
T GeoY = result[1] / result[2];
|
|
|
|
T GeoY = result[1] / result[2];
|
|
|
|
|
|
|
|
T GeoZ = T(EvHeight_i);
|
|
|
|
// 平移,获得地理坐标
|
|
|
|
// 平移,获得地理坐标
|
|
|
|
GeoX += se3_i[3];
|
|
|
|
GeoX += se3_i[3];
|
|
|
|
GeoY += se3_i[4];
|
|
|
|
GeoY += se3_i[4];
|
|
|
|
|
|
|
|
GeoZ += se3_i[5];
|
|
|
|
|
|
|
|
|
|
|
|
// 正算,投影到右图
|
|
|
|
// 正算,投影到右图
|
|
|
|
GeoX += -se3_j[3];
|
|
|
|
GeoX += -se3_j[3];
|
|
|
|
GeoY += -se3_j[4];
|
|
|
|
GeoY += -se3_j[4];
|
|
|
|
|
|
|
|
GeoZ += -se3_j[5];
|
|
|
|
|
|
|
|
|
|
|
|
T rvec_j[3] = { se3_j[0], se3_j[1], se3_j[2] };
|
|
|
|
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> pGeoR(GeoX, GeoY, GeoZ);
|
|
|
|
Eigen::Matrix<T, 3, 1> RightRota;
|
|
|
|
Eigen::Matrix<T, 3, 1> RightRota;
|
|
|
|
|
|
|
|
|
|
|
|
ceres::AngleAxisRotatePoint(rvec_j, pGeoR.data(), RightRota.data());
|
|
|
|
ceres::AngleAxisRotatePoint(rvec_j, pGeoR.data(), RightRota.data());
|
|
|
|
@ -205,26 +186,23 @@ struct SE3Residual
|
|
|
|
residual[1] = vR - T(keypoint_j_.pt.y);
|
|
|
|
residual[1] = vR - T(keypoint_j_.pt.y);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
private:
|
|
|
|
const cv::KeyPoint keypoint_i_; // 第 i 帧图像中的特征点
|
|
|
|
const cv::KeyPoint keypoint_i_; // 第 i 帧图像中的特征点
|
|
|
|
const cv::KeyPoint keypoint_j_; // 第 j 帧图像中的特征点
|
|
|
|
const cv::KeyPoint keypoint_j_; // 第 j 帧图像中的特征点
|
|
|
|
cv::Mat_<double> K; //内参
|
|
|
|
cv::Mat_<double> K; //内参
|
|
|
|
double EvHeight;//高差,用于三角化
|
|
|
|
double EvHeight_i;//高差,用于三角化
|
|
|
|
|
|
|
|
double EvHeight_j;//高差,用于三角化
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BA_Task::BA_Task(FileCache<FrameCache>* cache, FeatureMatcher* feaProcess)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BA_Task::BA_Task(FileCache<FrameCache>* cache)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_cache = cache;
|
|
|
|
_cache = cache;
|
|
|
|
_FeaMatcher = new FeatureMatcher(DetectorType::SIFT, MatcherType::FLANN);
|
|
|
|
_FeaMatcher = feaProcess;
|
|
|
|
|
|
|
|
|
|
|
|
//google::InitGoogleLogging("ceres");
|
|
|
|
//google::InitGoogleLogging("ceres");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -253,8 +231,10 @@ void BA_Task::InitTask()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map, std::unordered_map <KeyType, cv::Mat>& global_H)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex_);
|
|
|
|
|
|
|
|
|
|
|
|
// 任务容器初始化
|
|
|
|
// 任务容器初始化
|
|
|
|
InitTask();
|
|
|
|
InitTask();
|
|
|
|
|
|
|
|
|
|
|
|
@ -276,10 +256,10 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 整合为6D参数
|
|
|
|
// 整合为6D参数
|
|
|
|
std::vector<double*> se3_list(_currse3.size());
|
|
|
|
std::vector<double*> se3list(_currse3.size());
|
|
|
|
for (int i = 0; i < _currse3.size(); i++)
|
|
|
|
for (int i = 0; i < _currse3.size(); i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
se3_list[i] = (double*)_currse3[i].data;
|
|
|
|
se3list[i] = (double*)_currse3[i].data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
constK = cv::Mat(3, 3, CV_64FC1, ((double*)_origRtK[0].data) + 12);
|
|
|
|
constK = cv::Mat(3, 3, CV_64FC1, ((double*)_origRtK[0].data) + 12);
|
|
|
|
@ -287,6 +267,7 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
// 创建 Ceres 问题
|
|
|
|
// 创建 Ceres 问题
|
|
|
|
ceres::Problem problemH;
|
|
|
|
ceres::Problem problemH;
|
|
|
|
ceres::Problem problemSE3;
|
|
|
|
ceres::Problem problemSE3;
|
|
|
|
|
|
|
|
ceres::Problem problemH2;
|
|
|
|
|
|
|
|
|
|
|
|
// 添加残差块
|
|
|
|
// 添加残差块
|
|
|
|
int nParaCnt = 0;//参数组数
|
|
|
|
int nParaCnt = 0;//参数组数
|
|
|
|
@ -301,6 +282,7 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<cv::DMatch> matches;
|
|
|
|
std::vector<cv::DMatch> matches;
|
|
|
|
//_FeaMatcher->matchFeatures(_FeaDespVec[i],_FeaDespVec[j],matches);
|
|
|
|
//_FeaMatcher->matchFeatures(_FeaDespVec[i],_FeaDespVec[j],matches);
|
|
|
|
_FeaMatcher->matchFeatures_WithH(_FeaPtVec[i], _FeaDespVec[i], _FeaPtVec[j], _FeaDespVec[j], _origMatrix[i], _origMatrix[j], matches);
|
|
|
|
_FeaMatcher->matchFeatures_WithH(_FeaPtVec[i], _FeaDespVec[i], _FeaPtVec[j], _FeaDespVec[j], _origMatrix[i], _origMatrix[j], matches);
|
|
|
|
@ -324,6 +306,8 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
for (int m = 0; m < matches.size(); m++)
|
|
|
|
for (int m = 0; m < matches.size(); m++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto mc = matches[m];
|
|
|
|
auto mc = matches[m];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 注意:这里不对,应该找匹配点!! todo 节后完成
|
|
|
|
// 注意:这里不对,应该找匹配点!! todo 节后完成
|
|
|
|
cv::KeyPoint keypoint_i = _FeaPtVec[i][mc.queryIdx];
|
|
|
|
cv::KeyPoint keypoint_i = _FeaPtVec[i][mc.queryIdx];
|
|
|
|
cv::KeyPoint keypoint_j = _FeaPtVec[j][mc.trainIdx];
|
|
|
|
cv::KeyPoint keypoint_j = _FeaPtVec[j][mc.trainIdx];
|
|
|
|
@ -339,16 +323,18 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
cv::Mat Hj0 = _origMatrix[j];
|
|
|
|
cv::Mat Hj0 = _origMatrix[j];
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef OPT_H
|
|
|
|
#ifdef OPT_H
|
|
|
|
|
|
|
|
|
|
|
|
ceres::CostFunction* cost_function =
|
|
|
|
ceres::CostFunction* cost_function =
|
|
|
|
new ceres::AutoDiffCostFunction<HomographyResidual, 8, 8, 8>(
|
|
|
|
new ceres::AutoDiffCostFunction<HomographyResidual, 4, 8, 8>(
|
|
|
|
new HomographyResidual(keypoint_i, keypoint_j, Hi0, Hj0));
|
|
|
|
new HomographyResidual(keypoint_i, keypoint_j, Hi0, Hj0));
|
|
|
|
problemH.AddResidualBlock(cost_function, scale_loss, h_list[i], h_list[j]);
|
|
|
|
problemH2.AddResidualBlock(cost_function, scale_loss, h_list[i], h_list[j]);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#else
|
|
|
|
#ifdef OPT_SE3
|
|
|
|
ceres::CostFunction* cost_function =
|
|
|
|
ceres::CostFunction* cost_function =
|
|
|
|
new ceres::AutoDiffCostFunction<SE3Residual,2,6,6>(
|
|
|
|
new ceres::AutoDiffCostFunction<SE3Residual,2,6,6>(
|
|
|
|
new SE3Residual(keypoint_i, keypoint_j, constK, constHeight));
|
|
|
|
new SE3Residual(keypoint_i, keypoint_j, constK, _depth[i], _depth[j]));
|
|
|
|
problemSE3.AddResidualBlock(cost_function, scale_loss, se3_list[i],se3_list[j]);
|
|
|
|
problemSE3.AddResidualBlock(cost_function, scale_loss, se3list[i], se3list[j]);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
@ -361,38 +347,37 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
// 配置求解器
|
|
|
|
// 配置求解器
|
|
|
|
ceres::Solver::Options options;
|
|
|
|
ceres::Solver::Options options;
|
|
|
|
options.max_num_iterations = 10; // 增加最大迭代次数
|
|
|
|
options.max_num_iterations = 10; // 增加最大迭代次数
|
|
|
|
options.function_tolerance = 1e-5; // 设置更严格的函数值容忍度
|
|
|
|
options.function_tolerance = 1e-15; // 设置更严格的函数值容忍度
|
|
|
|
options.gradient_tolerance = 1e-5; // 设置更严格的梯度容忍度
|
|
|
|
options.gradient_tolerance = 1e-15; // 设置更严格的梯度容忍度
|
|
|
|
options.parameter_tolerance = 1e-5; // 设置更严格的参数容忍度
|
|
|
|
options.parameter_tolerance = 1e-15; // 设置更严格的参数容忍度
|
|
|
|
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 = 12; // 使用多线程
|
|
|
|
options.num_threads = 8; // 使用多线程
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ceres::Solver::Summary summary;
|
|
|
|
ceres::Solver::Summary summary;
|
|
|
|
|
|
|
|
|
|
|
|
// 求解
|
|
|
|
// 求解
|
|
|
|
#ifdef OPT_H
|
|
|
|
#ifdef OPT_H
|
|
|
|
ceres::Solve(options, &problemH, &summary);
|
|
|
|
ceres::Solve(options, &problemH2, &summary);
|
|
|
|
#else
|
|
|
|
|
|
|
|
ceres::Solve(options, &problemSE3, &summary);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//for (int i = 0; i < _origse3.size(); i++)
|
|
|
|
#ifdef OPT_SE3
|
|
|
|
//{
|
|
|
|
ceres::Solve(options, &problemSE3, &summary);
|
|
|
|
// std::cout << "------------" << std::endl;
|
|
|
|
#endif
|
|
|
|
// std::cout << _origse3[i] << std::endl;
|
|
|
|
|
|
|
|
// std::cout << _currse3[i] << std::endl;
|
|
|
|
|
|
|
|
// std::cout << "------------" << std::endl;
|
|
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 输出结果
|
|
|
|
// 输出结果
|
|
|
|
//std::cout << summary.BriefReport() << std::endl;
|
|
|
|
std::cout << summary.BriefReport() << std::endl;
|
|
|
|
|
|
|
|
for (int i = 0; i < _currse3.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
std::cout << "-----SE3------" << std::endl;
|
|
|
|
|
|
|
|
std::cout << _origse3[i]- _currse3[i] << std::endl;
|
|
|
|
|
|
|
|
std::cout << "------------" << std::endl;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef OPT_H
|
|
|
|
#ifdef OPT_SE3
|
|
|
|
// 将优化se3写入H
|
|
|
|
// 将优化se3写入H
|
|
|
|
updateSe3();
|
|
|
|
updateSe3toH();
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//for (int i = 0; i < _origMatrix.size(); i++)
|
|
|
|
//for (int i = 0; i < _origMatrix.size(); i++)
|
|
|
|
@ -406,22 +391,35 @@ void BA_Task::OptFrame(vector<KeyType> frameInd,cv::Mat H_map)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 优化后H写入文件缓存
|
|
|
|
// 优化后H写入文件缓存
|
|
|
|
writeFrameInfo();
|
|
|
|
for (size_t i = 0; i < _currMatrix.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto Key = _frameInd[i];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新缓存
|
|
|
|
|
|
|
|
updateCacheH(Key, _currMatrix[i], global_H);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool BA_Task::updateCacheH(KeyType Key, cv::Mat H)
|
|
|
|
bool BA_Task::updateCacheH(KeyType Key, cv::Mat H, std::unordered_map <KeyType, cv::Mat>& global_H)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
auto _t_frame_cache = std::make_shared<FrameCache>();
|
|
|
|
auto _t_frame_cache = std::make_shared<FrameCache>();
|
|
|
|
|
|
|
|
|
|
|
|
if (_cache->get(Key, _t_frame_cache))
|
|
|
|
if (_cache->get(Key, _t_frame_cache))
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
//cv::Mat old(3, 3, CV_64FC1, _t_frame_cache->H);
|
|
|
|
|
|
|
|
//std::cout << "before" << old << std::endl;
|
|
|
|
|
|
|
|
//std::cout << "after" << H << std::endl;
|
|
|
|
// 更新H
|
|
|
|
// 更新H
|
|
|
|
memcpy(_t_frame_cache->H, H.data, sizeof(double) * 9);
|
|
|
|
memcpy(_t_frame_cache->H, H.data, sizeof(double) * 9);
|
|
|
|
|
|
|
|
|
|
|
|
// 存储
|
|
|
|
// 存储
|
|
|
|
_cache->set(Key, _t_frame_cache);
|
|
|
|
_cache->set(Key, _t_frame_cache);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
global_H[Key] = H.clone();
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -432,7 +430,6 @@ 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);
|
|
|
|
_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++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
@ -442,6 +439,8 @@ int BA_Task::readFrameInfo(vector<KeyType> frameInd)
|
|
|
|
// 记录key
|
|
|
|
// 记录key
|
|
|
|
_frameInd.push_back(key);
|
|
|
|
_frameInd.push_back(key);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
_depth.push_back(_t_frame_cache->_para.nEvHeight);
|
|
|
|
|
|
|
|
|
|
|
|
// 注意Mat 浅拷贝陷阱!!!!!!
|
|
|
|
// 注意Mat 浅拷贝陷阱!!!!!!
|
|
|
|
|
|
|
|
|
|
|
|
// 特征点
|
|
|
|
// 特征点
|
|
|
|
@ -482,27 +481,17 @@ int BA_Task::readFrameInfo(vector<KeyType> frameInd)
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <Arith_GeoSolver.h>
|
|
|
|
#include <Arith_GeoSolver.h>
|
|
|
|
void BA_Task::updateSe3()
|
|
|
|
void BA_Task::updateSe3toH()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
for (size_t i = 0; i < _origse3.size(); i++)
|
|
|
|
for (size_t i = 0; i < _origse3.size(); i++)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
_currMatrix[i] = Transe3ToH((double*)_origse3[i].data, constK, constHeight);
|
|
|
|
_currMatrix[i] = Transe3ToH((double*)_currse3[i].data, constK, _depth[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int BA_Task::writeFrameInfo()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
for (size_t i = 0; i < _currMatrix.size(); i++)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
auto Key = _frameInd[i];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 更新缓存
|
|
|
|
|
|
|
|
updateCacheH(Key, _currMatrix[i]);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SINT32 BA_Task::CalMatchMat()
|
|
|
|
SINT32 BA_Task::CalMatchMat()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|