Skip to content

Commit

Permalink
[sfm] Add Sfm Filter
Browse files Browse the repository at this point in the history
Create new sfmdatas by selecting views from sfmData with regex.
  • Loading branch information
jmelou committed Oct 25, 2024
1 parent 977f4cc commit ac4bb57
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/aliceVision/sfm/utils/alignment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ void matchViewsByFilePattern(const sfmData::SfMData& sfmDataA,
const std::string& filePatternMatching,
std::vector<std::pair<IndexT, IndexT>>& out_commonViewIds);

std::map<std::string, IndexT> retrieveMatchingFilepath(const sfmData::SfMData& sfmData,
const std::string& filePatternMatching);

void matchViewsByMetadataMatching(const sfmData::SfMData& sfmDataA,
const sfmData::SfMData& sfmDataB,
const std::vector<std::string>& metadataList,
Expand Down
13 changes: 13 additions & 0 deletions src/software/utils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,19 @@ if(ALICEVISION_BUILD_SFM)
Boost::program_options
)

# SfM filter
alicevision_add_software(aliceVision_sfmFilter
SOURCE main_sfmFilter.cpp
FOLDER ${FOLDER_SOFTWARE_UTILS}
LINKS aliceVision_system
aliceVision_cmdline
aliceVision_feature
aliceVision_sfm
aliceVision_sfmData
aliceVision_sfmDataIO
Boost::program_options
)

# SfM to rig
alicevision_add_software(aliceVision_sfmToRig
SOURCE main_sfmToRig.cpp
Expand Down
131 changes: 131 additions & 0 deletions src/software/utils/main_sfmFilter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// This file is part of the AliceVision project.
// Copyright (c) 2024 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/.

#include <aliceVision/sfmData/SfMData.hpp>
#include <aliceVision/sfmDataIO/sfmDataIO.hpp>
#include <aliceVision/sfm/utils/alignment.hpp>

#include <aliceVision/cmdline/cmdline.hpp>
#include <aliceVision/system/main.hpp>
#include <aliceVision/system/Logger.hpp>
#include <aliceVision/stl/regex.hpp>

#include <boost/program_options.hpp>

#include <string>
#include <sstream>

// These constants define the current software version.
// They must be updated when the command line is changed.
#define ALICEVISION_SOFTWARE_VERSION_MAJOR 1
#define ALICEVISION_SOFTWARE_VERSION_MINOR 0

using namespace aliceVision;
using namespace aliceVision::sfm;

namespace po = boost::program_options;

int aliceVision_main(int argc, char** argv)
{
system::Timer timer;

// command-line parameters
std::string sfmDataFilename;
std::string outputSfMFilenameSelected;
std::string outputSfMFilenameUnselected;
std::string fileMatchingPattern;

// clang-format off
po::options_description requiredParams("Required parameters");
requiredParams.add_options()
("inputFile,i", po::value<std::string>(&sfmDataFilename)->required(),
"Path to the input SfMData file.\n")
("fileMatchingPattern,m", po::value<std::string>(&fileMatchingPattern)->required(),
"Matching pattern for the from_filepath method.\n")
("outputSfMData_selected,o", po::value<std::string>(&outputSfMFilenameSelected)->required(),
"Path to the output SfMData file.\n")
("outputSfMData_unselected,o", po::value<std::string>(&outputSfMFilenameUnselected)->required(),
"Path to the output SfMData file.\n");

CmdLine cmdline("AliceVision sfmFilter");
cmdline.add(requiredParams);
//cmdline.add(optionalParams);

if (!cmdline.execute(argc, argv))
{
return EXIT_FAILURE;
}

// Load input scene
sfmData::SfMData sfmData;
if (!sfmDataIO::load(sfmData, sfmDataFilename, sfmDataIO::ESfMData::ALL))
{
ALICEVISION_LOG_ERROR("The input SfMData file '" << sfmDataFilename << "' cannot be read");
return EXIT_FAILURE;
}

std::regex re(fileMatchingPattern);
std::vector<IndexT> selectedViews;

for (auto& viewIt : sfmData.getViews())
{
const std::string& imagePath = viewIt.second->getImage().getImagePath();
std::smatch matches;
if (std::regex_search(imagePath, matches, re))
{
selectedViews.push_back(viewIt.first);
}
}

sfmData::SfMData outputSfMData_selected = sfmData;
sfmData::SfMData outputSfMData_unselected = sfmData;
std::set<IndexT> viewIdsToRemove;
std::set<IndexT> viewIdsToKeep;

for (auto& viewIt : outputSfMData_selected.getViews())
{
const IndexT viewId = viewIt.first;
auto it = std::find(selectedViews.begin(), selectedViews.end(), viewId);
if (it == selectedViews.end())
{
viewIdsToRemove.insert(viewId);
}
else
{
viewIdsToKeep.insert(viewId);
}
}

for (auto r : viewIdsToRemove)
{
outputSfMData_selected.getViews().erase(r);
}

for (auto r : viewIdsToKeep)
{
outputSfMData_unselected.getViews().erase(r);
}


ALICEVISION_LOG_INFO("Save into '" << outputSfMFilenameSelected << "'");
// Export the SfMData scene in the expected format
if (!sfmDataIO::save(outputSfMData_selected, outputSfMFilenameSelected, sfmDataIO::ESfMData::ALL))
{
ALICEVISION_LOG_ERROR("An error occurred while trying to save '" << outputSfMFilenameSelected << "'");
return EXIT_FAILURE;
}

ALICEVISION_LOG_INFO("Save into '" << outputSfMFilenameUnselected << "'");
// Export the SfMData scene in the expected format
if (!sfmDataIO::save(outputSfMData_unselected, outputSfMFilenameUnselected, sfmDataIO::ESfMData::ALL))
{
ALICEVISION_LOG_ERROR("An error occurred while trying to save '" << outputSfMFilenameUnselected << "'");
return EXIT_FAILURE;
}

ALICEVISION_LOG_INFO("Task done in (s): " + std::to_string(timer.elapsed()));
return EXIT_SUCCESS;
}
21 changes: 21 additions & 0 deletions src/software/utils/main_sfmTransfer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ enum class EMatchingMethod : unsigned char
FROM_VIEWID = 0,
FROM_FILEPATH,
FROM_METADATA,
FROM_POSEID,
FROM_INTRINSICID
};

Expand All @@ -54,6 +55,8 @@ std::string EMatchingMethod_enumToString(EMatchingMethod alignmentMethod)
return "from_filepath";
case EMatchingMethod::FROM_METADATA:
return "from_metadata";
case EMatchingMethod::FROM_POSEID:
return "from_poseid";
case EMatchingMethod::FROM_INTRINSICID:
return "from_intrinsicid";
}
Expand All @@ -76,6 +79,8 @@ EMatchingMethod EMatchingMethod_stringToEnum(const std::string& alignmentMethod)
return EMatchingMethod::FROM_FILEPATH;
if (method == "from_metadata")
return EMatchingMethod::FROM_METADATA;
if (method == "from_poseid")
return EMatchingMethod::FROM_POSEID;
if (method == "from_intrinsicid")
return EMatchingMethod::FROM_INTRINSICID;
throw std::out_of_range("Invalid SfM alignment method : " + alignmentMethod);
Expand Down Expand Up @@ -184,6 +189,10 @@ int aliceVision_main(int argc, char** argv)
sfm::matchViewsByMetadataMatching(sfmData, sfmDataRef, metadataMatchingList, commonViewIds);
break;
}
case EMatchingMethod::FROM_POSEID:
{
break;
}
case EMatchingMethod::FROM_INTRINSICID:
{
break;
Expand All @@ -205,6 +214,18 @@ int aliceVision_main(int argc, char** argv)
}
}
}
else if (matchingMethod == EMatchingMethod::FROM_POSEID)
{
for (auto& view : sfmData.getViews())
{
auto pose = sfmDataRef.getPoses().find(view.second->getPoseId());
if (pose != sfmDataRef.getPoses().end())
{
view.second->setPoseId(pose->first);
sfmData.getPoses()[pose->first] = pose->second;
}
}
}
else if (!transferPoses && !transferIntrinsics)
{
ALICEVISION_LOG_ERROR("Nothing to do.");
Expand Down

0 comments on commit ac4bb57

Please sign in to comment.