main
Brett 2024-08-09 00:15:46 -04:00
parent 109af854ef
commit a81d01113c
4 changed files with 158 additions and 6 deletions

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.25) cmake_minimum_required(VERSION 3.25)
project(image-gp-6 VERSION 0.0.24) project(image-gp-6 VERSION 0.0.25)
include(FetchContent) include(FetchContent)

View File

@ -221,6 +221,13 @@ inline blt::gp::operation_t hsv_to_rgb([](const full_image_t& a) {
}, "hsv"); }, "hsv");
inline blt::gp::operation_t lit([]() { inline blt::gp::operation_t lit([]() {
full_image_t img{};
auto bw = program.get_random().get_float(0.0f, 1.0f);
for (auto& i : img.rgb_data)
i = bw;
return img;
}, "lit");
inline blt::gp::operation_t vec([]() {
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);
auto g = program.get_random().get_float(0.0f, 1.0f); auto g = program.get_random().get_float(0.0f, 1.0f);
@ -232,7 +239,7 @@ inline blt::gp::operation_t lit([]() {
img.rgb_data[i * CHANNELS + 2] = b; img.rgb_data[i * CHANNELS + 2] = b;
} }
return img; return img;
}, "lit"); }, "vec");
inline blt::gp::operation_t random_val([]() { inline blt::gp::operation_t random_val([]() {
full_image_t img{}; full_image_t img{};
for (auto& i : img.rgb_data) for (auto& i : img.rgb_data)
@ -262,7 +269,7 @@ inline blt::gp::operation_t perlin_warped([](const full_image_t& u, const full_i
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++) for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
{ {
auto ctx = get_ctx(i); auto ctx = get_ctx(i);
img.rgb_data[i] = perlin_noise(ctx.x / IMAGE_SIZE + u.rgb_data[i], ctx.y / IMAGE_SIZE + v.rgb_data[i], img.rgb_data[i] = perlin_noise((ctx.x + + u.rgb_data[i]) / IMAGE_SIZE, (ctx.y + v.rgb_data[i]) / IMAGE_SIZE,
static_cast<float>(i % CHANNELS) / CHANNELS); static_cast<float>(i % CHANNELS) / CHANNELS);
} }
return img; return img;
@ -397,6 +404,7 @@ void create_image_operations(blt::gp::operator_builder<context>& builder)
bool state = false; bool state = false;
builder.add_operator(lit, true); builder.add_operator(lit, true);
builder.add_operator(vec, true);
builder.add_operator(random_val); builder.add_operator(random_val);
builder.add_operator(op_x_r, state); builder.add_operator(op_x_r, state);
builder.add_operator(op_x_g, state); builder.add_operator(op_x_g, state);

View File

@ -24,6 +24,109 @@
#include <stb_image_resize2.h> #include <stb_image_resize2.h>
#include <stb_image_write.h> #include <stb_image_write.h>
struct stb_image_t
{
public:
stb_image_t() = default;
stb_image_t(const stb_image_t& copy) noexcept: width(copy.width), height(copy.height), channels(copy.channels)
{
data = static_cast<float*>(std::malloc(width * height * channels));
std::memcpy(data, copy.data, width * height * channels);
}
stb_image_t(stb_image_t&& move) noexcept:
width(move.width), height(move.height), channels(move.channels), data(std::exchange(move.data, nullptr))
{}
stb_image_t& operator=(const stb_image_t& copy)
{
if (&copy == this)
return *this;
if (width != copy.width || height != copy.height || channels != copy.channels)
{
width = copy.width;
height = copy.height;
channels = copy.channels;
stbi_image_free(data);
data = static_cast<float*>(std::malloc(width * height * channels * sizeof(float)));
}
std::memcpy(data, copy.data, width * height * channels);
return *this;
}
stb_image_t& operator=(stb_image_t&& move) noexcept
{
width = move.width;
height = move.height;
channels = move.channels;
data = std::exchange(move.data, data);
return *this;
}
stb_image_t& load(const std::string& path)
{
data = stbi_loadf(path.c_str(), &width, &height, &channels, CHANNELS);
channels = CHANNELS;
return *this;
}
stb_image_t& save(const std::string& str)
{
if (data == nullptr)
return *this;
auto uc_data = std::unique_ptr<unsigned char[]>(new unsigned char[width * height * channels]);
for (int i = 0; i < width * height * channels; i++)
uc_data[i] = static_cast<unsigned char>(data[i] * std::numeric_limits<unsigned char>::max());
stbi_write_png(str.c_str(), width, height, channels, uc_data.get(), 0);
return *this;
}
stb_image_t& resize(int new_width, int new_height)
{
auto new_data = static_cast<float*>(malloc(new_width * new_height * channels * sizeof(float)));
stbir_resize_float_linear(data, width, height, 0, new_data, new_width, new_height, 0,
static_cast<stbir_pixel_layout>(CHANNELS));
stbi_image_free(data);
data = new_data;
width = new_width;
height = new_height;
return *this;
}
[[nodiscard]] int get_width() const
{
return width;
}
[[nodiscard]] int get_height() const
{
return height;
}
float* get_data()
{
return data;
}
[[nodiscard]] const float* get_data() const
{
return data;
}
~stb_image_t()
{
stbi_image_free(data);
data = nullptr;
}
private:
int width{}, height{}, channels{};
float* data = nullptr;
};
struct full_image_t struct full_image_t
{ {
float rgb_data[DATA_SIZE * CHANNELS]{}; float rgb_data[DATA_SIZE * CHANNELS]{};
@ -44,9 +147,18 @@ struct full_image_t
stbi_image_free(data); stbi_image_free(data);
} }
void save(const std::string&) void load(const stb_image_t& image)
{ {
//stbi_write_png(str.c_str(), IMAGE_SIZE, IMAGE_SIZE, CHANNELS, rgb_data, 0); stbir_resize_float_linear(image.get_data(), image.get_width(), image.get_height(), 0, rgb_data, IMAGE_SIZE, IMAGE_SIZE, 0,
static_cast<stbir_pixel_layout>(CHANNELS));
}
void save(const std::string& str)
{
unsigned char data[DATA_SIZE * CHANNELS]{};
for (const auto& [index, value] : blt::enumerate(rgb_data))
data[index] = static_cast<unsigned char>(value * std::numeric_limits<unsigned char>::max());
stbi_write_png(str.c_str(), IMAGE_SIZE, IMAGE_SIZE, CHANNELS, data, 0);
} }
friend std::ostream& operator<<(std::ostream& str, const full_image_t&) friend std::ostream& operator<<(std::ostream& str, const full_image_t&)

View File

@ -122,7 +122,9 @@ class image_crossover_t : public blt::gp::crossover_t
std::array<full_image_t, POP_SIZE> generation_images; std::array<full_image_t, POP_SIZE> generation_images;
int match_method = cv::TM_SQDIFF;
full_image_t base_image; full_image_t base_image;
stb_image_t full_base_image;
blt::size_t last_run = 0; blt::size_t last_run = 0;
blt::i32 time_between_runs = 16; blt::i32 time_between_runs = 16;
bool is_running = false; bool is_running = false;
@ -246,6 +248,33 @@ constexpr auto create_fitness_function()
else else
fitness.raw_fitness += raw.total + raw.combined + 1.0; fitness.raw_fitness += raw.total + raw.combined + 1.0;
cv::Mat base_image_large{full_base_image.get_width(), full_base_image.get_height(), CV_32FC3, full_base_image.get_data()};
cv::Mat templ{IMAGE_SIZE, IMAGE_SIZE, CV_32FC3, v.rgb_data};
cv::Mat result;
int result_cols = base_image_large.cols - templ.cols + 1;
int result_rows = base_image_large.rows - templ.rows + 1;
result.create(result_rows, result_cols, CV_32FC1);
double minVal;
double maxVal;
cv::matchTemplate(base_image_large, templ, result, match_method);
minMaxLoc(result, &minVal, &maxVal, nullptr, nullptr, cv::Mat());
/// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
if (match_method == cv::TM_SQDIFF || match_method == cv::TM_SQDIFF_NORMED)
{
if (std::isinf(minVal) || std::isnan(minVal))
minVal = 200000;
fitness.raw_fitness += minVal * 0.01f;
//BLT_TRACE("%lf, %lf", minVal, maxVal);
} else
{
BLT_WARN("Hello!");
}
fitness.raw_fitness += last_fitness; fitness.raw_fitness += last_fitness;
} else } else
fitness.raw_fitness = fitness_values[index]; fitness.raw_fitness = fitness_values[index];
@ -323,7 +352,9 @@ void init(const blt::gfx::window_data&)
BLT_INFO("Using Seed: %ld", SEED); BLT_INFO("Using Seed: %ld", SEED);
BLT_START_INTERVAL("Image Test", "Main"); BLT_START_INTERVAL("Image Test", "Main");
BLT_DEBUG("Setup Base Image"); BLT_DEBUG("Setup Base Image");
base_image.load(load_image); full_base_image.load(load_image).resize(static_cast<int>(std::max(full_base_image.get_width() / 2ul, IMAGE_SIZE)),
static_cast<int>(std::max(full_base_image.get_height() / 2ul, IMAGE_SIZE)));
base_image.load(full_base_image);
BLT_DEBUG("Setup Types and Operators"); BLT_DEBUG("Setup Types and Operators");
type_system.register_type<full_image_t>(); type_system.register_type<full_image_t>();
@ -457,6 +488,7 @@ int main()
BLT_END_INTERVAL("Image Test", "Main"); BLT_END_INTERVAL("Image Test", "Main");
base_image.save("input.png"); base_image.save("input.png");
full_base_image.save("full_input.png");
auto v = get_fractal_value(base_image); auto v = get_fractal_value(base_image);
BLT_INFO("Base image values per channel: %lf", v.total); BLT_INFO("Base image values per channel: %lf", v.total);