Correct indices and near equality
This commit is contained in:
parent
1d28489c11
commit
7c2f9b36d7
@ -19,6 +19,11 @@ int min(int a, int b) {
|
|||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
void export_image(const char* filename, const void* data, int width, int height, int nbChannels) {
|
void export_image(const char* filename, const void* data, int width, int height, int nbChannels) {
|
||||||
if (!silent) std::cout << "Exporting to \"" << filename << "\".." << std::endl;
|
if (!silent) std::cout << "Exporting to \"" << filename << "\".." << std::endl;
|
||||||
int errcode = stbi_write_png(filename, width, height, nbChannels, data, nbChannels*width);
|
int errcode = stbi_write_png(filename, width, height, nbChannels, data, nbChannels*width);
|
||||||
@ -67,15 +72,15 @@ std::vector<int> optimal_vertical_seam(std::vector<float> energy, int width, int
|
|||||||
std::vector<float> dyn_energy(width*height);
|
std::vector<float> dyn_energy(width*height);
|
||||||
|
|
||||||
//* Find an end of the minimal connected vertical/horizontal seam
|
//* Find an end of the minimal connected vertical/horizontal seam
|
||||||
for (auto i=1; i < height; i++) {
|
for (auto i=0; i < width; i++) {
|
||||||
dyn_energy[width*i] = energy[width*i];
|
dyn_energy[i] = energy[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto j=1; j < width; j++) {
|
for (auto i=1; i < height; i++) {
|
||||||
for (auto i=0; i < height; i++) {
|
for (auto j=0; j < width; j++) {
|
||||||
float bot_center = (i > 0) ? dyn_energy[width*(i-1)+j] : __FLT_MAX__;
|
float bot_center = dyn_energy[width*(i-1) + j];
|
||||||
float bot_left = (i > 0 && j > 0) ? dyn_energy[width*(i-1)+(j-1)] : __FLT_MAX__;
|
float bot_left = (j > 0) ? dyn_energy[width*(i-1) + (j-1)] : __FLT_MAX__;
|
||||||
float bot_right = (i > 0 && j+1 < width) ? dyn_energy[width*(i-1)+(j+1)] : __FLT_MAX__;
|
float bot_right = (j+1 < width) ? dyn_energy[width*(i-1) + (j+1)] : __FLT_MAX__;
|
||||||
|
|
||||||
dyn_energy[width*i+j] = fmin(
|
dyn_energy[width*i+j] = fmin(
|
||||||
bot_center,
|
bot_center,
|
||||||
@ -83,7 +88,7 @@ std::vector<int> optimal_vertical_seam(std::vector<float> energy, int width, int
|
|||||||
bot_left,
|
bot_left,
|
||||||
bot_right
|
bot_right
|
||||||
)
|
)
|
||||||
) + energy[width*i+j];
|
) + energy[width*i + j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,9 +97,9 @@ std::vector<int> optimal_vertical_seam(std::vector<float> energy, int width, int
|
|||||||
int min_idx = -1;
|
int min_idx = -1;
|
||||||
float min_val = __FLT_MAX__;
|
float min_val = __FLT_MAX__;
|
||||||
for (auto j=0; j < width; j++) {
|
for (auto j=0; j < width; j++) {
|
||||||
if (min_val > dyn_energy[width*(height-1)+j]) {
|
if (min_val > dyn_energy[width*(height-1) + j]) {
|
||||||
min_idx = j;
|
min_idx = j;
|
||||||
min_val = dyn_energy[width*(height-1)+j];
|
min_val = dyn_energy[width*(height-1) + j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result[height-1] = min_idx;
|
result[height-1] = min_idx;
|
||||||
@ -102,22 +107,25 @@ std::vector<int> optimal_vertical_seam(std::vector<float> energy, int width, int
|
|||||||
//* Backtracking to find the path
|
//* Backtracking to find the path
|
||||||
for (auto i=height-1; i > 0; i--) {
|
for (auto i=height-1; i > 0; i--) {
|
||||||
// We want to find either (bot_l, bot_c, bot_r) with dyn_energy[.] = min_val - energy[cur]
|
// We want to find either (bot_l, bot_c, bot_r) with dyn_energy[.] = min_val - energy[cur]
|
||||||
float objective_energy = min_val - energy[i*width+min_idx]; //! With float, do we always have x + y - y = x ?
|
float objective_energy = min_val - energy[width*i + min_idx];
|
||||||
|
|
||||||
if (dyn_energy[(i-1)+height*min_idx] == objective_energy) {
|
//! With float, we don't always have x + y - y = x
|
||||||
// min_idx does not change
|
if (nearly_equal(dyn_energy[width*(i-1) + min_idx], objective_energy)) {
|
||||||
min_val = dyn_energy[(i-1)+height*min_idx];
|
// min_idx does not change
|
||||||
} else if (min_idx > 0 && dyn_energy[(i-1)+height*(min_idx-1)] == objective_energy) {
|
min_val = dyn_energy[(i-1)*width + min_idx];
|
||||||
min_val = dyn_energy[(i-1)+height*(min_idx - 1)];
|
} else if (min_idx > 0 && nearly_equal(dyn_energy[(i-1)*width + (min_idx-1)], objective_energy)) {
|
||||||
min_idx = min_idx - 1;
|
min_val = dyn_energy[(i-1)*width + (min_idx-1)];
|
||||||
} else if (min_idx+1 < width && dyn_energy[(i-1)+height*(min_idx+1)] == objective_energy) {
|
min_idx = min_idx - 1;
|
||||||
min_val = dyn_energy[(i-1)+height*(min_idx + 1)];
|
} else if (min_idx+1 < width && nearly_equal(dyn_energy[(i-1)*width + (min_idx+1)], objective_energy)) {
|
||||||
min_idx = min_idx + 1;
|
min_val = dyn_energy[(i-1)*width + (min_idx+1)];
|
||||||
} else {
|
min_idx = min_idx + 1;
|
||||||
std::cerr << "Unable to backtrack path !" << std::endl;
|
} else {
|
||||||
exit(1);
|
std::cerr << dyn_energy[(i-1)*width + min_idx] <<", "<< dyn_energy[(i-1)*width + (min_idx-1)]
|
||||||
}
|
<<", "<< dyn_energy[(i-1)*width + (min_idx+1)] <<" != "<< objective_energy << std::endl;
|
||||||
result[i-1] = min_idx;
|
std::cerr << "Unable to backtrack path !" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
result[i-1] = min_idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user