diff --git a/CMakeLists.txt b/CMakeLists.txt index c89645f..2516c13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,10 @@ add_subdirectory(libraries/BLT-With-Graphics-Template) include_directories(include/) file(GLOB_RECURSE PROJECT_BUILD_FILES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") -add_dependencies(BLT stats_lib_bindings_rust) +#set(META_LIBS common/pdqhashtypes.cpp io/hashio.cpp common/pdqhamming.cpp hashing/pdqhashing.cpp downscaling/downscaling.cpp hashing/torben.cpp) +#include_directories(libraries/ThreatExchange) +# +#list(TRANSFORM META_LIBS PREPEND ${CMAKE_SOURCE_DIR}/libraries/ThreatExchange/pdq/cpp/) add_executable(gp_image_test ${PROJECT_BUILD_FILES}) diff --git a/images/029a_-_Survival_of_the_Idiots_349.jpg b/images/029a_-_Survival_of_the_Idiots_349.jpg new file mode 100755 index 0000000..5a9cdbf Binary files /dev/null and b/images/029a_-_Survival_of_the_Idiots_349.jpg differ diff --git a/include/functions.h b/include/functions.h index 0095899..cff6082 100644 --- a/include/functions.h +++ b/include/functions.h @@ -264,6 +264,8 @@ float eval_DNF_SW(const image& img); float eval_DNF_SW_1(const image& img); +float eval_BAM(const image& img, const image& compare, float allowed_diff); + //template //bool isNan(F f) //{ diff --git a/include/image.h b/include/image.h index 445da9c..ad73a28 100644 --- a/include/image.h +++ b/include/image.h @@ -62,7 +62,7 @@ class image }, copy.data); } - image(image&& move) + image(image&& move) noexcept { data = std::move(move.data); move.data = nullptr; @@ -92,7 +92,7 @@ class image return *this; }; - image& operator=(image&& move) + image& operator=(image&& move) noexcept { std::swap(move.data, data); return *this; @@ -165,7 +165,7 @@ class image return std::visit(blt::lambda_visitor{ [x, y](const image_data_t* d) -> blt::vec3 { if (x < 0 || y < 0 || x >= width || y >= height) - return blt::vec3{0,0,0}; + return blt::vec3{0, 0, 0}; return (*d)[y * height + x]; }, [](const blt::vec3& v) -> blt::vec3 { diff --git a/src/functions.cpp b/src/functions.cpp index 7c74cb0..56fb804 100644 --- a/src/functions.cpp +++ b/src/functions.cpp @@ -243,9 +243,9 @@ void f_equ(image& img, float x, float y, blt::size_t argc, const image** argv, c GET_IMAGE(i2, 1); if (f_comp(i1.x(), i2.x()) && f_comp(i1.y(), i2.y()) && f_comp(i1.z(), i2.z())) - img.set({1,1,1}, xi, yi); + img.set({1, 1, 1}, xi, yi); else - img.set({0,0,0}, xi, yi); + img.set({0, 0, 0}, xi, yi); } void f_lt(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) @@ -255,9 +255,9 @@ void f_lt(image& img, float x, float y, blt::size_t argc, const image** argv, co GET_IMAGE(i2, 1); if (i1.x() < i2.x() && i1.y() < i2.y() && i1.z() < i2.z()) - img.set({1,1,1}, xi, yi); + img.set({1, 1, 1}, xi, yi); else - img.set({0,0,0}, xi, yi); + img.set({0, 0, 0}, xi, yi); } void f_gt(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) @@ -267,9 +267,9 @@ void f_gt(image& img, float x, float y, blt::size_t argc, const image** argv, co GET_IMAGE(i2, 1); if (i1.x() > i2.x() && i1.y() > i2.y() && i1.z() > i2.z()) - img.set({1,1,1}, xi, yi); + img.set({1, 1, 1}, xi, yi); else - img.set({0,0,0}, xi, yi); + img.set({0, 0, 0}, xi, yi); } void f_lte(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) @@ -279,9 +279,9 @@ void f_lte(image& img, float x, float y, blt::size_t argc, const image** argv, c GET_IMAGE(i2, 1); if (i1.x() <= i2.x() && i1.y() <= i2.y() && i1.z() <= i2.z()) - img.set({1,1,1}, xi, yi); + img.set({1, 1, 1}, xi, yi); else - img.set({0,0,0}, xi, yi); + img.set({0, 0, 0}, xi, yi); } void f_gte(image& img, float x, float y, blt::size_t argc, const image** argv, const data_t& extra_data) @@ -291,9 +291,9 @@ void f_gte(image& img, float x, float y, blt::size_t argc, const image** argv, c GET_IMAGE(i2, 1); if (i1.x() >= i2.x() && i1.y() >= i2.y() && i1.z() >= i2.z()) - img.set({1,1,1}, xi, yi); + img.set({1, 1, 1}, xi, yi); else - img.set({0,0,0}, xi, yi); + img.set({0, 0, 0}, xi, yi); } double on_data(const double* data, blt::size_t len) @@ -349,11 +349,13 @@ float eval_DNF_SW_1(const image& img) std::vector order(width * height); for (const auto& v : img.getData()) + { order.push_back(v.magnitude()); + } std::sort(order.begin(), order.end()); - blt::size_t len = width; + blt::size_t len = width * 4; blt::size_t current_pos = 0; double total = 0; while (true) @@ -371,3 +373,29 @@ float eval_DNF_SW_1(const image& img) return static_cast(total); } +float eval_BAM(const image& img, const image& compare, float allowed_diff) +{ + float values = 1; + for (blt::i32 i = 0; i < width; i++) + { + for (blt::i32 j = 0; j < height; j++) + { + auto v1 = img.get(i, j); + auto v2 = compare.get(i, j); + + auto r = std::abs(v1.x() - v2.x()); + auto g = std::abs(v1.y() - v2.y()); + auto b = std::abs(v1.z() - v2.z()); + + if (r <= allowed_diff) + values += 1 - r; + if (g <= allowed_diff) + values += 1 - g; + if (b <= allowed_diff) + values += 1 - b; + + } + } + return values; +} + diff --git a/src/main.cpp b/src/main.cpp index c92be02..d080927 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include "blt/gfx/renderer/resource_manager.h" #include "blt/gfx/renderer/batch_2d_renderer.h" @@ -25,9 +26,38 @@ blt::gfx::matrix_state_manager global_matrices; blt::gfx::resource_manager resources; blt::gfx::batch_renderer_2d renderer_2d(resources); +image compare; + class tree { public: +#define CROSSOVER_ERRORS \ + INST_ENUM(NULL_PARENT1) \ + INST_ENUM(NULL_PARENT2) \ + INST_ENUM(NULL_TREE1) \ + INST_ENUM(NULL_TREE2) \ + INST_ENUM(TYPE_NOT_ALLOWED_CHILD1) \ + INST_ENUM(TYPE_NOT_ALLOWED_CHILD2) + +#define INST_ENUM(TYPE) TYPE, + + enum class crossover_error_t + { + CROSSOVER_ERRORS + }; + +#undef INST_ENUM +#define INST_ENUM(TYPE) case crossover_error_t::TYPE: return #TYPE; + + static inline std::string crossover_error_to_string(crossover_error_t error) + { + switch (error) + { + CROSSOVER_ERRORS + } + return ""; + } + struct search_result_t { node* child; @@ -93,7 +123,7 @@ class tree while (true) { std::uniform_int_distribution children(0, current->argc - 1); - if (select(engine) == 0 || current->argc == 0) + if (parent != nullptr && (select(engine) == 0 || current->argc == 0)) break; index = children(engine); auto* next = current->sub_nodes[index]; @@ -102,6 +132,7 @@ class tree parent = current; current = next; } + return {current, parent, index}; } @@ -142,26 +173,30 @@ class tree return max_depth; } - static std::optional crossover(tree* p1, tree* p2) + static blt::expected crossover(tree* p1, tree* p2) { - if (p1 == nullptr || p2 == nullptr) - return {}; + if (p1 == nullptr) + return blt::unexpected(crossover_error_t::NULL_TREE1); + if (p2 == nullptr) + return blt::unexpected(crossover_error_t::NULL_TREE2); auto c1 = p1->clone(); auto c2 = p2->clone(); auto n1 = c1->select_random_child(); auto n2 = c2->select_random_child(); - if (n1.parent == nullptr || n2.parent == nullptr) - return {}; + if (n1.parent == nullptr) + return blt::unexpected(crossover_error_t::NULL_PARENT1); + if (n2.parent == nullptr) + return blt::unexpected(crossover_error_t::NULL_PARENT2); const auto& p1_allowed = function_arg_allowed_set_map[to_underlying(n1.parent->type)][n1.index]; const auto& p2_allowed = function_arg_allowed_set_map[to_underlying(n2.parent->type)][n2.index]; if (!p1_allowed.contains(n2.child->type)) - return {}; + return blt::unexpected(crossover_error_t::TYPE_NOT_ALLOWED_CHILD1); if (!p2_allowed.contains(n1.child->type)) - return {}; + return blt::unexpected(crossover_error_t::TYPE_NOT_ALLOWED_CHILD2); n1.parent->sub_nodes[n1.index] = n2.child; n2.parent->sub_nodes[n2.index] = n1.child; @@ -216,7 +251,7 @@ class tree float fitness() { auto& img = root->getImage(); - return eval_DNF_SW(img) * eval_DNF_SW_1(img) * static_cast(std::min(depth(root.get()), 5ul)); + return eval_BAM(img, compare, 0.1) * eval_DNF_SW_1(img) * static_cast(std::min(depth(root.get()), 5ul)); } void printTree() @@ -228,10 +263,6 @@ class tree class gp_population { public: - enum class crossover_error_t - { - - }; struct selection { blt::size_t index; @@ -329,6 +360,9 @@ class gp_population new_pop[p1.index] = {std::move(r->c1)}; new_pop[p2.index] = {std::move(r->c2)}; crossover_count++; + } else + { + BLT_ERROR(tree::crossover_error_to_string(r.error())); } } } @@ -426,6 +460,30 @@ void init() resources.set("img", texture); resources.enqueue("../libraries/BLT-With-Graphics-Template/resources/textures/parkerfemBOY.png", "cum"); + int x, y, channels; + auto data = stbi_load("../images/029a_-_Survival_of_the_Idiots_349.jpg", &x, &y, &channels, 3); + + if (data == nullptr) + throw std::runtime_error("failed to load compare image!"); + + auto resized = stbir_resize_uint8_linear(data, x, y, 0, nullptr, width, height, 0, (stbir_pixel_layout) 3); + + for (int j = 0; j < height; j++) + { + for (int i = 0; i < width; i++) + { + blt::size_t loc = (j * width + i) * 3; +#define CONVERT(v) static_cast(v) / static_cast(std::numeric_limits::max()) + compare.set(blt::vec3{CONVERT(resized[loc]), CONVERT(resized[loc + 1]), CONVERT(resized[loc + 2])}, i, height - 1 - j); +#undef CONVERT + } + } + + texture->upload((void*) compare.getData().data(), GL_RGB, 0, 0, 0, -1, -1, GL_FLOAT); + + stbi_image_free(data); + stbi_image_free(resized); + resources.load_resources(); }