Skip to content

Commit

Permalink
Make some process image_describer independent =>uUse only the regions…
Browse files Browse the repository at this point in the history
… type for dynamic loading. openMVG#274
  • Loading branch information
pmoulon committed May 4, 2015
1 parent 06c6b3b commit 134cb1e
Show file tree
Hide file tree
Showing 18 changed files with 270 additions and 117 deletions.
5 changes: 0 additions & 5 deletions src/nonFree/sift/SIFT_describer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,6 @@ struct SiftParams
bool _root_sift; // see [1]
};

/// Define the classic SIFT Keypoint
typedef Scalar_Regions<SIOPointFeature,unsigned char,128> SIFT_Regions;

class SIFT_Image_describer : public Image_describer
{
public:
Expand Down Expand Up @@ -206,6 +203,4 @@ class SIFT_Image_describer : public Image_describer
#include <cereal/archives/json.hpp>
CEREAL_REGISTER_TYPE_WITH_NAME(openMVG::features::SIFT_Image_describer, "SIFT_Image_describer");



#endif // OPENMVG_PATENTED_SIFT_SIFT_DESCRIBER_H
15 changes: 15 additions & 0 deletions src/openMVG/features/descriptor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,21 @@ class Descriptor
/// Istream interface
std::istream& read(std::istream& in);

template<class Archive>
void save(Archive & archive) const
{
std::vector<T> array(data,data+N);
archive( array );
}

template<class Archive>
void load(Archive & archive)
{
std::vector<T> array(N);
archive( array );
std::memcpy(data, array.data(), sizeof(T)*N);
}

private:
bin_type data[N];
};
Expand Down
15 changes: 15 additions & 0 deletions src/openMVG/features/feature.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ class PointFeature {
virtual inline std::istream& read(std::istream& in)
{ return in >> _coords(0) >> _coords(1); }

template<class Archive>
void serialize(Archive & ar)
{
ar (_coords(0), _coords(1));
}

protected:
Vec2f _coords; // (x, y).
};
Expand Down Expand Up @@ -98,6 +104,15 @@ class SIOPointFeature : public PointFeature {
return PointFeature::read(in) >> _scale >> _orientation;
}

template<class Archive>
void serialize(Archive & ar)
{
ar (
_coords(0), _coords(1),
_scale,
_orientation);
}

protected:
float _scale; // In pixels.
float _orientation; // In radians.
Expand Down
1 change: 1 addition & 0 deletions src/openMVG/features/features.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "openMVG/features/descriptor.hpp"
#include "openMVG/features/keypointSet.hpp"
#include "openMVG/features/regions.hpp"
#include "openMVG/features/regions_factory.hpp"
#include "openMVG/features/image_describer.hpp"
#include "openMVG/features/image_describer_akaze.hpp"

Expand Down
11 changes: 2 additions & 9 deletions src/openMVG/features/image_describer_akaze.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <numeric>

#include "openMVG/features/image_describer.hpp"
#include "openMVG/features/regions_factory.hpp"
#include "openMVG/features/akaze/AKAZE.hpp"
#include "openMVG/features/akaze/msurf_descriptor.hpp"
#include "openMVG/features/akaze/mldb_descriptor.hpp"
Expand All @@ -22,13 +23,6 @@ using namespace openMVG;
namespace openMVG {
namespace features {

/// Define the AKAZE Keypoint (with a float descriptor)
typedef Scalar_Regions<SIOPointFeature,float,64> AKAZE_Float_Regions;
/// Define the AKAZE Keypoint (with a LIOP descriptor)
typedef Scalar_Regions<SIOPointFeature,unsigned char,144> AKAZE_Liop_Regions;
/// Define the AKAZE Keypoint (with a binary descriptor saved in an uchar array)
typedef Binary_Regions<SIOPointFeature,64> AKAZE_Binary_Regions;

enum EAKAZE_DESCRIPTOR
{
AKAZE_MSURF,
Expand Down Expand Up @@ -143,7 +137,7 @@ class AKAZE_Image_describer : public Image_describer
for (int i = 0; i < static_cast<int>(kpts.size()); ++i)
{
AKAZEKeypoint ptAkaze = kpts[i];

// Feature masking
if (mask)
{
Expand Down Expand Up @@ -267,5 +261,4 @@ class AKAZE_Image_describer : public Image_describer
#include <cereal/archives/json.hpp>
CEREAL_REGISTER_TYPE_WITH_NAME(openMVG::features::AKAZE_Image_describer, "AKAZE_Image_describer");


#endif // OPENMVG_FEATURES_AKAZE_IMAGE_DESCRIBER_HPP
30 changes: 29 additions & 1 deletion src/openMVG/features/regions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ class Regions
virtual bool IsScalar() const = 0;
virtual bool IsBinary() const = 0;

virtual std::string Type_id() const = 0; // basis element used for description
/// basis element used for description
virtual std::string Type_id() const = 0;
virtual size_t DescriptorLength() const = 0;
//--

Expand All @@ -58,6 +59,9 @@ class Regions
/// Return a pointer to the first value of the descriptor array
// Used to avoid complex template imbrication
virtual const void * DescriptorRawData() const = 0;

virtual Regions * EmptyClone() const = 0;

};

/// Specialization of the abstract Regions class to handle Scalar descriptors
Expand Down Expand Up @@ -132,6 +136,18 @@ class Scalar_Regions : public Regions
inline const std::vector<DescriptorT> & Descriptors() const { return _vec_descs; }

const void * DescriptorRawData() const { return &_vec_descs[0];}

template<class Archive>
void serialize(Archive & ar)
{
ar(_vec_feats);
ar(_vec_descs);
}

virtual Regions * EmptyClone() const
{
return new Scalar_Regions();
}
private:
//--
//-- internal data
Expand Down Expand Up @@ -214,6 +230,18 @@ class Binary_Regions : public Regions

const void * DescriptorRawData() const { return &_vec_descs[0];}

template<class Archive>
void serialize(Archive & ar)
{
ar(_vec_feats);
ar(_vec_descs);
}

virtual Regions * EmptyClone() const
{
return new Binary_Regions();
}

private:
//--
//-- internal data
Expand Down
45 changes: 45 additions & 0 deletions src/openMVG/features/regions_factory.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef OPENMVG_FEATURES_REGIONS_FACTORY_HPP
#define OPENMVG_FEATURES_REGIONS_FACTORY_HPP

#include "openMVG/numeric/numeric.h"
#include "openMVG/features/regions.hpp"
#include "openMVG/features/feature.hpp"
#include "openMVG/features/descriptor.hpp"
#include <string>
#include <typeinfo>

namespace openMVG {
namespace features {

/// Define the classic SIFT Keypoint
typedef Scalar_Regions<SIOPointFeature,unsigned char,128> SIFT_Regions;

/// Define the AKAZE Keypoint (with a float descriptor)
typedef Scalar_Regions<SIOPointFeature,float,64> AKAZE_Float_Regions;
/// Define the AKAZE Keypoint (with a LIOP descriptor)
typedef Scalar_Regions<SIOPointFeature,unsigned char,144> AKAZE_Liop_Regions;
/// Define the AKAZE Keypoint (with a binary descriptor saved in an uchar array)
typedef Binary_Regions<SIOPointFeature,64> AKAZE_Binary_Regions;

} // namespace features
} // namespace openMVG

//--
// Register region type for serialization
//--
#include <cereal/cereal.hpp>
#include <cereal/types/polymorphic.hpp>
#include <cereal/archives/json.hpp>/*
CEREAL_REGISTER_TYPE_WITH_NAME(openMVG::features::SIFT_Regions, "SIFT_Regions");
CEREAL_REGISTER_TYPE_WITH_NAME(openMVG::features::AKAZE_Float_Regions, "AKAZE_Float_Regions");
CEREAL_REGISTER_TYPE_WITH_NAME(openMVG::features::AKAZE_Liop_Regions, "AKAZE_Liop_Regions");
CEREAL_REGISTER_TYPE_WITH_NAME(openMVG::features::AKAZE_Binary_Regions, "AKAZE_Binary_Regions");*/

#endif // OPENMVG_FEATURES_REGIONS_FACTORY_HPP
25 changes: 25 additions & 0 deletions src/openMVG/sfm/pipelines/sfm_features_provider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,31 @@ struct Features_Provider
return true;
}

virtual bool load(
const SfM_Data & sfm_data,
const std::string & feat_directory,
std::unique_ptr<features::Regions>& region_type)
{
// Read for each view the corresponding features and store them as PointFeatures
std::unique_ptr<features::Regions> regions(region_type->EmptyClone());
for (Views::const_iterator iter = sfm_data.getViews().begin();
iter != sfm_data.getViews().end(); ++iter)
{
const std::string sImageName = stlplus::create_filespec(sfm_data.s_root_path, iter->second.get()->s_Img_path);
const std::string basename = stlplus::basename_part(sImageName);
const std::string featFile = stlplus::create_filespec(feat_directory, basename, ".feat");

if (!regions->LoadFeatures(featFile))
{
std::cerr << "Invalid feature files for the view: " << sImageName << std::endl;
return false;
}
// save loaded Features as PointFeature
feats_per_view[iter->second.get()->id_view] = regions->GetRegionsPositions();
}
return true;
}


/// Return the PointFeatures belonging to the View, if the view does not exist
/// it return an empty PointFeature array.
Expand Down
25 changes: 25 additions & 0 deletions src/openMVG/sfm/pipelines/sfm_regions_provider.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,31 @@ struct Regions_Provider
return true;
}

// Load Regions related to a provided SfM_Data View container
virtual bool load(
const SfM_Data & sfm_data,
const std::string & feat_directory,
std::unique_ptr<features::Regions>& region_type)
{
// Read for each view the corresponding regions and store them
for (Views::const_iterator iter = sfm_data.getViews().begin();
iter != sfm_data.getViews().end(); ++iter)
{
const std::string sImageName = stlplus::create_filespec(sfm_data.s_root_path, iter->second.get()->s_Img_path);
const std::string basename = stlplus::basename_part(sImageName);
const std::string featFile = stlplus::create_filespec(feat_directory, basename, ".feat");
const std::string descFile = stlplus::create_filespec(feat_directory, basename, ".desc");

regions_per_view[iter->second.get()->id_view] = std::unique_ptr<features::Regions>(region_type->EmptyClone());
if (!regions_per_view[iter->second.get()->id_view]->Load(featFile, descFile))
{
std::cerr << "Invalid regions files for the view: " << sImageName << std::endl;
return false;
}
}
return true;
}

}; // Regions_Provider

} // namespace openMVG
Expand Down
47 changes: 47 additions & 0 deletions src/software/SfM/io_regions_type.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@

// Copyright (c) 2015 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef IO_REGIONS_TYPE_HPP
#define IO_REGIONS_TYPE_HPP

#include "openMVG/features/features.hpp"
#include <cereal/archives/json.hpp>

#include <fstream>
#include <vector>

namespace openMVG
{

// Init the regions_type from the image describer (used for regions loading)
static std::unique_ptr<features::Regions> Init_region_type_from_file
(
const std::string & sImage_describer_file
)
{
using namespace openMVG::features;
std::unique_ptr<Regions> regions_type;
if (stlplus::is_file(sImage_describer_file))
{
// Dynamically load the regions type from the file
std::ifstream stream(sImage_describer_file.c_str());
if (stream.is_open())
{
cereal::JSONInputArchive archive(stream);
archive(cereal::make_nvp("regions_type", regions_type));
}
}
else // By default init a SIFT regions type (keep compatibility)
{
regions_type.reset(new features::SIFT_Regions());
}
return regions_type;
}

} // namespace openMVG

#endif // IO_REGIONS_TYPE_HPP
26 changes: 9 additions & 17 deletions src/software/SfM/main_GlobalSfM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
#include <cstdlib>

#include "openMVG/sfm/pipelines/global/sfm_global_engine_relative_motions.hpp"
#include "nonFree/sift/SIFT_describer.hpp"
#include <cereal/archives/json.hpp>
#include "software/SfM/io_regions_type.hpp"

#include "openMVG/system/timer.hpp"
using namespace openMVG;
Expand Down Expand Up @@ -91,27 +90,20 @@ int main(int argc, char **argv)
return EXIT_FAILURE;
}

// Init the image describer (used for regions loading)
// Init the regions_type from the image describer file (used for image regions extraction)
using namespace openMVG::features;
std::unique_ptr<Image_describer> image_describer;
const std::string sImage_describer = stlplus::create_filespec(sMatchesDir, "image_describer", "json");
if (stlplus::is_file(sImage_describer))
std::unique_ptr<Regions> regions_type = Init_region_type_from_file(sImage_describer);
if (!regions_type)
{
// Dynamically load the image_describer from the file (will restore old used settings)
std::ifstream stream(sImage_describer.c_str());
if (!stream.is_open())
return false;

cereal::JSONInputArchive archive(stream);
archive(cereal::make_nvp("image_describer", image_describer));
}
else // By default init a SIFT_Image_describer (keep compatibility)
{
image_describer.reset(new SIFT_Image_describer());
std::cerr << "Invalid: "
<< sImage_describer << " regions type file." << std::endl;
return EXIT_FAILURE;
}

// Features reading
std::shared_ptr<Features_Provider> feats_provider = std::make_shared<Features_Provider>();
if (!feats_provider->load(sfm_data, sMatchesDir, image_describer)) {
if (!feats_provider->load(sfm_data, sMatchesDir, regions_type)) {
std::cerr << std::endl
<< "Invalid features." << std::endl;
return EXIT_FAILURE;
Expand Down
Loading

0 comments on commit 134cb1e

Please sign in to comment.