improvements

main
Brett 2025-07-16 02:55:34 -04:00
parent 91ec4b0a5c
commit 803dd10d2e
10 changed files with 122 additions and 35 deletions

BIN
grad.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
grad2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
grad3.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
grad3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@ -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

@ -1 +1 @@
Subproject commit 729a16ab574e31bf1b44446a777e4ee834518c6e
Subproject commit d4de35365d2df371b8b61c895ec0f6ae66d46fd8

@ -1 +1 @@
Subproject commit 2e09696a673eeae099bc87024e6f32e6c5815fa3
Subproject commit b2b584be519b64b59e6a661322b762d7747b5f96

View File

@ -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;}

View File

@ -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()
{}

View File

@ -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;