Skip to content

Commit

Permalink
Merge pull request #1517 from alicevision/dev/useSegmentationMasks
Browse files Browse the repository at this point in the history
Masking: Handle different file extensions for masks and allow mask inversion in `ImageSegmentation`
  • Loading branch information
mugulmd authored Aug 25, 2023
2 parents 68bf0a0 + 977ee55 commit c5caf62
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 20 deletions.
6 changes: 3 additions & 3 deletions src/aliceVision/image/io.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1288,15 +1288,15 @@ void writeImageWithFloat(const std::string& path, const Image<IndexT>& image,


bool tryLoadMask(Image<unsigned char>* mask, const std::vector<std::string>& masksFolders,
const IndexT viewId, const std::string & srcImage)
const IndexT viewId, const std::string& srcImage, const std::string& fileExtension)
{
for (const auto & masksFolder_str : masksFolders)
{
if (!masksFolder_str.empty() && fs::exists(masksFolder_str))
{
const auto masksFolder = fs::path(masksFolder_str);
const auto idMaskPath = masksFolder / fs::path(std::to_string(viewId)).replace_extension("png");
const auto nameMaskPath = masksFolder / fs::path(srcImage).filename().replace_extension("png");
const auto idMaskPath = masksFolder / fs::path(std::to_string(viewId)).replace_extension(fileExtension);
const auto nameMaskPath = masksFolder / fs::path(srcImage).filename().replace_extension(fileExtension);

if (fs::exists(idMaskPath))
{
Expand Down
2 changes: 1 addition & 1 deletion src/aliceVision/image/io.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,7 @@ struct ColorTypeInfo<RGBAfColor>
};

bool tryLoadMask(Image<unsigned char>* mask, const std::vector<std::string>& masksFolders,
const IndexT viewId, const std::string & srcImage);
const IndexT viewId, const std::string& srcImage, const std::string& fileExtension);

/**
* Returns the value of ALICEVISION_ROOT environmental variable, or empty string if it is not
Expand Down
23 changes: 15 additions & 8 deletions src/software/pipeline/main_imageSegmentation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
// 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
#define ALICEVISION_SOFTWARE_VERSION_MINOR 1

using namespace aliceVision;

Expand Down Expand Up @@ -65,14 +65,18 @@ void imageToPlanes(std::vector<float> & output, const image::Image<image::RGBfCo
}
}

void labelsToMask(image::Image<unsigned char> & mask, const image::Image<IndexT> & labels, const std::set<IndexT> & validClasses)
void labelsToMask(image::Image<unsigned char> & mask, const image::Image<IndexT> & labels, const std::set<IndexT> & validClasses,
const bool & maskInvert)
{
for (int i = 0; i < mask.Height(); i++)
{
for (int j = 0; j < mask.Width(); j++)
{
IndexT label = labels(i, j);
mask(i, j) = (validClasses.find(label) != validClasses.end()) ? 255 : 0;
if (maskInvert)
mask(i, j) = (validClasses.find(label) != validClasses.end()) ? 0 : 255;
else
mask(i, j) = (validClasses.find(label) != validClasses.end()) ? 255 : 0;
}
}
}
Expand All @@ -83,20 +87,23 @@ int aliceVision_main(int argc, char** argv)
std::string outputPath;
std::string modelWeightsPath;
std::vector<std::string> validClasses;
bool maskInvert = false;
int rangeStart = -1;
int rangeSize = 1;

// Description of mandatory parameters
po::options_description requiredParams("Required parameters");
requiredParams.add_options()
("input,i", po::value<std::string>(&sfmDataFilepath)->required(), "Input sfmData.")
("input,i", po::value<std::string>(&sfmDataFilepath)->required(), "Input SfMData.")
("modelPath,m", po::value<std::string>(&modelWeightsPath)->required(), "Input Model weights file.")
("output,o", po::value<std::string>(&outputPath)->required(), "output folder.");
("output,o", po::value<std::string>(&outputPath)->required(), "Output folder.");

po::options_description optionalParams("Optional parameters");
optionalParams.add_options()
("validClasses,c", po::value<std::vector<std::string>>(&validClasses)->multitoken(),
"Names of classes which are to be considered")
"Names of classes which are to be considered.")
("maskInvert", po::value<bool>(&maskInvert)->default_value(maskInvert),
"Invert mask values. If selected, the pixels corresponding to the mask will be set to 0.0 instead of 1.0.")
("rangeStart", po::value<int>(&rangeStart)->default_value(rangeStart),
"Range start for processing views (ordered by image filepath). Set to -1 to process all images.")
("rangeSize", po::value<int>(&rangeSize)->default_value(rangeSize),
Expand Down Expand Up @@ -231,7 +238,7 @@ int aliceVision_main(int argc, char** argv)


image::Image<unsigned char> mask(labels.Width(), labels.Height());
labelsToMask(mask, labels, validClassesIndices);
labelsToMask(mask, labels, validClassesIndices, maskInvert);

if (pixelRatio != 1.0)
{
Expand All @@ -247,7 +254,7 @@ int aliceVision_main(int argc, char** argv)
mask.swap(resizedMask);
}

//Store image
// Store image
std::stringstream ss;
ss << outputPath << "/" << view->getViewId() << ".exr";
image::writeImage(ss.str(), mask, image::ImageWriteOptions());
Expand Down
17 changes: 12 additions & 5 deletions src/software/pipeline/main_meshMasking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
// 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
#define ALICEVISION_SOFTWARE_VERSION_MINOR 1

using namespace aliceVision;

Expand All @@ -38,10 +38,12 @@ namespace fs = boost::filesystem;
*/
struct MaskCache
{
MaskCache(const mvsUtils::MultiViewParams& mp, const std::vector<std::string>& masksFolders, bool undistortMasks, int maxSize = 16)
MaskCache(const mvsUtils::MultiViewParams& mp, const std::vector<std::string>& masksFolders, bool undistortMasks,
const std::string maskExtension, int maxSize = 16)
: _mp(mp)
, _masksFolders(masksFolders)
, _undistortMasks(undistortMasks)
, _maskExtension(maskExtension)
, _maxSize(maxSize)
{
}
Expand All @@ -68,7 +70,7 @@ struct MaskCache
item = &_cache.back();
const IndexT viewId = _mp.getViewId(camId);
auto * const mask = item->mask.get();
const bool loaded = tryLoadMask(mask, _masksFolders, viewId, _mp.getImagePath(camId));
const bool loaded = tryLoadMask(mask, _masksFolders, viewId, _mp.getImagePath(camId), _maskExtension);
if (loaded)
{
if (_undistortMasks)
Expand Down Expand Up @@ -147,6 +149,7 @@ struct MaskCache
mvsUtils::MultiViewParams _mp;
std::vector<std::string> _masksFolders;
bool _undistortMasks;
std::string _maskExtension;
int _maxSize;
std::vector<Item> _cache;
};
Expand Down Expand Up @@ -347,6 +350,7 @@ void meshMasking(
const mvsUtils::MultiViewParams & mp,
mesh::Mesh & inputMesh,
const std::vector<std::string> & masksFolders,
const std::string & maskExtension,
const std::string & outputMeshPath,
const int threshold,
const bool invert,
Expand All @@ -355,7 +359,7 @@ void meshMasking(
const bool usePointsVisibilities
)
{
MaskCache maskCache(mp, masksFolders, undistortMasks);
MaskCache maskCache(mp, masksFolders, undistortMasks, maskExtension);

// compute visibility for every vertex
// also update inputMesh.pointsVisibilities according to the masks
Expand Down Expand Up @@ -513,6 +517,7 @@ int main(int argc, char **argv)
bool smoothBoundary = false;
bool undistortMasks = false;
bool usePointsVisibilities = false;
std::string maskExtension = "png";

po::options_description requiredParams("Required parameters");
requiredParams.add_options()
Expand All @@ -539,6 +544,8 @@ int main(int argc, char **argv)
"Undistort the masks with the same parameters as the matching image. Use it if the masks are drawn on the original images.")
("usePointsVisibilities", po::value<bool>(&usePointsVisibilities)->default_value(usePointsVisibilities),
"Use the points visibilities from the meshing to filter triangles. Example: when they are occluded, back-face, etc.")
("maskExtension", po::value<std::string>(&maskExtension)->default_value(maskExtension),
"File extension for the masks to use.")
;

CmdLine cmdline("AliceVision meshMasking");
Expand Down Expand Up @@ -613,7 +620,7 @@ int main(int argc, char **argv)
}

ALICEVISION_LOG_INFO("Mask mesh");
meshMasking(mp, inputMesh, masksFolders, outputMeshPath, threshold, invert, smoothBoundary, undistortMasks, usePointsVisibilities);
meshMasking(mp, inputMesh, masksFolders, maskExtension, outputMeshPath, threshold, invert, smoothBoundary, undistortMasks, usePointsVisibilities);
ALICEVISION_LOG_INFO("Task done in (s): " + std::to_string(timer.elapsed()));
return EXIT_SUCCESS;
}
10 changes: 7 additions & 3 deletions src/software/pipeline/main_prepareDenseScene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
// These constants define the current software version.
// They must be updated when the command line is changed.
#define ALICEVISION_SOFTWARE_VERSION_MAJOR 2
#define ALICEVISION_SOFTWARE_VERSION_MINOR 0
#define ALICEVISION_SOFTWARE_VERSION_MINOR 1

using namespace aliceVision;
using namespace aliceVision::camera;
Expand Down Expand Up @@ -79,6 +79,7 @@ void process(const std::string &dstColorImage, const IntrinsicBase* cam, const o
bool prepareDenseScene(const SfMData& sfmData,
const std::vector<std::string>& imagesFolders,
const std::vector<std::string>& masksFolders,
const std::string& maskExtension,
int beginIndex,
int endIndex,
const std::string& outFolder,
Expand Down Expand Up @@ -246,7 +247,7 @@ bool prepareDenseScene(const SfMData& sfmData,
}

image::Image<unsigned char> mask;
if(tryLoadMask(&mask, masksFolders, viewId, srcImage))
if(tryLoadMask(&mask, masksFolders, viewId, srcImage, maskExtension))
{
process<Image<RGBAfColor>>(dstColorImage, cam, metadata, srcImage, evCorrection, exposureCompensation, [&mask] (Image<RGBAfColor> & image)
{
Expand Down Expand Up @@ -286,6 +287,7 @@ int aliceVision_main(int argc, char *argv[])
std::string outImageFileTypeName = image::EImageFileType_enumToString(image::EImageFileType::EXR);
std::vector<std::string> imagesFolders;
std::vector<std::string> masksFolders;
std::string maskExtension = "png";
int rangeStart = -1;
int rangeSize = 1;
bool saveMetadata = true;
Expand All @@ -307,6 +309,8 @@ int aliceVision_main(int argc, char *argv[])
("masksFolders", po::value<std::vector<std::string>>(&masksFolders)->multitoken(),
"Use masks from specific folder(s).\n"
"Filename should be the same or the image uid.")
("maskExtension", po::value<std::string>(&maskExtension)->default_value(maskExtension),
"File extension of the masks to use.")
("outputFileType", po::value<std::string>(&outImageFileTypeName)->default_value(outImageFileTypeName),
image::EImageFileType_informations().c_str())
("saveMetadata", po::value<bool>(&saveMetadata)->default_value(saveMetadata),
Expand Down Expand Up @@ -371,7 +375,7 @@ int aliceVision_main(int argc, char *argv[])
}

// export
if(prepareDenseScene(sfmData, imagesFolders, masksFolders, rangeStart, rangeEnd,
if(prepareDenseScene(sfmData, imagesFolders, masksFolders, maskExtension, rangeStart, rangeEnd,
outFolder, outputFileType, saveMetadata, saveMatricesTxtFiles, evCorrection))
return EXIT_SUCCESS;

Expand Down

0 comments on commit c5caf62

Please sign in to comment.