diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index a96c79d..f1804a4 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -5,9 +5,6 @@
-
-
-
@@ -17,6 +14,7 @@
+
@@ -25,5 +23,6 @@
+
\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 964a41a..6c66d67 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25)
-project(image-gp-2 VERSION 0.0.6)
+project(image-gp-2 VERSION 0.0.7)
option(ENABLE_ADDRSAN "Enable the address sanitizer" OFF)
option(ENABLE_UBSAN "Enable the ub sanitizer" OFF)
diff --git a/include/gp_system.h b/include/gp_system.h
index ddee68b..ff58e92 100644
--- a/include/gp_system.h
+++ b/include/gp_system.h
@@ -29,4 +29,6 @@ bool should_terminate();
image_storage_t& get_image(blt::size_t index);
+void cleanup();
+
#endif //GP_SYSTEM_H
diff --git a/include/image_storage.h b/include/image_storage.h
index 4cdb9ec..819026c 100644
--- a/include/image_storage.h
+++ b/include/image_storage.h
@@ -28,7 +28,7 @@
using image_pixel_t = float;
constexpr blt::i32 IMAGE_DIMENSIONS = 256;
-constexpr blt::i32 IMAGE_CHANNELS = 4;
+constexpr blt::i32 IMAGE_CHANNELS = 1;
constexpr blt::size_t IMAGE_SIZE = IMAGE_DIMENSIONS * IMAGE_DIMENSIONS;
constexpr blt::size_t IMAGE_SIZE_CHANNELS = IMAGE_SIZE * IMAGE_CHANNELS;
@@ -38,16 +38,16 @@ struct image_storage_t
{
std::array data;
- static image_storage_t from_file(const std::string& path);
+ static std::array from_file(const std::string& path);
- image_pixel_t& get(const blt::size_t x, const blt::size_t y, const blt::i32 c)
+ image_pixel_t& get(const blt::size_t x, const blt::size_t y)
{
- return data[(y * IMAGE_DIMENSIONS + x) * IMAGE_CHANNELS + c];
+ return data[(y * IMAGE_DIMENSIONS + x) * IMAGE_CHANNELS];
}
- [[nodiscard]] const image_pixel_t& get(const blt::size_t x, const blt::size_t y, const blt::i32 c) const
+ [[nodiscard]] const image_pixel_t& get(const blt::size_t x, const blt::size_t y) const
{
- return data[(y * IMAGE_DIMENSIONS + x) * IMAGE_CHANNELS + c];
+ return data[(y * IMAGE_DIMENSIONS + x) * IMAGE_CHANNELS];
}
};
diff --git a/lib/blt b/lib/blt
index 284743c..729a16a 160000
--- a/lib/blt
+++ b/lib/blt
@@ -1 +1 @@
-Subproject commit 284743c683aebae3277f64a07cdd0deedf629039
+Subproject commit 729a16ab574e31bf1b44446a777e4ee834518c6e
diff --git a/lib/blt-gp b/lib/blt-gp
index a742164..0eea218 160000
--- a/lib/blt-gp
+++ b/lib/blt-gp
@@ -1 +1 @@
-Subproject commit a742164bedd31cac6d828032ee1a4a18c64d0cac
+Subproject commit 0eea2189e37a372f7a012a07120ee0aed2b1646a
diff --git a/src/gp_system.cpp b/src/gp_system.cpp
index 7f13fdd..1ebb2e2 100644
--- a/src/gp_system.cpp
+++ b/src/gp_system.cpp
@@ -24,34 +24,28 @@
using namespace blt::gp;
-gp_program program{
- []() {
- return std::random_device()();
- }
-};
+std::array programs;
-std::vector images;
-image_storage_t reference_image = image_storage_t::from_file("../silly.png");
+std::vector> images;
+auto reference_image = image_storage_t::from_file("../silly.png");
+template
void fitness_func(const tree_t& tree, fitness_t& fitness, const blt::size_t index)
{
auto image = tree.get_evaluation_ref();
- std::memcpy(images[index].data.data(), image->get_data().data.data(), IMAGE_SIZE_BYTES);
+
+ // std::memcpy(images[index].data.data(), image->get_data().data.data(), IMAGE_SIZE_BYTES);
auto& data = image->get_data();
for (blt::size_t x = 0; x < IMAGE_DIMENSIONS; ++x)
{
for (blt::size_t y = 0; y < IMAGE_DIMENSIONS; ++y)
{
+ images[index][(x * IMAGE_DIMENSIONS + y) * 3 + Channel] = data.get(x, y);
+
auto multiplier = (1 - std::abs((static_cast(x) / (static_cast(IMAGE_DIMENSIONS) / 2)) - 1)) + (1 - std::abs(
(static_cast(y) / (static_cast(IMAGE_DIMENSIONS) / 2)) - 1));
- for (blt::size_t c = 0; c < IMAGE_CHANNELS; ++c)
- {
- const auto diff_r = data.get(x, y, 0) - reference_image.get(x, y, 0);
- const auto diff_g = data.get(x, y, 1) - reference_image.get(x, y, 1);
- const auto diff_b = data.get(x, y, 2) - reference_image.get(x, y, 2);
- const auto total = (diff_r + diff_g + diff_b) / 3;
- fitness.raw_fitness += (total * total) * multiplier;
- }
+ const auto diff = data.get(x, y) - reference_image[Channel].get(x, y);
+ fitness.raw_fitness += (diff * diff) * multiplier;
}
}
fitness.raw_fitness /= static_cast(IMAGE_SIZE_CHANNELS);
@@ -59,15 +53,14 @@ void fitness_func(const tree_t& tree, fitness_t& fitness, const blt::size_t inde
fitness.adjusted_fitness = -fitness.standardized_fitness;
}
-void setup_operations()
+void setup_operations(gp_program* program)
{
static operation_t op_image_x([]() {
image_t ret;
for (blt::size_t x = 0; x < IMAGE_DIMENSIONS; ++x)
{
for (blt::size_t y = 0; y < IMAGE_DIMENSIONS; ++y)
- for (blt::i32 c = 0; c < IMAGE_CHANNELS; ++c)
- ret.get_data().get(x, y, c) = static_cast(x) / static_cast(IMAGE_DIMENSIONS - 1);
+ ret.get_data().get(x, y) = static_cast(x) / static_cast(IMAGE_DIMENSIONS - 1);
}
return ret;
});
@@ -76,8 +69,7 @@ void setup_operations()
for (blt::size_t x = 0; x < IMAGE_DIMENSIONS; ++x)
{
for (blt::size_t y = 0; y < IMAGE_DIMENSIONS; ++y)
- for (blt::i32 c = 0; c < IMAGE_CHANNELS; ++c)
- ret.get_data().get(x, y, c) = static_cast(y) / static_cast(IMAGE_DIMENSIONS - 1);
+ ret.get_data().get(x, y) = static_cast(y) / static_cast(IMAGE_DIMENSIONS - 1);
}
return ret;
});
@@ -86,8 +78,7 @@ void setup_operations()
for (blt::size_t x = 0; x < IMAGE_DIMENSIONS; ++x)
{
for (blt::size_t y = 0; y < IMAGE_DIMENSIONS; ++y)
- for (blt::i32 c = 0; c < IMAGE_CHANNELS; ++c)
- ret.get_data().get(x, y, c) = static_cast(x + y) / static_cast((IMAGE_DIMENSIONS - 1) * (IMAGE_DIMENSIONS - 1));
+ ret.get_data().get(x, y) = static_cast(x + y) / static_cast((IMAGE_DIMENSIONS - 1) * (IMAGE_DIMENSIONS - 1));
}
return ret;
});
@@ -95,9 +86,9 @@ void setup_operations()
const auto blend = std::min(std::max(f, 0.0f), 1.0f);
const auto beta = 1.0f - blend;
image_t ret;
- const cv::Mat src1{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32FC4, a.as_void()};
- const cv::Mat src2{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32FC4, b.as_void()};
- cv::Mat dst{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32FC4, ret.get_data().data.data()};
+ const cv::Mat src1{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32FC1, a.as_void()};
+ const cv::Mat src2{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32FC1, b.as_void()};
+ cv::Mat dst{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32FC1, ret.get_data().data.data()};
addWeighted(src1, blend, src2, beta, 0.0, dst);
return ret;
}, "blend");
@@ -117,14 +108,14 @@ void setup_operations()
return -std::log(-a);
return std::log(a);
}, "log_float");
- static auto lit = operation_t([]() {
- return program.get_random().get_float(-1.0f, 1.0f);
+ static auto lit = operation_t([program]() {
+ return program->get_random().get_float(-1.0f, 1.0f);
}, "lit_float").set_ephemeral();
operator_builder builder{};
builder.build(make_add(), make_sub(), make_mul(), make_div(), op_image_x, op_image_y, op_image_xy,
make_add(), make_sub(), make_mul(), make_prot_div(), op_sin, op_cos, op_exp, op_log, lit);
- program.set_operations(builder.grab());
+ program->set_operations(builder.grab());
}
void setup_gp_system(const blt::size_t population_size)
@@ -132,24 +123,30 @@ void setup_gp_system(const blt::size_t population_size)
prog_config_t config{};
config.population_size = population_size;
config.elites = 2;
- program.set_config(config);
+ program = new gp_program{
+ []() {
+ return std::random_device()();
+ },
+ config
+ };
+
images.resize(population_size);
setup_operations();
static auto sel = select_tournament_t{};
- program.generate_initial_population(program.get_typesystem().get_type().id());
- program.setup_generational_evaluation(fitness_func, sel, sel, sel);
+ program->generate_initial_population(program->get_typesystem().get_type().id());
+ program->setup_generational_evaluation(fitness_func, sel, sel, sel);
}
void run_step()
{
- BLT_TRACE("------------\\{Begin Generation {}}------------", program.get_current_generation());
+ BLT_TRACE("------------\\{Begin Generation {}}------------", program->get_current_generation());
BLT_TRACE("Creating next generation");
- program.create_next_generation();
+ program->create_next_generation();
BLT_TRACE("Move to next generation");
- program.next_generation();
+ program->next_generation();
BLT_TRACE("Evaluate Fitness");
- program.evaluate_fitness();
- const auto& stats = program.get_population_stats();
+ program->evaluate_fitness();
+ const auto& stats = program->get_population_stats();
BLT_TRACE("Avg Fit: {:0.6f}, Best Fit: {:0.6f}, Worst Fit: {:0.6f}, Overall Fit: {:0.6f}", stats.average_fitness.load(std::memory_order_relaxed),
stats.best_fitness.load(std::memory_order_relaxed), stats.worst_fitness.load(std::memory_order_relaxed),
stats.overall_fitness.load(std::memory_order_relaxed));
@@ -158,10 +155,15 @@ void run_step()
bool should_terminate()
{
- return program.should_terminate();
+ return program->should_terminate();
}
image_storage_t& get_image(blt::size_t index)
{
return images[index];
}
+
+void cleanup()
+{
+ delete program;
+}
diff --git a/src/image_storage.cpp b/src/image_storage.cpp
index 6f013de..e148ddc 100644
--- a/src/image_storage.cpp
+++ b/src/image_storage.cpp
@@ -21,17 +21,31 @@
#include
#include
-image_storage_t image_storage_t::from_file(const std::string& path)
+std::array 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);
- image_storage_t storage{};
- stbir_resize_float_linear(data, x, y, 0, storage.data.data(), IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, 0, STBIR_RGBA);
+ const auto resized = stbir_resize_float_linear(data, x, y, 0, nullptr, IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, 0, STBIR_RGBA);
+
+ image_storage_t storage_r{};
+ image_storage_t storage_g{};
+ image_storage_t storage_b{};
+
+ for (blt::size_t i = 0; i < IMAGE_DIMENSIONS; ++i)
+ {
+ for (blt::size_t j = 0; j < IMAGE_DIMENSIONS; ++j)
+ {
+ storage_r.get(i, j) = resized[(i * IMAGE_DIMENSIONS + j) * 4];
+ storage_g.get(i, j) = resized[(i * IMAGE_DIMENSIONS + j) * 4 + 1];
+ storage_b.get(i, j) = resized[(i * IMAGE_DIMENSIONS + j) * 4 + 2];
+ }
+ }
stbi_image_free(data);
- return storage;
+ stbi_image_free(resized);
+ return {storage_r, storage_g, storage_b};
}
image_t operator/(const image_t& lhs, const image_t& rhs)
diff --git a/src/main.cpp b/src/main.cpp
index a0c93c7..431d2a3 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -34,6 +34,7 @@ std::thread run_gp()
} else
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
+ cleanup();
}
};
}
@@ -51,6 +52,8 @@ void init(const blt::gfx::window_data&)
global_matrices.create_internals();
resources.load_resources();
renderer_2d.create();
+
+ setWindowSize(1400, 720);
}
void update(const blt::gfx::window_data& data)
@@ -123,21 +126,24 @@ void update(const blt::gfx::window_data& data)
const auto allocated_blocks = g_allocated_blocks.load(std::memory_order_relaxed);
const auto deallocated_blocks = g_deallocated_blocks.load(std::memory_order_relaxed);
ImGui::Text("Allocated Blocks / Deallocated Blocks: (%ld / %ld) (%ld / %ld) (Total: %ld)", allocated_blocks, deallocated_blocks,
- g_image_list.images.size(), allocated_blocks - deallocated_blocks, g_image_list.images.size() + (allocated_blocks - deallocated_blocks));
+ g_image_list.images.size(), allocated_blocks - deallocated_blocks,
+ g_image_list.images.size() + (allocated_blocks - deallocated_blocks));
}
ImGui::End();
for (blt::size_t i = 0; i < population_size; i++)
gl_images[i]->upload(get_image(i).data.data(), IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, GL_RGBA, GL_FLOAT);
- for (int i = 0; i < 10; i++)
+ constexpr int images_x = 10;
+ constexpr int images_y = 6;
+ for (int i = 0; i < images_x; i++)
{
- for (int j = 0; j < 6; j++)
+ for (int j = 0; j < images_y; j++)
{
constexpr float padding_x = 32;
constexpr float padding_y = 32;
- constexpr float img_width = 128;
- constexpr float img_height = 128;
+ const float img_width = (static_cast(data.width) - padding_x * 2 - padding_x * (images_x-1) - 256) / images_x;
+ const float img_height = (static_cast(data.height) - padding_y * 2 - padding_y * (images_y-1) - 32) / images_y;
const float x = 256 + static_cast(i) * img_width + padding_x * static_cast(i) + img_width;
const float y = static_cast(data.height) - (16 + static_cast(j) * img_height + padding_y * static_cast(j) +
img_height);