main
Brett 2024-08-13 21:41:02 -04:00
parent 9675abd672
commit ce18a344c8
4 changed files with 77 additions and 52 deletions

View File

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

View File

@ -35,8 +35,8 @@ inline constexpr blt::size_t CHANNELS = 3;
inline constexpr blt::u64 u64_size_min = 1;
inline constexpr blt::u64 u64_size_max = 9;
inline constexpr float THRESHOLD = 0.5;
inline constexpr auto load_image = "../GSab4SWWcAA1TNR.png";
//inline constexpr auto load_image = "../hannah.png";
//inline constexpr auto load_image = "../GSab4SWWcAA1TNR.png";
inline constexpr auto load_image = "../hannah.png";
inline constexpr blt::size_t MAX_ARG_C = 8;
inline blt::gp::image_crossover_t image_crossover;

View File

@ -187,6 +187,10 @@ inline blt::gp::operation_t bilateral_filter([](const full_image_t& a, blt::u64
return img;
}, "bilateral_filter");
inline blt::gp::operation_t l_system([](const full_image_t& a) {
return a;
}, "l_system");
inline blt::gp::operation_t hsv_to_rgb([](const full_image_t& a) {
using blt::mem::type_cast;
full_image_t img{};
@ -399,6 +403,7 @@ void create_image_operations(blt::gp::operator_builder<context>& builder)
builder.add_operator(hsv_to_rgb);
builder.add_operator(gaussian_blur);
builder.add_operator(median_blur);
builder.add_operator(l_system);
// idk when it got enabled but this works on 4.10
#if CV_VERSION_MAJOR >= 4 && CV_VERSION_MINOR >= 10
builder.add_operator(bilateral_filter);

View File

@ -44,6 +44,19 @@ blt::gfx::first_person_camera_2d camera;
static constexpr blt::size_t TYPE_COUNT = 3;
const static int h_bins = 50, s_bins = 60;
const static int histSize[] = {h_bins, s_bins};
// hue varies from 0 to 179, saturation from 0 to 255
const static float h_ranges[] = {0, 180};
const static float s_ranges[] = {0, 256};
const static float* ranges[] = {h_ranges, s_ranges};
// Use the 0-th and 1-st channels
const static int channels[] = {0, 1};
float difference_weight = 0.01;
float fractal_weight = 1;
float histogram_weight = 2.0;
std::array<double, POP_SIZE> fitness_values{};
double last_fitness = 0;
double hovered_fitness = 0;
@ -108,22 +121,11 @@ std::array<std::function<void(blt::gp::gp_program& program, void*, void*)>, TYPE
}
};
class image_crossover_t : public blt::gp::crossover_t
{
public:
blt::expected<result_t, error_t> apply(blt::gp::gp_program& prog, const blt::gp::tree_t& p1, const blt::gp::tree_t& p2) final
{
auto sel = prog.get_random().choice();
if (sel)
return blt::gp::crossover_t::apply(prog, p1, p2);
std::abort();
}
};
std::array<full_image_t, POP_SIZE> generation_images;
int match_method = cv::TM_SQDIFF;
full_image_t base_image;
cv::Mat hsv_base;
cv::Mat hist_base;
stb_image_t full_base_image;
blt::size_t last_run = 0;
blt::i32 time_between_runs = 16;
@ -234,51 +236,38 @@ constexpr auto create_fitness_function()
if (fitness_values[index] < 0)
{
fitness.raw_fitness = 0;
double total_difference = 0;
for (blt::size_t i = 0; i < DATA_CHANNELS_SIZE; i++)
{
auto diff = compare_values(v.rgb_data[i], base_image.rgb_data[i]);
fitness.raw_fitness += diff;
total_difference += diff;
if (diff < 0.01)
fitness.raw_fitness -= fitness.raw_fitness * 0.02;
total_difference -= total_difference * 0.02;
}
fitness.raw_fitness /= (IMAGE_SIZE * IMAGE_SIZE);
double total_fractal = 0;
auto raw = get_fractal_value(v);
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));
//BLT_DEBUG("Fitness %lf %lf %lf || %lf => %lf (fit: %lf)", raw.r, raw.g, raw.b, raw.total, raw.combined, fit);
if (std::isnan(raw.total) || std::isnan(raw.combined))
fitness.raw_fitness += 400;
total_fractal += 400;
else
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!");
// }
total_fractal += raw.total + raw.combined + 1.0;
cv::Mat src{IMAGE_SIZE, IMAGE_SIZE, CV_32FC3, v.rgb_data};
cv::Mat src_hsv;
cv::Mat src_hist;
cv::cvtColor(src, src_hsv, cv::COLOR_RGB2HSV);
calcHist(&src_hsv, 1, channels, cv::Mat(), src_hist, 2, histSize, ranges, true, false);
normalize(src_hist, src_hist, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
// auto total_hist = compareHist(hist_base, src_hist, cv::HISTCMP_BHATTACHARYYA);
auto total_hist = compareHist(hist_base, src_hist, cv::HISTCMP_CORREL);
fitness.raw_fitness = (total_difference * difference_weight) + (total_fractal * fractal_weight) + (total_hist * histogram_weight);
/*BLT_TRACE(
"Normal Variants: {Difference: %lf | Fractal: %lf | Histogram: %lf } Weighted Variants: { Difference: %lf | Fractal: %lf | Histogram: %lf } Total Fitness: %lf",
total_difference, total_fractal, total_hist, (total_difference * difference_weight), (total_fractal * fractal_weight),
(total_hist * histogram_weight), fitness.raw_fitness);*/
fitness.raw_fitness += last_fitness;
} else
@ -361,6 +350,12 @@ void init(const blt::gfx::window_data&)
static_cast<int>(std::max(full_base_image.get_height() / 2ul, IMAGE_SIZE)));
base_image.load(full_base_image);
cv::Mat base{IMAGE_SIZE, IMAGE_SIZE, CV_32FC3, base_image.rgb_data};
cv::cvtColor(base, hsv_base, cv::COLOR_RGB2HSV);
cv::calcHist(&hsv_base, 1, channels, cv::Mat(), hist_base, 2, histSize, ranges, true, false);
cv::normalize(hist_base, hist_base, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());
BLT_DEBUG("Setup Types and Operators");
type_system.register_type<full_image_t>();
type_system.register_type<float>();
@ -399,6 +394,31 @@ void update(const blt::gfx::window_data& data)
program.reset_program(type_system.get_type<full_image_t>().id(), true);
ImGui::InputInt("Time Between Runs", &time_between_runs, 16);
ImGui::Checkbox("Run", &is_running);
ImGui::Separator();
static float difference_min = 0.001, difference_max = 1;
static float fractal_min = 0.1, fractal_max = 2.0;
static float hist_min = 0.1, hist_max = 5.0;
ImGui::InputFloat("Difference Min", &difference_min, difference_min / 2.0f);
ImGui::SameLine();
ImGui::InputFloat("Difference Max", &difference_max, difference_max / 2.0f);
ImGui::InputFloat("Fractal Min", &fractal_min, fractal_min / 2.0f);
ImGui::SameLine();
ImGui::InputFloat("Fractal Max", &fractal_max, fractal_max / 2.0f);
ImGui::InputFloat("Histogram Min", &hist_min, hist_min / 2.0f);
ImGui::SameLine();
ImGui::InputFloat("Histogram Max", &hist_max, hist_max / 2.0f);
ImGui::Separator();
ImGui::SliderFloat("Difference Weight", &difference_weight, difference_min, difference_max);
ImGui::SliderFloat("Fractal Weight", &fractal_weight, fractal_min, fractal_max);
ImGui::SliderFloat("Hist Weight", &histogram_weight, hist_min, hist_max);
auto& stats = program.get_population_stats();
ImGui::Text("Stats:");
ImGui::Text("Average fitness: %lf", stats.average_fitness.load());