Skip to content

Commit

Permalink
Merge pull request #695 from alicevision/dev/sfmTransformFromMarkers
Browse files Browse the repository at this point in the history
Coordinate system alignment to specific markers or between scenes
  • Loading branch information
fabiencastan committed Sep 26, 2019
2 parents 9c9d4b4 + b3762bc commit 50707aa
Show file tree
Hide file tree
Showing 15 changed files with 1,252 additions and 63 deletions.
2 changes: 1 addition & 1 deletion src/aliceVision/feature/cctag/ImageDescriber_CCTAG.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
#include <numeric>

namespace cctag {
class Parameters; // Hidden implementation
struct Parameters; // Hidden implementation
}

namespace aliceVision {
Expand Down
9 changes: 9 additions & 0 deletions src/aliceVision/feature/imageDescriberCommon.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ EImageDescriberType EImageDescriberType_stringToEnum(const std::string& imageDes
*/
std::vector<EImageDescriberType> EImageDescriberType_stringToEnums(const std::string& describerMethods);

inline bool isMarker(EImageDescriberType imageDescriberType)
{
#if ALICEVISION_IS_DEFINED(ALICEVISION_HAVE_CCTAG)
return imageDescriberType == EImageDescriberType::CCTAG3 || imageDescriberType == EImageDescriberType::CCTAG4;
#else
return false;
#endif
}

/**
* @brief getStrongSupportCoeff
* @param imageDescriberType
Expand Down
3 changes: 3 additions & 0 deletions src/aliceVision/mesh/Texturing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,9 @@ void Texturing::loadFromOBJ(const std::string& filename, bool flipNormals)

void Texturing::remapVisibilities(EVisibilityRemappingMethod remappingMethod, const Mesh& refMesh, const mesh::PointsVisibility& refPointsVisibilities)
{
if (refPointsVisibilities.empty())
throw std::runtime_error("Texturing: Cannot remap visibilities as there is no reference points.");

assert(pointsVisibilities == nullptr);
pointsVisibilities = new mesh::PointsVisibility();

Expand Down
1 change: 1 addition & 0 deletions src/aliceVision/sfm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ set(sfm_files_sources
pipeline/localization/SfMLocalizer.cpp
pipeline/localization/SfMLocalizationSingle3DTrackObservationDatabase.cpp
pipeline/sequential/ReconstructionEngine_sequentialSfM.cpp
pipeline/ReconstructionEngine.cpp
pipeline/RigSequence.cpp
pipeline/RelativePoseInfo.cpp
pipeline/structureFromKnownPoses/StructureEstimationFromKnownPoses.cpp
Expand Down
77 changes: 77 additions & 0 deletions src/aliceVision/sfm/pipeline/ReconstructionEngine.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// This file is part of the AliceVision project.
// Copyright (c) 2019 AliceVision contributors.
// This Source Code Form is subject to the terms of the Mozilla Public License,
// v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at https://mozilla.org/MPL/2.0/.

#pragma once

#include "ReconstructionEngine.hpp"

#include <aliceVision/feature/RegionsPerView.hpp>
#include <aliceVision/sfm/pipeline/regionsIO.hpp>


namespace aliceVision {
namespace sfm {


void retrieveMarkersId(sfmData::SfMData& sfmData)
{
std::set<feature::EImageDescriberType> allMarkerDescTypes;
#if ALICEVISION_IS_DEFINED(ALICEVISION_HAVE_CCTAG)
allMarkerDescTypes.insert(feature::EImageDescriberType::CCTAG3);
allMarkerDescTypes.insert(feature::EImageDescriberType::CCTAG4);
#endif
if (allMarkerDescTypes.empty())
return;

std::set<feature::EImageDescriberType> usedDescTypes = sfmData.getLandmarkDescTypes();

std::vector<feature::EImageDescriberType> markerDescTypes;
std::set_intersection(allMarkerDescTypes.begin(), allMarkerDescTypes.end(),
usedDescTypes.begin(), usedDescTypes.end(),
std::back_inserter(markerDescTypes));

std::set<feature::EImageDescriberType> markerDescTypes_set(markerDescTypes.begin(), markerDescTypes.end());

if(markerDescTypes.empty())
return;

// load the corresponding view regions
feature::RegionsPerView regionPerView;
std::set<IndexT> filter;
// It could be optimized by loading only the minimal number of desc files,
// but as we are only retrieving them for markers, the performance impact is limited.
if (!sfm::loadRegionsPerView(regionPerView, sfmData, sfmData.getFeaturesFolders(), markerDescTypes, filter))
{
ALICEVISION_THROW_ERROR("Error while loading markers regions.");
}
for (auto& landmarkIt : sfmData.getLandmarks())
{
auto& landmark = landmarkIt.second;
if (landmark.observations.empty())
continue;
if (markerDescTypes_set.find(landmark.descType) == markerDescTypes_set.end())
continue;
landmark.rgb = image::BLACK;

const auto obs = landmark.observations.begin();
const feature::Regions& regions = regionPerView.getRegions(obs->first, landmark.descType);
const feature::CCTAG_Regions& cctagRegions = dynamic_cast<const feature::CCTAG_Regions&>(regions);
const auto& d = cctagRegions.Descriptors()[obs->second.id_feat];
for (int i = 0; i < d.size(); ++i)
{
if (d[i] == 255)
{
ALICEVISION_LOG_TRACE("Found marker: " << i << " (landmarkId: " << landmarkIt.first << ").");
landmark.rgb.r() = i;
break;
}
}
}
}


} // namespace sfm
} // namespace aliceVision
9 changes: 9 additions & 0 deletions src/aliceVision/sfm/pipeline/ReconstructionEngine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
namespace aliceVision {
namespace sfm {

void retrieveMarkersId(sfmData::SfMData& sfmData);


/**
* @brief Basic Reconstruction Engine.
* Process Function handle the reconstruction.
Expand Down Expand Up @@ -68,12 +71,18 @@ class ReconstructionEngine
sfmData::colorizeTracks(_sfmData);
}

void retrieveMarkersId()
{
aliceVision::sfm::retrieveMarkersId(_sfmData);
}

protected:
/// Output folder where outputs will be stored
std::string _outputFolder;
/// Internal SfMData
sfmData::SfMData _sfmData;
};


} // namespace sfm
} // namespace aliceVision
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,13 @@ std::size_t ReconstructionEngine_sequentialSfM::fuseMatchesIntoTracks()
// build tracks with STL compliant type
tracksBuilder.exportToSTL(_map_tracks);
ALICEVISION_LOG_DEBUG("Build tracks per view");

// Init tracksPerView to have an entry in the map for each view (even if there is no track at all)
for(const auto& viewIt: _sfmData.views)
{
// create an entry in the map
_map_tracksPerView[viewIt.first];
}
track::tracksUtilsMap::computeTracksPerView(_map_tracks, _map_tracksPerView);
ALICEVISION_LOG_DEBUG("Build tracks pyramid per view");
computeTracksPyramidPerView(
Expand Down Expand Up @@ -652,7 +659,8 @@ bool ReconstructionEngine_sequentialSfM::bundleAdjustment(std::set<IndexT>& newR
// - the number of cameras to refine cannot be < to the number of newly added cameras (set to 'refine' by default)
if((nbRefinedPoses <= newReconstructedViews.size()) && _sfmData.getRigs().empty())
{
throw std::runtime_error("The local bundle adjustment refinement has not been done: the new cameras are not connected to the rest of the graph.");
ALICEVISION_LOG_INFO("Local bundle adjustment: the new cameras are not connected to the rest of the graph"
" (nbRefinedPoses: " << nbRefinedPoses << ", newReconstructedViews.size(): " << newReconstructedViews.size() << ").");
}
}

Expand Down Expand Up @@ -722,6 +730,12 @@ void ReconstructionEngine_sequentialSfM::exportStatistics(double reconstructionT
<< "\t- elapsed time: " << reconstructionTime << std::endl
<< "\t- residual RMSE: " << residual);

std::map<feature::EImageDescriberType, int> descTypeUsage = _sfmData.getLandmarkDescTypesUsages();
for(const auto& d: descTypeUsage)
{
ALICEVISION_LOG_INFO(" - # " << EImageDescriberType_enumToString(d.first) << ": " << d.second);
}

// residual histogram
Histogram<double> residualHistogram;
computeResidualsHistogram(&residualHistogram);
Expand Down Expand Up @@ -843,11 +857,7 @@ bool ReconstructionEngine_sequentialSfM::findConnectedViews(
const bool isIntrinsicsReconstructed = reconstructedIntrinsics.count(intrinsicId);

// Compute 2D - 3D possible content
aliceVision::track::TracksPerView::const_iterator tracksIdsIt = _map_tracksPerView.find(viewId);
if(tracksIdsIt == _map_tracksPerView.end())
continue;

const aliceVision::track::TrackIdSet& set_tracksIds = tracksIdsIt->second;
const aliceVision::track::TrackIdSet& set_tracksIds = _map_tracksPerView.at(viewId);
if (set_tracksIds.empty())
continue;

Expand Down

0 comments on commit 50707aa

Please sign in to comment.