LF-Net就是"LF-Net: Learning Local Features from Images"一種端到端的深度學(xué)習(xí)局部特征子.
基于OpenMVG稍微對特征提取部分進(jìn)行改造即可使用深度學(xué)習(xí)特征點(diǎn)進(jìn)行重建
主要內(nèi)容:
- OpenMVG代碼修改
- 重建實(shí)驗(yàn)對比
- 結(jié)論
一. 代碼修改
主要修改代碼如下:
1.在regions_factory_io.hpp注冊下新的特征點(diǎn)览绿,用來序列化
CEREAL_REGISTER_TYPE_WITH_NAME(openMVG::features::LFNET_Float_Regions , "LFNET_Float_Regions");
CEREAL_REGISTER_POLYMORPHIC_RELATION(openMVG::features::Regions, openMVG::features::LFNET_Float_Regions)
2.在region_factory.hpp聲明新的特征點(diǎn)類型:
using LFNET_Float_Regions = Scalar_Regions<SIOPointFeature, float, 256>;
EIGEN_DEFINE_STL_VECTOR_SPECIALIZATION_INITIALIZER_LIST(openMVG::features::LFNET_Float_Regions)
3.最后寫一下怎么讀取特征點(diǎn)策严,我直接寫了新的app實(shí)現(xiàn)這個功能.
class LFNET_Image_describer : public Image_describer
{
public:
using Regions_type = LFNET_Float_Regions;
LFNET_Image_describer() : Image_describer() {}
~LFNET_Image_describer() {}
bool Set_configuration_preset(EDESCRIBER_PRESET preset){
return true;
}
std::unique_ptr<Regions> Describe(
const image::Image<unsigned char>& image,
const image::Image<unsigned char> * mask = nullptr
) override
{
return Describe_LFNET(image, mask);
}
std::unique_ptr<Regions_type> Describe_LFNET(
const image::Image<unsigned char>& image,
const image::Image<unsigned char>* mask = nullptr
)
{
std::string filename_=filename;
auto regions = std::unique_ptr<Regions_type>(new Regions_type);
std::ifstream infile_feat(filename_);
std::string feature;
float feat_onePoint; //存儲每行按空格分開的每一個float數(shù)據(jù)
std::vector<float> lines; //存儲每行數(shù)據(jù)
std::vector<vector<float>> lines_feat; //存儲所有數(shù)據(jù)
lines_feat.clear();
while(!infile_feat.eof())
{
getline(infile_feat, feature); //一次讀取一行數(shù)據(jù)
stringstream stringin(feature); //使用串流實(shí)現(xiàn)對string的輸入輸出操作
lines.clear();
while (stringin >> feat_onePoint) { //按空格一次讀取一個數(shù)據(jù)存入feat_onePoint
lines.push_back(feat_onePoint); //存儲每行按空格分開的數(shù)據(jù)
}
if(lines.size() != 0){
lines_feat.push_back(lines); //存儲所有數(shù)據(jù)
}
}
infile_feat.close();
regions->Features().reserve(lines_feat.size());
regions->Descriptors().reserve(lines_feat.size());
// Copy keypoints and descriptors in the regions
int cpt = 0;
for (auto i_kp = lines_feat.begin();
i_kp != lines_feat.end();
++i_kp, ++cpt)
{
SIOPointFeature feat((*i_kp)[0], (*i_kp)[1], 0, 0);
regions->Features().push_back(feat);
Descriptor<float, 256> desc;
//
for (int j = 0; j < 256; j++)
{
desc[j] = (*i_kp)[j+2];
}
//
regions->Descriptors().push_back(desc);
}
return regions;
};
/// Allocate Regions type depending of the Image_describer
std::unique_ptr<Regions> Allocate() const override
{
return std::unique_ptr<Regions_type>(new Regions_type);
}
template<class Archive>
void serialize( Archive & ar )
{
}
};
#include <cereal/cereal.hpp>
#include <cereal/types/polymorphic.hpp>
CEREAL_REGISTER_TYPE_WITH_NAME(LFNET_Image_describer, "LFNET_Image_describer");
CEREAL_REGISTER_POLYMORPHIC_RELATION(openMVG::features::Image_describer, LFNET_Image_describer)
二. 重建實(shí)驗(yàn)對比
對于重建的結(jié)果如下:
看起來效果還是可以的,對比下SIFT的方法結(jié)果饿敲,由于我只是更改了pipline特征提取的一層妻导,后面優(yōu)化流程是一樣的,所以可以很好的進(jìn)行對比研究.
SIFT里面中間有四幀重建失敗了.....導(dǎo)致看起來不太好,還需要再試試倔韭,一次性重建一千多張圖片還是很費(fèi)時間的
每隔五幀重建對比:
中間有兩幀失敗了术浪,導(dǎo)致誤差比較大,分別是"1305031938.769073.png"和"1305031938.936828.png"連續(xù)兩幀寿酌,這樣導(dǎo)致的誤差就比較大了
這相鄰四幀如下:
看起來是中間無紋理區(qū)域?qū)е缕ヅ涫?br>
而且圖片比較模糊
不過實(shí)際比較下發(fā)現(xiàn)其實(shí)在這相鄰幾幀匹配效果是不錯的:
所以還是重建過程中在這一段累積的誤差最后導(dǎo)致在這里失敗了......
同時還有問題就是胰苏,邊緣的特征點(diǎn)形成畫框一樣的分布都不是好的特征點(diǎn)
每隔十幀重建對比:
初看效果出奇的好,不過要考慮到醇疼,其中只成功了70幀硕并,本來130幀的,也就是因?yàn)閛verlap太大直接崩了.
看看哪塊崩來秧荆?
外點(diǎn)還是蠻多的
不過應(yīng)該不至于ransac都找不到正確匹配吧..