Add --until-mask-removal

Are all seams contributing to mask ?
This commit is contained in:
augustin64 2025-04-03 08:48:38 +02:00
parent a7d2c74a89
commit 7b07f66bfb

View File

@ -12,9 +12,12 @@
#include <SimpleProgressBar.hpp> #include <SimpleProgressBar.hpp>
#include <stb_image_write.h> #include <stb_image_write.h>
#define DEFAULT_SEAMS 1
// Global flags // Global flags
bool silent = false; bool silent = false;
bool test_energy = false; bool test_energy = false;
bool until_mask_removal = false;
int max_step = 1; int max_step = 1;
// Get index for any table indexed by [width*(i : height) + (j : width)], but a // Get index for any table indexed by [width*(i : height) + (j : width)], but a
@ -310,6 +313,18 @@ std::vector<std::pair<int, float>> mask_energy(std::vector<float> energy,
return output; return output;
} }
bool does_seam_remove_mask(unsigned char* mask, int width, int height, int nbChannels,
std::vector<int> opt_seam, bool vertical)
{
int dim_large = vertical ? width : height;
int dim_long = vertical ? height : width;
for (int i=0; i < dim_long; i++) {
if (mask[im_index(i, opt_seam[i])] == 0) return true;
}
return false;
}
void seam_carving(unsigned char *source, int width, int height, int nbChannels, void seam_carving(unsigned char *source, int width, int height, int nbChannels,
const char *out_filename, int nbSeams, bool vertical, unsigned char* mask=nullptr) { const char *out_filename, int nbSeams, bool vertical, unsigned char* mask=nullptr) {
int nbColorChannels = nbChannels > 3 ? 3 : nbChannels; int nbColorChannels = nbChannels > 3 ? 3 : nbChannels;
@ -384,16 +399,23 @@ void seam_carving(unsigned char *source, int width, int height, int nbChannels,
} }
} }
SimpleProgressBar::ProgressBar bar(nbSeams); SimpleProgressBar::ProgressBar bar(until_mask_removal ? dim_large : nbSeams);
bar.print(); bar.print();
for (auto seam_index = 0; seam_index < nbSeams; seam_index++) { auto seam_index = 0;
while (seam_index++ < nbSeams || until_mask_removal) {
std::vector<int> opt_seam; std::vector<int> opt_seam;
if (mask) { if (mask) {
opt_seam = carving_step( opt_seam = carving_step(
source_img, masked_energy, output_img, output_masked_energy, source_img, masked_energy, output_img, output_masked_energy,
curWidth, curHeight, nbChannels, nbColorChannels, vertical curWidth, curHeight, nbChannels, nbColorChannels, vertical
); );
if (
until_mask_removal &&
!does_seam_remove_mask(mask, width, height, nbChannels, opt_seam, vertical)
) break;
} else { } else {
opt_seam = carving_step( opt_seam = carving_step(
source_img, source_energy, output_img, output_energy, source_img, source_energy, output_img, output_energy,
@ -446,7 +468,7 @@ int main(int argc, char **argv) {
std::string maskImage; std::string maskImage;
std::string sourceImage; std::string sourceImage;
std::string outputImage = "output.png"; std::string outputImage = "output.png";
int nbSeams = 1; int nbSeams = DEFAULT_SEAMS;
bool vertical = false; bool vertical = false;
app.add_option("-s,--source", sourceImage, "Source image") app.add_option("-s,--source", sourceImage, "Source image")
@ -466,6 +488,8 @@ int main(int argc, char **argv) {
app.add_flag("--silent", silent, "No verbose messages"); app.add_flag("--silent", silent, "No verbose messages");
app.add_flag("--test-energy", test_energy, app.add_flag("--test-energy", test_energy,
"Don't resize image, just try the specified energy function"); "Don't resize image, just try the specified energy function");
app.add_flag("-u,--until-mask-removal", until_mask_removal,
"Carve the image until there are no more red pixels in the mask");
CLI11_PARSE(app, argc, argv); CLI11_PARSE(app, argc, argv);
// Image loading // Image loading
@ -505,6 +529,14 @@ int main(int argc, char **argv) {
//* . (1) nothing in particular //* . (1) nothing in particular
//* . (0) we want to remove the pixel //* . (0) we want to remove the pixel
} }
if (until_mask_removal && maskImage.empty()) {
std::cerr << "Flag --until-mask-removal but no mask provided." << std::endl;
until_mask_removal = false;
}
if (until_mask_removal && nbSeams != DEFAULT_SEAMS) {
std::cerr << "Flag --nb-seams specified but --until-mask-removal provided." << std::endl;
nbSeams = DEFAULT_SEAMS;
}
nbSeams = std::min(nbSeams, vertical ? width-1 : height-1); // We want to keep at least one row or column nbSeams = std::min(nbSeams, vertical ? width-1 : height-1); // We want to keep at least one row or column