nyah
parent
c59298d4b5
commit
5352406cbf
|
@ -1,5 +1,5 @@
|
||||||
cmake_minimum_required(VERSION 3.25)
|
cmake_minimum_required(VERSION 3.25)
|
||||||
project(image-gp-6 VERSION 0.0.12)
|
project(image-gp-6 VERSION 0.0.13)
|
||||||
|
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Brett Terpstra
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMAGE_GP_6_CONFIG_H
|
||||||
|
#define IMAGE_GP_6_CONFIG_H
|
||||||
|
|
||||||
|
constexpr size_t log2(size_t n) // NOLINT
|
||||||
|
{
|
||||||
|
return ((n < 2) ? 1 : 1 + log2(n / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const blt::u64 SEED = std::random_device()();
|
||||||
|
static constexpr blt::size_t IMAGE_SIZE = 128;
|
||||||
|
static constexpr blt::size_t IMAGE_PADDING = 16;
|
||||||
|
static constexpr blt::size_t POP_SIZE = 64;
|
||||||
|
static constexpr blt::size_t CHANNELS = 3;
|
||||||
|
static constexpr blt::size_t DATA_SIZE = IMAGE_SIZE * IMAGE_SIZE;
|
||||||
|
static constexpr blt::size_t DATA_CHANNELS_SIZE = DATA_SIZE * CHANNELS;
|
||||||
|
static constexpr blt::size_t BOX_COUNT = static_cast<blt::size_t>(log2(IMAGE_SIZE / 2));
|
||||||
|
static constexpr float THRESHOLD = 0.3;
|
||||||
|
static constexpr auto load_image = "../029a_-_Survival_of_the_Idiots_349.jpg";
|
||||||
|
|
||||||
|
blt::gp::prog_config_t config = blt::gp::prog_config_t()
|
||||||
|
.set_initial_min_tree_size(4)
|
||||||
|
.set_initial_max_tree_size(8)
|
||||||
|
.set_elite_count(2)
|
||||||
|
.set_max_generations(50)
|
||||||
|
.set_mutation_chance(1.0)
|
||||||
|
.set_crossover_chance(1.0)
|
||||||
|
.set_reproduction_chance(0.5)
|
||||||
|
.set_pop_size(POP_SIZE)
|
||||||
|
.set_thread_count(16);
|
||||||
|
|
||||||
|
#endif //IMAGE_GP_6_CONFIG_H
|
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Brett Terpstra
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMAGE_GP_6_HELPER_H
|
||||||
|
#define IMAGE_GP_6_HELPER_H
|
||||||
|
|
||||||
|
template<typename SINGLE_FUNC>
|
||||||
|
constexpr static auto make_single(SINGLE_FUNC&& func)
|
||||||
|
{
|
||||||
|
return [func](const full_image_t& a) {
|
||||||
|
full_image_t img{};
|
||||||
|
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
|
||||||
|
img.rgb_data[i] = func(a.rgb_data[i]);
|
||||||
|
return img;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename DOUBLE_FUNC>
|
||||||
|
constexpr static auto make_double(DOUBLE_FUNC&& func)
|
||||||
|
{
|
||||||
|
return [func](const full_image_t& a, const full_image_t& b) {
|
||||||
|
full_image_t img{};
|
||||||
|
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
|
||||||
|
img.rgb_data[i] = func(a.rgb_data[i], b.rgb_data[i]);
|
||||||
|
return img;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //IMAGE_GP_6_HELPER_H
|
|
@ -0,0 +1,55 @@
|
||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Brett Terpstra
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMAGE_GP_6_IMAGES_H
|
||||||
|
#define IMAGE_GP_6_IMAGES_H
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
struct full_image_t
|
||||||
|
{
|
||||||
|
float rgb_data[DATA_SIZE * CHANNELS]{};
|
||||||
|
|
||||||
|
full_image_t()
|
||||||
|
{
|
||||||
|
for (auto& v : rgb_data)
|
||||||
|
v = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void load(const std::string& path)
|
||||||
|
{
|
||||||
|
int width, height, channels;
|
||||||
|
auto data = stbi_loadf(path.c_str(), &width, &height, &channels, CHANNELS);
|
||||||
|
|
||||||
|
stbir_resize_float_linear(data, width, height, 0, rgb_data, IMAGE_SIZE, IMAGE_SIZE, 0, static_cast<stbir_pixel_layout>(CHANNELS));
|
||||||
|
|
||||||
|
stbi_image_free(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void save(const std::string&)
|
||||||
|
{
|
||||||
|
//stbi_write_png(str.c_str(), IMAGE_SIZE, IMAGE_SIZE, CHANNELS, rgb_data, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& str, const full_image_t&)
|
||||||
|
{
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //IMAGE_GP_6_IMAGES_H
|
|
@ -1 +1 @@
|
||||||
Subproject commit 8e5a3f3b7c52a361a47199108be082730b1aeddd
|
Subproject commit 5d72923998fd59cf76a7e777642a9c34e76bfb3d
|
306
src/main.cpp
306
src/main.cpp
|
@ -36,22 +36,8 @@
|
||||||
#include "opencv2/imgproc.hpp"
|
#include "opencv2/imgproc.hpp"
|
||||||
#include <random>
|
#include <random>
|
||||||
#include "slr.h"
|
#include "slr.h"
|
||||||
|
#include <images.h>
|
||||||
constexpr size_t log2(size_t n) // NOLINT
|
#include <helper.h>
|
||||||
{
|
|
||||||
return ((n < 2) ? 1 : 1 + log2(n / 2));
|
|
||||||
}
|
|
||||||
|
|
||||||
static const blt::u64 SEED = std::random_device()();
|
|
||||||
static constexpr blt::size_t IMAGE_SIZE = 128;
|
|
||||||
static constexpr blt::size_t IMAGE_PADDING = 16;
|
|
||||||
static constexpr blt::size_t POP_SIZE = 64;
|
|
||||||
static constexpr blt::size_t CHANNELS = 3;
|
|
||||||
static constexpr blt::size_t DATA_SIZE = IMAGE_SIZE * IMAGE_SIZE;
|
|
||||||
static constexpr blt::size_t DATA_CHANNELS_SIZE = DATA_SIZE * CHANNELS;
|
|
||||||
static constexpr blt::size_t BOX_COUNT = static_cast<blt::size_t>(log2(IMAGE_SIZE / 2));
|
|
||||||
static constexpr float THRESHOLD = 0.3;
|
|
||||||
static constexpr auto load_image = "../silly.png";
|
|
||||||
|
|
||||||
blt::gfx::matrix_state_manager global_matrices;
|
blt::gfx::matrix_state_manager global_matrices;
|
||||||
blt::gfx::resource_manager resources;
|
blt::gfx::resource_manager resources;
|
||||||
|
@ -86,95 +72,32 @@ inline blt::size_t get_index(blt::size_t x, blt::size_t y)
|
||||||
return y * IMAGE_SIZE + x;
|
return y * IMAGE_SIZE + x;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct full_image_t
|
|
||||||
{
|
|
||||||
float rgb_data[DATA_SIZE * CHANNELS]{};
|
|
||||||
|
|
||||||
full_image_t()
|
|
||||||
{
|
|
||||||
for (auto& v : rgb_data)
|
|
||||||
v = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void load(const std::string& path)
|
|
||||||
{
|
|
||||||
int width, height, channels;
|
|
||||||
auto data = stbi_loadf(path.c_str(), &width, &height, &channels, CHANNELS);
|
|
||||||
|
|
||||||
stbir_resize_float_linear(data, width, height, 0, rgb_data, IMAGE_SIZE, IMAGE_SIZE, 0, static_cast<stbir_pixel_layout>(CHANNELS));
|
|
||||||
|
|
||||||
stbi_image_free(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void save(const std::string&)
|
|
||||||
{
|
|
||||||
//stbi_write_png(str.c_str(), IMAGE_SIZE, IMAGE_SIZE, CHANNELS, rgb_data, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& str, const full_image_t&)
|
|
||||||
{
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
std::array<full_image_t, POP_SIZE> generation_images;
|
std::array<full_image_t, POP_SIZE> generation_images;
|
||||||
|
|
||||||
full_image_t base_image;
|
full_image_t base_image;
|
||||||
blt::size_t last_run = 0;
|
blt::size_t last_run = 0;
|
||||||
blt::i32 time_between_runs = 100;
|
blt::i32 time_between_runs = 16;
|
||||||
bool is_running = false;
|
bool is_running = false;
|
||||||
|
|
||||||
blt::gp::prog_config_t config = blt::gp::prog_config_t()
|
|
||||||
.set_initial_min_tree_size(4)
|
|
||||||
.set_initial_max_tree_size(8)
|
|
||||||
.set_elite_count(2)
|
|
||||||
.set_max_generations(50)
|
|
||||||
.set_mutation_chance(1.0)
|
|
||||||
.set_crossover_chance(1.0)
|
|
||||||
.set_reproduction_chance(0.5)
|
|
||||||
.set_pop_size(POP_SIZE)
|
|
||||||
.set_thread_count(16);
|
|
||||||
|
|
||||||
blt::gp::type_provider type_system;
|
blt::gp::type_provider type_system;
|
||||||
blt::gp::gp_program program{type_system, SEED, config};
|
blt::gp::gp_program program{type_system, SEED, config};
|
||||||
|
std::unique_ptr<std::thread> gp_thread = nullptr;
|
||||||
|
|
||||||
template<typename SINGLE_FUNC>
|
blt::gp::operation_t add(make_double(std::plus()), "add");
|
||||||
constexpr static auto make_single(SINGLE_FUNC&& func)
|
blt::gp::operation_t sub(make_double(std::minus()), "sub");
|
||||||
{
|
blt::gp::operation_t mul(make_double(std::multiplies()), "mul");
|
||||||
return [func](const full_image_t& a) {
|
|
||||||
full_image_t img{};
|
|
||||||
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
|
|
||||||
img.rgb_data[i] = func(a.rgb_data[i]);
|
|
||||||
return img;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
blt::gp::operation_t add([](const full_image_t& a, const full_image_t& b) {
|
|
||||||
full_image_t img{};
|
|
||||||
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
|
|
||||||
img.rgb_data[i] = a.rgb_data[i] + b.rgb_data[i];
|
|
||||||
return img;
|
|
||||||
}, "add");
|
|
||||||
blt::gp::operation_t sub([](const full_image_t& a, const full_image_t& b) {
|
|
||||||
full_image_t img{};
|
|
||||||
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
|
|
||||||
img.rgb_data[i] = a.rgb_data[i] - b.rgb_data[i];
|
|
||||||
return img;
|
|
||||||
}, "sub");
|
|
||||||
blt::gp::operation_t mul([](const full_image_t& a, const full_image_t& b) {
|
|
||||||
full_image_t img{};
|
|
||||||
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
|
|
||||||
img.rgb_data[i] = a.rgb_data[i] * b.rgb_data[i];
|
|
||||||
return img;
|
|
||||||
}, "mul");
|
|
||||||
blt::gp::operation_t pro_div([](const full_image_t& a, const full_image_t& b) {
|
blt::gp::operation_t pro_div([](const full_image_t& a, const full_image_t& b) {
|
||||||
full_image_t img{};
|
full_image_t img{};
|
||||||
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
|
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
|
||||||
img.rgb_data[i] = b.rgb_data[i] == 0 ? 0 : (a.rgb_data[i] / b.rgb_data[i]);
|
img.rgb_data[i] = b.rgb_data[i] == 0 ? 0 : (a.rgb_data[i] / b.rgb_data[i]);
|
||||||
return img;
|
return img;
|
||||||
}, "div");
|
}, "div");
|
||||||
blt::gp::operation_t op_sin(make_single((float (*)(float)) &std::sin), "sin");
|
blt::gp::operation_t op_sin(make_single([](float a) {
|
||||||
blt::gp::operation_t op_cos(make_single((float (*)(float)) &std::cos), "cos");
|
return (std::sin(a) + 1.0f) / 2.0f;
|
||||||
|
}), "sin");
|
||||||
|
blt::gp::operation_t op_cos(make_single([](float a) {
|
||||||
|
return (std::cos(a) + 1.0f) / 2.0f;
|
||||||
|
}), "cos");
|
||||||
blt::gp::operation_t op_atan(make_single((float (*)(float)) &std::atan), "atan");
|
blt::gp::operation_t op_atan(make_single((float (*)(float)) &std::atan), "atan");
|
||||||
blt::gp::operation_t op_exp(make_single((float (*)(float)) &std::exp), "exp");
|
blt::gp::operation_t op_exp(make_single((float (*)(float)) &std::exp), "exp");
|
||||||
blt::gp::operation_t op_abs(make_single((float (*)(float)) &std::abs), "abs");
|
blt::gp::operation_t op_abs(make_single((float (*)(float)) &std::abs), "abs");
|
||||||
|
@ -215,6 +138,50 @@ blt::gp::operation_t bitwise_xor([](const full_image_t& a, const full_image_t& b
|
||||||
return img;
|
return img;
|
||||||
}, "xor");
|
}, "xor");
|
||||||
|
|
||||||
|
blt::gp::operation_t dissolve([](const full_image_t& a, const full_image_t& b) {
|
||||||
|
using blt::mem::type_cast;
|
||||||
|
full_image_t img{};
|
||||||
|
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
|
||||||
|
{
|
||||||
|
auto diff = (a.rgb_data[i] - b.rgb_data[i]) / 2.0f;
|
||||||
|
img.rgb_data[i] = a.rgb_data[i] + diff;
|
||||||
|
}
|
||||||
|
return img;
|
||||||
|
}, "dissolve");
|
||||||
|
|
||||||
|
blt::gp::operation_t hsv_to_rgb([](const full_image_t& a) {
|
||||||
|
using blt::mem::type_cast;
|
||||||
|
full_image_t img{};
|
||||||
|
for (blt::size_t i = 0; i < DATA_SIZE; i++)
|
||||||
|
{
|
||||||
|
auto h = static_cast<blt::i32>(a.rgb_data[i * CHANNELS + 0]) % 360;
|
||||||
|
auto s = a.rgb_data[i * CHANNELS + 1];
|
||||||
|
auto v = a.rgb_data[i * CHANNELS + 2];
|
||||||
|
auto c = v * s;
|
||||||
|
auto x = c * static_cast<float>(1 - std::abs(((h / 60) % 2) - 1));
|
||||||
|
auto m = v - c;
|
||||||
|
|
||||||
|
blt::vec3 rgb;
|
||||||
|
if (h >= 0 && h < 60)
|
||||||
|
rgb = {c, x, 0.0f};
|
||||||
|
else if (h >= 60 && h < 120)
|
||||||
|
rgb = {x, c, 0.0f};
|
||||||
|
else if (h >= 120 && h < 180)
|
||||||
|
rgb = {0.0f, c, x};
|
||||||
|
else if (h >= 180 && h < 240)
|
||||||
|
rgb = {0.0f, x, c};
|
||||||
|
else if (h >= 240 && h < 300)
|
||||||
|
rgb = {x, 0.0f, c};
|
||||||
|
else if (h >= 300 && h < 360)
|
||||||
|
rgb = {c, 0.0f, x};
|
||||||
|
|
||||||
|
img.rgb_data[i * CHANNELS] = rgb.x() + m;
|
||||||
|
img.rgb_data[i * CHANNELS + 1] = rgb.y() + m;
|
||||||
|
img.rgb_data[i * CHANNELS + 2] = rgb.z() + m;
|
||||||
|
}
|
||||||
|
return img;
|
||||||
|
}, "hsv");
|
||||||
|
|
||||||
blt::gp::operation_t lit([]() {
|
blt::gp::operation_t lit([]() {
|
||||||
full_image_t img{};
|
full_image_t img{};
|
||||||
auto r = program.get_random().get_float(0.0f, 1.0f);
|
auto r = program.get_random().get_float(0.0f, 1.0f);
|
||||||
|
@ -335,7 +302,7 @@ constexpr float compare_values(float a, float b)
|
||||||
|
|
||||||
struct fractal_stats
|
struct fractal_stats
|
||||||
{
|
{
|
||||||
blt::f64 box_size, num_boxes, xy, x2, y2;
|
blt::f64 r, g, b, total, combined;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool in_box(full_image_t& image, blt::size_t channel, blt::size_t box_size, blt::size_t i, blt::size_t j)
|
bool in_box(full_image_t& image, blt::size_t channel, blt::size_t box_size, blt::size_t i, blt::size_t j)
|
||||||
|
@ -353,49 +320,69 @@ bool in_box(full_image_t& image, blt::size_t channel, blt::size_t box_size, blt:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
blt::f64 get_fractal_value(full_image_t& image, blt::size_t channel)
|
fractal_stats get_fractal_value(full_image_t& image)
|
||||||
{
|
{
|
||||||
std::array<fractal_stats, BOX_COUNT> box_data{};
|
fractal_stats stats{};
|
||||||
std::array<double, BOX_COUNT> x_data{};
|
std::array<double, BOX_COUNT> x_data{};
|
||||||
std::array<double, BOX_COUNT> y_data{};
|
std::array<double, BOX_COUNT> boxes_r{};
|
||||||
|
std::array<double, BOX_COUNT> boxes_g{};
|
||||||
|
std::array<double, BOX_COUNT> boxes_b{};
|
||||||
|
std::array<double, BOX_COUNT> boxes_total{};
|
||||||
|
std::array<double, BOX_COUNT> boxes_combined{};
|
||||||
for (blt::size_t box_size = IMAGE_SIZE / 2; box_size > 1; box_size /= 2)
|
for (blt::size_t box_size = IMAGE_SIZE / 2; box_size > 1; box_size /= 2)
|
||||||
{
|
{
|
||||||
blt::ptrdiff_t num_boxes = 0;
|
blt::ptrdiff_t num_boxes_r = 0;
|
||||||
|
blt::ptrdiff_t num_boxes_g = 0;
|
||||||
|
blt::ptrdiff_t num_boxes_b = 0;
|
||||||
|
blt::ptrdiff_t num_boxes_total = 0;
|
||||||
|
blt::ptrdiff_t num_boxes_combined = 0;
|
||||||
for (blt::size_t i = 0; i < IMAGE_SIZE; i += box_size)
|
for (blt::size_t i = 0; i < IMAGE_SIZE; i += box_size)
|
||||||
{
|
{
|
||||||
for (blt::size_t j = 0; j < IMAGE_SIZE; j += box_size)
|
for (blt::size_t j = 0; j < IMAGE_SIZE; j += box_size)
|
||||||
{
|
{
|
||||||
if (in_box(image, channel, box_size, i, j))
|
auto r = in_box(image, 0, box_size, i, j);
|
||||||
num_boxes++;
|
auto g = in_box(image, 1, box_size, i, j);
|
||||||
|
auto b = in_box(image, 2, box_size, i, j);
|
||||||
|
|
||||||
|
if (r)
|
||||||
|
num_boxes_r++;
|
||||||
|
if (g)
|
||||||
|
num_boxes_g++;
|
||||||
|
if (b)
|
||||||
|
num_boxes_b++;
|
||||||
|
if (r && g && b)
|
||||||
|
num_boxes_combined++;
|
||||||
|
if (r || g || b)
|
||||||
|
num_boxes_total++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto x = static_cast<blt::f64>(std::log2(box_size));
|
auto x = static_cast<blt::f64>(std::log2(box_size));
|
||||||
auto y = static_cast<blt::f64>(num_boxes == 0 ? 0 : std::log2(num_boxes));
|
|
||||||
//auto y = static_cast<blt::f64>(num_boxes);
|
|
||||||
box_data[static_cast<blt::size_t>(std::log2(box_size)) - 1] = {x, y, x * y, x * x, y * y};
|
|
||||||
x_data[static_cast<blt::size_t>(std::log2(box_size)) - 1] = x;
|
x_data[static_cast<blt::size_t>(std::log2(box_size)) - 1] = x;
|
||||||
y_data[static_cast<blt::size_t>(std::log2(box_size)) - 1] = y;
|
boxes_r[static_cast<blt::size_t>(std::log2(box_size)) - 1] = static_cast<blt::f64>(num_boxes_r == 0 ? 0 : std::log2(num_boxes_r));
|
||||||
//BLT_DEBUG("%lf vs %lf", x, y);
|
boxes_g[static_cast<blt::size_t>(std::log2(box_size)) - 1] = static_cast<blt::f64>(num_boxes_g == 0 ? 0 : std::log2(num_boxes_g));
|
||||||
|
boxes_b[static_cast<blt::size_t>(std::log2(box_size)) - 1] = static_cast<blt::f64>(num_boxes_b == 0 ? 0 : std::log2(num_boxes_b));
|
||||||
|
boxes_total[static_cast<blt::size_t>(std::log2(box_size)) - 1] = static_cast<blt::f64>(num_boxes_combined == 0 ? 0 : std::log2(
|
||||||
|
num_boxes_combined));
|
||||||
|
boxes_combined[static_cast<blt::size_t>(std::log2(box_size)) - 1] = static_cast<blt::f64>(num_boxes_total == 0 ? 0 : std::log2(
|
||||||
|
num_boxes_total));
|
||||||
}
|
}
|
||||||
// fractal_stats total{};
|
|
||||||
// for (const auto& b : box_data)
|
|
||||||
// {
|
|
||||||
// total.box_size += b.box_size;
|
|
||||||
// total.num_boxes += b.num_boxes;
|
|
||||||
// total.xy += b.xy;
|
|
||||||
// total.x2 += b.x2;
|
|
||||||
// total.y2 += b.y2;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// auto n = static_cast<blt::f64>(BOX_COUNT);
|
|
||||||
// auto b0 = ((total.num_boxes * total.x2) - (total.box_size * total.xy)) / ((n * total.x2) - (total.box_size * total.box_size));
|
|
||||||
// auto b1 = ((n * total.xy) - (total.box_size * total.num_boxes)) / ((n * total.x2) - (total.box_size * total.box_size));
|
|
||||||
//
|
|
||||||
// return b1;
|
|
||||||
|
|
||||||
slr count{x_data, y_data};
|
slr count_r{x_data, boxes_r};
|
||||||
|
slr count_g{x_data, boxes_g};
|
||||||
|
slr count_b{x_data, boxes_b};
|
||||||
|
slr count_total{x_data, boxes_total};
|
||||||
|
slr count_combined{x_data, boxes_combined};
|
||||||
|
|
||||||
return count.beta;
|
#define FUNC(f) (-f)
|
||||||
|
stats.r = FUNC(count_r.beta);
|
||||||
|
stats.g = FUNC(count_g.beta);
|
||||||
|
stats.b = FUNC(count_b.beta);
|
||||||
|
stats.total = FUNC(count_total.beta);
|
||||||
|
stats.combined = FUNC(count_combined.beta);
|
||||||
|
#undef FUNC
|
||||||
|
|
||||||
|
return stats;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr auto create_fitness_function()
|
constexpr auto create_fitness_function()
|
||||||
|
@ -409,19 +396,15 @@ constexpr auto create_fitness_function()
|
||||||
fitness.raw_fitness += compare_values(v.rgb_data[i], base_image.rgb_data[i]);
|
fitness.raw_fitness += compare_values(v.rgb_data[i], base_image.rgb_data[i]);
|
||||||
|
|
||||||
fitness.raw_fitness /= (IMAGE_SIZE * IMAGE_SIZE);
|
fitness.raw_fitness /= (IMAGE_SIZE * IMAGE_SIZE);
|
||||||
|
auto raw = get_fractal_value(v);
|
||||||
for (blt::size_t channel = 0; channel < CHANNELS; channel++)
|
auto fit = std::max(0.0, 1.0 - std::abs(1.35 - raw.combined));
|
||||||
{
|
auto fit2 = std::max(0.0, 1.0 - std::abs(1.35 - raw.total));
|
||||||
auto raw = -get_fractal_value(v, channel);
|
//BLT_DEBUG("Fitness %lf %lf %lf || %lf => %lf (fit: %lf)", raw.r, raw.g, raw.b, raw.total, raw.combined, fit);
|
||||||
auto fit = 1.0 - std::max(0.0, 1.0 - std::abs(1.35 - raw));
|
if (std::isnan(raw.total) || std::isnan(raw.combined))
|
||||||
BLT_DEBUG("Fitness %lf (raw: %lf) for channel %lu", fit, raw, channel);
|
|
||||||
if (std::isnan(raw))
|
|
||||||
fitness.raw_fitness += 400;
|
fitness.raw_fitness += 400;
|
||||||
else
|
else
|
||||||
fitness.raw_fitness += raw;
|
fitness.raw_fitness += raw.total + raw.combined + 1.0;
|
||||||
}
|
|
||||||
|
|
||||||
//BLT_TRACE("Raw fitness: %lf for %ld", fitness.raw_fitness, index);
|
|
||||||
fitness.standardized_fitness = fitness.raw_fitness;
|
fitness.standardized_fitness = fitness.raw_fitness;
|
||||||
fitness.adjusted_fitness = (1.0 / (1.0 + fitness.standardized_fitness));
|
fitness.adjusted_fitness = (1.0 / (1.0 + fitness.standardized_fitness));
|
||||||
};
|
};
|
||||||
|
@ -430,16 +413,16 @@ constexpr auto create_fitness_function()
|
||||||
void execute_generation()
|
void execute_generation()
|
||||||
{
|
{
|
||||||
BLT_TRACE("------------{Begin Generation %ld}------------", program.get_current_generation());
|
BLT_TRACE("------------{Begin Generation %ld}------------", program.get_current_generation());
|
||||||
BLT_TRACE("Evaluate Fitness");
|
|
||||||
BLT_START_INTERVAL("Image Test", "Fitness");
|
|
||||||
program.evaluate_fitness();
|
|
||||||
BLT_END_INTERVAL("Image Test", "Fitness");
|
|
||||||
BLT_START_INTERVAL("Image Test", "Gen");
|
BLT_START_INTERVAL("Image Test", "Gen");
|
||||||
auto sel = blt::gp::select_tournament_t{};
|
auto sel = blt::gp::select_tournament_t{};
|
||||||
program.create_next_generation(sel, sel, sel);
|
program.create_next_generation(sel, sel, sel);
|
||||||
BLT_END_INTERVAL("Image Test", "Gen");
|
BLT_END_INTERVAL("Image Test", "Gen");
|
||||||
BLT_TRACE("Move to next generation");
|
BLT_TRACE("Move to next generation");
|
||||||
program.next_generation();
|
program.next_generation();
|
||||||
|
BLT_TRACE("Evaluate Fitness");
|
||||||
|
BLT_START_INTERVAL("Image Test", "Fitness");
|
||||||
|
program.evaluate_fitness();
|
||||||
|
BLT_END_INTERVAL("Image Test", "Fitness");
|
||||||
BLT_TRACE("----------------------------------------------");
|
BLT_TRACE("----------------------------------------------");
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
@ -454,6 +437,26 @@ void print_stats()
|
||||||
BLT_INFO("Overall fitness: %lf", stats.overall_fitness.load());
|
BLT_INFO("Overall fitness: %lf", stats.overall_fitness.load());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::atomic_bool run_generation = false;
|
||||||
|
|
||||||
|
void run_gp()
|
||||||
|
{
|
||||||
|
BLT_DEBUG("Generate Initial Population");
|
||||||
|
static constexpr auto fitness_func = create_fitness_function();
|
||||||
|
program.generate_population(type_system.get_type<full_image_t>().id(), fitness_func, true);
|
||||||
|
|
||||||
|
while (!program.should_thread_terminate())
|
||||||
|
{
|
||||||
|
if ((run_generation || is_running) && (blt::system::getCurrentTimeMilliseconds() - last_run) > static_cast<blt::size_t>(time_between_runs))
|
||||||
|
{
|
||||||
|
execute_generation();
|
||||||
|
print_stats();
|
||||||
|
run_generation = false;
|
||||||
|
last_run = blt::system::getCurrentTimeMilliseconds();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void init(const blt::gfx::window_data&)
|
void init(const blt::gfx::window_data&)
|
||||||
{
|
{
|
||||||
using namespace blt::gfx;
|
using namespace blt::gfx;
|
||||||
|
@ -488,6 +491,8 @@ void init(const blt::gfx::window_data&)
|
||||||
builder.add_operator(bitwise_and);
|
builder.add_operator(bitwise_and);
|
||||||
builder.add_operator(bitwise_or);
|
builder.add_operator(bitwise_or);
|
||||||
builder.add_operator(bitwise_xor);
|
builder.add_operator(bitwise_xor);
|
||||||
|
builder.add_operator(dissolve);
|
||||||
|
builder.add_operator(hsv_to_rgb);
|
||||||
|
|
||||||
builder.add_operator(lit, true);
|
builder.add_operator(lit, true);
|
||||||
builder.add_operator(random_val);
|
builder.add_operator(random_val);
|
||||||
|
@ -500,13 +505,11 @@ void init(const blt::gfx::window_data&)
|
||||||
|
|
||||||
program.set_operations(builder.build());
|
program.set_operations(builder.build());
|
||||||
|
|
||||||
BLT_DEBUG("Generate Initial Population");
|
|
||||||
static constexpr auto fitness_func = create_fitness_function();
|
|
||||||
program.generate_population(type_system.get_type<full_image_t>().id(), fitness_func, true);
|
|
||||||
|
|
||||||
global_matrices.create_internals();
|
global_matrices.create_internals();
|
||||||
resources.load_resources();
|
resources.load_resources();
|
||||||
renderer_2d.create();
|
renderer_2d.create();
|
||||||
|
|
||||||
|
gp_thread = std::make_unique<std::thread>(run_gp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(const blt::gfx::window_data& data)
|
void update(const blt::gfx::window_data& data)
|
||||||
|
@ -522,8 +525,7 @@ void update(const blt::gfx::window_data& data)
|
||||||
ImGui::Button("Run Generation");
|
ImGui::Button("Run Generation");
|
||||||
if (ImGui::IsItemClicked() && !is_running)
|
if (ImGui::IsItemClicked() && !is_running)
|
||||||
{
|
{
|
||||||
execute_generation();
|
run_generation = true;
|
||||||
print_stats();
|
|
||||||
}
|
}
|
||||||
ImGui::InputInt("Time Between Runs", &time_between_runs);
|
ImGui::InputInt("Time Between Runs", &time_between_runs);
|
||||||
ImGui::Checkbox("Run", &is_running);
|
ImGui::Checkbox("Run", &is_running);
|
||||||
|
@ -536,14 +538,6 @@ void update(const blt::gfx::window_data& data)
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_running && (blt::system::getCurrentTimeMilliseconds() - last_run) > static_cast<blt::size_t>(time_between_runs))
|
|
||||||
{
|
|
||||||
execute_generation();
|
|
||||||
print_stats();
|
|
||||||
|
|
||||||
last_run = blt::system::getCurrentTimeMilliseconds();
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto mouse_pos = blt::make_vec2(blt::gfx::calculateRay2D(data.width, data.height, global_matrices.getScale2D(), global_matrices.getView2D(),
|
const auto mouse_pos = blt::make_vec2(blt::gfx::calculateRay2D(data.width, data.height, global_matrices.getScale2D(), global_matrices.getView2D(),
|
||||||
global_matrices.getOrtho()));
|
global_matrices.getOrtho()));
|
||||||
|
|
||||||
|
@ -571,7 +565,10 @@ void update(const blt::gfx::window_data& data)
|
||||||
|
|
||||||
if (blt::gfx::mousePressedLastFrame())
|
if (blt::gfx::mousePressedLastFrame())
|
||||||
{
|
{
|
||||||
program.get_current_pop().get_individuals()[i].tree.print(program, std::cout, false);
|
auto& ind = program.get_current_pop().get_individuals()[i];
|
||||||
|
std::cout << "Fitness: " << ind.fitness.adjusted_fitness << " " << ind.fitness.raw_fitness << " ";
|
||||||
|
ind.tree.print(program, std::cout, false);
|
||||||
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (blt::gfx::mousePressedLastFrame())
|
// if (blt::gfx::mousePressedLastFrame())
|
||||||
|
@ -617,13 +614,16 @@ int main()
|
||||||
BLT_END_INTERVAL("Image Test", "Main");
|
BLT_END_INTERVAL("Image Test", "Main");
|
||||||
|
|
||||||
base_image.save("input.png");
|
base_image.save("input.png");
|
||||||
for (blt::size_t i = 0; i < CHANNELS; i++)
|
|
||||||
{
|
auto v = get_fractal_value(base_image);
|
||||||
auto v = -get_fractal_value(base_image, i);
|
BLT_INFO("Base image values per channel: %lf", v.total);
|
||||||
BLT_INFO("Base image values per channel: %lf", v);
|
|
||||||
}
|
|
||||||
|
|
||||||
BLT_PRINT_PROFILE("Image Test", blt::PRINT_CYCLES | blt::PRINT_THREAD | blt::PRINT_WALL);
|
BLT_PRINT_PROFILE("Image Test", blt::PRINT_CYCLES | blt::PRINT_THREAD | blt::PRINT_WALL);
|
||||||
|
|
||||||
|
is_running = false;
|
||||||
|
program.kill();
|
||||||
|
if (gp_thread->joinable())
|
||||||
|
gp_thread->join();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
Loading…
Reference in New Issue