improvements
parent
91ec4b0a5c
commit
803dd10d2e
|
@ -50,4 +50,6 @@ std::tuple<const std::vector<float>&, const std::vector<float>&, const std::vect
|
|||
|
||||
std::array<blt::gp::population_t*, 3> get_populations();
|
||||
|
||||
void set_use_gamma_correction(bool use);
|
||||
|
||||
#endif //GP_SYSTEM_H
|
||||
|
|
2
lib/blt
2
lib/blt
|
@ -1 +1 @@
|
|||
Subproject commit 729a16ab574e31bf1b44446a777e4ee834518c6e
|
||||
Subproject commit d4de35365d2df371b8b61c895ec0f6ae66d46fd8
|
|
@ -1 +1 @@
|
|||
Subproject commit 2e09696a673eeae099bc87024e6f32e6c5815fa3
|
||||
Subproject commit b2b584be519b64b59e6a661322b762d7747b5f96
|
|
@ -38,11 +38,16 @@ float filter_nan(const float f, const float failure = 0.0f)
|
|||
return f;
|
||||
}
|
||||
|
||||
bool use_gamma_correction = false;
|
||||
|
||||
std::array<gp_program*, 3> programs;
|
||||
prog_config_t config{};
|
||||
|
||||
std::vector<std::array<image_ipixel_t, IMAGE_DIMENSIONS * IMAGE_DIMENSIONS * 3>> images;
|
||||
auto reference_image = image_storage_t::from_file("../silly.png");
|
||||
std::vector<std::array<image_ipixel_t, IMAGE_DIMENSIONS * IMAGE_DIMENSIONS>> images_red;
|
||||
std::vector<std::array<image_ipixel_t, IMAGE_DIMENSIONS * IMAGE_DIMENSIONS>> images_green;
|
||||
std::vector<std::array<image_ipixel_t, IMAGE_DIMENSIONS * IMAGE_DIMENSIONS>> images_blue;
|
||||
std::array<image_storage_t, 3> reference_image;
|
||||
|
||||
std::vector<float> average_fitness;
|
||||
std::vector<float> best_fitness;
|
||||
|
@ -59,23 +64,44 @@ void fitness_func(const tree_t& tree, fitness_t& fitness, const blt::size_t inde
|
|||
{
|
||||
for (blt::size_t y = 0; y < IMAGE_DIMENSIONS; ++y)
|
||||
{
|
||||
images[index][(x * IMAGE_DIMENSIONS + y) * 3 + Channel] = data.get(x, y);
|
||||
switch (Channel)
|
||||
{
|
||||
case 0:
|
||||
images_red[index][(y * IMAGE_DIMENSIONS + x)] = data.get(x, y);
|
||||
break;
|
||||
case 1:
|
||||
images_green[index][(y * IMAGE_DIMENSIONS + x)] = data.get(x, y);
|
||||
break;
|
||||
case 2:
|
||||
images_blue[index][(y * IMAGE_DIMENSIONS + x)] = data.get(x, y);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// images[index][(y * IMAGE_DIMENSIONS + x) * 3 + Channel] = data.get(x, y);
|
||||
|
||||
auto our = static_cast<double>(data.get(x, y)) / static_cast<double>(std::numeric_limits<blt::u32>::max());
|
||||
const auto our = static_cast<double>(data.get(x, y)) / static_cast<double>(std::numeric_limits<blt::u32>::max());
|
||||
|
||||
auto theirs = reference_image[Channel].get(x, y);
|
||||
const auto theirs = reference_image[Channel].get(x, y);
|
||||
|
||||
auto gamma_ours = std::pow(our, 1.0f / 2.2f);
|
||||
auto gamma_theirs = std::pow(theirs, 1.0f / 2.2f);
|
||||
const auto gamma_ours = std::pow(our, 1.0f / 2.2f);
|
||||
// const auto gamma_theirs = std::pow(theirs, 1.0f / 2.2f);
|
||||
|
||||
const auto diff = gamma_ours - gamma_theirs;
|
||||
fitness.raw_fitness += static_cast<float>((diff * diff));
|
||||
if (use_gamma_correction)
|
||||
{
|
||||
const auto diff = gamma_ours - theirs;
|
||||
fitness.raw_fitness += static_cast<float>((diff * diff));
|
||||
} else
|
||||
{
|
||||
const auto diff = our - theirs;
|
||||
fitness.raw_fitness += static_cast<float>((diff * diff));
|
||||
}
|
||||
}
|
||||
}
|
||||
// fitness.raw_fitness /= static_cast<float>(IMAGE_SIZE_CHANNELS);
|
||||
fitness.raw_fitness = static_cast<float>(std::sqrt(fitness.raw_fitness));
|
||||
fitness.standardized_fitness = fitness.raw_fitness;
|
||||
fitness.adjusted_fitness = -fitness.standardized_fitness;
|
||||
fitness.set_normal(static_cast<float>(std::sqrt(fitness.raw_fitness)));
|
||||
// fitness.raw_fitness = static_cast<float>(std::sqrt(fitness.raw_fitness));
|
||||
// fitness.standardized_fitness = fitness.raw_fitness;
|
||||
// fitness.adjusted_fitness = -fitness.standardized_fitness;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -313,14 +339,16 @@ void setup_operations(gp_program* program)
|
|||
operator_builder builder{};
|
||||
builder.build(op_image_ephemeral, make_add<image_t>(), make_sub<image_t>(), make_mul<image_t>(), make_div<image_t>(), op_image_x, op_image_y,
|
||||
op_image_sin, op_image_gt, op_image_lt, op_image_cos, op_image_log, op_image_exp, op_image_or, op_image_and, op_image_xor,
|
||||
op_image_cos_off, op_image_sin_off, op_image_perlin, op_image_noise, op_image_random, op_image_2d_perlin_eph, op_image_not, op_image_grad,
|
||||
op_image_2d_perlin_oct);
|
||||
op_image_cos_off, op_image_sin_off, op_image_perlin, op_image_noise, op_image_random, op_image_2d_perlin_eph, op_image_not,
|
||||
op_image_grad, op_image_2d_perlin_oct);
|
||||
// builder.build(op_image_grad, op_image_x, op_image_y);
|
||||
program->set_operations(builder.grab());
|
||||
}
|
||||
|
||||
void setup_gp_system(const blt::size_t population_size)
|
||||
{
|
||||
reference_image = image_storage_t::from_file("../silly.png");
|
||||
|
||||
config.set_pop_size(population_size);
|
||||
config.set_elite_count(2);
|
||||
config.set_thread_count(0);
|
||||
|
@ -340,6 +368,9 @@ void setup_gp_system(const blt::size_t population_size)
|
|||
setup_operations<struct p3>(programs[2]);
|
||||
|
||||
images.resize(population_size);
|
||||
images_red.resize(population_size);
|
||||
images_green.resize(population_size);
|
||||
images_blue.resize(population_size);
|
||||
|
||||
static auto sel = select_tournament_t{};
|
||||
|
||||
|
@ -397,6 +428,13 @@ bool should_terminate()
|
|||
|
||||
std::array<image_ipixel_t, IMAGE_DIMENSIONS * IMAGE_DIMENSIONS * 3>& get_image(const blt::size_t index)
|
||||
{
|
||||
for (const auto& [i, image_red, image_green, image_blue] : blt::zip(images_red[index], images_green[index],
|
||||
images_blue[index]).enumerate().flatten())
|
||||
{
|
||||
images[index][i * 3] = image_red;
|
||||
images[index][i * 3 + 1] = image_green;
|
||||
images[index][i * 3 + 2] = image_blue;
|
||||
}
|
||||
return images[index];
|
||||
}
|
||||
|
||||
|
@ -418,6 +456,9 @@ std::array<image_pixel_t, IMAGE_DIMENSIONS * IMAGE_DIMENSIONS * 3> to_gl_image(c
|
|||
{
|
||||
for (blt::size_t y = 0; y < IMAGE_DIMENSIONS; ++y)
|
||||
{
|
||||
// image_data[(x * IMAGE_DIMENSIONS + y) * 3 + 0] = std::pow(image[0].get(x, y), 1.0f / 2.2f);
|
||||
// image_data[(x * IMAGE_DIMENSIONS + y) * 3 + 1] = std::pow(image[1].get(x, y), 1.0f / 2.2f);
|
||||
// image_data[(x * IMAGE_DIMENSIONS + y) * 3 + 2] = std::pow(image[2].get(x, y), 1.0f / 2.2f);
|
||||
image_data[(x * IMAGE_DIMENSIONS + y) * 3 + 0] = image[0].get(x, y);
|
||||
image_data[(x * IMAGE_DIMENSIONS + y) * 3 + 1] = image[1].get(x, y);
|
||||
image_data[(x * IMAGE_DIMENSIONS + y) * 3 + 2] = image[2].get(x, y);
|
||||
|
@ -435,6 +476,12 @@ void set_population_size(const blt::u32 size)
|
|||
{
|
||||
if (size > images.size())
|
||||
images.resize(size);
|
||||
if (size > images_red.size())
|
||||
images_red.resize(size);
|
||||
if (size > images_green.size())
|
||||
images_green.resize(size);
|
||||
if (size > images_blue.size())
|
||||
images_blue.resize(size);
|
||||
config.set_pop_size(size);
|
||||
for (const auto program : programs)
|
||||
program->set_config(config);
|
||||
|
@ -467,3 +514,6 @@ std::array<population_t*, 3> get_populations()
|
|||
{
|
||||
return {&programs[0]->get_current_pop(), &programs[1]->get_current_pop(), &programs[2]->get_current_pop()};
|
||||
}
|
||||
|
||||
void set_use_gamma_correction(bool use)
|
||||
{use_gamma_correction = true;}
|
||||
|
|
|
@ -21,13 +21,27 @@
|
|||
#include <blt/iterator/zip.h>
|
||||
#include <blt/math/vectors.h>
|
||||
|
||||
inline float srgb_to_linear(const float v) noexcept
|
||||
{
|
||||
return (v <= 0.04045f) ? (v / 12.92f)
|
||||
: std::pow((v + 0.055f) / 1.055f, 2.4f);
|
||||
}
|
||||
|
||||
|
||||
std::array<image_storage_t, 3> image_storage_t::from_file(const std::string& path)
|
||||
{
|
||||
stbi_set_flip_vertically_on_load(true);
|
||||
int x, y, channels;
|
||||
auto* data = stbi_loadf(path.c_str(), &x, &y, &channels, 4);
|
||||
auto* data = stbi_load(path.c_str(), &x, &y, &channels, 4);
|
||||
|
||||
const auto resized = stbir_resize_float_linear(data, x, y, 0, nullptr, IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, 0, STBIR_RGBA);
|
||||
unsigned char* resized = nullptr;
|
||||
|
||||
if (x == IMAGE_DIMENSIONS && y == IMAGE_DIMENSIONS)
|
||||
{
|
||||
resized = data;
|
||||
data = nullptr;
|
||||
} else
|
||||
resized = stbir_resize_uint8_srgb(data, x, y, 0, nullptr, IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, 0, STBIR_RGBA);
|
||||
|
||||
image_storage_t storage_r{};
|
||||
image_storage_t storage_g{};
|
||||
|
@ -37,9 +51,9 @@ std::array<image_storage_t, 3> image_storage_t::from_file(const std::string& pat
|
|||
{
|
||||
for (blt::size_t j = 0; j < IMAGE_DIMENSIONS; ++j)
|
||||
{
|
||||
storage_r.get(i, j) = resized[(j * IMAGE_DIMENSIONS + x) * 4];
|
||||
storage_g.get(i, j) = resized[(j * IMAGE_DIMENSIONS + x) * 4 + 1];
|
||||
storage_b.get(i, j) = resized[(j * IMAGE_DIMENSIONS + x) * 4 + 2];
|
||||
storage_r.get(i, j) = static_cast<float>(resized[(i * IMAGE_DIMENSIONS + j) * 4]) / 255.0f;
|
||||
storage_g.get(i, j) = static_cast<float>(resized[(i * IMAGE_DIMENSIONS + j) * 4 + 1]) / 255.0f;
|
||||
storage_b.get(i, j) = static_cast<float>(resized[(i * IMAGE_DIMENSIONS + j) * 4 + 2]) / 255.0f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,7 +63,9 @@ std::array<image_storage_t, 3> image_storage_t::from_file(const std::string& pat
|
|||
}
|
||||
|
||||
std::array<image_storage_t, 3> image_istorage_t::from_file(const std::string& path)
|
||||
{}
|
||||
{
|
||||
BLT_ERROR("NOT IMPLEMENTED!");
|
||||
}
|
||||
|
||||
void image_istorage_t::normalize()
|
||||
{}
|
||||
|
|
45
src/main.cpp
45
src/main.cpp
|
@ -30,6 +30,9 @@ void update_population_size(const blt::u32 new_size)
|
|||
for (blt::size_t i = population_size; i < new_size; i++)
|
||||
{
|
||||
auto texture = new texture_gl2D(IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, GL_RGBA8);
|
||||
texture->bind();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl_images.push_back(texture);
|
||||
resources.set(std::to_string(i), texture);
|
||||
}
|
||||
|
@ -41,7 +44,6 @@ std::thread run_gp()
|
|||
{
|
||||
return std::thread{
|
||||
[]() {
|
||||
setup_gp_system(population_size);
|
||||
while (!should_exit)
|
||||
{
|
||||
if (run_generation)
|
||||
|
@ -64,10 +66,16 @@ void init(const blt::gfx::window_data&)
|
|||
for (blt::size_t i = 0; i < population_size; i++)
|
||||
{
|
||||
auto texture = new texture_gl2D(IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, GL_RGBA8);
|
||||
texture->bind();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
gl_images.push_back(texture);
|
||||
resources.set(std::to_string(i), texture);
|
||||
}
|
||||
const auto texture = new texture_gl2D(IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, GL_RGBA8);
|
||||
texture->bind();
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
texture->upload(to_gl_image(get_reference_image()).data(), IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, GL_RGB, GL_FLOAT);
|
||||
resources.set("reference", texture);
|
||||
global_matrices.create_internals();
|
||||
|
@ -98,6 +106,7 @@ void update(const blt::gfx::window_data& data)
|
|||
|
||||
static blt::i32 image_to_enlarge = -1;
|
||||
bool clicked_on_image = false;
|
||||
static bool use_gramma_correction = false;
|
||||
static bool show_best = false;
|
||||
|
||||
// Create the tab bar
|
||||
|
@ -128,6 +137,8 @@ void update(const blt::gfx::window_data& data)
|
|||
run_generation = true;
|
||||
ImGui::InputInt("Min Time Between Runs (ms)", &min_between_runs);
|
||||
ImGui::Checkbox("Show Best", &show_best);
|
||||
if (ImGui::Checkbox("Use Gamma Correction?", &use_gramma_correction))
|
||||
set_use_gamma_correction(use_gramma_correction);
|
||||
}
|
||||
ImGui::EndChild();
|
||||
|
||||
|
@ -218,9 +229,15 @@ void update(const blt::gfx::window_data& data)
|
|||
|
||||
if (ImGui::BeginTabItem("Reference"))
|
||||
{
|
||||
blt::f32 w = data.width;
|
||||
auto h = data.height - top_bar_height - 10;
|
||||
renderer_2d.drawRectangle({static_cast<blt::f32>(w / 2), h / 2, w, h}, "reference");
|
||||
auto w = static_cast<float>(data.width);
|
||||
auto h = static_cast<float>(data.height) - top_bar_height - 10;
|
||||
|
||||
renderer_2d.drawRectangle({
|
||||
w / 2,
|
||||
h / 2,
|
||||
std::min(w, static_cast<float>(IMAGE_DIMENSIONS)),
|
||||
std::min(h, static_cast<float>(IMAGE_DIMENSIONS))
|
||||
}, "reference");
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
|
@ -271,7 +288,8 @@ void update(const blt::gfx::window_data& data)
|
|||
gl_images[i]->upload(get_image(i).data(), IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, GL_RGB, GL_UNSIGNED_INT);
|
||||
}
|
||||
|
||||
if ((blt::gfx::isMousePressed(0) && blt::gfx::mousePressedLastFrame() && !clicked_on_image) || (blt::gfx::isKeyPressed(GLFW_KEY_ESCAPE) && blt::gfx::keyPressedLastFrame()))
|
||||
if ((blt::gfx::isMousePressed(0) && blt::gfx::mousePressedLastFrame() && !clicked_on_image) || (blt::gfx::isKeyPressed(GLFW_KEY_ESCAPE) &&
|
||||
blt::gfx::keyPressedLastFrame()))
|
||||
image_to_enlarge = -1;
|
||||
|
||||
if (show_best)
|
||||
|
@ -281,20 +299,20 @@ void update(const blt::gfx::window_data& data)
|
|||
{
|
||||
const auto width = std::min(static_cast<float>(data.width) - side_bar_width, static_cast<float>(256) * 3) / 3;
|
||||
const auto height = std::min(static_cast<float>(data.height) - top_bar_height, static_cast<float>(256) * 3) / 3;
|
||||
renderer_2d.drawRectangle(blt::gfx::rectangle2d_t{blt::gfx::anchor_t::BOTTOM_LEFT,
|
||||
side_bar_width + 256 + i * width, 64, width, height
|
||||
}, std::to_string(best_image), 1);
|
||||
renderer_2d.drawRectangle(blt::gfx::rectangle2d_t{blt::gfx::anchor_t::BOTTOM_LEFT, side_bar_width + 256 + i * width, 64, width, height},
|
||||
std::to_string(best_image), 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (image_to_enlarge != -1)
|
||||
{
|
||||
if (blt::gfx::isKeyPressed(GLFW_KEY_R) && blt::gfx::keyPressedLastFrame())
|
||||
{
|
||||
|
||||
}
|
||||
renderer_2d.drawRectangle(blt::gfx::rectangle2d_t{blt::gfx::anchor_t::BOTTOM_LEFT,
|
||||
side_bar_width + 256, 64, std::min(static_cast<float>(data.width) - side_bar_width, static_cast<float>(256) * 3),
|
||||
{}
|
||||
renderer_2d.drawRectangle(blt::gfx::rectangle2d_t{
|
||||
blt::gfx::anchor_t::BOTTOM_LEFT,
|
||||
side_bar_width + 256,
|
||||
64,
|
||||
std::min(static_cast<float>(data.width) - side_bar_width, static_cast<float>(256) * 3),
|
||||
std::min(static_cast<float>(data.height) - top_bar_height, static_cast<float>(256) * 3)
|
||||
}, std::to_string(image_to_enlarge), 1);
|
||||
}
|
||||
|
@ -313,6 +331,7 @@ void destroy(const blt::gfx::window_data&)
|
|||
|
||||
int main()
|
||||
{
|
||||
setup_gp_system(population_size);
|
||||
auto run_gp_thread = run_gp();
|
||||
blt::gfx::init(blt::gfx::window_data{"Image GP", init, update, destroy}.setSyncInterval(1));
|
||||
should_exit = true;
|
||||
|
|
Loading…
Reference in New Issue