Merge branch 'mask'
This commit is contained in:
commit
14cccecfa1
@ -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,7 @@ 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, \
|
||||
@ -121,6 +119,7 @@ std::string function = "grad";
|
||||
// Here, we use this /ugly/ macro to avoid defining a function that would be way
|
||||
// slower...
|
||||
|
||||
|
||||
/** e_1 energy*/
|
||||
std::vector<float> energy_e1(std::vector<unsigned char> source, int width,
|
||||
int height, int nbChannels) {
|
||||
@ -160,8 +159,8 @@ std::vector<int> optimal_seam(std::vector<T> 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];
|
||||
@ -177,7 +176,7 @@ std::vector<int> optimal_seam(std::vector<T> 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];
|
||||
}
|
||||
@ -306,7 +305,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -338,30 +337,6 @@ std::vector<int> carving_step(const std::vector<unsigned char> source_img,
|
||||
return opt_seam;
|
||||
}
|
||||
|
||||
std::vector<std::pair<int, float>> mask_energy(std::vector<float> energy,
|
||||
int width, int height,
|
||||
unsigned char *mask) {
|
||||
std::vector<std::pair<int, float>> 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<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;
|
||||
}
|
||||
|
||||
auto seam_carving(unsigned char *source, int width, int height, int nbChannels,
|
||||
int nbSeams, bool vertical, unsigned char *mask = nullptr) {
|
||||
@ -492,9 +467,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);
|
||||
}
|
||||
@ -564,8 +537,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
|
||||
|
@ -1,17 +1,42 @@
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <random>
|
||||
#include <vector>
|
||||
#include "utils.hpp"
|
||||
|
||||
bool nearly_equal(float a, float b) {
|
||||
return std::nextafter(a, std::numeric_limits<float>::lowest()) <= b &&
|
||||
std::nextafter(a, std::numeric_limits<float>::max()) >= b;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::vector<std::pair<int, float>> mask_energy(std::vector<float> energy,
|
||||
int width, int height, unsigned char* mask) {
|
||||
std::vector<std::pair<int, float>> output(width*height);
|
||||
|
||||
for (auto i=0; i < width*height; i++) {
|
||||
output[i] = {mask[i], energy[i]};
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
std::pair<int, float> operator+(std::pair<int, float>& p1, std::pair<int, float>& p2) {
|
||||
return {
|
||||
// If one of the two pixels is "protected" (ie 2), we want to prevent this line removing
|
||||
|
@ -1,5 +1,8 @@
|
||||
#include <random>
|
||||
|
||||
// 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,12 @@ std::pair<int, float> operator+(std::pair<int, float>& p1, std::pair<int, float>
|
||||
|
||||
void operator+=(std::pair<int, float>& p1, std::pair<int, float>& p2);
|
||||
|
||||
bool does_seam_remove_mask(unsigned char* mask, int width, int height, int nbChannels,
|
||||
std::vector<int> opt_seam, bool vertical);
|
||||
|
||||
std::vector<std::pair<int, float>> mask_energy(std::vector<float> energy,
|
||||
int width, int height, unsigned char* mask);
|
||||
|
||||
namespace limits {
|
||||
struct max_energy {
|
||||
template<class T> operator T() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user