From 4be042a7835a119c2d8c9f49284494f200183a2e Mon Sep 17 00:00:00 2001 From: Theo Date: Wed, 29 Jan 2020 10:48:18 +0100 Subject: [PATCH 1/5] [feature] Single PointFeature class with scale and orientation --- .../CommonDataByPair_matchedPoints.hpp | 5 +- .../CommonDataByPair_vldSegment.hpp | 8 +- src/aliceVision/feature/KeypointSet.hpp | 2 +- src/aliceVision/feature/PointFeature.hpp | 72 ++++-------- src/aliceVision/feature/Regions.hpp | 105 +++++++----------- .../feature/akaze/ImageDescriber_AKAZE.cpp | 8 +- .../feature/akaze/descriptorLIOP.cpp | 2 +- .../feature/akaze/descriptorLIOP.hpp | 2 +- .../feature/akaze/descriptorMLDB.hpp | 2 +- .../feature/akaze/descriptorMSURF.hpp | 4 +- .../feature/cctag/ImageDescriber_CCTAG.cpp | 6 +- src/aliceVision/feature/features_test.cpp | 2 +- .../openCV/ImageDescriber_AKAZE_OCV.cpp | 2 +- .../openCV/ImageDescriber_SIFT_OCV.cpp | 2 +- src/aliceVision/feature/regionsFactory.hpp | 12 +- src/aliceVision/feature/selection.cpp | 22 ++-- src/aliceVision/feature/selection.hpp | 8 +- src/aliceVision/feature/sift/SIFT.hpp | 14 +-- src/aliceVision/feature/svgVisualization.cpp | 32 +++--- src/aliceVision/feature/svgVisualization.hpp | 22 ++-- .../matching/IndMatchDecorator.hpp | 14 --- src/aliceVision/matching/kvld/algorithm.cpp | 4 +- src/aliceVision/matching/kvld/algorithm.h | 4 +- src/aliceVision/matching/kvld/kvld.cpp | 4 +- src/aliceVision/matching/kvld/kvld.h | 4 +- src/aliceVision/matching/kvld/kvld_draw.h | 12 +- .../GeometricFilterMatrix_HGrowing.cpp | 18 +-- .../GeometricFilterMatrix_HGrowing.hpp | 23 ++-- .../geometricFilterUtils.cpp | 38 +++---- .../geometricFilterUtils.hpp | 24 ++-- .../geometricFilterUtils_test.cpp | 6 +- .../ReconstructionEngine_sequentialSfM.cpp | 4 +- src/aliceVision/sfm/sfmFilters.cpp | 9 +- src/aliceVision/sfm/utils/syntheticScene.hpp | 6 +- src/aliceVision/sfmData/Landmark.hpp | 4 +- src/samples/kvldFilter/main_kvldFilter.cpp | 8 +- .../robustEssential/main_robustEssential.cpp | 16 +-- .../main_robustEssentialBA.cpp | 16 +-- .../main_robustEssentialSpherical.cpp | 8 +- .../main_robustFundamental.cpp | 12 +- .../main_robustFundamentalGuided.cpp | 16 +-- .../main_robustHomography.cpp | 12 +- .../main_robustHomographyGrowing.cpp | 38 +++---- .../main_robustHomographyGuided.cpp | 16 +-- .../siftPutativeMatches/main_siftMatching.cpp | 8 +- .../pipeline/main_featureMatching.cpp | 4 +- src/software/utils/CMakeLists.txt | 18 +-- .../colorHarmonizeEngineGlobal.cpp | 6 +- 48 files changed, 311 insertions(+), 373 deletions(-) diff --git a/src/aliceVision/colorHarmonization/CommonDataByPair_matchedPoints.hpp b/src/aliceVision/colorHarmonization/CommonDataByPair_matchedPoints.hpp index 05a337e529..563bb0f26e 100644 --- a/src/aliceVision/colorHarmonization/CommonDataByPair_matchedPoints.hpp +++ b/src/aliceVision/colorHarmonization/CommonDataByPair_matchedPoints.hpp @@ -10,6 +10,7 @@ #include "aliceVision/colorHarmonization/CommonDataByPair.hpp" #include "aliceVision/matching/IndMatch.hpp" #include "aliceVision/feature/feature.hpp" +#include "aliceVision/feature/RegionsPerView.hpp" #include @@ -53,8 +54,8 @@ class CommonDataByPair_matchedPoints : public CommonDataByPair for(const matching::IndMatch& match : matchesPerDescIt.second) //< loop over matches { - const feature::SIOPointFeature& L = feature::getSIOPointFeatures(*_regionsL.at(descType)).at(match._i); - const feature::SIOPointFeature& R = feature::getSIOPointFeatures(*_regionsR.at(descType)).at(match._j); + const feature::PointFeature& L = _regionsL.at(descType)->Features().at(match._i); + const feature::PointFeature& R = _regionsR.at(descType)->Features().at(match._j); image::FilledCircle( L.x(), L.y(), ( int )_radius, ( unsigned char ) 255, &maskLeft ); image::FilledCircle( R.x(), R.y(), ( int )_radius, ( unsigned char ) 255, &maskRight ); diff --git a/src/aliceVision/colorHarmonization/CommonDataByPair_vldSegment.hpp b/src/aliceVision/colorHarmonization/CommonDataByPair_vldSegment.hpp index 1c3345d2e2..947fe8977c 100644 --- a/src/aliceVision/colorHarmonization/CommonDataByPair_vldSegment.hpp +++ b/src/aliceVision/colorHarmonization/CommonDataByPair_vldSegment.hpp @@ -20,8 +20,8 @@ class CommonDataByPair_vldSegment : public CommonDataByPair CommonDataByPair_vldSegment( const std::string& sLeftImage, const std::string& sRightImage, const matching::IndMatches& matchesPerDesc, - const std::vector& featsL, - const std::vector& featsR) + const std::vector& featsL, + const std::vector& featsR) : CommonDataByPair( sLeftImage, sRightImage ) , _matches( matchesPerDesc ) , _featsL( featsL ) @@ -104,8 +104,8 @@ class CommonDataByPair_vldSegment : public CommonDataByPair private: // Left and Right features - const std::vector& _featsL; - const std::vector& _featsR; + const std::vector& _featsL; + const std::vector& _featsR; // Left and Right corresponding index (putatives matches) matching::IndMatches _matches; }; diff --git a/src/aliceVision/feature/KeypointSet.hpp b/src/aliceVision/feature/KeypointSet.hpp index 256dc4cc91..68002a8748 100644 --- a/src/aliceVision/feature/KeypointSet.hpp +++ b/src/aliceVision/feature/KeypointSet.hpp @@ -18,7 +18,7 @@ namespace feature { /// Association storage of associated feature and descriptor for a given image. /// Load, save, R/W accessor operation. /// -/// typedef vector featsT; +/// typedef vector featsT; /// typedef vector > descsT; /// KeypointSet< featsT, descsT > kpSet; template diff --git a/src/aliceVision/feature/PointFeature.hpp b/src/aliceVision/feature/PointFeature.hpp index b278a31bbe..0d662bd1af 100644 --- a/src/aliceVision/feature/PointFeature.hpp +++ b/src/aliceVision/feature/PointFeature.hpp @@ -27,55 +27,26 @@ class PointFeature { friend std::istream& operator>>(std::istream& in, PointFeature& obj); public: - PointFeature(float x=0.0f, float y=0.0f) - : _coords(x, y) {} + PointFeature() {} + PointFeature(float x, float y, float scale, float orient) + : _coords(x, y), + _scale(scale), + _orientation(orient) + {} float x() const { return _coords(0); } float y() const { return _coords(1); } const Vec2f & coords() const { return _coords;} + float scale() const { return _scale; } + float& scale() { return _scale; } float& x() { return _coords(0); } float& y() { return _coords(1); } Vec2f& coords() { return _coords;} -protected: - Vec2f _coords; // (x, y) -}; - -typedef std::vector PointFeatures; - -//with overloaded operators: -inline std::ostream& operator<<(std::ostream& out, const PointFeature& obj) -{ - return out << obj._coords(0) << " " << obj._coords(1); -} - -inline std::istream& operator>>(std::istream& in, PointFeature& obj) -{ - return in >> obj._coords(0) >> obj._coords(1); -} - -/** - * Base class for ScaleInvariant Oriented Point features. - * Add scale and orientation description to basis PointFeature. - */ -class SIOPointFeature : public PointFeature { - - friend std::ostream& operator<<(std::ostream& out, const SIOPointFeature& obj); - friend std::istream& operator>>(std::istream& in, SIOPointFeature& obj); - -public: - SIOPointFeature(float x=0.0f, float y=0.0f, - float scale=0.0f, float orient=0.0f) - : PointFeature(x,y) - , _scale(scale) - , _orientation(orient) {} - - float scale() const { return _scale; } - float& scale() { return _scale; } float orientation() const { return _orientation; } float& orientation() { return _orientation; } - + /** * @brief Return the orientation of the feature as an unit vector. * @return a unit vector corresponding to the orientation of the feature. @@ -93,33 +64,34 @@ class SIOPointFeature : public PointFeature { { return scale()*getOrientationVector(); } - - bool operator ==(const SIOPointFeature& b) const { + + bool operator ==(const PointFeature& b) const { return (_scale == b.scale()) && (_orientation == b.orientation()) && (x() == b.x()) && (y() == b.y()) ; } - bool operator !=(const SIOPointFeature& b) const { + bool operator !=(const PointFeature& b) const { return !((*this)==b); } protected: - float _scale; // In pixels. - float _orientation; // In radians. + Vec2f _coords = {0.0f, 0.0f}; // (x, y) + float _scale = 0.0f; // In pixels. + float _orientation = 0.0f; // In radians. }; -// -inline std::ostream& operator<<(std::ostream& out, const SIOPointFeature& obj) +typedef std::vector PointFeatures; + +//with overloaded operators: +inline std::ostream& operator<<(std::ostream& out, const PointFeature& obj) { - const PointFeature *pf = static_cast(&obj); - return out << *pf << " " << obj._scale << " " << obj._orientation; + return out << obj._coords(0) << " " << obj._coords(1) << " " << obj._scale << " " << obj._orientation; } -inline std::istream& operator>>(std::istream& in, SIOPointFeature& obj) +inline std::istream& operator>>(std::istream& in, PointFeature& obj) { - PointFeature *pf = static_cast(&obj); - return in >> *pf >> obj._scale >> obj._orientation; + return in >> obj._coords(0) >> obj._coords(1) >> obj._scale >> obj._orientation; } /// Read feats from file diff --git a/src/aliceVision/feature/Regions.hpp b/src/aliceVision/feature/Regions.hpp index 87f44fb724..dd864d0e89 100644 --- a/src/aliceVision/feature/Regions.hpp +++ b/src/aliceVision/feature/Regions.hpp @@ -23,7 +23,7 @@ namespace aliceVision { namespace feature { /** - * @brief Store a featureIndes and the associated point3dId + * @brief Store a featureIndex and the associated point3dId */ struct FeatureInImage { @@ -43,12 +43,42 @@ struct FeatureInImage /// Describe an image a set of regions (position, ...) + attributes /// Each region is described by a set of attributes (descriptor) +/** + * @brief The Regions class describe a set of regions extracted from an image. + * It contains both a feature (position, scale, orientation) and a descriptor (photometric neighborhood description). + */ class Regions { public: virtual ~Regions() = 0; +protected: + std::vector _vec_feats; // region features + +public: + void LoadFeatures(const std::string& sfileNameFeats) + { + loadFeatsFromFile(sfileNameFeats, _vec_feats); + } + + PointFeatures GetRegionsPositions() const + { + return PointFeatures(_vec_feats.begin(), _vec_feats.end()); + } + + Vec2 GetRegionPosition(std::size_t i) const + { + return Vec2f(_vec_feats[i].coords()).cast(); + } + + /// Return the number of defined regions + std::size_t RegionCount() const {return _vec_feats.size();} + + /// Mutable and non-mutable PointFeature getters. + inline std::vector & Features() { return _vec_feats; } + inline const std::vector & Features() const { return _vec_feats; } + //-- // IO - one file for region features, one file for region descriptors //-- @@ -63,9 +93,6 @@ class Regions virtual void SaveDesc(const std::string& sfileNameDescs) const = 0; - virtual void LoadFeatures( - const std::string& sfileNameFeats) = 0; - //-- //- Basic description of a descriptor [Type, Length] //-- @@ -76,13 +103,6 @@ class Regions virtual std::string Type_id() const = 0; virtual std::size_t DescriptorLength() const = 0; - //-- Assume that a region can always be represented at least by a 2D positions - virtual PointFeatures GetRegionsPositions() const = 0; - virtual Vec2 GetRegionPosition(std::size_t i) const = 0; - - /// Return the number of defined regions - virtual std::size_t RegionCount() const = 0; - /** * @brief Return a blind pointer to the container of the descriptors array. * @@ -119,55 +139,6 @@ class Regions inline Regions::~Regions() {} -template -class FeatRegions : public Regions -{ -public: - /// Region type - typedef FeatT FeatureT; - /// Container for multiple regions - typedef std::vector FeatsT; - - virtual ~FeatRegions() {} - -protected: - std::vector _vec_feats; // region features - -public: - void LoadFeatures(const std::string& sfileNameFeats) - { - loadFeatsFromFile(sfileNameFeats, _vec_feats); - } - - PointFeatures GetRegionsPositions() const - { - return PointFeatures(_vec_feats.begin(), _vec_feats.end()); - } - - Vec2 GetRegionPosition(std::size_t i) const - { - return Vec2f(_vec_feats[i].coords()).cast(); - } - - /// Return the number of defined regions - std::size_t RegionCount() const {return _vec_feats.size();} - - /// Mutable and non-mutable FeatureT getters. - inline std::vector & Features() { return _vec_feats; } - inline const std::vector & Features() const { return _vec_feats; } -}; - -inline const std::vector& getSIOPointFeatures(const Regions& regions) -{ - static const std::vector emptyFeats; - - const FeatRegions* sioFeatures = dynamic_cast*>(®ions); - if(sioFeatures == nullptr) - return emptyFeats; - return sioFeatures->Features(); -} - - enum class ERegionType: bool { Binary = 0, @@ -191,11 +162,11 @@ struct SquaredMetric }; -template -class FeatDescRegions : public FeatRegions +template +class FeatDescRegions : public Regions { public: - typedef FeatDescRegions This; + typedef FeatDescRegions This; /// Region descriptor typedef Descriptor DescriptorT; /// Container for multiple regions description @@ -318,11 +289,11 @@ class FeatDescRegions : public FeatRegions }; -template -using ScalarRegions = FeatDescRegions; +template +using ScalarRegions = FeatDescRegions; -template -using BinaryRegions = FeatDescRegions; +template +using BinaryRegions = FeatDescRegions; diff --git a/src/aliceVision/feature/akaze/ImageDescriber_AKAZE.cpp b/src/aliceVision/feature/akaze/ImageDescriber_AKAZE.cpp index 5dbcdf56cf..98a265978d 100644 --- a/src/aliceVision/feature/akaze/ImageDescriber_AKAZE.cpp +++ b/src/aliceVision/feature/akaze/ImageDescriber_AKAZE.cpp @@ -63,7 +63,7 @@ bool ImageDescriber_AKAZE::describe(const image::Image& image, point.angle = 0.0f; regionsCasted->Features()[i] = - SIOPointFeature(point.x, point.y, point.size, point.angle); + PointFeature(point.x, point.y, point.size, point.angle); ComputeMSURFDescriptor(cur_slice.Lx, cur_slice.Ly, point.octave, regionsCasted->Features()[i], @@ -102,12 +102,12 @@ bool ImageDescriber_AKAZE::describe(const image::Image& image, point.angle = 0.0f; regionsCasted->Features()[i] = - SIOPointFeature(point.x, point.y, point.size, point.angle); + PointFeature(point.x, point.y, point.size, point.angle); // compute LIOP descriptor (do not need rotation computation, since // LIOP descriptor is rotation invariant). // rescale for LIOP patch extraction - const SIOPointFeature fp = SIOPointFeature(point.x, point.y, point.size/2.0, point.angle); + const PointFeature fp = PointFeature(point.x, point.y, point.size/2.0, point.angle); float desc[144]; liop_extractor.extract(image, fp, desc); @@ -143,7 +143,7 @@ bool ImageDescriber_AKAZE::describe(const image::Image& image, else point.angle = 0.0f; - regionsCasted->Features()[i] = SIOPointFeature(point.x, point.y, point.size, point.angle); + regionsCasted->Features()[i] = PointFeature(point.x, point.y, point.size, point.angle); // compute MLDB descriptor Descriptor desc; diff --git a/src/aliceVision/feature/akaze/descriptorLIOP.cpp b/src/aliceVision/feature/akaze/descriptorLIOP.cpp index 4532f992a7..cd0857fb22 100644 --- a/src/aliceVision/feature/akaze/descriptorLIOP.cpp +++ b/src/aliceVision/feature/akaze/descriptorLIOP.cpp @@ -287,7 +287,7 @@ void DescriptorExtractor_LIOP::CreateLIOP_GOrder( void DescriptorExtractor_LIOP::extract( const image::Image& I, - const SIOPointFeature& feat, + const PointFeature& feat, float desc[144]) { memset(desc, 0, sizeof(float)*144); diff --git a/src/aliceVision/feature/akaze/descriptorLIOP.hpp b/src/aliceVision/feature/akaze/descriptorLIOP.hpp index bf34c32264..99e7ffd7fd 100644 --- a/src/aliceVision/feature/akaze/descriptorLIOP.hpp +++ b/src/aliceVision/feature/akaze/descriptorLIOP.hpp @@ -45,7 +45,7 @@ class DescriptorExtractor_LIOP void extract( const image::Image & I, - const SIOPointFeature & feat, + const PointFeature & feat, float desc[144]); void CreateLIOP_GOrder( diff --git a/src/aliceVision/feature/akaze/descriptorMLDB.hpp b/src/aliceVision/feature/akaze/descriptorMLDB.hpp index a58af6291d..86161d7417 100644 --- a/src/aliceVision/feature/akaze/descriptorMLDB.hpp +++ b/src/aliceVision/feature/akaze/descriptorMLDB.hpp @@ -145,7 +145,7 @@ namespace feature { const image::Image &Lx, const image::Image &Ly, const int id_octave , - const SIOPointFeature & ipt , + const PointFeature & ipt , Descriptor & desc ) { // // Note : in KAZE description we compute descriptor of previous slice and never the current one diff --git a/src/aliceVision/feature/akaze/descriptorMSURF.hpp b/src/aliceVision/feature/akaze/descriptorMSURF.hpp index 9db894f8ab..e2100d37e1 100644 --- a/src/aliceVision/feature/akaze/descriptorMSURF.hpp +++ b/src/aliceVision/feature/akaze/descriptorMSURF.hpp @@ -42,7 +42,7 @@ namespace feature { const ImageT & Lx , const ImageT & Ly , const int id_octave , - const SIOPointFeature & ipt , + const PointFeature & ipt , Descriptor< Real , 64 > & desc ) { @@ -144,7 +144,7 @@ namespace feature { const ImageT & Lx , const ImageT & Ly , const int id_octave , - const SIOPointFeature & ipt , + const PointFeature & ipt , Descriptor< unsigned char , 64 > & desc ) { Descriptor< float , 64 > descFloat; diff --git a/src/aliceVision/feature/cctag/ImageDescriber_CCTAG.cpp b/src/aliceVision/feature/cctag/ImageDescriber_CCTAG.cpp index ec91a869fa..155ad6b930 100644 --- a/src/aliceVision/feature/cctag/ImageDescriber_CCTAG.cpp +++ b/src/aliceVision/feature/cctag/ImageDescriber_CCTAG.cpp @@ -122,11 +122,13 @@ bool ImageDescriber_CCTAG::describe(const image::Image& image, #else //todo: #ifdef depreciated cctag::MemoryPool::instance().updateMemoryAuthorizedWithRAM(); cctag::View cctagView((const unsigned char *) image.data(), image.Width(), image.Height(), image.Depth()*image.Width()); - boost::ptr_list cctags; cctag::cctagDetection(cctags, _cudaPipe, 1 ,cctagView._grayView ,*_params._internalParams, durations ); #endif durations->print( std::cerr ); + // There is no notion of orientation in CCTag + const float orientation = 0.0f; + for (const auto & cctag : cctags) { if ( cctag.getStatus() > 0 ) @@ -141,7 +143,7 @@ bool ImageDescriber_CCTAG::describe(const image::Image& image, } desc[cctag.id()] = (unsigned char) 255; regionsCasted->Descriptors().push_back(desc); - regionsCasted->Features().push_back(SIOPointFeature(cctag.x(), cctag.y())); + regionsCasted->Features().push_back(PointFeature(cctag.x(), cctag.y(), cctag.scale(), orientation)); // TODO: scale factor } } diff --git a/src/aliceVision/feature/features_test.cpp b/src/aliceVision/feature/features_test.cpp index db2332511b..33e29d74f7 100644 --- a/src/aliceVision/feature/features_test.cpp +++ b/src/aliceVision/feature/features_test.cpp @@ -22,7 +22,7 @@ using namespace aliceVision; using namespace aliceVision::feature; // Define a feature and a container of features -typedef SIOPointFeature Feature_T; +typedef PointFeature Feature_T; typedef std::vector Feats_T; // Define a descriptor and a container of descriptors diff --git a/src/aliceVision/feature/openCV/ImageDescriber_AKAZE_OCV.cpp b/src/aliceVision/feature/openCV/ImageDescriber_AKAZE_OCV.cpp index 8f75fdbb90..7c0f59f918 100644 --- a/src/aliceVision/feature/openCV/ImageDescriber_AKAZE_OCV.cpp +++ b/src/aliceVision/feature/openCV/ImageDescriber_AKAZE_OCV.cpp @@ -48,7 +48,7 @@ bool ImageDescriber_AKAZE_OCV::describe(const image::Image& image for(const auto& i_keypoint : vec_keypoints) { - SIOPointFeature feat(i_keypoint.pt.x, i_keypoint.pt.y, i_keypoint.size, i_keypoint.angle); + PointFeature feat(i_keypoint.pt.x, i_keypoint.pt.y, i_keypoint.size, i_keypoint.angle); regionsCasted->Features().push_back(feat); memcpy(descriptor.getData(), diff --git a/src/aliceVision/feature/openCV/ImageDescriber_SIFT_OCV.cpp b/src/aliceVision/feature/openCV/ImageDescriber_SIFT_OCV.cpp index 84c723e4f5..beb7c74428 100644 --- a/src/aliceVision/feature/openCV/ImageDescriber_SIFT_OCV.cpp +++ b/src/aliceVision/feature/openCV/ImageDescriber_SIFT_OCV.cpp @@ -161,7 +161,7 @@ bool ImageDescriber_SIFT_openCV::describe(const image::Image& ima int cpt = 0; for(const auto& i_kp : v_keypoints) { - SIOPointFeature feat(i_kp.pt.x, i_kp.pt.y, i_kp.size, i_kp.angle); + PointFeature feat(i_kp.pt.x, i_kp.pt.y, i_kp.size, i_kp.angle); regionsCasted->Features().push_back(feat); Descriptor desc; diff --git a/src/aliceVision/feature/regionsFactory.hpp b/src/aliceVision/feature/regionsFactory.hpp index ed84c0ebe1..194078843c 100644 --- a/src/aliceVision/feature/regionsFactory.hpp +++ b/src/aliceVision/feature/regionsFactory.hpp @@ -14,18 +14,18 @@ namespace aliceVision { namespace feature { /// Define the classic SIFT Keypoint -typedef ScalarRegions SIFT_Regions; +using SIFT_Regions = ScalarRegions; /// Define the classic SIFT features using float representation -typedef ScalarRegions SIFT_Float_Regions; +using SIFT_Float_Regions = ScalarRegions; /// Define the classic CCTag Keypoint -typedef ScalarRegions CCTAG_Regions; +using CCTAG_Regions = ScalarRegions; /// Define the AKAZE Keypoint (with a float descriptor) -typedef ScalarRegions AKAZE_Float_Regions; +using AKAZE_Float_Regions = ScalarRegions; /// Define the AKAZE Keypoint (with a LIOP descriptor) -typedef ScalarRegions AKAZE_Liop_Regions; +using AKAZE_Liop_Regions = ScalarRegions; /// Define the AKAZE Keypoint (with a binary descriptor saved in an uchar array) -typedef BinaryRegions AKAZE_BinaryRegions; +using AKAZE_BinaryRegions = BinaryRegions<64>; } // namespace feature } // namespace aliceVision diff --git a/src/aliceVision/feature/selection.cpp b/src/aliceVision/feature/selection.cpp index b3e3830788..b6e7d4ed4c 100644 --- a/src/aliceVision/feature/selection.cpp +++ b/src/aliceVision/feature/selection.cpp @@ -23,12 +23,12 @@ const size_t gridSize = 3; */ void sortMatches_byFeaturesScale( const aliceVision::matching::IndMatches& inputMatches, - const aliceVision::feature::FeatRegions& regionsI, - const aliceVision::feature::FeatRegions& regionsJ, + const aliceVision::feature::Regions& regionsI, + const aliceVision::feature::Regions& regionsJ, aliceVision::matching::IndMatches& outputMatches) { - const std::vector& vecFeatureI = regionsI.Features(); - const std::vector& vecFeatureJ = regionsJ.Features(); + const std::vector& vecFeatureI = regionsI.Features(); + const std::vector& vecFeatureJ = regionsJ.Features(); //outputMatches will contain the sorted matches if inputMatches. outputMatches.reserve(inputMatches.size()); @@ -38,17 +38,17 @@ void sortMatches_byFeaturesScale( std::vector> vecFeatureScale; for (size_t i = 0; i < inputMatches.size(); i++) - { + { float scale1 = vecFeatureI[inputMatches[i]._i].scale(); float scale2 = vecFeatureJ[inputMatches[i]._j].scale(); vecFeatureScale.emplace_back((scale1 + scale2) / 2.0, i); - } + } std::sort(vecFeatureScale.begin(), vecFeatureScale.end(), matchCompare); //The sorted match vector is filled according to the result of the sorting above. for (size_t i = 0; i < vecFeatureScale.size(); i++) - { + { outputMatches.push_back(inputMatches[vecFeatureScale[i].second]); } } @@ -96,8 +96,8 @@ void thresholdMatches(aliceVision::matching::IndMatches& outputMatches, const st * @param[in] sfm_data The sfm data file * @param[out] outMatches The remaining matches */ -void matchesGridFiltering(const aliceVision::feature::FeatRegions& lRegions, - const aliceVision::feature::FeatRegions& rRegions, +void matchesGridFiltering(const aliceVision::feature::Regions& lRegions, + const aliceVision::feature::Regions& rRegions, const aliceVision::Pair& indexImagePair, const aliceVision::sfmData::SfMData sfm_data, aliceVision::matching::IndMatches& outMatches) @@ -121,8 +121,8 @@ void matchesGridFiltering(const aliceVision::feature::FeatRegions& regionsI, - const aliceVision::feature::FeatRegions& regionsJ, + const aliceVision::feature::Regions& regionsI, + const aliceVision::feature::Regions& regionsJ, aliceVision::matching::IndMatches& outputMatches); /** @@ -62,8 +62,8 @@ void thresholdMatches(aliceVision::matching::IndMatches& outputMatches, const st * @param[in] sfm_data The sfm data file * @param[out] outMatches The remaining matches */ -void matchesGridFiltering(const aliceVision::feature::FeatRegions& lRegions, - const aliceVision::feature::FeatRegions& rRegions, +void matchesGridFiltering(const aliceVision::feature::Regions& lRegions, + const aliceVision::feature::Regions& rRegions, const aliceVision::Pair& indexImagePair, const aliceVision::sfmData::SfMData sfm_data, aliceVision::matching::IndMatches& outMatches); diff --git a/src/aliceVision/feature/sift/SIFT.hpp b/src/aliceVision/feature/sift/SIFT.hpp index 13bfed8f0e..9c7875d991 100644 --- a/src/aliceVision/feature/sift/SIFT.hpp +++ b/src/aliceVision/feature/sift/SIFT.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +// #include // TO CHECK #include extern "C" { @@ -212,11 +212,11 @@ bool extractSIFT(const image::Image& image, // Process SIFT computation vl_sift_process_first_octave(filt, image.data()); - typedef ScalarRegions SIFT_Region_T; - regions.reset( new SIFT_Region_T ); + using SIFT_Region_T = ScalarRegions; + SIFT_Region_T * regionsCasted = new SIFT_Region_T(); + regions.reset(regionsCasted); // Build alias to cached data - SIFT_Region_T * regionsCasted = dynamic_cast(regions.get()); // reserve some memory for faster keypoint saving const std::size_t reserveSize = (params._gridSize && params._maxTotalKeypoints) ? params._maxTotalKeypoints : 2000; regionsCasted->Features().reserve(reserveSize); @@ -254,7 +254,7 @@ bool extractSIFT(const image::Image& image, for (int q=0 ; q < nangles ; ++q) { vl_sift_calc_keypoint_descriptor(filt, &vlFeatDescriptor[0], keys+i, angles[q]); - const SIOPointFeature fp(keys[i].x, keys[i].y, + const PointFeature fp(keys[i].x, keys[i].y, keys[i].sigma, static_cast(angles[q])); convertSIFT(&vlFeatDescriptor[0], descriptor, params._rootSift); @@ -283,7 +283,7 @@ bool extractSIFT(const image::Image& image, std::iota(indexSort.begin(), indexSort.end(), 0); std::sort(indexSort.begin(), indexSort.end(), [&](std::size_t a, std::size_t b){ return features[a].scale() > features[b].scale(); }); - std::vector sortedFeatures(features.size()); + std::vector sortedFeatures(features.size()); std::vector sortedDescriptors(features.size()); for(std::size_t i: indexSort) { @@ -339,7 +339,7 @@ bool extractSIFT(const image::Image& image, filtered_indexes.insert(filtered_indexes.end(), rejected_indexes.begin(), rejected_indexes.begin() + remainingElements); } - std::vector filtered_features(filtered_indexes.size()); + std::vector filtered_features(filtered_indexes.size()); std::vector filtered_descriptors(filtered_indexes.size()); for(IndexT i = 0; i < filtered_indexes.size(); ++i) { diff --git a/src/aliceVision/feature/svgVisualization.cpp b/src/aliceVision/feature/svgVisualization.cpp index 04bcf5385f..520c0c016e 100644 --- a/src/aliceVision/feature/svgVisualization.cpp +++ b/src/aliceVision/feature/svgVisualization.cpp @@ -62,10 +62,10 @@ float getStrokeEstimate(const std::pair & imgSize) void drawMatchesSideBySide(const std::string& imagePathLeft, const std::pair& imageSizeLeft, - const std::vector& keypointsLeft, + const std::vector& keypointsLeft, const std::string& imagePathRight, const std::pair& imageSizeRight, - const std::vector& keypointsRight, + const std::vector& keypointsRight, const matching::IndMatches& matches, const std::string &outputSVGPath) { @@ -115,10 +115,10 @@ void drawMatchesSideBySide(const std::string& imagePathLeft, void drawHomographyMatches(const std::string& imagePathLeft, const std::pair& imageSizeLeft, - const std::vector& siofeatures_I, + const std::vector& siofeatures_I, const std::string& imagePathRight, const std::pair& imageSizeRight, - const std::vector& siofeatures_J, + const std::vector& siofeatures_J, const std::vector>& homographiesAndMatches, const matching::IndMatches& putativeMatches, const std::string& outFilename) @@ -137,8 +137,8 @@ void drawHomographyMatches(const std::string& imagePathLeft, { const float radius{1.f}; const float strokeSize{2.f}; - const feature::SIOPointFeature &fI = siofeatures_I.at(match._i); - const feature::SIOPointFeature &fJ = siofeatures_J.at(match._j); + const feature::PointFeature &fI = siofeatures_I.at(match._i); + const feature::PointFeature &fJ = siofeatures_J.at(match._j); const svg::svgStyle style = svg::svgStyle().stroke("white", strokeSize); svgStream.drawCircle(fI.x(), fI.y(), radius, style); @@ -158,8 +158,8 @@ void drawHomographyMatches(const std::string& imagePathLeft, for (const auto &match : bestMatchesId) { - const feature::SIOPointFeature &fI = siofeatures_I.at(match._i); - const feature::SIOPointFeature &fJ = siofeatures_J.at(match._j); + const feature::PointFeature &fI = siofeatures_I.at(match._i); + const feature::PointFeature &fJ = siofeatures_J.at(match._j); const svg::svgStyle style = svg::svgStyle().stroke(color, strokeSize); @@ -232,7 +232,7 @@ void saveMatches2SVG(const std::string &imagePathLeft, void saveKeypoints2SVG(const std::string &inputImagePath, const std::pair & imageSize, - const std::vector &keypoints, + const std::vector &keypoints, const std::string &outputSVGPath, bool richKeypoint /*= true*/) { @@ -245,7 +245,7 @@ void saveKeypoints2SVG(const std::string &inputImagePath, const float radius = getRadiusEstimate(imageSize); const float strokeWidth = getStrokeEstimate(imageSize); - for(const feature::SIOPointFeature &kpt : keypoints) + for(const feature::PointFeature &kpt : keypoints) { svgStream.drawCircle(kpt.x(), kpt.y(), (richKeypoint) ? kpt.scale()*radius : radius, svg::svgStyle().stroke("yellow", strokeWidth)); if(richKeypoint) @@ -280,10 +280,10 @@ void saveKeypoints2SVG(const std::string &inputImagePath, */ void drawKeypointsSideBySide(const std::string&imagePathLeft, const std::pair& imageSizeLeft, - const std::vector& keypointsLeft, + const std::vector& keypointsLeft, const std::string &imagePathRight, const std::pair& imageSizeRight, - const std::vector& keypointsRight, + const std::vector& keypointsRight, const std::string &outputSVGPath, bool richKeypoint) { @@ -557,8 +557,8 @@ void saveEpipolarGeometry2SVG(const std::string &imagePath, void saveMatchesAsMotion(const std::string &imagePath, const std::pair & imageSize, - const std::vector &keypoints, - const std::vector &otherKeypoints, + const std::vector &keypoints, + const std::vector &otherKeypoints, const matching::IndMatches &matches, const std::string &outputSVGPath, bool left, @@ -595,8 +595,8 @@ void saveMatchesAsMotion(const std::string &imagePath, void saveMatchesAsMotion(const std::string &imagePath, const std::pair & imageSize, - const std::vector &keypoints, - const std::vector &otherKeypoints, + const std::vector &keypoints, + const std::vector &otherKeypoints, const std::vector>& homographiesAndMatches, const std::string &outputSVGPath, bool left, diff --git a/src/aliceVision/feature/svgVisualization.hpp b/src/aliceVision/feature/svgVisualization.hpp index 510d107a12..3e6581d415 100644 --- a/src/aliceVision/feature/svgVisualization.hpp +++ b/src/aliceVision/feature/svgVisualization.hpp @@ -54,10 +54,10 @@ std::string describerTypeColor(feature::EImageDescriberType descType); */ void drawMatchesSideBySide(const std::string& imagePathLeft, const std::pair& imageSizeLeft, - const std::vector& keypointsLeft, + const std::vector& keypointsLeft, const std::string& imagePathRight, const std::pair& imageSizeRight, - const std::vector& keypointsRight, + const std::vector& keypointsRight, const matching::IndMatches& matches, const std::string &outputSVGPath); @@ -81,10 +81,10 @@ void drawMatchesSideBySide(const std::string& imagePathLeft, */ void drawHomographyMatches(const std::string& imagePathLeft, const std::pair& imageSizeLeft, - const std::vector& siofeatures_I, + const std::vector& siofeatures_I, const std::string& imagePathRight, const std::pair& imageSizeRight, - const std::vector& siofeatures_J, + const std::vector& siofeatures_J, const std::vector>& homographiesAndMatches, const matching::IndMatches& putativeMatches, const std::string& outFilename); @@ -158,10 +158,10 @@ void saveMatches2SVG(const std::string &imagePathLeft, */ void drawKeypointsSideBySide(const std::string&imagePathLeft, const std::pair& imageSizeLeft, - const std::vector& keypointsLeft, + const std::vector& keypointsLeft, const std::string &imagePathRight, const std::pair& imageSizeRight, - const std::vector& keypointsRight, + const std::vector& keypointsRight, const std::string &outputSVGPath, bool richKeypoint = true); @@ -179,7 +179,7 @@ void drawKeypointsSideBySide(const std::string&imagePathLeft, */ void saveKeypoints2SVG(const std::string &inputImagePath, const std::pair & imageSize, - const std::vector &keypoints, + const std::vector &keypoints, const std::string &outputSVGPath, bool richKeypoint = true); /** @@ -259,8 +259,8 @@ void saveEpipolarGeometry2SVG(const std::string &imagePath, */ void saveMatchesAsMotion(const std::string &imagePath, const std::pair & imageSize, - const std::vector &keypoints, - const std::vector &otherKeypoints, + const std::vector &keypoints, + const std::vector &otherKeypoints, const matching::IndMatches &matches, const std::string &outputSVGPath, bool left, @@ -268,8 +268,8 @@ void saveMatchesAsMotion(const std::string &imagePath, void saveMatchesAsMotion(const std::string &imagePath, const std::pair & imageSize, - const std::vector &keypoints, - const std::vector &otherKeypoints, + const std::vector &keypoints, + const std::vector &otherKeypoints, const std::vector>& homographiesAndMatches, const std::string &outputSVGPath, bool left, diff --git a/src/aliceVision/matching/IndMatchDecorator.hpp b/src/aliceVision/matching/IndMatchDecorator.hpp index 2de82b92bf..76ca414dcf 100644 --- a/src/aliceVision/matching/IndMatchDecorator.hpp +++ b/src/aliceVision/matching/IndMatchDecorator.hpp @@ -58,20 +58,6 @@ class IndMatchDecorator }; public: - IndMatchDecorator(const std::vector & vec_matches, - const std::vector & leftFeat, - const std::vector & rightFeat) - :_vec_matches(vec_matches) - { - for (size_t i = 0; i < vec_matches.size(); ++i) { - const size_t I = vec_matches[i]._i; - const size_t J = vec_matches[i]._j; - _vecDecoredMatches.push_back( - IndMatchDecoratorStruct(leftFeat[I].x(),leftFeat[I].y(), - rightFeat[J].x(), rightFeat[J].y(), vec_matches[i])); - } - } - IndMatchDecorator(const std::vector & vec_matches, const std::vector & leftFeat, const std::vector & rightFeat) diff --git a/src/aliceVision/matching/kvld/algorithm.cpp b/src/aliceVision/matching/kvld/algorithm.cpp index fbd5ad65ce..9a5d95577d 100644 --- a/src/aliceVision/matching/kvld/algorithm.cpp +++ b/src/aliceVision/matching/kvld/algorithm.cpp @@ -38,7 +38,7 @@ float getRange( //=============================IO interface======================// -std::ofstream& writeDetector( std::ofstream& out, const aliceVision::feature::SIOPointFeature& feature ) +std::ofstream& writeDetector( std::ofstream& out, const aliceVision::feature::PointFeature& feature ) { out << feature.x() << " " << feature.y() << " " @@ -47,7 +47,7 @@ std::ofstream& writeDetector( std::ofstream& out, const aliceVision::feature::SI return out; } -std::ifstream& readDetector( std::ifstream& in, aliceVision::feature::SIOPointFeature& point ) +std::ifstream& readDetector( std::ifstream& in, aliceVision::feature::PointFeature& point ) { in >> point.x() >> point.y() diff --git a/src/aliceVision/matching/kvld/algorithm.h b/src/aliceVision/matching/kvld/algorithm.h index ba010ced68..b583f71002 100644 --- a/src/aliceVision/matching/kvld/algorithm.h +++ b/src/aliceVision/matching/kvld/algorithm.h @@ -86,8 +86,8 @@ private : //=============================IO interface ======================// -std::ofstream& writeDetector( std::ofstream& out, const aliceVision::feature::SIOPointFeature& vect ); -std::ifstream& readDetector( std::ifstream& in, aliceVision::feature::SIOPointFeature& point ); +std::ofstream& writeDetector( std::ofstream& out, const aliceVision::feature::PointFeature& vect ); +std::ifstream& readDetector( std::ifstream& in, aliceVision::feature::PointFeature& point ); //======================================elemetuary operations================================// template < typename T > inline T point_distance( const T x1, const T y1, const T x2, const T y2 ) diff --git a/src/aliceVision/matching/kvld/kvld.cpp b/src/aliceVision/matching/kvld/kvld.cpp index 1e9c65446a..7c3a289770 100644 --- a/src/aliceVision/matching/kvld/kvld.cpp +++ b/src/aliceVision/matching/kvld/kvld.cpp @@ -200,8 +200,8 @@ VLD::VLD( const ImageScale& series, T const& P1, T const& P2 ) : contrast( 0.0 ) float KVLD( const Image< float >& I1, const Image< float >& I2, - const std::vector & F1, - const std::vector & F2, + const std::vector & F1, + const std::vector & F2, const vector< Pair >& matches, vector< Pair >& matchesFiltered, vector< double >& score, diff --git a/src/aliceVision/matching/kvld/kvld.h b/src/aliceVision/matching/kvld/kvld.h index cb09328a04..ccd80d9375 100644 --- a/src/aliceVision/matching/kvld/kvld.h +++ b/src/aliceVision/matching/kvld/kvld.h @@ -165,8 +165,8 @@ class VLD float KVLD(const aliceVision::image::Image< float >& I1, const aliceVision::image::Image< float >& I2, - const std::vector & F1, - const std::vector & F2, + const std::vector & F1, + const std::vector & F2, const std::vector< aliceVision::Pair >& matches, std::vector< aliceVision::Pair >& matchesFiltered, std::vector< double >& score, diff --git a/src/aliceVision/matching/kvld/kvld_draw.h b/src/aliceVision/matching/kvld/kvld_draw.h index 3a585c78c3..09cfbf5a7c 100644 --- a/src/aliceVision/matching/kvld/kvld_draw.h +++ b/src/aliceVision/matching/kvld/kvld_draw.h @@ -17,8 +17,8 @@ namespace aliceVision { void getKVLDMask( image::Image< unsigned char > *maskL, image::Image< unsigned char > *maskR, - const std::vector< feature::SIOPointFeature > &vec_F1, - const std::vector< feature::SIOPointFeature > &vec_F2, + const std::vector< feature::PointFeature > &vec_F1, + const std::vector< feature::PointFeature > &vec_F2, const std::vector< Pair >& vec_matches, const std::vector< bool >& vec_valide, const aliceVision::Mat& mat_E) @@ -29,15 +29,15 @@ void getKVLDMask( { if( vec_valide[ it1 ] && vec_valide[ it2 ] && mat_E( it1, it2 ) >= 0 ) { - const feature::SIOPointFeature & l1 = vec_F1[ vec_matches[ it1 ].first ]; - const feature::SIOPointFeature & l2 = vec_F1[ vec_matches[ it2 ].first ]; + const feature::PointFeature & l1 = vec_F1[ vec_matches[ it1 ].first ]; + const feature::PointFeature & l2 = vec_F1[ vec_matches[ it2 ].first ]; float l = ( l1.coords() - l2.coords() ).norm(); int widthL = std::max( 1.f, l / ( dimension + 1.f ) ); image::DrawLineThickness(l1.x(), l1.y(), l2.x(), l2.y(), 255, widthL, maskL); - const feature::SIOPointFeature & r1 = vec_F2[ vec_matches[ it1 ].second ]; - const feature::SIOPointFeature & r2 = vec_F2[ vec_matches[ it2 ].second ]; + const feature::PointFeature & r1 = vec_F2[ vec_matches[ it1 ].second ]; + const feature::PointFeature & r2 = vec_F2[ vec_matches[ it2 ].second ]; float r = ( r1.coords() - r2.coords() ).norm(); int widthR = std::max( 1.f, r / ( dimension + 1.f ) ); diff --git a/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_HGrowing.cpp b/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_HGrowing.cpp index 0f747f55be..e6fb8b2c39 100644 --- a/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_HGrowing.cpp +++ b/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_HGrowing.cpp @@ -61,8 +61,8 @@ std::size_t GeometricFilterMatrix_HGrowing::getNbAllVerifiedMatches() const -bool growHomography(const std::vector &featuresI, - const std::vector &featuresJ, +bool growHomography(const std::vector &featuresI, + const std::vector &featuresJ, const matching::IndMatches &matches, const IndexT &seedMatchId, std::set &planarMatchesIndices, Mat3 &transformation, @@ -74,8 +74,8 @@ bool growHomography(const std::vector &featuresI, transformation = Mat3::Identity(); const matching::IndMatch & seedMatch = matches.at(seedMatchId); - const feature::SIOPointFeature & seedFeatureI = featuresI.at(seedMatch._i); - const feature::SIOPointFeature & seedFeatureJ = featuresJ.at(seedMatch._j); + const feature::PointFeature & seedFeatureI = featuresI.at(seedMatch._i); + const feature::PointFeature & seedFeatureJ = featuresJ.at(seedMatch._j); double currTolerance; @@ -111,8 +111,8 @@ bool growHomography(const std::vector &featuresI, -void filterMatchesByHGrowing(const std::vector& siofeatures_I, - const std::vector& siofeatures_J, +void filterMatchesByHGrowing(const std::vector& siofeatures_I, + const std::vector& siofeatures_J, const matching::IndMatches& putativeMatches, std::vector>& homographiesAndMatches, matching::IndMatches& outGeometricInliers, @@ -210,8 +210,8 @@ void filterMatchesByHGrowing(const std::vector& siofea void drawHomographyMatches(const sfmData::View &viewI, const sfmData::View &viewJ, - const std::vector &siofeatures_I, - const std::vector &siofeatures_J, + const std::vector &siofeatures_I, + const std::vector &siofeatures_J, const std::vector> &homographiesAndMatches, const matching::IndMatches &putativeMatches, const std::string &outFilename) @@ -234,4 +234,4 @@ void drawHomographyMatches(const sfmData::View &viewI, } } -} \ No newline at end of file +} diff --git a/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_HGrowing.hpp b/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_HGrowing.hpp index 0d1b01107b..86645035f2 100644 --- a/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_HGrowing.hpp +++ b/src/aliceVision/matchingImageCollection/GeometricFilterMatrix_HGrowing.hpp @@ -82,8 +82,8 @@ struct GrowParameters * @param[in] param The parameters of the algorihm. * @return true if the \c transformation is different than the identity matrix. */ -bool growHomography(const std::vector &featuresI, - const std::vector &featuresJ, +bool growHomography(const std::vector &featuresI, + const std::vector &featuresJ, const matching::IndMatches &matches, const IndexT &seedMatchId, std::set &planarMatchesIndices, @@ -118,8 +118,8 @@ struct HGrowingFilteringParam * @param[out] outGeometricInliers All the matches that supports one of the found homographies. * @param[in] param The parameters of the algorithm. */ -void filterMatchesByHGrowing(const std::vector& siofeatures_I, - const std::vector& siofeatures_J, +void filterMatchesByHGrowing(const std::vector& siofeatures_I, + const std::vector& siofeatures_J, const matching::IndMatches& putativeMatches, std::vector>& homographiesAndMatches, @@ -139,8 +139,8 @@ void filterMatchesByHGrowing(const std::vector& siofea */ void drawHomographyMatches(const sfmData::View &viewI, const sfmData::View &viewJ, - const std::vector &siofeatures_I, - const std::vector &siofeatures_J, + const std::vector &siofeatures_I, + const std::vector &siofeatures_J, const std::vector> &homographiesAndMatches, const matching::IndMatches &putativeMatches, const std::string &outFilename); @@ -223,13 +223,11 @@ struct GeometricFilterMatrix_HGrowing : public GeometricFilterMatrix const Regions & regions_I = regionsPerView.getRegions(viewId_I, descType); const Regions & regions_J = regionsPerView.getRegions(viewId_J, descType); - const std::vector& siofeatures_I = getSIOPointFeatures(regions_I); - const std::vector& siofeatures_J = getSIOPointFeatures(regions_J); std::vector> homographiesAndMatches; matching::IndMatches outGeometricInliers; - filterMatchesByHGrowing(siofeatures_I, - siofeatures_J, + filterMatchesByHGrowing(regions_I.Features(), + regions_J.Features(), putativeMatchesPerType.at(descType), homographiesAndMatches, outGeometricInliers, @@ -243,7 +241,6 @@ struct GeometricFilterMatrix_HGrowing : public GeometricFilterMatrix continue; } - if (boost::filesystem::exists(outputSvgDir)) { const std::size_t nbMatches = outGeometricInliers.size(); @@ -254,8 +251,8 @@ struct GeometricFilterMatrix_HGrowing : public GeometricFilterMatrix const std::string outFilename = (boost::filesystem::path(outputSvgDir) / boost::filesystem::path(name)).string(); drawHomographyMatches(viewI, viewJ, - siofeatures_I, - siofeatures_J, + regions_I.Features(), + regions_J.Features(), homographiesAndMatches, putativeMatchesPerType.at(descType), outFilename); diff --git a/src/aliceVision/matchingImageCollection/geometricFilterUtils.cpp b/src/aliceVision/matchingImageCollection/geometricFilterUtils.cpp index 388daf1408..7958dd05d7 100644 --- a/src/aliceVision/matchingImageCollection/geometricFilterUtils.cpp +++ b/src/aliceVision/matchingImageCollection/geometricFilterUtils.cpp @@ -56,8 +56,8 @@ void centerMatrix(const Eigen::Matrix2Xf & points2d, Mat3 & t) } -void centeringMatrices(const std::vector & featuresI, - const std::vector & featuresJ, +void centeringMatrices(const std::vector & featuresI, + const std::vector & featuresJ, const matching::IndMatches & matches, Mat3 & cI, Mat3 & cJ, @@ -94,8 +94,8 @@ void centeringMatrices(const std::vector & featuresI, centerMatrix(ptsJ, cJ); } -void computeSimilarity(const feature::SIOPointFeature & feat1, - const feature::SIOPointFeature & feat2, +void computeSimilarity(const feature::PointFeature & feat1, + const feature::PointFeature & feat2, Mat3 & S) { S = Mat3::Identity(); @@ -125,8 +125,8 @@ void computeSimilarity(const feature::SIOPointFeature & feat1, S = A2 * A1.inverse(); } -void estimateAffinity(const std::vector & featuresI, - const std::vector & featuresJ, +void estimateAffinity(const std::vector & featuresI, + const std::vector & featuresJ, const matching::IndMatches & matches, Mat3 & affineTransformation, const std::set & usefulMatchesId) @@ -155,8 +155,8 @@ void estimateAffinity(const std::vector & featuresI, int iMatch = 0; for (IndexT matchId : matchesId) { - const feature::SIOPointFeature & featI = featuresI.at(matches.at(matchId)._i); - const feature::SIOPointFeature & featJ = featuresJ.at(matches.at(matchId)._j); + const feature::PointFeature & featI = featuresI.at(matches.at(matchId)._i); + const feature::PointFeature & featJ = featuresJ.at(matches.at(matchId)._j); const Vec2 featICoords (featI.x(), featI.y()); M.block(iMatch,0,1,3) = featICoords.homogeneous().transpose(); @@ -175,8 +175,8 @@ void estimateAffinity(const std::vector & featuresI, affineTransformation(2,2) = 1.; } -void estimateHomography(const std::vector &featuresI, - const std::vector &featuresJ, +void estimateHomography(const std::vector &featuresI, + const std::vector &featuresJ, const matching::IndMatches &matches, Mat3 &H, const std::set &usefulMatchesId) @@ -208,8 +208,8 @@ void estimateHomography(const std::vector &featuresI, IndexT iMatch = 0; for(IndexT matchId : matchesId) { - const feature::SIOPointFeature & featI = featuresI.at(matches.at(matchId)._i); - const feature::SIOPointFeature & featJ = featuresJ.at(matches.at(matchId)._j); + const feature::PointFeature & featI = featuresI.at(matches.at(matchId)._i); + const feature::PointFeature & featJ = featuresJ.at(matches.at(matchId)._j); Vec2 fI(featI.x(), featI.y()); Vec2 fJ(featJ.x(), featJ.y()); Vec3 ptI = CI * fI.homogeneous(); @@ -234,8 +234,8 @@ void estimateHomography(const std::vector &featuresI, H /= H(2,2); } -void findTransformationInliers(const std::vector &featuresI, - const std::vector &featuresJ, +void findTransformationInliers(const std::vector &featuresI, + const std::vector &featuresJ, const matching::IndMatches &matches, const Mat3 &transformation, double tolerance, @@ -247,8 +247,8 @@ void findTransformationInliers(const std::vector &feat #pragma omp parallel for for (int iMatch = 0; iMatch < matches.size(); ++iMatch) { - const feature::SIOPointFeature & featI = featuresI.at(matches.at(iMatch)._i); - const feature::SIOPointFeature & featJ = featuresJ.at(matches.at(iMatch)._j); + const feature::PointFeature & featI = featuresI.at(matches.at(iMatch)._i); + const feature::PointFeature & featJ = featuresJ.at(matches.at(iMatch)._j); const Vec2 ptI(featI.x(), featI.y()); const Vec2 ptJ(featJ.x(), featJ.y()); @@ -354,8 +354,8 @@ class RefineHRobustCostFunctor double _softThresh; }; -bool refineHomography(const std::vector &featuresI, - const std::vector &featuresJ, +bool refineHomography(const std::vector &featuresI, + const std::vector &featuresJ, const matching::IndMatches& remainingMatches, Mat3& homography, std::set& bestMatchesId, @@ -424,4 +424,4 @@ bool refineHomography(const Mat2X& features_I, return true; } } -} \ No newline at end of file +} diff --git a/src/aliceVision/matchingImageCollection/geometricFilterUtils.hpp b/src/aliceVision/matchingImageCollection/geometricFilterUtils.hpp index 2c0f11007f..1c0a755dcb 100644 --- a/src/aliceVision/matchingImageCollection/geometricFilterUtils.hpp +++ b/src/aliceVision/matchingImageCollection/geometricFilterUtils.hpp @@ -191,8 +191,8 @@ void centerMatrix(const Eigen::Matrix2Xf & points2d, Mat3 & t); * @param[out] cJ The standardizing matrix to apply to (the subpart of) \c featuresJ * @param[in] usefulMatchesId To consider a subpart of \c matches only. */ -void centeringMatrices(const std::vector & featuresI, - const std::vector & featuresJ, +void centeringMatrices(const std::vector & featuresI, + const std::vector & featuresJ, const matching::IndMatches & matches, Mat3 & cI, Mat3 & cJ, @@ -204,8 +204,8 @@ void centeringMatrices(const std::vector & featuresI, * @param[in] feat2 The second feature with known scale & orientation. * @param[out] S The similarity transformation between f1 et f2 so that f2 = S * f1. */ -void computeSimilarity(const feature::SIOPointFeature & feat1, - const feature::SIOPointFeature & feat2, +void computeSimilarity(const feature::PointFeature & feat1, + const feature::PointFeature & feat2, Mat3 & S); /** @@ -217,8 +217,8 @@ void computeSimilarity(const feature::SIOPointFeature & feat1, * @param[out] affineTransformation The estimated Affine transformation. * @param[in] usefulMatchesId To consider a subpart of \c matches only. */ -void estimateAffinity(const std::vector & featuresI, - const std::vector & featuresJ, +void estimateAffinity(const std::vector & featuresI, + const std::vector & featuresJ, const matching::IndMatches & matches, Mat3 & affineTransformation, const std::set & usefulMatchesId = std::set()); @@ -232,8 +232,8 @@ void estimateAffinity(const std::vector & featuresI, * @param[out] H The estimated Homography transformation. * @param[in] usefulMatchesId To consider a subpart of \c matches only. */ -void estimateHomography(const std::vector & featuresI, - const std::vector & featuresJ, +void estimateHomography(const std::vector & featuresI, + const std::vector & featuresJ, const matching::IndMatches & matches, Mat3 &H, const std::set & usefulMatchesId = std::set()); @@ -247,8 +247,8 @@ void estimateHomography(const std::vector & featuresI, * @param[in] tolerance The tolerated pixel error. * @param[in] inliersId The index in the \c matches vector. */ -void findTransformationInliers(const std::vector & featuresI, - const std::vector & featuresJ, +void findTransformationInliers(const std::vector & featuresI, + const std::vector & featuresJ, const matching::IndMatches & matches, const Mat3 & transformation, double tolerance, @@ -270,8 +270,8 @@ void findTransformationInliers(const Mat2X& featuresI, std::set &inliersId); -bool refineHomography(const std::vector &featuresI, - const std::vector &featuresJ, +bool refineHomography(const std::vector &featuresI, + const std::vector &featuresJ, const matching::IndMatches& remainingMatches, Mat3& homography, std::set& bestMatchesId, diff --git a/src/aliceVision/matchingImageCollection/geometricFilterUtils_test.cpp b/src/aliceVision/matchingImageCollection/geometricFilterUtils_test.cpp index 810262cf22..d0d71f648c 100644 --- a/src/aliceVision/matchingImageCollection/geometricFilterUtils_test.cpp +++ b/src/aliceVision/matchingImageCollection/geometricFilterUtils_test.cpp @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(matchingImageCollection_centerMatrix) BOOST_AUTO_TEST_CASE(matchingImageCollection_similarityEstimation) { // same point should give the identity matrix - const feature::SIOPointFeature feat1 {1.0f, 5.0f, 1.0f, 0.1f}; + const feature::PointFeature feat1 {1.0f, 5.0f, 1.0f, 0.1f}; Mat3 S; matchingImageCollection::computeSimilarity(feat1, feat1, S); @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE(matchingImageCollection_similarityEstimation) // generate a random point with a random scale and orientation const Vec2f point = Vec2f::Random(); const Vec2f param = Vec2f::Random(); - const feature::SIOPointFeature feat2 {point(0), point(1), param(0), param(1)}; + const feature::PointFeature feat2 {point(0), point(1), param(0), param(1)}; // estimate the similarity matchingImageCollection::computeSimilarity(feat1, feat2, S); @@ -75,4 +75,4 @@ BOOST_AUTO_TEST_CASE(matchingImageCollection_similarityEstimation) // std::cout << result.isZero() << std::endl; // std::cout << point.cast() - ptIp_hom.hnormalized() << std::endl; } -} \ No newline at end of file +} diff --git a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp index 8df05ab80e..670ebebe0f 100644 --- a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp +++ b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp @@ -1657,12 +1657,14 @@ void ReconstructionEngine_sequentialSfM::updateScene(const IndexT viewIndex, con { const Vec3 X = resectionData.pt3D.col(i); const Vec2 x = resectionData.pt2D.col(i); + Landmark& landmark = _sfmData.structure[*iterTrackId]; + double scale = _featuresPerView->getFeatures(viewIndex, landmark.descType)[i].scale(); // TODO: check i index, TODO: replace x() with scale() const Vec2 residual = resectionData.optionalIntrinsic->residual(resectionData.pose, X, x); if (residual.norm() < resectionData.error_max && resectionData.pose.depth(X) > 0) { // Inlier, add the point to the reconstructed track - _sfmData.structure[*iterTrackId].observations[viewIndex] = Observation(x, resectionData.featuresId[i].second); + landmark.observations[viewIndex] = Observation(x, resectionData.featuresId[i].second, scale); } } } diff --git a/src/aliceVision/sfm/sfmFilters.cpp b/src/aliceVision/sfm/sfmFilters.cpp index 9af3d189d1..84185b671f 100644 --- a/src/aliceVision/sfm/sfmFilters.cpp +++ b/src/aliceVision/sfm/sfmFilters.cpp @@ -32,7 +32,14 @@ IndexT RemoveOutliers_PixelResidualError(sfmData::SfMData& sfmData, const sfmData::View * view = sfmData.views.at(itObs->first).get(); const geometry::Pose3 pose = sfmData.getPose(*view).getTransform(); const camera::IntrinsicBase * intrinsic = sfmData.intrinsics.at(view->getIntrinsicId()).get(); - const Vec2 residual = intrinsic->residual(pose, iterTracks->second.X, itObs->second.x); + + Vec2 residual = intrinsic->residual(pose, iterTracks->second.X, itObs->second.x); + if(itObs->second.scale > 0) // TODO-SCALE: add an option to use the scale optionally + { + // Apply the scale of the feature to get a residual value + // relative to the feature precision. + residual /= itObs->second.scale; + } if((pose.depth(iterTracks->second.X) < 0) || (residual.norm() > dThresholdPixel)) { diff --git a/src/aliceVision/sfm/utils/syntheticScene.hpp b/src/aliceVision/sfm/utils/syntheticScene.hpp index 2c83ea5a29..a51654fea0 100644 --- a/src/aliceVision/sfm/utils/syntheticScene.hpp +++ b/src/aliceVision/sfm/utils/syntheticScene.hpp @@ -56,6 +56,10 @@ void generateSyntheticFeatures(feature::FeaturesPerView& out_featuresPerView, out_featuresPerView.addFeatures(it.first, descType, pointFeatures); } } + // Use arbitrary values for feature scale and orientation + const float scale = 0.0f; + const float orientation = 0.0f; + // Fill with the observation values for(const auto& it: sfmData.getLandmarks()) { @@ -66,7 +70,7 @@ void generateSyntheticFeatures(feature::FeaturesPerView& out_featuresPerView, const IndexT viewId = obsIt.first; const sfmData::Observation& obs = obsIt.second; - out_featuresPerView.getFeaturesPerDesc(viewId)[descType][obs.id_feat] = feature::PointFeature(obs.x(0) + noise(generator), obs.x(1) + noise(generator)); + out_featuresPerView.getFeaturesPerDesc(viewId)[descType][obs.id_feat] = feature::PointFeature(obs.x(0) + noise(generator), obs.x(1) + noise(generator), scale, orientation); } } } diff --git a/src/aliceVision/sfmData/Landmark.hpp b/src/aliceVision/sfmData/Landmark.hpp index 10d62a7d93..569321c86b 100644 --- a/src/aliceVision/sfmData/Landmark.hpp +++ b/src/aliceVision/sfmData/Landmark.hpp @@ -22,13 +22,15 @@ namespace sfmData { struct Observation { Observation(): id_feat(UndefinedIndexT) {} - Observation(const Vec2 & p, IndexT idFeat) + Observation(const Vec2 & p, IndexT idFeat, double scale_ = 1.0) // TODO: remove default value to scale : x(p) , id_feat(idFeat) + , scale(scale_) {} Vec2 x; IndexT id_feat; + double scale = 1.0; bool operator==(const Observation& other) const { diff --git a/src/samples/kvldFilter/main_kvldFilter.cpp b/src/samples/kvldFilter/main_kvldFilter.cpp index c1c3f39365..92084dc1c6 100644 --- a/src/samples/kvldFilter/main_kvldFilter.cpp +++ b/src/samples/kvldFilter/main_kvldFilter.cpp @@ -134,11 +134,11 @@ int main(int argc, char **argv) //-- Draw features : for (size_t i=0; i < featsL.size(); ++i ) { - const SIOPointFeature point = regionsL->Features()[i]; + const PointFeature point = regionsL->Features()[i]; DrawCircle(point.x(), point.y(), point.scale(), 255, &concat); } for (size_t i=0; i < featsR.size(); ++i ) { - const SIOPointFeature point = regionsR->Features()[i]; + const PointFeature point = regionsR->Features()[i]; DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } string out_filename = "01_features.jpg"; @@ -161,8 +161,8 @@ int main(int argc, char **argv) svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for (size_t i = 0; i < vec_PutativeMatches.size(); ++i) { //Get back linked feature, draw a circle and link them by a line - const SIOPointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; - const SIOPointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; + const PointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; + const PointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); svgStream.drawCircle(L.x(), L.y(), L.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(R.x()+imageL.Width(), R.y(), R.scale(),svgStyle().stroke("yellow", 2.0)); diff --git a/src/samples/robustEssential/main_robustEssential.cpp b/src/samples/robustEssential/main_robustEssential.cpp index 39bdb14895..3fcb73a13e 100644 --- a/src/samples/robustEssential/main_robustEssential.cpp +++ b/src/samples/robustEssential/main_robustEssential.cpp @@ -84,11 +84,11 @@ int main() { //-- Draw features : for (size_t i=0; i < featsL.size(); ++i ) { - const SIOPointFeature point = regionsL->Features()[i]; + const PointFeature point = regionsL->Features()[i]; DrawCircle(point.x(), point.y(), point.scale(), 255, &concat); } for (size_t i=0; i < featsR.size(); ++i ) { - const SIOPointFeature point = regionsR->Features()[i]; + const PointFeature point = regionsR->Features()[i]; DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } string out_filename = "02_features.jpg"; @@ -120,8 +120,8 @@ int main() { svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for (size_t i = 0; i < vec_PutativeMatches.size(); ++i) { //Get back linked feature, draw a circle and link them by a line - const SIOPointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; - const SIOPointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; + const PointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; + const PointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); svgStream.drawCircle(L.x(), L.y(), L.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(R.x()+imageL.Width(), R.y(), R.scale(),svgStyle().stroke("yellow", 2.0)); @@ -174,8 +174,8 @@ int main() { svgStream.drawImage(jpg_filenameL, imageL.Width(), imageL.Height()); svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for (size_t i = 0; i < relativePose_info.vec_inliers.size(); ++i) { - const SIOPointFeature & LL = regionsL->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._i]; - const SIOPointFeature & RR = regionsR->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._j]; + const PointFeature & LL = regionsL->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._i]; + const PointFeature & RR = regionsR->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._j]; const Vec2f L = LL.coords(); const Vec2f R = RR.coords(); svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); @@ -203,8 +203,8 @@ int main() { std::vector vec_residuals; vec_residuals.reserve(relativePose_info.vec_inliers.size() * 4); for (size_t i = 0; i < relativePose_info.vec_inliers.size(); ++i) { - const SIOPointFeature & LL = regionsL->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._i]; - const SIOPointFeature & RR = regionsR->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._j]; + const PointFeature & LL = regionsL->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._i]; + const PointFeature & RR = regionsR->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._j]; // Point triangulation Vec3 X; TriangulateDLT(P1, LL.coords().cast(), P2, RR.coords().cast(), &X); diff --git a/src/samples/robustEssentialBA/main_robustEssentialBA.cpp b/src/samples/robustEssentialBA/main_robustEssentialBA.cpp index 18636ab7ae..a975718d27 100644 --- a/src/samples/robustEssentialBA/main_robustEssentialBA.cpp +++ b/src/samples/robustEssentialBA/main_robustEssentialBA.cpp @@ -93,11 +93,11 @@ int main() { //-- Draw features : for (size_t i=0; i < featsL.size(); ++i ) { - const SIOPointFeature point = regionsL->Features()[i]; + const PointFeature point = regionsL->Features()[i]; DrawCircle(point.x(), point.y(), point.scale(), 255, &concat); } for (size_t i=0; i < featsR.size(); ++i ) { - const SIOPointFeature point = regionsR->Features()[i]; + const PointFeature point = regionsR->Features()[i]; DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } string out_filename = "02_features.jpg"; @@ -129,8 +129,8 @@ int main() { svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for (size_t i = 0; i < vec_PutativeMatches.size(); ++i) { //Get back linked feature, draw a circle and link them by a line - const SIOPointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; - const SIOPointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; + const PointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; + const PointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); svgStream.drawCircle(L.x(), L.y(), L.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(R.x()+imageL.Width(), R.y(), R.scale(),svgStyle().stroke("yellow", 2.0)); @@ -183,8 +183,8 @@ int main() { svgStream.drawImage(jpg_filenameL, imageL.Width(), imageL.Height()); svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for (size_t i = 0; i < relativePose_info.vec_inliers.size(); ++i) { - const SIOPointFeature & LL = regionsL->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._i]; - const SIOPointFeature & RR = regionsR->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._j]; + const PointFeature & LL = regionsL->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._i]; + const PointFeature & RR = regionsR->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._j]; const Vec2f L = LL.coords(); const Vec2f R = RR.coords(); svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); @@ -247,8 +247,8 @@ int main() { const Mat34 P2 = tinyScene.intrinsics[tinyScene.views[1]->getIntrinsicId()]->get_projective_equivalent(pose1); sfmData::Landmarks & landmarks = tinyScene.structure; for (size_t i = 0; i < relativePose_info.vec_inliers.size(); ++i) { - const SIOPointFeature & LL = regionsL->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._i]; - const SIOPointFeature & RR = regionsR->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._j]; + const PointFeature & LL = regionsL->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._i]; + const PointFeature & RR = regionsR->Features()[vec_PutativeMatches[relativePose_info.vec_inliers[i]]._j]; // Point triangulation Vec3 X; TriangulateDLT(P1, LL.coords().cast(), P2, RR.coords().cast(), &X); diff --git a/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp b/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp index e992e9eef4..d685537bbc 100644 --- a/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp +++ b/src/samples/robustEssentialSpherical/main_robustEssentialSpherical.cpp @@ -85,11 +85,11 @@ int main() { //-- Draw features : for (size_t i=0; i < featsL.size(); ++i ) { - const SIOPointFeature point = regionsL->Features()[i]; + const PointFeature point = regionsL->Features()[i]; DrawCircle(point.x(), point.y(), point.scale(), 255, &concat); } for (size_t i=0; i < featsR.size(); ++i ) { - const SIOPointFeature point = regionsR->Features()[i]; + const PointFeature point = regionsR->Features()[i]; DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } string out_filename = "02_features.jpg"; @@ -115,8 +115,8 @@ int main() { svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for (size_t i = 0; i < vec_PutativeMatches.size(); ++i) { //Get back linked feature, draw a circle and link them by a line - const SIOPointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; - const SIOPointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; + const PointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; + const PointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); svgStream.drawCircle(L.x(), L.y(), L.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(R.x()+imageL.Width(), R.y(), R.scale(),svgStyle().stroke("yellow", 2.0)); diff --git a/src/samples/robustFundamental/main_robustFundamental.cpp b/src/samples/robustFundamental/main_robustFundamental.cpp index 970dd1ebe5..697919473e 100644 --- a/src/samples/robustFundamental/main_robustFundamental.cpp +++ b/src/samples/robustFundamental/main_robustFundamental.cpp @@ -116,11 +116,11 @@ int main(int argc, char **argv) //-- Draw features : for (size_t i=0; i < featsL.size(); ++i ) { - const SIOPointFeature point = regionsL->Features()[i]; + const PointFeature point = regionsL->Features()[i]; DrawCircle(point.x(), point.y(), point.scale(), 255, &concat); } for (size_t i=0; i < featsR.size(); ++i ) { - const SIOPointFeature point = regionsR->Features()[i]; + const PointFeature point = regionsR->Features()[i]; DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } string out_filename = "02_features.jpg"; @@ -144,8 +144,8 @@ int main(int argc, char **argv) for (size_t i = 0; i < vec_PutativeMatches.size(); ++i) { //Get back linked feature, draw a circle and link them by a line - const SIOPointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; - const SIOPointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; + const PointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; + const PointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); svgStream.drawCircle(L.x(), L.y(), L.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(R.x()+imageL.Width(), R.y(), R.scale(),svgStyle().stroke("yellow", 2.0)); @@ -206,8 +206,8 @@ int main(int argc, char **argv) svgStream.drawImage(jpgFilenameR, imageR.Width(), imageR.Height(), imageL.Width()); for ( size_t i = 0; i < vec_inliers.size(); ++i) { - const SIOPointFeature & LL = regionsL->Features()[vec_PutativeMatches[vec_inliers[i]]._i]; - const SIOPointFeature & RR = regionsR->Features()[vec_PutativeMatches[vec_inliers[i]]._j]; + const PointFeature & LL = regionsL->Features()[vec_PutativeMatches[vec_inliers[i]]._i]; + const PointFeature & RR = regionsR->Features()[vec_PutativeMatches[vec_inliers[i]]._j]; const Vec2f L = LL.coords(); const Vec2f R = RR.coords(); svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); diff --git a/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp b/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp index 5e2cd978bd..6959a0ae2d 100644 --- a/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp +++ b/src/samples/robustFundamentalGuided/main_robustFundamentalGuided.cpp @@ -74,11 +74,11 @@ int main() { //-- Draw features : for (size_t i=0; i < featsL.size(); ++i ) { - const SIOPointFeature point = regionsL->Features()[i]; + const PointFeature point = regionsL->Features()[i]; DrawCircle(point.x(), point.y(), point.scale(), 255, &concat); } for (size_t i=0; i < featsR.size(); ++i ) { - const SIOPointFeature point = regionsR->Features()[i]; + const PointFeature point = regionsR->Features()[i]; DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } string out_filename = "02_features.jpg"; @@ -101,8 +101,8 @@ int main() { svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for (size_t i = 0; i < vec_PutativeMatches.size(); ++i) { //Get back linked feature, draw a circle and link them by a line - const SIOPointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; - const SIOPointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; + const PointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; + const PointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); svgStream.drawCircle(L.x(), L.y(), L.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(R.x()+imageL.Width(), R.y(), R.scale(),svgStyle().stroke("yellow", 2.0)); @@ -160,8 +160,8 @@ int main() { svgStream.drawImage(jpg_filenameL, imageL.Width(), imageL.Height()); svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for ( size_t i = 0; i < vec_inliers.size(); ++i) { - const SIOPointFeature & LL = regionsL->Features()[vec_PutativeMatches[vec_inliers[i]]._i]; - const SIOPointFeature & RR = regionsR->Features()[vec_PutativeMatches[vec_inliers[i]]._j]; + const PointFeature & LL = regionsL->Features()[vec_PutativeMatches[vec_inliers[i]]._i]; + const PointFeature & RR = regionsR->Features()[vec_PutativeMatches[vec_inliers[i]]._j]; const Vec2f L = LL.coords(); const Vec2f R = RR.coords(); svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); @@ -230,8 +230,8 @@ int main() { svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for ( size_t i = 0; i < vec_corresponding_index.size(); ++i) { - const SIOPointFeature & LL = regionsL->Features()[vec_corresponding_index[i]._i]; - const SIOPointFeature & RR = regionsR->Features()[vec_corresponding_index[i]._j]; + const PointFeature & LL = regionsL->Features()[vec_corresponding_index[i]._i]; + const PointFeature & RR = regionsR->Features()[vec_corresponding_index[i]._j]; const Vec2f L = LL.coords(); const Vec2f R = RR.coords(); svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); diff --git a/src/samples/robustHomography/main_robustHomography.cpp b/src/samples/robustHomography/main_robustHomography.cpp index 0bc97f7a73..7712b3bb74 100644 --- a/src/samples/robustHomography/main_robustHomography.cpp +++ b/src/samples/robustHomography/main_robustHomography.cpp @@ -73,11 +73,11 @@ int main() { //-- Draw features : for (size_t i=0; i < featsL.size(); ++i ) { - const SIOPointFeature point = regionsL->Features()[i]; + const PointFeature point = regionsL->Features()[i]; DrawCircle(point.x(), point.y(), point.scale(), 255, &concat); } for (size_t i=0; i < featsR.size(); ++i ) { - const SIOPointFeature point = regionsR->Features()[i]; + const PointFeature point = regionsR->Features()[i]; DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } string out_filename = "02_features.jpg"; @@ -100,8 +100,8 @@ int main() { svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for (size_t i = 0; i < vec_PutativeMatches.size(); ++i) { //Get back linked feature, draw a circle and link them by a line - const SIOPointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; - const SIOPointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; + const PointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; + const PointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); svgStream.drawCircle(L.x(), L.y(), L.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(R.x()+imageL.Width(), R.y(), R.scale(),svgStyle().stroke("yellow", 2.0)); @@ -159,8 +159,8 @@ int main() { svgStream.drawImage(jpg_filenameL, imageL.Width(), imageL.Height()); svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for ( size_t i = 0; i < vec_inliers.size(); ++i) { - const SIOPointFeature & LL = regionsL->Features()[vec_PutativeMatches[vec_inliers[i]]._i]; - const SIOPointFeature & RR = regionsR->Features()[vec_PutativeMatches[vec_inliers[i]]._j]; + const PointFeature & LL = regionsL->Features()[vec_PutativeMatches[vec_inliers[i]]._i]; + const PointFeature & RR = regionsR->Features()[vec_PutativeMatches[vec_inliers[i]]._j]; const Vec2f L = LL.coords(); const Vec2f R = RR.coords(); svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); diff --git a/src/samples/robustHomographyGrowing/main_robustHomographyGrowing.cpp b/src/samples/robustHomographyGrowing/main_robustHomographyGrowing.cpp index 960de9131d..8906947f59 100644 --- a/src/samples/robustHomographyGrowing/main_robustHomographyGrowing.cpp +++ b/src/samples/robustHomographyGrowing/main_robustHomographyGrowing.cpp @@ -203,12 +203,6 @@ int main(int argc, char **argv) extract(imageDescriber, imageLeft, regions_perImage[0]); extract(imageDescriber, imageRight, regions_perImage[1]); - const std::vector& pointsLeft = regions_perImage.at(0)->GetRegionsPositions(); - const std::vector& pointsRight = regions_perImage.at(1)->GetRegionsPositions(); - // get the SIOPointFeature - const feature::FeatRegions* siofeatures_I = dynamic_cast*>(regions_perImage.at(0).get()); - const feature::FeatRegions* siofeatures_J = dynamic_cast*>(regions_perImage.at(1).get()); - //-- // Display images sides by side with extracted features @@ -218,10 +212,10 @@ int main(int argc, char **argv) const string out_filename = "01.features."+describerTypesName+".svg"; drawKeypointsSideBySide(filenameLeft, imageLeftSize, - feature::getSIOPointFeatures(*regions_perImage.at(0)), + regions_perImage.at(0).get()->Features(), filenameRight, imageRightSize, - feature::getSIOPointFeatures(*regions_perImage.at(1)), + fregions_perImage.at(1).get()->Features(), out_filename); } @@ -234,8 +228,8 @@ int main(int argc, char **argv) matching::DistanceRatioMatch(ratioThreshold, matching::BRUTE_FORCE_L2, - *regions_perImage[0].get(), - *regions_perImage[1].get(), + *regions_perImage[0], + *regions_perImage[1], vec_PutativeMatches); // two ways to show the matches @@ -243,10 +237,10 @@ int main(int argc, char **argv) // side by side drawMatchesSideBySide(filenameLeft, imageLeftSize, - feature::getSIOPointFeatures(*regions_perImage.at(0)), + regions_perImage.at(0).get()->Features(), filenameRight, imageRightSize, - feature::getSIOPointFeatures(*regions_perImage.at(1)), + regions_perImage.at(1).get()->Features(), vec_PutativeMatches, "02.putativeMatchesSideBySide." + describerTypesName + ".svg"); } @@ -257,8 +251,8 @@ int main(int argc, char **argv) const bool richKpts = false; saveMatchesAsMotion(filenameLeft, imageLeftSize, - feature::getSIOPointFeatures(*regions_perImage.at(0)), - feature::getSIOPointFeatures(*regions_perImage.at(1)), + regions_perImage.at(0).get()->Features(), + regions_perImage.at(1).get()->Features(), vec_PutativeMatches, "03.putativeMatchesMotion."+describerTypesName+".svg", isLeft, richKpts); @@ -282,8 +276,8 @@ int main(int argc, char **argv) // First sort the putative matches by increasing distance ratio value sortMatches_byDistanceRatio(vec_PutativeMatches); - matchingImageCollection::filterMatchesByHGrowing(siofeatures_I->Features(), - siofeatures_J->Features(), + matchingImageCollection::filterMatchesByHGrowing(regions_perImage.at(0).get()->Features(), + regions_perImage.at(1).get()->Features(), vec_PutativeMatches, homographiesAndMatches, outGeometricInliers, @@ -308,8 +302,8 @@ int main(int argc, char **argv) // first visualize all the filtered matched together, without distinction of which homography they belong to saveMatchesAsMotion(filenameLeft, imageLeftSize, - feature::getSIOPointFeatures(*regions_perImage.at(0)), - feature::getSIOPointFeatures(*regions_perImage.at(1)), + regions_perImage.at(0).get()->Features(), + regions_perImage.at(1).get()->Features(), outGeometricInliers, "04.allGrownMatchesMotion."+describerTypesName+".svg", isLeft, richKpts); @@ -317,8 +311,8 @@ int main(int argc, char **argv) // now visualize the matches grouped by homography with different colors saveMatchesAsMotion(filenameLeft, imageLeftSize, - feature::getSIOPointFeatures(*regions_perImage.at(0)), - feature::getSIOPointFeatures(*regions_perImage.at(1)), + regions_perImage.at(0).get()->Features(), + regions_perImage.at(1).get()->Features(), homographiesAndMatches, "05.allGrownMatchesByHomographyMotion."+describerTypesName+".svg", isLeft, richKpts); @@ -326,10 +320,10 @@ int main(int argc, char **argv) // finally we can visualize the pair of images size by size with the matches grouped by color drawHomographyMatches(filenameLeft, imageLeftSize, - feature::getSIOPointFeatures(*regions_perImage.at(0)), + regions_perImage.at(0).get()->Features(), filenameRight, imageRightSize, - feature::getSIOPointFeatures(*regions_perImage.at(1)), + regions_perImage.at(1).get()->Features(), homographiesAndMatches, vec_PutativeMatches, "06.allGrownMatchesByHomography."+describerTypesName+".svg"); diff --git a/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp b/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp index b6c3e91058..2919508df4 100644 --- a/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp +++ b/src/samples/robustHomographyGuided/main_robustHomographyGuided.cpp @@ -73,11 +73,11 @@ int main() { //-- Draw features : for (size_t i=0; i < featsL.size(); ++i ) { - const SIOPointFeature point = regionsL->Features()[i]; + const PointFeature point = regionsL->Features()[i]; DrawCircle(point.x(), point.y(), point.scale(), 255, &concat); } for (size_t i=0; i < featsR.size(); ++i ) { - const SIOPointFeature point = regionsR->Features()[i]; + const PointFeature point = regionsR->Features()[i]; DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } string out_filename = "02_features.jpg"; @@ -100,8 +100,8 @@ int main() { svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for (size_t i = 0; i < vec_PutativeMatches.size(); ++i) { //Get back linked feature, draw a circle and link them by a line - const SIOPointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; - const SIOPointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; + const PointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; + const PointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); svgStream.drawCircle(L.x(), L.y(), L.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(R.x()+imageL.Width(), R.y(), R.scale(),svgStyle().stroke("yellow", 2.0)); @@ -159,8 +159,8 @@ int main() { svgStream.drawImage(jpg_filenameL, imageL.Width(), imageL.Height()); svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for ( size_t i = 0; i < vec_inliers.size(); ++i) { - const SIOPointFeature & LL = regionsL->Features()[vec_PutativeMatches[vec_inliers[i]]._i]; - const SIOPointFeature & RR = regionsR->Features()[vec_PutativeMatches[vec_inliers[i]]._j]; + const PointFeature & LL = regionsL->Features()[vec_PutativeMatches[vec_inliers[i]]._i]; + const PointFeature & RR = regionsR->Features()[vec_PutativeMatches[vec_inliers[i]]._j]; const Vec2f L = LL.coords(); const Vec2f R = RR.coords(); svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); @@ -229,8 +229,8 @@ int main() { svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for ( size_t i = 0; i < vec_corresponding_index.size(); ++i) { - const SIOPointFeature & LL = regionsL->Features()[vec_corresponding_index[i]._i]; - const SIOPointFeature & RR = regionsR->Features()[vec_corresponding_index[i]._j]; + const PointFeature & LL = regionsL->Features()[vec_corresponding_index[i]._i]; + const PointFeature & RR = regionsR->Features()[vec_corresponding_index[i]._j]; const Vec2f L = LL.coords(); const Vec2f R = RR.coords(); svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); diff --git a/src/samples/siftPutativeMatches/main_siftMatching.cpp b/src/samples/siftPutativeMatches/main_siftMatching.cpp index 21e0153a11..c3005f4290 100644 --- a/src/samples/siftPutativeMatches/main_siftMatching.cpp +++ b/src/samples/siftPutativeMatches/main_siftMatching.cpp @@ -67,11 +67,11 @@ int main() { //-- Draw features : for (size_t i=0; i < featsL.size(); ++i ) { - const SIOPointFeature point = regionsL->Features()[i]; + const PointFeature point = regionsL->Features()[i]; DrawCircle(point.x(), point.y(), point.scale(), 255, &concat); } for (size_t i=0; i < featsR.size(); ++i ) { - const SIOPointFeature point = regionsR->Features()[i]; + const PointFeature point = regionsR->Features()[i]; DrawCircle(point.x()+imageL.Width(), point.y(), point.scale(), 255, &concat); } const std::string out_filename = "01_features.jpg"; @@ -94,8 +94,8 @@ int main() { svgStream.drawImage(jpg_filenameR, imageR.Width(), imageR.Height(), imageL.Width()); for (size_t i = 0; i < vec_PutativeMatches.size(); ++i) { //Get back linked feature, draw a circle and link them by a line - const SIOPointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; - const SIOPointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; + const PointFeature L = regionsL->Features()[vec_PutativeMatches[i]._i]; + const PointFeature R = regionsR->Features()[vec_PutativeMatches[i]._j]; svgStream.drawLine(L.x(), L.y(), R.x()+imageL.Width(), R.y(), svgStyle().stroke("green", 2.0)); svgStream.drawCircle(L.x(), L.y(), L.scale(), svgStyle().stroke("yellow", 2.0)); svgStream.drawCircle(R.x()+imageL.Width(), R.y(), R.scale(),svgStyle().stroke("yellow", 2.0)); diff --git a/src/software/pipeline/main_featureMatching.cpp b/src/software/pipeline/main_featureMatching.cpp index e52debe5e6..a1831a84a4 100644 --- a/src/software/pipeline/main_featureMatching.cpp +++ b/src/software/pipeline/main_featureMatching.cpp @@ -539,8 +539,8 @@ int main(int argc, char **argv) assert(descType != feature::EImageDescriberType::UNINITIALIZED); const aliceVision::matching::IndMatches& inputMatches = match.second; - const feature::FeatRegions* rRegions = dynamic_cast*>(®ionPerView.getRegions(indexImagePair.second, descType)); - const feature::FeatRegions* lRegions = dynamic_cast*>(®ionPerView.getRegions(indexImagePair.first, descType)); + const feature::Regions* rRegions = ®ionPerView.getRegions(indexImagePair.second, descType); + const feature::Regions* lRegions = ®ionPerView.getRegions(indexImagePair.first, descType); // get the regions for the current view pair: if(rRegions && lRegions) diff --git a/src/software/utils/CMakeLists.txt b/src/software/utils/CMakeLists.txt index 8e7d4e33c7..dde1546276 100644 --- a/src/software/utils/CMakeLists.txt +++ b/src/software/utils/CMakeLists.txt @@ -199,14 +199,14 @@ alicevision_add_software(aliceVision_utils_split360Images # Project 180° fisheye images into equirectangular -alicevision_add_software(aliceVision_utils_fisheyeProjection - SOURCE main_fisheyeProjection.cpp - FOLDER ${FOLDER_SOFTWARE_UTILS} - LINKS aliceVision_system - aliceVision_numeric - aliceVision_image - ${OPENIMAGEIO_LIBRARIES} - ${Boost_LIBRARIES} -) +#alicevision_add_software(aliceVision_utils_fisheyeProjection +# SOURCE main_fisheyeProjection.cpp +# FOLDER ${FOLDER_SOFTWARE_UTILS} +# LINKS aliceVision_system +# aliceVision_numeric +# aliceVision_image +# ${OPENIMAGEIO_LIBRARIES} +# ${Boost_LIBRARIES} +#) endif() # ALICEVISION_BUILD_SFM diff --git a/src/software/utils/sfmColorHarmonize/colorHarmonizeEngineGlobal.cpp b/src/software/utils/sfmColorHarmonize/colorHarmonizeEngineGlobal.cpp index 17574dbad8..292a94e9ef 100644 --- a/src/software/utils/sfmColorHarmonize/colorHarmonizeEngineGlobal.cpp +++ b/src/software/utils/sfmColorHarmonize/colorHarmonizeEngineGlobal.cpp @@ -50,7 +50,7 @@ using namespace aliceVision::lInfinity; using namespace aliceVision::sfm; using namespace aliceVision::sfmData; -typedef feature::SIOPointFeature FeatureT; +typedef feature::PointFeature FeatureT; typedef vector featsT; ColorHarmonizationEngineGlobal::ColorHarmonizationEngineGlobal( @@ -254,8 +254,8 @@ bool ColorHarmonizationEngineGlobal::Process() p_imaNames.first, p_imaNames.second, matches, - feature::getSIOPointFeatures(_regionsPerView.getRegions(viewI, descType)), - feature::getSIOPointFeatures(_regionsPerView.getRegions(viewJ, descType))); + _regionsPerView.getRegions(viewI, descType).Features(), + _regionsPerView.getRegions(viewJ, descType).Features()); dataSelector.computeMask( maskI, maskJ ); } From 97afb1f50508a3f4576b6085a5e827b2ddafe1f8 Mon Sep 17 00:00:00 2001 From: Theo Date: Thu, 30 Jan 2020 16:03:04 +0100 Subject: [PATCH 2/5] [feature] Add scale as parameter in functions for sfm --- src/aliceVision/localization/optimization.cpp | 5 +- .../resection/resectionLORansac_test.cpp | 3 +- src/aliceVision/sfm/BundleAdjustmentCeres.cpp | 32 ++++---- src/aliceVision/sfm/ResidualErrorFunctor.hpp | 73 ++++++++++--------- src/aliceVision/sfm/bundleAdjustment_test.cpp | 3 +- .../global/ReconstructionEngine_globalSfM.cpp | 13 ++-- .../pipeline/localization/SfMLocalizer.cpp | 3 +- .../ReconstructionEngine_panorama.cpp | 5 +- .../ReconstructionEngine_sequentialSfM.cpp | 18 +++-- .../StructureEstimationFromKnownPoses.cpp | 6 +- src/aliceVision/sfm/utils/syntheticScene.cpp | 6 +- src/aliceVision/sfmData/Landmark.hpp | 2 +- src/aliceVision/sfmDataIO/alembicIO_test.cpp | 5 +- src/aliceVision/sfmDataIO/sfmDataIO_test.cpp | 3 +- .../main_robustEssentialBA.cpp | 6 +- .../main_robustHomographyGrowing.cpp | 2 +- src/software/export/main_exportMatlab.cpp | 3 +- src/software/pipeline/main_meshing.cpp | 3 +- 18 files changed, 106 insertions(+), 85 deletions(-) diff --git a/src/aliceVision/localization/optimization.cpp b/src/aliceVision/localization/optimization.cpp index 9af5f0cd59..d40c63129a 100644 --- a/src/aliceVision/localization/optimization.cpp +++ b/src/aliceVision/localization/optimization.cpp @@ -100,6 +100,7 @@ bool refineSequence(std::vector & vec_localizationResult, } } + const double unknownScale = 0.0; for(size_t viewID = 0; viewID < numViews; ++viewID) { LocalizationResult &currResult = vec_localizationResult[viewID]; @@ -165,7 +166,7 @@ bool refineSequence(std::vector & vec_localizationResult, } // the 3D point exists already, add the observation - landmark.observations[viewID] = sfmData::Observation(feature, match.featId); + landmark.observations[viewID] = sfmData::Observation(feature, match.featId, unknownScale); } else { @@ -173,7 +174,7 @@ bool refineSequence(std::vector & vec_localizationResult, sfmData::Landmark newLandmark; newLandmark.descType = match.descType; newLandmark.X = currResult.getPt3D().col(idx); - newLandmark.observations[viewID] = sfmData::Observation(feature, match.featId); + newLandmark.observations[viewID] = sfmData::Observation(feature, match.featId, unknownScale); tinyScene.structure[match.landmarkId] = std::move(newLandmark); } } diff --git a/src/aliceVision/multiview/resection/resectionLORansac_test.cpp b/src/aliceVision/multiview/resection/resectionLORansac_test.cpp index 7d5de0b1fd..f8aa21cb6a 100644 --- a/src/aliceVision/multiview/resection/resectionLORansac_test.cpp +++ b/src/aliceVision/multiview/resection/resectionLORansac_test.cpp @@ -63,12 +63,13 @@ bool refinePoseAsItShouldbe(const Mat & pt3D, { }); // structure data (2D-3D correspondences) + const double unknownScale = 0.0; for(size_t i = 0; i < vec_inliers.size(); ++i) { const size_t idx = vec_inliers[i]; Landmark landmark; landmark.X = pt3D.col(idx); - landmark.observations[0] = Observation(pt2D.col(idx), UndefinedIndexT); + landmark.observations[0] = Observation(pt2D.col(idx), UndefinedIndexT, unknownScale); sfm_data.structure[i] = std::move(landmark); } diff --git a/src/aliceVision/sfm/BundleAdjustmentCeres.cpp b/src/aliceVision/sfm/BundleAdjustmentCeres.cpp index fbddfa745d..41747112a2 100644 --- a/src/aliceVision/sfm/BundleAdjustmentCeres.cpp +++ b/src/aliceVision/sfm/BundleAdjustmentCeres.cpp @@ -35,22 +35,22 @@ using namespace aliceVision::geometry; * @param[in] observation The corresponding observation * @return cost functor */ -ceres::CostFunction* createCostFunctionFromIntrinsics(const IntrinsicBase* intrinsicPtr, const Vec2& observation) +ceres::CostFunction* createCostFunctionFromIntrinsics(const IntrinsicBase* intrinsicPtr, const sfmData::Observation& observation) { switch(intrinsicPtr->getType()) { case PINHOLE_CAMERA: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_Pinhole(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_Pinhole(observation)); case PINHOLE_CAMERA_RADIAL1: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeRadialK1(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeRadialK1(observation)); case PINHOLE_CAMERA_RADIAL3: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeRadialK3(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeRadialK3(observation)); case PINHOLE_CAMERA_BROWN: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeBrownT2(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeBrownT2(observation)); case PINHOLE_CAMERA_FISHEYE: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeFisheye(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeFisheye(observation)); case PINHOLE_CAMERA_FISHEYE1: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeFisheye1(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeFisheye1(observation)); default: throw std::logic_error("Cannot create cost function, unrecognized intrinsic type in BA."); } @@ -62,22 +62,22 @@ ceres::CostFunction* createCostFunctionFromIntrinsics(const IntrinsicBase* intri * @param[in] observation The corresponding observation * @return cost functor */ -ceres::CostFunction* createRigCostFunctionFromIntrinsics(const IntrinsicBase* intrinsicPtr, const Vec2& observation) +ceres::CostFunction* createRigCostFunctionFromIntrinsics(const IntrinsicBase* intrinsicPtr, const sfmData::Observation& observation) { switch(intrinsicPtr->getType()) { case PINHOLE_CAMERA: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_Pinhole(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_Pinhole(observation)); case PINHOLE_CAMERA_RADIAL1: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeRadialK1(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeRadialK1(observation)); case PINHOLE_CAMERA_RADIAL3: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeRadialK3(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeRadialK3(observation)); case PINHOLE_CAMERA_BROWN: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeBrownT2(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeBrownT2(observation)); case PINHOLE_CAMERA_FISHEYE: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeFisheye(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeFisheye(observation)); case PINHOLE_CAMERA_FISHEYE1: - return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeFisheye1(observation.data())); + return new ceres::AutoDiffCostFunction(new ResidualErrorFunctor_PinholeFisheye1(observation)); default: throw std::logic_error("Cannot create rig cost function, unrecognized intrinsic type in BA."); } @@ -573,7 +573,7 @@ void BundleAdjustmentCeres::addLandmarksToProblem(const sfmData::SfMData& sfmDat if(view.isPartOfRig() && !view.isPoseIndependant()) { - ceres::CostFunction* costFunction = createRigCostFunctionFromIntrinsics(sfmData.getIntrinsicPtr(view.getIntrinsicId()), observation.x); + ceres::CostFunction* costFunction = createRigCostFunctionFromIntrinsics(sfmData.getIntrinsicPtr(view.getIntrinsicId()), observation); problem.AddResidualBlock(costFunction, lossFunction, @@ -584,7 +584,7 @@ void BundleAdjustmentCeres::addLandmarksToProblem(const sfmData::SfMData& sfmDat } else { - ceres::CostFunction* costFunction = createCostFunctionFromIntrinsics(sfmData.getIntrinsicPtr(view.getIntrinsicId()), observation.x); + ceres::CostFunction* costFunction = createCostFunctionFromIntrinsics(sfmData.getIntrinsicPtr(view.getIntrinsicId()), observation); problem.AddResidualBlock(costFunction, lossFunction, diff --git a/src/aliceVision/sfm/ResidualErrorFunctor.hpp b/src/aliceVision/sfm/ResidualErrorFunctor.hpp index d5e392b1a1..46d3082443 100644 --- a/src/aliceVision/sfm/ResidualErrorFunctor.hpp +++ b/src/aliceVision/sfm/ResidualErrorFunctor.hpp @@ -8,6 +8,7 @@ #pragma once #include +#include #include @@ -29,10 +30,9 @@ namespace sfm { */ struct ResidualErrorFunctor_Pinhole { - ResidualErrorFunctor_Pinhole(const double* const pos_2dpoint) + explicit ResidualErrorFunctor_Pinhole(const sfmData::Observation& obs) + : _obs(obs) { - m_pos_2dpoint[0] = pos_2dpoint[0]; - m_pos_2dpoint[1] = pos_2dpoint[1]; } // Enum to map intrinsics parameters between aliceVision & ceres camera data parameter block. @@ -58,8 +58,9 @@ struct ResidualErrorFunctor_Pinhole // Compute and return the error is the difference between the predicted // and observed position - out_residuals[0] = projected_x - T(m_pos_2dpoint[0]); - out_residuals[1] = projected_y - T(m_pos_2dpoint[1]); + const T scale(_obs.scale > 0.0 ? _obs.scale : 1.0); + out_residuals[0] = (projected_x - T(_obs.x[0])) / scale; + out_residuals[1] = (projected_y - T(_obs.x[1])) / scale; } template @@ -162,7 +163,7 @@ struct ResidualErrorFunctor_Pinhole return true; } - double m_pos_2dpoint[2]; // The 2D observation + const sfmData::Observation& _obs; // The 2D observation }; /** @@ -178,10 +179,9 @@ struct ResidualErrorFunctor_Pinhole */ struct ResidualErrorFunctor_PinholeRadialK1 { - ResidualErrorFunctor_PinholeRadialK1(const double* const pos_2dpoint) + explicit ResidualErrorFunctor_PinholeRadialK1(const sfmData::Observation& obs) + : _obs(obs) { - m_pos_2dpoint[0] = pos_2dpoint[0]; - m_pos_2dpoint[1] = pos_2dpoint[1]; } // Enum to map intrinsics parameters between aliceVision & ceres camera data parameter block. @@ -216,8 +216,9 @@ struct ResidualErrorFunctor_PinholeRadialK1 // Compute and return the error is the difference between the predicted // and observed position - out_residuals[0] = projected_x - T(m_pos_2dpoint[0]); - out_residuals[1] = projected_y - T(m_pos_2dpoint[1]); + const T scale(_obs.scale > 0.0 ? _obs.scale : 1.0); + out_residuals[0] = (projected_x - T(_obs.x[0])) / scale; + out_residuals[1] = (projected_y - T(_obs.x[1])) / scale; } template @@ -316,7 +317,7 @@ struct ResidualErrorFunctor_PinholeRadialK1 return true; } - double m_pos_2dpoint[2]; // The 2D observation + const sfmData::Observation& _obs; // The 2D observation }; /** @@ -332,10 +333,9 @@ struct ResidualErrorFunctor_PinholeRadialK1 */ struct ResidualErrorFunctor_PinholeRadialK3 { - ResidualErrorFunctor_PinholeRadialK3(const double* const pos_2dpoint) + explicit ResidualErrorFunctor_PinholeRadialK3(const sfmData::Observation& obs) + : _obs(obs) { - m_pos_2dpoint[0] = pos_2dpoint[0]; - m_pos_2dpoint[1] = pos_2dpoint[1]; } // Enum to map intrinsics parameters between aliceVision & ceres camera data parameter block. @@ -375,8 +375,9 @@ struct ResidualErrorFunctor_PinholeRadialK3 // Compute and return the error is the difference between the predicted // and observed position - out_residuals[0] = projected_x - T(m_pos_2dpoint[0]); - out_residuals[1] = projected_y - T(m_pos_2dpoint[1]); + const T scale(_obs.scale > 0.0 ? _obs.scale : 1.0); + out_residuals[0] = (projected_x - T(_obs.x[0])) / scale; + out_residuals[1] = (projected_y - T(_obs.x[1])) / scale; } template @@ -469,7 +470,7 @@ struct ResidualErrorFunctor_PinholeRadialK3 return true; } - double m_pos_2dpoint[2]; // The 2D observation + const sfmData::Observation& _obs; // The 2D observation }; /** @@ -485,10 +486,9 @@ struct ResidualErrorFunctor_PinholeRadialK3 */ struct ResidualErrorFunctor_PinholeBrownT2 { - ResidualErrorFunctor_PinholeBrownT2(const double* const pos_2dpoint) + explicit ResidualErrorFunctor_PinholeBrownT2(const sfmData::Observation& obs) + : _obs(obs) { - m_pos_2dpoint[0] = pos_2dpoint[0]; - m_pos_2dpoint[1] = pos_2dpoint[1]; } // Enum to map intrinsics parameters between aliceVision & ceres camera data parameter block. @@ -534,8 +534,9 @@ struct ResidualErrorFunctor_PinholeBrownT2 // Compute and return the error is the difference between the predicted // and observed position - out_residuals[0] = projected_x - T(m_pos_2dpoint[0]); - out_residuals[1] = projected_y - T(m_pos_2dpoint[1]); + const T scale(_obs.scale > 0.0 ? _obs.scale : 1.0); + out_residuals[0] = (projected_x - T(_obs.x[0])) / scale; + out_residuals[1] = (projected_y - T(_obs.x[1])) / scale; } template @@ -635,7 +636,7 @@ struct ResidualErrorFunctor_PinholeBrownT2 return true; } - double m_pos_2dpoint[2]; // The 2D observation + const sfmData::Observation& _obs; // The 2D observation }; @@ -652,10 +653,9 @@ struct ResidualErrorFunctor_PinholeBrownT2 */ struct ResidualErrorFunctor_PinholeFisheye { - ResidualErrorFunctor_PinholeFisheye(const double* const pos_2dpoint) + explicit ResidualErrorFunctor_PinholeFisheye(const sfmData::Observation& obs) + : _obs(obs) { - m_pos_2dpoint[0] = pos_2dpoint[0]; - m_pos_2dpoint[1] = pos_2dpoint[1]; } // Enum to map intrinsics parameters between aliceVision & ceres camera data parameter block. @@ -702,8 +702,9 @@ struct ResidualErrorFunctor_PinholeFisheye // Compute and return the error is the difference between the predicted // and observed position - out_residuals[0] = projected_x - T(m_pos_2dpoint[0]); - out_residuals[1] = projected_y - T(m_pos_2dpoint[1]); + const T scale(_obs.scale > 0.0 ? _obs.scale : 1.0); + out_residuals[0] = (projected_x - T(_obs.x[0])) / scale; + out_residuals[1] = (projected_y - T(_obs.x[1])) / scale; } @@ -803,7 +804,7 @@ struct ResidualErrorFunctor_PinholeFisheye return true; } - double m_pos_2dpoint[2]; // The 2D observation + const sfmData::Observation& _obs; // The 2D observation }; /** @@ -819,10 +820,9 @@ struct ResidualErrorFunctor_PinholeFisheye */ struct ResidualErrorFunctor_PinholeFisheye1 { - ResidualErrorFunctor_PinholeFisheye1(const double* const pos_2dpoint) + explicit ResidualErrorFunctor_PinholeFisheye1(const sfmData::Observation& obs) + : _obs(obs) { - m_pos_2dpoint[0] = pos_2dpoint[0]; - m_pos_2dpoint[1] = pos_2dpoint[1]; } // Enum to map intrinsics parameters between aliceVision & ceres camera data parameter block. @@ -857,8 +857,9 @@ struct ResidualErrorFunctor_PinholeFisheye1 // Compute and return the error is the difference between the predicted // and observed position - out_residuals[0] = projected_x - T(m_pos_2dpoint[0]); - out_residuals[1] = projected_y - T(m_pos_2dpoint[1]); + const T scale(_obs.scale > 0.0 ? _obs.scale : 1.0); + out_residuals[0] = (projected_x - T(_obs.x[0])) / scale; + out_residuals[1] = (projected_y - T(_obs.x[1])) / scale; } template @@ -957,7 +958,7 @@ struct ResidualErrorFunctor_PinholeFisheye1 return true; } - double m_pos_2dpoint[2]; // The 2D observation + const sfmData::Observation& _obs; // The 2D observation }; diff --git a/src/aliceVision/sfm/bundleAdjustment_test.cpp b/src/aliceVision/sfm/bundleAdjustment_test.cpp index 24b25cb183..7a23bd89c3 100644 --- a/src/aliceVision/sfm/bundleAdjustment_test.cpp +++ b/src/aliceVision/sfm/bundleAdjustment_test.cpp @@ -305,6 +305,7 @@ SfMData getInputScene(const NViewDataSet & d, const NViewDatasetConfigurator & c } // 4. Landmarks + const double unknownScale = 0.0; for (int i = 0; i < npoints; ++i) { // Collect the image of point i in each frame. @@ -316,7 +317,7 @@ SfMData getInputScene(const NViewDataSet & d, const NViewDatasetConfigurator & c pt(0) += rand()/RAND_MAX - .5; pt(1) += rand()/RAND_MAX - .5; - landmark.observations[j] = Observation(pt, i); + landmark.observations[j] = Observation(pt, i, unknownScale); } sfm_data.structure[i] = landmark; } diff --git a/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp b/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp index 099698f053..38ae65a879 100644 --- a/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp +++ b/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp @@ -301,7 +301,7 @@ bool ReconstructionEngine_globalSfM::Compute_Initial_Structure(matching::Pairwis const size_t imaIndex = it->first; const size_t featIndex = it->second; const PointFeature & pt = _featuresPerView->getFeatures(imaIndex, track.descType)[featIndex]; - obs[imaIndex] = Observation(pt.coords().cast(), featIndex); + obs[imaIndex] = Observation(pt.coords().cast(), featIndex, pt.scale()); } } @@ -443,6 +443,7 @@ void ReconstructionEngine_globalSfM::Compute_Relative_Rotations(rotationAveragin poseWiseMatches[Pair(v1->getPoseId(), v2->getPoseId())].insert(pair); } + const double unknownScale = 0.0; boost::progress_display progressBar( poseWiseMatches.size(), std::cout, "\n- Relative pose computation -\n" ); #pragma omp parallel for schedule(dynamic) // Compute the relative pose from pairwise point matches: @@ -556,13 +557,15 @@ void ReconstructionEngine_globalSfM::Compute_Relative_Rotations(rotationAveragin const matching::IndMatches & matches = matchesPerDescIt.second; for (const matching::IndMatch& match: matches) { - const Vec2 x1_ = _featuresPerView->getFeatures(I, descType)[match._i].coords().cast(); - const Vec2 x2_ = _featuresPerView->getFeatures(J, descType)[match._j].coords().cast(); + const PointFeature& p1 = _featuresPerView->getFeatures(I, descType)[match._i]; + const PointFeature& p2 = _featuresPerView->getFeatures(J, descType)[match._j]; + const Vec2 x1_ = p1.coords().cast(); + const Vec2 x2_ = p2.coords().cast(); Vec3 X; TriangulateDLT(P1, x1_, P2, x2_, &X); Observations obs; - obs[view_I->getViewId()] = Observation(x1_, match._i); - obs[view_J->getViewId()] = Observation(x2_, match._j); + obs[view_I->getViewId()] = Observation(x1_, match._i, p1.scale()); + obs[view_J->getViewId()] = Observation(x2_, match._j, p2.scale()); Landmark& newLandmark = landmarks[landmarkId++]; newLandmark.descType = descType; newLandmark.observations = obs; diff --git a/src/aliceVision/sfm/pipeline/localization/SfMLocalizer.cpp b/src/aliceVision/sfm/pipeline/localization/SfMLocalizer.cpp index 0efe1e3673..1d77d26f84 100644 --- a/src/aliceVision/sfm/pipeline/localization/SfMLocalizer.cpp +++ b/src/aliceVision/sfm/pipeline/localization/SfMLocalizer.cpp @@ -197,13 +197,14 @@ bool SfMLocalizer::RefinePose(camera::IntrinsicBase* intrinsics, std::shared_ptr localIntrinsics(intrinsics->clone()); tinyScene.intrinsics[0] = localIntrinsics; + const double unknownScale = 0.0; // structure data (2D-3D correspondences) for(std::size_t i = 0; i < matchingData.vec_inliers.size(); ++i) { const std::size_t idx = matchingData.vec_inliers[i]; sfmData::Landmark landmark; landmark.X = matchingData.pt3D.col(idx); - landmark.observations[0] = sfmData::Observation(matchingData.pt2D.col(idx), UndefinedIndexT); + landmark.observations[0] = sfmData::Observation(matchingData.pt2D.col(idx), UndefinedIndexT, unknownScale); // TODO-SCALE tinyScene.structure[i] = std::move(landmark); } diff --git a/src/aliceVision/sfm/pipeline/panorama/ReconstructionEngine_panorama.cpp b/src/aliceVision/sfm/pipeline/panorama/ReconstructionEngine_panorama.cpp index 3a4d195ae9..1b92fd2db6 100644 --- a/src/aliceVision/sfm/pipeline/panorama/ReconstructionEngine_panorama.cpp +++ b/src/aliceVision/sfm/pipeline/panorama/ReconstructionEngine_panorama.cpp @@ -658,7 +658,10 @@ void ReconstructionEngine_panorama::Compute_Relative_Rotations(rotationAveraging Vec2 pt1 = _featuresPerView->getFeatures(I, descType)[match._i].coords().cast(); Vec2 pt2 = _featuresPerView->getFeatures(J, descType)[match._j].coords().cast(); - sfm::Constraint2D constraint(I, sfm::Observation(pt1, 0), J, sfm::Observation(pt2, 0)); + const PointFeature& pI = _featuresPerView->getFeatures(I, descType)[match._i]; + const PointFeature& pJ = _featuresPerView->getFeatures(J, descType)[match._j]; + + sfm::Constraint2D constraint(I, sfm::Observation(pt1, 0, pI.scale()), J, sfm::Observation(pt2, 0, pJ.scale())); constraints2d.push_back(constraint); index_inlier++; diff --git a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp index 670ebebe0f..e16333255b 100644 --- a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp +++ b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp @@ -25,7 +25,6 @@ #include #include #include -#include #include @@ -1760,7 +1759,7 @@ void ReconstructionEngine_sequentialSfM::triangulate_multiViewsLORANSAC(SfMData& std::transform(mapTracksToTriangulate.begin(), mapTracksToTriangulate.end(), std::inserter(setTracksId, setTracksId.begin()), stl::RetrieveKey()); - + #pragma omp parallel for for (int i = 0; i < setTracksId.size(); i++) // each track (already reconstructed or not) { @@ -1876,7 +1875,8 @@ void ReconstructionEngine_sequentialSfM::triangulate_multiViewsLORANSAC(SfMData& for (const IndexT & viewId : inliers) // add inliers as observations { const Vec2 x = _featuresPerView->getFeatures(viewId, track.descType)[track.featPerView.at(viewId)].coords().cast(); - landmark.observations[viewId] = Observation(x, track.featPerView.at(viewId)); + const feature::PointFeature& p = _featuresPerView->getFeatures(viewId, track.descType)[track.featPerView.at(viewId)]; + landmark.observations[viewId] = Observation(x, track.featPerView.at(viewId), p.scale()); } #pragma omp critical { @@ -1911,7 +1911,7 @@ void ReconstructionEngine_sequentialSfM::triangulate_2Views(SfMData& scene, cons std::set allReconstructedViews; allReconstructedViews.insert(previousReconstructedViews.begin(), previousReconstructedViews.end()); allReconstructedViews.insert(newReconstructedViews.begin(), newReconstructedViews.end()); - + #pragma omp parallel for schedule(dynamic) for (ptrdiff_t i = 0; i < static_cast(allReconstructedViews.size()); ++i) { @@ -1948,6 +1948,8 @@ void ReconstructionEngine_sequentialSfM::triangulate_2Views(SfMData& scene, cons const Vec2 xI = _featuresPerView->getFeatures(I, track.descType)[track.featPerView.at(I)].coords().cast(); const Vec2 xJ = _featuresPerView->getFeatures(J, track.descType)[track.featPerView.at(J)].coords().cast(); + const feature::PointFeature& featI = _featuresPerView->getFeatures(I, track.descType)[track.featPerView.at(I)]; + const feature::PointFeature& featJ = _featuresPerView->getFeatures(J, track.descType)[track.featPerView.at(J)]; // test if the track already exists in 3D bool trackIdExists; #pragma omp critical @@ -1968,7 +1970,7 @@ void ReconstructionEngine_sequentialSfM::triangulate_2Views(SfMData& scene, cons const double acThreshold = (acThresholdIt != _map_ACThreshold.end()) ? acThresholdIt->second : 4.0; if (poseI.depth(landmark.X) > 0 && residual.norm() < std::max(4.0, acThreshold)) { - landmark.observations[I] = Observation(xI, track.featPerView.at(I)); + landmark.observations[I] = Observation(xI, track.featPerView.at(I), featI.scale()); ++extented_track; } } @@ -1980,7 +1982,7 @@ void ReconstructionEngine_sequentialSfM::triangulate_2Views(SfMData& scene, cons const double acThreshold = (acThresholdIt != _map_ACThreshold.end()) ? acThresholdIt->second : 4.0; if (poseJ.depth(landmark.X) > 0 && residual.norm() < std::max(4.0, acThreshold)) { - landmark.observations[J] = Observation(xJ, track.featPerView.at(J)); + landmark.observations[J] = Observation(xJ, track.featPerView.at(J), featJ.scale()); ++extented_track; } } @@ -2031,8 +2033,8 @@ void ReconstructionEngine_sequentialSfM::triangulate_2Views(SfMData& scene, cons landmark.X = X_euclidean; landmark.descType = track.descType; - landmark.observations[I] = Observation(xI, track.featPerView.at(I)); - landmark.observations[J] = Observation(xJ, track.featPerView.at(J)); + landmark.observations[I] = Observation(xI, track.featPerView.at(I), featI.scale()); + landmark.observations[J] = Observation(xJ, track.featPerView.at(J), featJ.scale()); ++new_added_track; } // critical diff --git a/src/aliceVision/sfm/pipeline/structureFromKnownPoses/StructureEstimationFromKnownPoses.cpp b/src/aliceVision/sfm/pipeline/structureFromKnownPoses/StructureEstimationFromKnownPoses.cpp index 94a0993b8d..cbd75873af 100644 --- a/src/aliceVision/sfm/pipeline/structureFromKnownPoses/StructureEstimationFromKnownPoses.cpp +++ b/src/aliceVision/sfm/pipeline/structureFromKnownPoses/StructureEstimationFromKnownPoses.cpp @@ -272,8 +272,10 @@ void StructureEstimationFromKnownPoses::triangulate( { const size_t imaIndex = it->first; const size_t featIndex = it->second; - const Vec2 pt = regionsPerView.getRegions(imaIndex, track.descType).GetRegionPosition(featIndex); - observations[imaIndex] = Observation(pt, featIndex); + const feature::Regions& regions = regionsPerView.getRegions(imaIndex, track.descType); + const feature::PointFeature& feat = regions.Features()[featIndex]; + + observations[imaIndex] = Observation(feat.coords().cast(), featIndex, feat.scale()); } } diff --git a/src/aliceVision/sfm/utils/syntheticScene.cpp b/src/aliceVision/sfm/utils/syntheticScene.cpp index e156954588..20670713a1 100644 --- a/src/aliceVision/sfm/utils/syntheticScene.cpp +++ b/src/aliceVision/sfm/utils/syntheticScene.cpp @@ -96,6 +96,7 @@ sfmData::SfMData getInputScene(const NViewDataSet& d, } // 4. Landmarks + const double unknownScale = 0.0; for(int i = 0; i < npoints; ++i) { // Collect the image of point i in each frame. @@ -103,7 +104,7 @@ sfmData::SfMData getInputScene(const NViewDataSet& d, landmark.X = d._X.col(i); for (int j = 0; j < nviews; ++j) { const Vec2 pt = d._x[j].col(i); - landmark.observations[j] = sfmData::Observation(pt, i); + landmark.observations[j] = sfmData::Observation(pt, i, unknownScale); } sfmData.structure[i] = landmark; } @@ -178,6 +179,7 @@ sfmData::SfMData getInputRigScene(const NViewDataSet& d, } // 5. Landmarks + const double unknownScale = 0.0; for(int landmarkId = 0; landmarkId < nbPoints; ++landmarkId) { // Collect the image of point i in each frame. @@ -188,7 +190,7 @@ sfmData::SfMData getInputRigScene(const NViewDataSet& d, const sfmData::View& view = *sfmData.views.at(viewId); const geometry::Pose3 camPose = sfmData.getPose(view).getTransform(); const Vec2 pt = Project(sfmData.intrinsics.at(0)->get_projective_equivalent(camPose), landmark.X); - landmark.observations[viewId] = sfmData::Observation(pt, landmarkId); + landmark.observations[viewId] = sfmData::Observation(pt, landmarkId, unknownScale); } sfmData.structure[landmarkId] = landmark; } diff --git a/src/aliceVision/sfmData/Landmark.hpp b/src/aliceVision/sfmData/Landmark.hpp index 569321c86b..49ae37162a 100644 --- a/src/aliceVision/sfmData/Landmark.hpp +++ b/src/aliceVision/sfmData/Landmark.hpp @@ -22,7 +22,7 @@ namespace sfmData { struct Observation { Observation(): id_feat(UndefinedIndexT) {} - Observation(const Vec2 & p, IndexT idFeat, double scale_ = 1.0) // TODO: remove default value to scale + Observation(const Vec2 & p, IndexT idFeat, double scale_) : x(p) , id_feat(idFeat) , scale(scale_) diff --git a/src/aliceVision/sfmDataIO/alembicIO_test.cpp b/src/aliceVision/sfmDataIO/alembicIO_test.cpp index c1c6e0c1f2..61ebf75a44 100644 --- a/src/aliceVision/sfmDataIO/alembicIO_test.cpp +++ b/src/aliceVision/sfmDataIO/alembicIO_test.cpp @@ -117,13 +117,14 @@ SfMData createTestScene(IndexT singleViewsCount, nbIntrinsics += subPoseCount; } + const double unknownScale = 0.0; // Fill with not meaningful tracks for(IndexT i = 0; i < pointCount; ++i) { // Add structure Observations observations; - observations[0] = Observation( Vec2(std::rand() % 10000, std::rand() % 10000), 0); - observations[1] = Observation( Vec2(std::rand() % 10000, std::rand() % 10000), 1); + observations[0] = Observation( Vec2(std::rand() % 10000, std::rand() % 10000), 0, unknownScale); + observations[1] = Observation( Vec2(std::rand() % 10000, std::rand() % 10000), 1, unknownScale); sfm_data.structure[i].observations = observations; sfm_data.structure[i].X = Vec3(std::rand() % 10000, std::rand() % 10000, std::rand() % 10000); sfm_data.structure[i].rgb = image::RGBColor((std::rand() % 1000) / 1000.0, (std::rand() % 1000) / 1000.0, (std::rand() % 1000) / 1000.0); diff --git a/src/aliceVision/sfmDataIO/sfmDataIO_test.cpp b/src/aliceVision/sfmDataIO/sfmDataIO_test.cpp index 48e5503182..a8abadb57b 100644 --- a/src/aliceVision/sfmDataIO/sfmDataIO_test.cpp +++ b/src/aliceVision/sfmDataIO/sfmDataIO_test.cpp @@ -60,9 +60,10 @@ sfmData::SfMData createTestScene(std::size_t viewsCount = 2, std::size_t observa // Fill with not meaningful tracks sfmData::Observations observations; + const double unknownScale = 0.0; for(std::size_t i = 0; i < observationCount; ++i) { - observations[i] = sfmData::Observation( Vec2(i,i), i); + observations[i] = sfmData::Observation( Vec2(i,i), i, unknownScale); } sfmData.structure[0].observations = observations; diff --git a/src/samples/robustEssentialBA/main_robustEssentialBA.cpp b/src/samples/robustEssentialBA/main_robustEssentialBA.cpp index a975718d27..6a57599a05 100644 --- a/src/samples/robustEssentialBA/main_robustEssentialBA.cpp +++ b/src/samples/robustEssentialBA/main_robustEssentialBA.cpp @@ -255,9 +255,9 @@ int main() { // Reject point that is behind the camera if (pose0.depth(X) < 0 && pose1.depth(X) < 0) continue; - // Add a new landmark (3D point with it's 2d observations) - landmarks[i].observations[tinyScene.views[0]->getViewId()] = sfmData::Observation(LL.coords().cast(), vec_PutativeMatches[relativePose_info.vec_inliers[i]]._i); - landmarks[i].observations[tinyScene.views[1]->getViewId()] = sfmData::Observation(RR.coords().cast(), vec_PutativeMatches[relativePose_info.vec_inliers[i]]._j); + // Add a new landmark (3D point with its 2d observations) + landmarks[i].observations[tinyScene.views[0]->getViewId()] = sfmData::Observation(LL.coords().cast(), vec_PutativeMatches[relativePose_info.vec_inliers[i]]._i, LL.scale()); + landmarks[i].observations[tinyScene.views[1]->getViewId()] = sfmData::Observation(RR.coords().cast(), vec_PutativeMatches[relativePose_info.vec_inliers[i]]._j, RR.scale()); landmarks[i].X = X; } sfmDataIO::Save(tinyScene, "EssentialGeometry_start.ply", sfmDataIO::ESfMData::ALL); diff --git a/src/samples/robustHomographyGrowing/main_robustHomographyGrowing.cpp b/src/samples/robustHomographyGrowing/main_robustHomographyGrowing.cpp index 8906947f59..fca1eb807f 100644 --- a/src/samples/robustHomographyGrowing/main_robustHomographyGrowing.cpp +++ b/src/samples/robustHomographyGrowing/main_robustHomographyGrowing.cpp @@ -215,7 +215,7 @@ int main(int argc, char **argv) regions_perImage.at(0).get()->Features(), filenameRight, imageRightSize, - fregions_perImage.at(1).get()->Features(), + regions_perImage.at(1).get()->Features(), out_filename); } diff --git a/src/software/export/main_exportMatlab.cpp b/src/software/export/main_exportMatlab.cpp index e732963f8c..b03dfcbe6b 100644 --- a/src/software/export/main_exportMatlab.cpp +++ b/src/software/export/main_exportMatlab.cpp @@ -39,6 +39,7 @@ bool exportToMatlab( const std::string & outDirectory ) { + const double unknownScale = 0.0; // WARNING: Observation::id_feat is used to put the ID of the 3D landmark. std::map > observationsPerView; @@ -54,7 +55,7 @@ bool exportToMatlab( for(const auto& obs: landmark.observations) { const IndexT obsView = obs.first; // The ID of the view that provides this 2D observation. - observationsPerView[obsView].push_back(Observation(obs.second.x, landmarkId)); + observationsPerView[obsView].push_back(Observation(obs.second.x, landmarkId, unknownScale)); } } landmarksFile.close(); diff --git a/src/software/pipeline/main_meshing.cpp b/src/software/pipeline/main_meshing.cpp index b5c41165db..2db60fb731 100644 --- a/src/software/pipeline/main_meshing.cpp +++ b/src/software/pipeline/main_meshing.cpp @@ -94,6 +94,7 @@ void createDenseSfMData(const sfmData::SfMData& sfmData, outSfmData = sfmData; outSfmData.getLandmarks().clear(); + const double unknownScale = 0.0; for(std::size_t i = 0; i < vertices.size(); ++i) { const Point3d& point = vertices.at(i); @@ -106,7 +107,7 @@ void createDenseSfMData(const sfmData::SfMData& sfmData, { const sfmData::View& view = sfmData.getView(mp.getViewId(cam)); const camera::IntrinsicBase* intrinsicPtr = sfmData.getIntrinsicPtr(view.getIntrinsicId()); - const sfmData::Observation observation(intrinsicPtr->project(sfmData.getPose(view).getTransform(), pt3D, true), UndefinedIndexT); // apply distortion + const sfmData::Observation observation(intrinsicPtr->project(sfmData.getPose(view).getTransform(), pt3D, true), UndefinedIndexT, unknownScale); // apply distortion landmark.observations[view.getViewId()] = observation; } } From 15d6db5824f277d0b6bc168d6e29b74f95ebdf93 Mon Sep 17 00:00:00 2001 From: Theo Date: Wed, 5 Feb 2020 12:58:37 +0100 Subject: [PATCH 3/5] [feature] SfM: add scale as an option in SfM command line --- .../feature/cctag/ImageDescriber_CCTAG.cpp | 3 +- .../robustEstimation/estimators.hpp | 2 +- src/aliceVision/sfm/BundleAdjustment.hpp | 55 +++++++++++++++++++ src/aliceVision/sfm/BundleAdjustmentCeres.hpp | 3 + .../global/ReconstructionEngine_globalSfM.cpp | 4 +- .../global/ReconstructionEngine_globalSfM.hpp | 1 + .../ReconstructionEngine_sequentialSfM.cpp | 6 +- .../ReconstructionEngine_sequentialSfM.hpp | 3 +- src/aliceVision/sfm/sfmFilters.cpp | 5 +- src/aliceVision/sfm/sfmFilters.hpp | 2 + src/software/pipeline/main_imageMatching.cpp | 5 +- src/software/pipeline/main_incrementalSfM.cpp | 9 ++- 12 files changed, 85 insertions(+), 13 deletions(-) diff --git a/src/aliceVision/feature/cctag/ImageDescriber_CCTAG.cpp b/src/aliceVision/feature/cctag/ImageDescriber_CCTAG.cpp index 155ad6b930..aa91d84658 100644 --- a/src/aliceVision/feature/cctag/ImageDescriber_CCTAG.cpp +++ b/src/aliceVision/feature/cctag/ImageDescriber_CCTAG.cpp @@ -143,7 +143,8 @@ bool ImageDescriber_CCTAG::describe(const image::Image& image, } desc[cctag.id()] = (unsigned char) 255; regionsCasted->Descriptors().push_back(desc); - regionsCasted->Features().push_back(PointFeature(cctag.x(), cctag.y(), cctag.scale(), orientation)); // TODO: scale factor + const float scale = std::max(cctag.outerEllipse().a(), cctag.outerEllipse().b()); + regionsCasted->Features().push_back(PointFeature(cctag.x(), cctag.y(), scale, orientation)); } } diff --git a/src/aliceVision/robustEstimation/estimators.hpp b/src/aliceVision/robustEstimation/estimators.hpp index 07f3cbd038..aecb1846c7 100644 --- a/src/aliceVision/robustEstimation/estimators.hpp +++ b/src/aliceVision/robustEstimation/estimators.hpp @@ -66,7 +66,7 @@ inline std::ostream& operator<<(std::ostream& os, ERobustEstimator e) return os << ERobustEstimator_enumToString(e); } -inline std::istream& operator>>(std::istream& in, robustEstimation::ERobustEstimator& estimatorType) +inline std::istream& operator>>(std::istream& in, ERobustEstimator& estimatorType) { std::string token; in >> token; diff --git a/src/aliceVision/sfm/BundleAdjustment.hpp b/src/aliceVision/sfm/BundleAdjustment.hpp index 22566aa253..d802ff1524 100644 --- a/src/aliceVision/sfm/BundleAdjustment.hpp +++ b/src/aliceVision/sfm/BundleAdjustment.hpp @@ -8,6 +8,9 @@ #pragma once #include +#include +#include +#include namespace aliceVision { @@ -17,6 +20,58 @@ class SfMData; namespace sfm { +/** + * @brief Defines basic, scale and covariance options for features that can be used in a bundle adjustment. + */ +enum class EFeatureConstraint +{ + BASIC = 0, + SCALE = 1 +}; + +/** +*@brief convert an enum ESfMobservationConstraint to its corresponding string +* +*/ +inline std::string ESfMobservationConstraint_enumToString(EFeatureConstraint m) +{ + switch(m) + { + case EFeatureConstraint::BASIC: return "Basic"; + case EFeatureConstraint::SCALE: return "Scale"; + } + throw std::out_of_range("Invalid ESfMobservationConstraint enum: " + std::to_string(int(m))); +} + +/** +* @brief convert a string featureConstraint to its corresponding enum featureConstraint +* @param String +* @return ESfMobservationConstraint +*/ +inline EFeatureConstraint ESfMobservationConstraint_stringToEnum(const std::string& m) +{ + std::string featureConstraint = m; + std::transform(featureConstraint.begin(), featureConstraint.end(), featureConstraint.begin(), ::tolower); + + if(featureConstraint == "basic") return EFeatureConstraint::BASIC; + if(featureConstraint == "scale") return EFeatureConstraint::SCALE; + + throw std::out_of_range("Invalid ESfMobservationConstraint: " + m); +} + +inline std::ostream& operator<<(std::ostream& os, EFeatureConstraint m) +{ + return os << ESfMobservationConstraint_enumToString(m); +} + +inline std::istream& operator>>(std::istream& in, EFeatureConstraint& m) +{ + std::string token; + in >> token; + m = ESfMobservationConstraint_stringToEnum(token); + return in; +} + class BundleAdjustment { public: diff --git a/src/aliceVision/sfm/BundleAdjustmentCeres.hpp b/src/aliceVision/sfm/BundleAdjustmentCeres.hpp index 1708425e20..b8bab64c3c 100644 --- a/src/aliceVision/sfm/BundleAdjustmentCeres.hpp +++ b/src/aliceVision/sfm/BundleAdjustmentCeres.hpp @@ -277,6 +277,9 @@ class BundleAdjustmentCeres : public BundleAdjustment /// user Ceres options to use in the solver CeresOptions _ceresOptions; + /// user FeatureConstraint options to use + EFeatureConstraint _featureConstraint; + /// last adjustment iteration statisics Statistics _statistics; diff --git a/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp b/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp index 38ae65a879..5f684d87f3 100644 --- a/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp +++ b/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp @@ -361,7 +361,7 @@ bool ReconstructionEngine_globalSfM::Compute_Initial_Structure(matching::Pairwis bool ReconstructionEngine_globalSfM::Adjust() { // refine sfm scene (in a 3 iteration process (free the parameters regarding their incertainty order)): - BundleAdjustmentCeres::CeresOptions options; + BundleAdjustmentCeres::CeresOptions options; options.useParametersOrdering = false; // disable parameters ordering BundleAdjustmentCeres BA(options); @@ -389,7 +389,7 @@ bool ReconstructionEngine_globalSfM::Adjust() // Remove outliers (max_angle, residual error) const size_t pointcount_initial = _sfmData.structure.size(); - RemoveOutliers_PixelResidualError(_sfmData, 4.0); + RemoveOutliers_PixelResidualError(_sfmData, _featureConstraint, 4.0); const size_t pointcount_pixelresidual_filter = _sfmData.structure.size(); RemoveOutliers_AngleError(_sfmData, 2.0); const size_t pointcount_angular_filter = _sfmData.structure.size(); diff --git a/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.hpp b/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.hpp index 95e2aa733c..2c30b00b88 100644 --- a/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.hpp +++ b/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.hpp @@ -65,6 +65,7 @@ class ReconstructionEngine_globalSfM : public ReconstructionEngine ERotationAveragingMethod _eRotationAveragingMethod; ETranslationAveragingMethod _eTranslationAveragingMethod; bool _lockAllIntrinsics = false; + EFeatureConstraint _featureConstraint = EFeatureConstraint::BASIC; // Data provider feature::FeaturesPerView* _featuresPerView; diff --git a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp index e16333255b..19326764c7 100644 --- a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp +++ b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp @@ -689,7 +689,7 @@ bool ReconstructionEngine_sequentialSfM::bundleAdjustment(std::set& newR statistics.show(); } - nbOutliers = removeOutliers(_params.maxReprojectionError); + nbOutliers = removeOutliers(); std::set removedViewsIdIteration; eraseUnstablePosesAndObservations(this->_sfmData, _params.minPointsPerPose, _params.minTrackLength, &removedViewsIdIteration); @@ -2054,9 +2054,9 @@ void ReconstructionEngine_sequentialSfM::triangulate_2Views(SfMData& scene, cons } } -std::size_t ReconstructionEngine_sequentialSfM::removeOutliers(double precision) +std::size_t ReconstructionEngine_sequentialSfM::removeOutliers() { - const std::size_t nbOutliersResidualErr = RemoveOutliers_PixelResidualError(_sfmData, precision, 2); + const std::size_t nbOutliersResidualErr = RemoveOutliers_PixelResidualError(_sfmData, _params.featureConstraint, _params.maxReprojectionError, 2); const std::size_t nbOutliersAngleErr = RemoveOutliers_AngleError(_sfmData, _params.minAngleForLandmark); ALICEVISION_LOG_INFO("Remove outliers: " << std::endl diff --git a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.hpp b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.hpp index 1fdc52e067..167bb8c464 100644 --- a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.hpp +++ b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.hpp @@ -55,6 +55,7 @@ class ReconstructionEngine_sequentialSfM : public ReconstructionEngine double minAngleForTriangulation = 3.0; double minAngleForLandmark = 2.0; double maxReprojectionError = 4.0; + EFeatureConstraint featureConstraint = EFeatureConstraint::BASIC; float minAngleInitialPair = 5.0f; float maxAngleInitialPair = 40.0f; bool filterTrackForks = true; @@ -355,7 +356,7 @@ class ReconstructionEngine_sequentialSfM : public ReconstructionEngine * @param[in] precision * @return number of removed outliers */ - std::size_t removeOutliers(double precision); + std::size_t removeOutliers(); private: diff --git a/src/aliceVision/sfm/sfmFilters.cpp b/src/aliceVision/sfm/sfmFilters.cpp index 84185b671f..c8dc84636f 100644 --- a/src/aliceVision/sfm/sfmFilters.cpp +++ b/src/aliceVision/sfm/sfmFilters.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include @@ -16,12 +17,14 @@ namespace aliceVision { namespace sfm { IndexT RemoveOutliers_PixelResidualError(sfmData::SfMData& sfmData, + EFeatureConstraint featureConstraint, const double dThresholdPixel, const unsigned int minTrackLength) { IndexT outlier_count = 0; sfmData::Landmarks::iterator iterTracks = sfmData.structure.begin(); + while(iterTracks != sfmData.structure.end()) { sfmData::Observations & observations = iterTracks->second.observations; @@ -34,7 +37,7 @@ IndexT RemoveOutliers_PixelResidualError(sfmData::SfMData& sfmData, const camera::IntrinsicBase * intrinsic = sfmData.intrinsics.at(view->getIntrinsicId()).get(); Vec2 residual = intrinsic->residual(pose, iterTracks->second.X, itObs->second.x); - if(itObs->second.scale > 0) // TODO-SCALE: add an option to use the scale optionally + if(featureConstraint == EFeatureConstraint::SCALE) { // Apply the scale of the feature to get a residual value // relative to the feature precision. diff --git a/src/aliceVision/sfm/sfmFilters.hpp b/src/aliceVision/sfm/sfmFilters.hpp index fdbb580fad..3434e19fbd 100644 --- a/src/aliceVision/sfm/sfmFilters.hpp +++ b/src/aliceVision/sfm/sfmFilters.hpp @@ -8,6 +8,7 @@ #pragma once #include +#include namespace aliceVision { @@ -33,6 +34,7 @@ inline PairSet Pair_filter(const IterablePairs& pairs, const IterableIndex& inde /// Remove observations with too large reprojection error. /// Return the number of removed tracks. IndexT RemoveOutliers_PixelResidualError(sfmData::SfMData& sfmData, + EFeatureConstraint featureConstraint, const double dThresholdPixel, const unsigned int minTrackLength = 2); diff --git a/src/software/pipeline/main_imageMatching.cpp b/src/software/pipeline/main_imageMatching.cpp index 6a8d39ef7a..1ee0bd5618 100644 --- a/src/software/pipeline/main_imageMatching.cpp +++ b/src/software/pipeline/main_imageMatching.cpp @@ -686,7 +686,8 @@ int main(int argc, char** argv) // load SfMData sfmData::SfMData sfmDataA, sfmDataB; - if(!sfmDataIO::Load(sfmDataA, sfmDataFilenameA, sfmDataIO::ESfMData::ALL)) + using namespace sfmDataIO; + if(!sfmDataIO::Load(sfmDataA, sfmDataFilenameA, ESfMData(ESfMData::VIEWS|ESfMData::EXTRINSICS|ESfMData::INTRINSICS))) { ALICEVISION_LOG_ERROR("The input SfMData file '" + sfmDataFilenameA + "' cannot be read."); return EXIT_FAILURE; @@ -694,7 +695,7 @@ int main(int argc, char** argv) if(useMultiSfM) { - if(!sfmDataIO::Load(sfmDataB, sfmDataFilenameB, sfmDataIO::ESfMData::ALL)) + if(!sfmDataIO::Load(sfmDataB, sfmDataFilenameB, ESfMData(ESfMData::VIEWS|ESfMData::EXTRINSICS|ESfMData::INTRINSICS))) { ALICEVISION_LOG_ERROR("The input SfMData file '" + sfmDataFilenameB + "' cannot be read."); return EXIT_FAILURE; diff --git a/src/software/pipeline/main_incrementalSfM.cpp b/src/software/pipeline/main_incrementalSfM.cpp index 452c6c0a97..1a916dff0a 100644 --- a/src/software/pipeline/main_incrementalSfM.cpp +++ b/src/software/pipeline/main_incrementalSfM.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,8 @@ using namespace aliceVision; namespace po = boost::program_options; namespace fs = boost::filesystem; using namespace aliceVision::track; +using namespace aliceVision::sfm; + /** * @brief Retrieve the view id in the sfmData from the image filename. @@ -78,7 +81,7 @@ int main(int argc, char **argv) std::string outputSfM; // user optional parameters - + // user optional parameters std::string outputSfMViewsAndPoses; std::string extraInfoFolder; std::string describerTypesName = feature::EImageDescriberType_enumToString(feature::EImageDescriberType::SIFT); @@ -164,7 +167,9 @@ int main(int argc, char **argv) ("useRigConstraint", po::value(&sfmParams.useRigConstraint)->default_value(sfmParams.useRigConstraint), "Enable/Disable rig constraint.\n") ("lockScenePreviouslyReconstructed", po::value(&lockScenePreviouslyReconstructed)->default_value(lockScenePreviouslyReconstructed), - "Lock/Unlock scene previously reconstructed.\n"); + "Lock/Unlock scene previously reconstructed.\n") + ("observationConstraint", po::value(&sfmParams.featureConstraint)->default_value(sfmParams.featureConstraint), + "Use of an observation constraint : basic, scale the observation or use of the covariance.\n"); po::options_description logParams("Log parameters"); logParams.add_options() From 884a3f62bed75e8bd4e780ba706f7b6350a05cdc Mon Sep 17 00:00:00 2001 From: Fabien Castan Date: Thu, 19 Mar 2020 14:55:34 +0100 Subject: [PATCH 4/5] [sfm] fix usage of observations scale in SfM * fix feature index in multiview triangulate * fix removeOutliers for observations without scale --- src/aliceVision/feature/sift/SIFT.hpp | 2 +- .../ReconstructionEngine_sequentialSfM.cpp | 7 ++++--- src/aliceVision/sfm/sfmFilters.cpp | 2 +- src/aliceVision/sfmData/Landmark.hpp | 6 +++--- src/software/pipeline/main_incrementalSfM.cpp | 1 - src/software/utils/CMakeLists.txt | 18 +++++++++--------- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/aliceVision/feature/sift/SIFT.hpp b/src/aliceVision/feature/sift/SIFT.hpp index 9c7875d991..8846484028 100644 --- a/src/aliceVision/feature/sift/SIFT.hpp +++ b/src/aliceVision/feature/sift/SIFT.hpp @@ -10,7 +10,7 @@ #include #include #include -// #include // TO CHECK +#include #include extern "C" { diff --git a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp index 19326764c7..d538426885 100644 --- a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp +++ b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp @@ -1656,14 +1656,15 @@ void ReconstructionEngine_sequentialSfM::updateScene(const IndexT viewIndex, con { const Vec3 X = resectionData.pt3D.col(i); const Vec2 x = resectionData.pt2D.col(i); - Landmark& landmark = _sfmData.structure[*iterTrackId]; - double scale = _featuresPerView->getFeatures(viewIndex, landmark.descType)[i].scale(); // TODO: check i index, TODO: replace x() with scale() const Vec2 residual = resectionData.optionalIntrinsic->residual(resectionData.pose, X, x); if (residual.norm() < resectionData.error_max && resectionData.pose.depth(X) > 0) { + Landmark& landmark = _sfmData.structure[*iterTrackId]; + const IndexT idFeat = resectionData.featuresId[i].second; + const double scale = _featuresPerView->getFeatures(viewIndex, landmark.descType)[idFeat].scale(); // Inlier, add the point to the reconstructed track - landmark.observations[viewIndex] = Observation(x, resectionData.featuresId[i].second, scale); + landmark.observations[viewIndex] = Observation(x, idFeat, scale); } } } diff --git a/src/aliceVision/sfm/sfmFilters.cpp b/src/aliceVision/sfm/sfmFilters.cpp index c8dc84636f..c29db80855 100644 --- a/src/aliceVision/sfm/sfmFilters.cpp +++ b/src/aliceVision/sfm/sfmFilters.cpp @@ -37,7 +37,7 @@ IndexT RemoveOutliers_PixelResidualError(sfmData::SfMData& sfmData, const camera::IntrinsicBase * intrinsic = sfmData.intrinsics.at(view->getIntrinsicId()).get(); Vec2 residual = intrinsic->residual(pose, iterTracks->second.X, itObs->second.x); - if(featureConstraint == EFeatureConstraint::SCALE) + if(featureConstraint == EFeatureConstraint::SCALE && itObs->second.scale > 0.0) { // Apply the scale of the feature to get a residual value // relative to the feature precision. diff --git a/src/aliceVision/sfmData/Landmark.hpp b/src/aliceVision/sfmData/Landmark.hpp index 49ae37162a..9a086a8a6b 100644 --- a/src/aliceVision/sfmData/Landmark.hpp +++ b/src/aliceVision/sfmData/Landmark.hpp @@ -21,7 +21,7 @@ namespace sfmData { */ struct Observation { - Observation(): id_feat(UndefinedIndexT) {} + Observation() {} Observation(const Vec2 & p, IndexT idFeat, double scale_) : x(p) , id_feat(idFeat) @@ -29,8 +29,8 @@ struct Observation {} Vec2 x; - IndexT id_feat; - double scale = 1.0; + IndexT id_feat = UndefinedIndexT; + double scale = 0.0; bool operator==(const Observation& other) const { diff --git a/src/software/pipeline/main_incrementalSfM.cpp b/src/software/pipeline/main_incrementalSfM.cpp index 1a916dff0a..18ab030f1f 100644 --- a/src/software/pipeline/main_incrementalSfM.cpp +++ b/src/software/pipeline/main_incrementalSfM.cpp @@ -80,7 +80,6 @@ int main(int argc, char **argv) std::vector matchesFolders; std::string outputSfM; - // user optional parameters // user optional parameters std::string outputSfMViewsAndPoses; std::string extraInfoFolder; diff --git a/src/software/utils/CMakeLists.txt b/src/software/utils/CMakeLists.txt index dde1546276..8e7d4e33c7 100644 --- a/src/software/utils/CMakeLists.txt +++ b/src/software/utils/CMakeLists.txt @@ -199,14 +199,14 @@ alicevision_add_software(aliceVision_utils_split360Images # Project 180° fisheye images into equirectangular -#alicevision_add_software(aliceVision_utils_fisheyeProjection -# SOURCE main_fisheyeProjection.cpp -# FOLDER ${FOLDER_SOFTWARE_UTILS} -# LINKS aliceVision_system -# aliceVision_numeric -# aliceVision_image -# ${OPENIMAGEIO_LIBRARIES} -# ${Boost_LIBRARIES} -#) +alicevision_add_software(aliceVision_utils_fisheyeProjection + SOURCE main_fisheyeProjection.cpp + FOLDER ${FOLDER_SOFTWARE_UTILS} + LINKS aliceVision_system + aliceVision_numeric + aliceVision_image + ${OPENIMAGEIO_LIBRARIES} + ${Boost_LIBRARIES} +) endif() # ALICEVISION_BUILD_SFM From 9b0c623fc4998065d02840f15dc9337b6a81c988 Mon Sep 17 00:00:00 2001 From: Fabien Castan Date: Fri, 20 Mar 2020 16:31:35 +0100 Subject: [PATCH 5/5] [sfm] do not set observation scale if featureConstraint is BASIC This disables the usage of scale in BA. --- .../global/ReconstructionEngine_globalSfM.cpp | 11 +++++++---- .../ReconstructionEngine_sequentialSfM.cpp | 17 +++++++++++------ 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp b/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp index 5f684d87f3..acb7514126 100644 --- a/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp +++ b/src/aliceVision/sfm/pipeline/global/ReconstructionEngine_globalSfM.cpp @@ -301,7 +301,9 @@ bool ReconstructionEngine_globalSfM::Compute_Initial_Structure(matching::Pairwis const size_t imaIndex = it->first; const size_t featIndex = it->second; const PointFeature & pt = _featuresPerView->getFeatures(imaIndex, track.descType)[featIndex]; - obs[imaIndex] = Observation(pt.coords().cast(), featIndex, pt.scale()); + + const double scale = (_featureConstraint == EFeatureConstraint::BASIC) ? 0.0 : pt.scale(); + obs[imaIndex] = Observation(pt.coords().cast(), featIndex, scale); } } @@ -443,7 +445,6 @@ void ReconstructionEngine_globalSfM::Compute_Relative_Rotations(rotationAveragin poseWiseMatches[Pair(v1->getPoseId(), v2->getPoseId())].insert(pair); } - const double unknownScale = 0.0; boost::progress_display progressBar( poseWiseMatches.size(), std::cout, "\n- Relative pose computation -\n" ); #pragma omp parallel for schedule(dynamic) // Compute the relative pose from pairwise point matches: @@ -564,8 +565,10 @@ void ReconstructionEngine_globalSfM::Compute_Relative_Rotations(rotationAveragin Vec3 X; TriangulateDLT(P1, x1_, P2, x2_, &X); Observations obs; - obs[view_I->getViewId()] = Observation(x1_, match._i, p1.scale()); - obs[view_J->getViewId()] = Observation(x2_, match._j, p2.scale()); + const double scaleI = (_featureConstraint == EFeatureConstraint::BASIC) ? 0.0 : p1.scale(); + const double scaleJ = (_featureConstraint == EFeatureConstraint::BASIC) ? 0.0 : p2.scale(); + obs[view_I->getViewId()] = Observation(x1_, match._i, scaleI); + obs[view_J->getViewId()] = Observation(x2_, match._j, scaleJ); Landmark& newLandmark = landmarks[landmarkId++]; newLandmark.descType = descType; newLandmark.observations = obs; diff --git a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp index d538426885..b2ec35b2c4 100644 --- a/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp +++ b/src/aliceVision/sfm/pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp @@ -1662,7 +1662,7 @@ void ReconstructionEngine_sequentialSfM::updateScene(const IndexT viewIndex, con { Landmark& landmark = _sfmData.structure[*iterTrackId]; const IndexT idFeat = resectionData.featuresId[i].second; - const double scale = _featuresPerView->getFeatures(viewIndex, landmark.descType)[idFeat].scale(); + const double scale = (_params.featureConstraint == EFeatureConstraint::BASIC) ? 0.0 : _featuresPerView->getFeatures(viewIndex, landmark.descType)[idFeat].scale(); // Inlier, add the point to the reconstructed track landmark.observations[viewIndex] = Observation(x, idFeat, scale); } @@ -1877,7 +1877,8 @@ void ReconstructionEngine_sequentialSfM::triangulate_multiViewsLORANSAC(SfMData& { const Vec2 x = _featuresPerView->getFeatures(viewId, track.descType)[track.featPerView.at(viewId)].coords().cast(); const feature::PointFeature& p = _featuresPerView->getFeatures(viewId, track.descType)[track.featPerView.at(viewId)]; - landmark.observations[viewId] = Observation(x, track.featPerView.at(viewId), p.scale()); + const double scale = (_params.featureConstraint == EFeatureConstraint::BASIC) ? 0.0 : p.scale(); + landmark.observations[viewId] = Observation(x, track.featPerView.at(viewId), scale); } #pragma omp critical { @@ -1971,7 +1972,8 @@ void ReconstructionEngine_sequentialSfM::triangulate_2Views(SfMData& scene, cons const double acThreshold = (acThresholdIt != _map_ACThreshold.end()) ? acThresholdIt->second : 4.0; if (poseI.depth(landmark.X) > 0 && residual.norm() < std::max(4.0, acThreshold)) { - landmark.observations[I] = Observation(xI, track.featPerView.at(I), featI.scale()); + const double scale = (_params.featureConstraint == EFeatureConstraint::BASIC) ? 0.0 : featI.scale(); + landmark.observations[I] = Observation(xI, track.featPerView.at(I), scale); ++extented_track; } } @@ -1983,7 +1985,8 @@ void ReconstructionEngine_sequentialSfM::triangulate_2Views(SfMData& scene, cons const double acThreshold = (acThresholdIt != _map_ACThreshold.end()) ? acThresholdIt->second : 4.0; if (poseJ.depth(landmark.X) > 0 && residual.norm() < std::max(4.0, acThreshold)) { - landmark.observations[J] = Observation(xJ, track.featPerView.at(J), featJ.scale()); + const double scale = (_params.featureConstraint == EFeatureConstraint::BASIC) ? 0.0 : featJ.scale(); + landmark.observations[J] = Observation(xJ, track.featPerView.at(J), scale); ++extented_track; } } @@ -2034,8 +2037,10 @@ void ReconstructionEngine_sequentialSfM::triangulate_2Views(SfMData& scene, cons landmark.X = X_euclidean; landmark.descType = track.descType; - landmark.observations[I] = Observation(xI, track.featPerView.at(I), featI.scale()); - landmark.observations[J] = Observation(xJ, track.featPerView.at(J), featJ.scale()); + const double scaleI = (_params.featureConstraint == EFeatureConstraint::BASIC) ? 0.0 : featI.scale(); + const double scaleJ = (_params.featureConstraint == EFeatureConstraint::BASIC) ? 0.0 : featJ.scale(); + landmark.observations[I] = Observation(xI, track.featPerView.at(I), scaleI); + landmark.observations[J] = Observation(xJ, track.featPerView.at(J), scaleJ); ++new_added_track; } // critical