more ops
parent
3fc1de7ea5
commit
614a5bef14
|
@ -52,4 +52,6 @@ std::array<blt::gp::population_t*, 3> get_populations();
|
|||
|
||||
void set_use_gamma_correction(bool use);
|
||||
|
||||
std::pair<std::array<std::vector<float>, 3>&, std::array<std::vector<float>, 3>&> get_mean_and_variance();
|
||||
|
||||
#endif //GP_SYSTEM_H
|
||||
|
|
|
@ -38,6 +38,22 @@ float filter_nan(const float f, const float failure = 0.0f)
|
|||
return f;
|
||||
}
|
||||
|
||||
std::vector<float> to_cv2(const image_t& a)
|
||||
{
|
||||
std::vector<float> converted_data(IMAGE_SIZE);
|
||||
for (const auto& [o, v] : blt::in_pairs(converted_data, a.get_data().data))
|
||||
o = static_cast<float>(v) / static_cast<float>(std::numeric_limits<blt::u32>::max());
|
||||
return converted_data;
|
||||
}
|
||||
|
||||
image_t from_cv2(const std::vector<float>& a)
|
||||
{
|
||||
image_t ret;
|
||||
for (const auto& [o, v] : blt::in_pairs(ret.get_data().data, a))
|
||||
o = static_cast<blt::u32>(v * static_cast<float>(std::numeric_limits<blt::u32>::max()));
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool use_gamma_correction = false;
|
||||
|
||||
std::array<gp_program*, 3> programs;
|
||||
|
@ -54,6 +70,9 @@ std::vector<float> best_fitness;
|
|||
std::vector<float> worst_fitness;
|
||||
std::vector<float> overall_fitness;
|
||||
|
||||
std::array<std::vector<float>, 3> mean_vec;
|
||||
std::array<std::vector<float>, 3> variance_vec;
|
||||
|
||||
template <size_t Channel>
|
||||
void fitness_func(const tree_t& tree, fitness_t& fitness, const blt::size_t index)
|
||||
{
|
||||
|
@ -203,6 +222,18 @@ void setup_operations(gp_program* program)
|
|||
ret.get_data().data[i] = static_cast<blt::u32>(std::exp(v / limit) * limit);
|
||||
return ret;
|
||||
}, "exp_image");
|
||||
static operation_t op_image_abs([](const image_t a) {
|
||||
image_t ret{};
|
||||
for (const auto& [i, v] : blt::enumerate(std::as_const(a.get_data().data)))
|
||||
ret.get_data().data[i] = std::numeric_limits<blt::u32>::max() - v;
|
||||
return ret;
|
||||
}, "abs_image");
|
||||
static operation_t op_image_mod([](const image_t a, const image_t b) {
|
||||
image_t ret{};
|
||||
for (const auto& [i, av, bv] : blt::in_pairs(std::as_const(a.get_data().data), std::as_const(b.get_data().data)).enumerate().flatten())
|
||||
ret.get_data().data[i] = bv == 0 ? 0 : av % bv;
|
||||
return ret;
|
||||
}, "mod_image");
|
||||
static operation_t op_image_or([](const image_t a, const image_t b) {
|
||||
image_t ret{};
|
||||
for (const auto& [i, av, bv] : blt::in_pairs(std::as_const(a.get_data().data), std::as_const(b.get_data().data)).enumerate().flatten())
|
||||
|
@ -227,6 +258,29 @@ void setup_operations(gp_program* program)
|
|||
ret.get_data().data[i] = ~av;
|
||||
return ret;
|
||||
}, "bit_not_image");
|
||||
static operation_t op_image_srgb([](const image_t a) {
|
||||
constexpr auto limit = static_cast<double>(std::numeric_limits<blt::u32>::max());
|
||||
image_t ret{};
|
||||
for (const auto& [i, av] : blt::enumerate(std::as_const(a.get_data().data)).flatten())
|
||||
ret.get_data().data[i] = static_cast<blt::u32>(std::pow(av / limit, 1.0/2.2) * limit);
|
||||
return ret;
|
||||
}, "srgb_image");
|
||||
static operation_t op_image_linear([](const image_t a) {
|
||||
struct f
|
||||
{
|
||||
static float srgb_to_linear(const float v) noexcept
|
||||
{
|
||||
return (v <= 0.04045f) ? (v / 12.92f)
|
||||
: std::pow((v + 0.055f) / 1.055f, 2.4f);
|
||||
}
|
||||
};
|
||||
|
||||
constexpr auto limit = static_cast<float>(std::numeric_limits<blt::u32>::max());
|
||||
image_t ret{};
|
||||
for (const auto& [i, av] : blt::enumerate(std::as_const(a.get_data().data)).flatten())
|
||||
ret.get_data().data[i] = static_cast<blt::u32>(f::srgb_to_linear(static_cast<float>(av) / limit) * limit);
|
||||
return ret;
|
||||
}, "srgb_image");
|
||||
static operation_t op_image_gt([](const image_t a, const image_t b) {
|
||||
image_t ret{};
|
||||
for (const auto& [i, av, bv] : blt::in_pairs(std::as_const(a.get_data().data), std::as_const(b.get_data().data)).enumerate().flatten())
|
||||
|
@ -313,62 +367,67 @@ void setup_operations(gp_program* program)
|
|||
}, "passthrough");
|
||||
|
||||
static operation_t op_erode([program](const image_t a) {
|
||||
constexpr auto limit = static_cast<float>(std::numeric_limits<blt::u32>::max());
|
||||
const auto erosion_size = program->get_random().get_i32(3, 12);
|
||||
std::vector<float> converted_data(IMAGE_SIZE);
|
||||
std::vector<float> converted_data = to_cv2(a);
|
||||
std::vector<float> output_data(IMAGE_SIZE);
|
||||
|
||||
for (const auto& [o, v] : blt::in_pairs(converted_data, a.get_data().data))
|
||||
o = static_cast<float>(v) / limit;
|
||||
|
||||
const cv::Mat src{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, converted_data.data()};
|
||||
cv::Mat dst{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, output_data.data()};
|
||||
|
||||
const cv::Mat element = cv::getStructuringElement( cv::MORPH_ERODE,
|
||||
cv::Size( erosion_size, erosion_size ));
|
||||
cv::erode( src, dst, element );
|
||||
const cv::Mat element = cv::getStructuringElement(cv::MORPH_ERODE, cv::Size(erosion_size, erosion_size));
|
||||
cv::erode(src, dst, element);
|
||||
|
||||
image_t ret{};
|
||||
for (const auto& [o, v] : blt::in_pairs(ret.get_data().data, output_data))
|
||||
o = static_cast<blt::u32>(v * limit);
|
||||
|
||||
return ret;
|
||||
return from_cv2(output_data);
|
||||
}, "erode_image");
|
||||
|
||||
static operation_t op_dilate([program](const image_t a) {
|
||||
constexpr auto limit = static_cast<float>(std::numeric_limits<blt::u32>::max());
|
||||
const auto dilate_size = program->get_random().get_i32(3, 12);
|
||||
std::vector<float> converted_data(IMAGE_SIZE);
|
||||
std::vector<float> converted_data = to_cv2(a);
|
||||
std::vector<float> output_data(IMAGE_SIZE);
|
||||
for (const auto& [o, v] : blt::in_pairs(converted_data, a.get_data().data))
|
||||
o = static_cast<float>(v) / limit;
|
||||
|
||||
const cv::Mat src{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, converted_data.data()};
|
||||
cv::Mat dst{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, output_data.data()};
|
||||
|
||||
const cv::Mat element = cv::getStructuringElement( cv::MORPH_DILATE,
|
||||
cv::Size( dilate_size, dilate_size ));
|
||||
cv::dilate( src, dst, element );
|
||||
const cv::Mat element = cv::getStructuringElement(cv::MORPH_DILATE, cv::Size(dilate_size, dilate_size));
|
||||
cv::dilate(src, dst, element);
|
||||
|
||||
image_t ret{};
|
||||
for (const auto& [o, v] : blt::in_pairs(ret.get_data().data, output_data))
|
||||
o = static_cast<blt::u32>(v * limit);
|
||||
|
||||
return ret;
|
||||
return from_cv2(output_data);
|
||||
}, "dilate_image");
|
||||
static operation_t op_band_pass([program](const image_t a) {
|
||||
auto input = to_cv2(a);
|
||||
std::vector<float> output_data(IMAGE_SIZE);
|
||||
|
||||
const cv::Mat src{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, input.data()};
|
||||
cv::Mat dst{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F, output_data.data()};
|
||||
|
||||
const auto sigmaLow = program->get_random().get_float(0.5f, 2.0f);
|
||||
const auto sigmaHigh = program->get_random().get_float(3.f, 12.f);
|
||||
|
||||
const auto size = program->get_random().get_i32(1,5) * 2 + 1;
|
||||
|
||||
cv::Mat low{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F}, high{IMAGE_DIMENSIONS, IMAGE_DIMENSIONS, CV_32F};
|
||||
cv::GaussianBlur(src, low, cv::Size(size, size), sigmaLow);
|
||||
cv::GaussianBlur(src, high, cv::Size(size, size), sigmaHigh);
|
||||
|
||||
cv::Mat dog = high - low;
|
||||
cv::normalize(dog, dog, 0, 1, cv::NORM_MINMAX);
|
||||
dog.copyTo(dst);
|
||||
|
||||
return from_cv2(output_data);
|
||||
}, "band_pass");
|
||||
|
||||
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_erode, op_dilate);
|
||||
// builder.build(op_erode, op_image_2d_perlin_oct);
|
||||
op_band_pass, op_image_perlin, op_image_noise, op_image_random, op_image_2d_perlin_eph, op_image_not, op_image_srgb,
|
||||
op_image_grad, op_image_2d_perlin_oct, op_erode, op_dilate, op_image_abs, op_image_mod, op_image_linear);
|
||||
// builder.build(op_thresh, op_image_2d_perlin_oct);
|
||||
program->set_operations(builder.grab());
|
||||
}
|
||||
|
||||
void setup_gp_system(const blt::size_t population_size)
|
||||
{
|
||||
reference_image = image_storage_t::from_file("../backend.png");
|
||||
reference_image = image_storage_t::from_file("../silly.png");
|
||||
|
||||
config.set_pop_size(population_size);
|
||||
config.set_elite_count(2);
|
||||
|
@ -416,6 +475,41 @@ void run_step()
|
|||
for (const auto program : programs)
|
||||
program->evaluate_fitness();
|
||||
for (const auto [i, program] : blt::enumerate(programs))
|
||||
{
|
||||
auto& cur = program->get_current_pop();
|
||||
auto mean = std::accumulate(cur.begin(), cur.end(), 0.0, [](const double a, const individual_t& b) {
|
||||
return a + b.fitness.adjusted_fitness;
|
||||
}) / static_cast<double>(cur.get_individuals().size());
|
||||
|
||||
auto variance = std::accumulate(cur.begin(), cur.end(), 0.0, [mean](const double a, const individual_t& b) {
|
||||
const auto amount = (b.fitness.adjusted_fitness - mean);
|
||||
return a + amount * amount;
|
||||
}) / static_cast<double>(cur.get_individuals().size());
|
||||
|
||||
mean_vec[i].push_back(static_cast<float>(mean));
|
||||
variance_vec[i].push_back(static_cast<float>(variance));
|
||||
|
||||
if (i == 0)
|
||||
BLT_TRACE("Channel Red");
|
||||
else if (i == 1)
|
||||
BLT_TRACE("Channel Green");
|
||||
else
|
||||
BLT_TRACE("Channel Blue");
|
||||
BLT_TRACE(" Program has variance of {}", variance);
|
||||
|
||||
if (program->get_random().choice())
|
||||
{
|
||||
const auto amount = static_cast<size_t>(static_cast<double>(cur.get_individuals().size()) * 0.1);
|
||||
for (size_t j = 0; j < amount; j++)
|
||||
{
|
||||
static grow_generator_t gen;
|
||||
const auto index = cur.get_individuals().size() - 1 - j;
|
||||
cur.get_individuals()[index].tree.regen(gen, program->get_typesystem().get_type<image_t>().id(), 6, 10);
|
||||
}
|
||||
}
|
||||
program->evaluate_fitness();
|
||||
}
|
||||
for (const auto [i, program] : blt::enumerate(programs))
|
||||
{
|
||||
const auto& stats = program->get_population_stats();
|
||||
if (i == 0)
|
||||
|
@ -449,8 +543,8 @@ 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())
|
||||
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;
|
||||
|
@ -537,4 +631,11 @@ std::array<population_t*, 3> get_populations()
|
|||
}
|
||||
|
||||
void set_use_gamma_correction(bool use)
|
||||
{use_gamma_correction = true;}
|
||||
{
|
||||
use_gamma_correction = true;
|
||||
}
|
||||
|
||||
std::pair<std::array<std::vector<float>, 3>&, std::array<std::vector<float>, 3>&> get_mean_and_variance()
|
||||
{
|
||||
return {mean_vec, variance_vec};
|
||||
}
|
||||
|
|
49
src/main.cpp
49
src/main.cpp
|
@ -200,7 +200,54 @@ void update(const blt::gfx::window_data& data)
|
|||
// 3. Statistics tab
|
||||
if (ImGui::BeginTabItem("Statistics"))
|
||||
{
|
||||
ImGui::Text("Here you can view statistics.");
|
||||
auto [mean_chan, variance_chan] = get_mean_and_variance();
|
||||
|
||||
for (const auto [i, mean] : blt::enumerate(mean_chan))
|
||||
{
|
||||
std::string type;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
type = "Red";
|
||||
break;
|
||||
case 1:
|
||||
type = "Green";
|
||||
break;
|
||||
case 2:
|
||||
type = "Blue";
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (ImPlot::BeginPlot(("Mean Graph " + type).c_str()))
|
||||
{
|
||||
ImPlot::PlotLine("Mean", mean.data(), static_cast<int>(mean.size()));
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto [i, variance] : blt::enumerate(variance_chan))
|
||||
{
|
||||
std::string type;
|
||||
switch (i)
|
||||
{
|
||||
case 0:
|
||||
type = "Red";
|
||||
break;
|
||||
case 1:
|
||||
type = "Green";
|
||||
break;
|
||||
case 2:
|
||||
type = "Blue";
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
if (ImPlot::BeginPlot(("Variance Graph " + type).c_str()))
|
||||
{
|
||||
ImPlot::PlotLine("Variance", variance.data(), static_cast<int>(variance.size()));
|
||||
ImPlot::EndPlot();
|
||||
}
|
||||
}
|
||||
|
||||
auto pops = get_populations();
|
||||
|
||||
|
|
Loading…
Reference in New Issue