Skip to content

Commit 11a2b6a

Browse files
authored
Merge pull request #1814 from alicevision/dev/maskProcessing
Mask processing app
2 parents fa44c99 + f50d936 commit 11a2b6a

File tree

2 files changed

+213
-0
lines changed

2 files changed

+213
-0
lines changed

src/software/utils/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ if(ALICEVISION_BUILD_SFM)
5353
${Boost_LIBRARIES}
5454
)
5555

56+
alicevision_add_software(aliceVision_maskProcessing
57+
SOURCE main_maskProcessing.cpp
58+
FOLDER ${FOLDER_SOFTWARE_UTILS}
59+
LINKS aliceVision_system
60+
aliceVision_cmdline
61+
aliceVision_image
62+
${Boost_LIBRARIES}
63+
)
64+
5665
if(ALICEVISION_HAVE_OPENCV)
5766
target_link_libraries(aliceVision_imageProcessing_exe PRIVATE ${OpenCV_LIBS})
5867
endif()
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
// This file is part of the AliceVision project.
2+
// Copyright (c) 2025 AliceVision contributors.
3+
// This Source Code Form is subject to the terms of the Mozilla Public License,
4+
// v. 2.0. If a copy of the MPL was not distributed with this file,
5+
// You can obtain one at https://mozilla.org/MPL/2.0/.
6+
7+
#include <aliceVision/cmdline/cmdline.hpp>
8+
#include <aliceVision/system/main.hpp>
9+
#include <aliceVision/image/io.hpp>
10+
11+
#include <boost/program_options.hpp>
12+
13+
#include <string>
14+
#include <sstream>
15+
#include <random>
16+
#include <filesystem>
17+
18+
// These constants define the current software version.
19+
// They must be updated when the command line is changed.
20+
#define ALICEVISION_SOFTWARE_VERSION_MAJOR 1
21+
#define ALICEVISION_SOFTWARE_VERSION_MINOR 0
22+
23+
using namespace aliceVision;
24+
25+
namespace po = boost::program_options;
26+
27+
28+
namespace {
29+
30+
/**
31+
* @brief operator method enum
32+
*/
33+
enum class EMaskOperator : unsigned char
34+
{
35+
OR = 0,
36+
AND,
37+
NOT
38+
};
39+
40+
/**
41+
* @brief Convert an EMaskOperator enum to its corresponding string
42+
* @param[in] maskOperator The given EMaskOperator enum
43+
* @return string
44+
*/
45+
std::string EMaskOperator_enumToString(EMaskOperator maskOperator)
46+
{
47+
switch (maskOperator)
48+
{
49+
case EMaskOperator::OR:
50+
return "or";
51+
case EMaskOperator::AND:
52+
return "and";
53+
case EMaskOperator::NOT:
54+
return "not";
55+
}
56+
throw std::out_of_range("Invalid EMaskOperator enum");
57+
}
58+
59+
/**
60+
* @brief Convert a string to its corresponding EMaskOperator enum
61+
* @param[in] MaskOperator The given string
62+
* @return EMaskOperator enum
63+
*/
64+
EMaskOperator EMaskOperator_stringToEnum(const std::string& maskOperator)
65+
{
66+
std::string op = maskOperator;
67+
std::transform(op.begin(), op.end(), op.begin(), ::tolower); // tolower
68+
69+
if (op == "or")
70+
return EMaskOperator::OR;
71+
if (op == "and")
72+
return EMaskOperator::AND;
73+
if (op == "not")
74+
return EMaskOperator::NOT;
75+
76+
77+
throw std::out_of_range("Invalid mask operator : " + maskOperator);
78+
}
79+
80+
inline std::istream& operator>>(std::istream& in, EMaskOperator& maskOperator)
81+
{
82+
std::string token(std::istreambuf_iterator<char>(in), {});
83+
maskOperator = EMaskOperator_stringToEnum(token);
84+
return in;
85+
}
86+
87+
inline std::ostream& operator<<(std::ostream& os, EMaskOperator e) { return os << EMaskOperator_enumToString(e); }
88+
89+
} // namespace
90+
91+
92+
int aliceVision_main(int argc, char** argv)
93+
{
94+
// command-line parameters
95+
std::vector<std::string> directoryNames;
96+
std::string outDirectory;
97+
EMaskOperator maskOperator = EMaskOperator::OR;
98+
99+
// clang-format off
100+
po::options_description requiredParams("Required parameters");
101+
requiredParams.add_options()
102+
("inputs,i", po::value<std::vector<std::string>>(&directoryNames)->multitoken(),
103+
"Path to directories to process.")
104+
("output,o", po::value<std::string>(&outDirectory)->required(),
105+
"Output directory.");
106+
107+
po::options_description optionalParams("Optional parameters");
108+
optionalParams.add_options()
109+
("operator", po::value<EMaskOperator>(&maskOperator)->default_value(maskOperator), "");
110+
// clang-format on
111+
112+
CmdLine cmdline("AliceVision sfmMerge");
113+
cmdline.add(requiredParams);
114+
cmdline.add(optionalParams);
115+
if (!cmdline.execute(argc, argv))
116+
{
117+
return EXIT_FAILURE;
118+
}
119+
120+
if (directoryNames.empty())
121+
{
122+
ALICEVISION_LOG_ERROR("At least one directory should be given.");
123+
return EXIT_FAILURE;
124+
}
125+
126+
std::string path = directoryNames[0];
127+
for (auto &p : std::filesystem::recursive_directory_iterator(path))
128+
{
129+
const std::filesystem::path refpath = p.path();
130+
if (p.path().extension() != ".exr")
131+
{
132+
continue;
133+
}
134+
135+
ALICEVISION_LOG_INFO("Processing " << refpath.string());
136+
137+
std::filesystem::path outputDirectoryPath(outDirectory);
138+
std::filesystem::path outputPath = outputDirectoryPath / refpath.filename();
139+
140+
141+
image::Image<unsigned char> img;
142+
aliceVision::image::readImage(refpath.string(), img, image::EImageColorSpace::NO_CONVERSION);
143+
144+
if (maskOperator == EMaskOperator::NOT)
145+
{
146+
for (int i = 0; i < img.height(); i++)
147+
{
148+
for (int j = 0; j < img.width(); j++)
149+
{
150+
img(i, j) = (img(i, j) > 0)?0:255;
151+
}
152+
}
153+
}
154+
else
155+
{
156+
for (int otherDirIndex = 1; otherDirIndex < directoryNames.size(); otherDirIndex++)
157+
{
158+
std::filesystem::path otherPath(directoryNames[otherDirIndex]);
159+
160+
std::filesystem::path otherMaskPath = otherPath / refpath.filename();
161+
if (!std::filesystem::exists(otherMaskPath))
162+
{
163+
continue;
164+
}
165+
166+
image::Image<unsigned char> otherImg;
167+
aliceVision::image::readImage(otherMaskPath.string(), otherImg, image::EImageColorSpace::NO_CONVERSION);
168+
169+
if (otherImg.width() != img.width())
170+
{
171+
continue;
172+
}
173+
174+
if (otherImg.height() != img.height())
175+
{
176+
continue;
177+
}
178+
179+
180+
for (int i = 0; i < img.height(); i++)
181+
{
182+
for (int j = 0; j < img.width(); j++)
183+
{
184+
if (maskOperator == EMaskOperator::AND)
185+
{
186+
img(i, j) = img(i, j) & otherImg(i, j);
187+
}
188+
else if (maskOperator == EMaskOperator::OR)
189+
{
190+
img(i, j) = img(i, j) | otherImg(i, j);
191+
}
192+
}
193+
}
194+
}
195+
}
196+
197+
aliceVision::image::ImageWriteOptions wopt;
198+
aliceVision::image::writeImage(outputPath.string(), img, wopt);
199+
}
200+
201+
202+
203+
return EXIT_SUCCESS;
204+
}

0 commit comments

Comments
 (0)