diff --git a/src/seam-carving.cpp b/src/seam-carving.cpp index 8d8ace2..cd60c6a 100644 --- a/src/seam-carving.cpp +++ b/src/seam-carving.cpp @@ -18,10 +18,8 @@ bool silent = false; bool test_energy = false; bool until_mask_removal = false; int max_step = 1; +std::string function = "grad"; -// Get index for any table indexed by [width*(i : height) + (j : width)], but a -// : dim_long, b : dim_large -#define im_index(a, b) (vertical ? (width * a + b) : (width * b + a)) void export_image(const char *filename, const void *data, int width, int height, int nbChannels) { @@ -35,7 +33,6 @@ void export_image(const char *filename, const void *data, int width, int height, } } -std::string function = "grad"; #define compute_energy_for_pixel( \ source, width, height, i, j, \ @@ -136,10 +133,14 @@ std::string function = "grad"; << std::endl; \ exit(1); \ }; + + + // Le alpha n'est pas pris en compte dans l'énergie // Here, we use this /ugly/ macro to avoid defining a function that would be way // slower... + /** e_1 energy*/ std::vector energy_e1(std::vector source, int width, int height, int nbChannels) { @@ -179,8 +180,8 @@ std::vector optimal_seam(std::vector energy, int width, int height, int lower_bound = std::max(j - max_step, 0); int upper_bound = std::min(j + max_step, dim_large - 1); - for (auto k = lower_bound; k <= upper_bound; - k++) { // Compute energy based on predecessors + // Compute energy based on predecessors + for (auto k = lower_bound; k <= upper_bound; k++) { if (dyn_energy[dim_large * (i - 1) + k] < dyn_energy[dim_large * i + j]) { dyn_energy[dim_large * i + j] = dyn_energy[dim_large * (i - 1) + k]; @@ -196,7 +197,7 @@ std::vector optimal_seam(std::vector energy, int width, int height, T min_val = limits::max_energy(); for (auto j = 0; j < dim_large; j++) { - if (min_val > dyn_energy[dim_large * (dim_long - 1) + j]) { + if (dyn_energy[dim_large * (dim_long - 1) + j] < min_val) { min_idx = j; min_val = dyn_energy[dim_large * (dim_long - 1) + j]; } @@ -325,7 +326,7 @@ void recompute_energy_along_seam( (((0 < j0 + j_offset) && (j0 + j_offset < dim_long)))) { compute_energy_for_pixel(carved_img, newWidth, newHeight, x, y, nbChannels, nbColorChannels, - output_energy[width * y + x].first); + output_energy[width * y + x].second); } } } @@ -357,30 +358,6 @@ std::vector carving_step(const std::vector source_img, return opt_seam; } -std::vector> mask_energy(std::vector energy, - int width, int height, - unsigned char *mask) { - std::vector> output(width * height); - - for (auto i = 0; i < width * height; i++) { - output[i] = {mask[i], energy[i]}; - } - - return output; -} - -bool does_seam_remove_mask(unsigned char *mask, int width, int height, - int nbChannels, std::vector 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; -} auto seam_carving(unsigned char *source, int width, int height, int nbChannels, int nbSeams, bool vertical, unsigned char *mask = nullptr) { @@ -469,7 +446,7 @@ auto seam_carving(unsigned char *source, int width, int height, int nbChannels, nbChannels, nbColorChannels, vertical); if (until_mask_removal && - !does_seam_remove_mask(mask, width, height, nbChannels, opt_seam, + !does_seam_remove_mask(masked_energy, width, height, nbChannels, opt_seam, vertical)) break; @@ -511,9 +488,7 @@ auto seam_carving(unsigned char *source, int width, int height, int nbChannels, std::cout << std::endl; // Add newline after ProgressBar if (test_energy) { - return std::make_tuple(test_energy_output, width, height, nbChannels); - } else { return std::make_tuple(source_img, curWidth, curHeight, nbChannels); } @@ -583,8 +558,8 @@ int main(int argc, char **argv) { mask[i] = positive ? 2 : (negative ? 0 : 1); } - //* From now on, mask has the same dimensions as source and one single - // channel + //* "mask" has the same dimensions as source and one single channel + //* The values are: //* . (2) we want to keep the pixel //* . (1) nothing in particular diff --git a/src/utils.cpp b/src/utils.cpp index 64ac8c8..357b4d5 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -1,17 +1,43 @@ +#include +#include +#include +#include + #define STB_IMAGE_IMPLEMENTATION #include #define STB_IMAGE_WRITE_IMPLEMENTATION #include -#include -#include -#include +#include "utils.hpp" bool nearly_equal(float a, float b) { return std::nextafter(a, std::numeric_limits::lowest()) <= b && std::nextafter(a, std::numeric_limits::max()) >= b; } +bool does_seam_remove_mask(std::vector> energy, int width, int height, int nbChannels, + std::vector 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 (std::get<0>(energy[im_index(i, opt_seam[i])]) == 0) return true; + } + return false; +} + +std::vector> mask_energy(std::vector energy, + int width, int height, unsigned char* mask) { + std::vector> output(width*height); + + for (auto i=0; i < width*height; i++) { + output[i] = {mask[i], energy[i]}; + } + + return output; +} + std::pair operator+(std::pair& p1, std::pair& p2) { return { // If one of the two pixels is "protected" (ie 2), we want to prevent this line removing @@ -23,4 +49,15 @@ std::pair operator+(std::pair& p1, std::pair void operator+=(std::pair& p1, std::pair& p2) { p1 = p1+p2; +} + +std::string str_of_e(std::pair energy) { + std::stringstream ss; + ss << "(" << energy.first << ", " << energy.second << ")"; + return ss.str(); +} +std::string str_of_e(float energy) { + std::stringstream ss; + ss << "(" << energy << ")"; + return ss.str(); } \ No newline at end of file diff --git a/src/utils.hpp b/src/utils.hpp index 1d53aa4..04be50a 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -1,5 +1,8 @@ #include +// Get index for any table indexed by [width*(i : height) + (j : width)], but a +// : dim_long, b : dim_large +#define im_index(a, b) (vertical ? (width * a + b) : (width * b + a)) bool nearly_equal(float a, float b); @@ -7,6 +10,18 @@ std::pair operator+(std::pair& p1, std::pair void operator+=(std::pair& p1, std::pair& p2); +bool does_seam_remove_mask(std::vector> energy, int width, int height, int nbChannels, + std::vector opt_seam, bool vertical); + +std::vector> mask_energy(std::vector energy, + int width, int height, unsigned char* mask); + + +// Unfortunately, std::cout << (std::pair<>) does not work and can't be rewritten +std::string str_of_e(std::pair energy); +std::string str_of_e(float energy); + + namespace limits { struct max_energy { template operator T() {