From 13e59c2dc479c9fb43c5bc470d037d1b6d5a796c Mon Sep 17 00:00:00 2001 From: Phuntsok Drak-pa Date: Thu, 21 Mar 2019 02:49:00 +0100 Subject: [PATCH] added method 2 --- CMakeLists.txt | 1 + include/genimg/method1.hh | 3 ++ src/main.cc | 4 ++ src/method1.cc | 85 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 89 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 70c13b3..c2b4730 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ conan_basic_setup() enable_cxx_compiler_flag_if_supported("-Wall") enable_cxx_compiler_flag_if_supported("-pedantic") +enable_cxx_compiler_flag_if_supported("-O3") # include_directories() set(TGT genetic-image) diff --git a/include/genimg/method1.hh b/include/genimg/method1.hh index 15710a4..4c92613 100644 --- a/include/genimg/method1.hh +++ b/include/genimg/method1.hh @@ -9,4 +9,7 @@ void method1(cv::Mat &t_reference, cv::Mat &t_output, int t_iterations, std::mt19937 &t_gen); +void method2(cv::Mat &t_reference, cv::Mat &t_output, int t_iterations, + std::mt19937 &t_gen); + #endif /* GENETIC_IMAGE_INCLUDE_GENIMG_METHOD1_METHOD1_HH_ */ diff --git a/src/main.cc b/src/main.cc index 51f5957..a51d509 100644 --- a/src/main.cc +++ b/src/main.cc @@ -18,6 +18,10 @@ int main(int ac, char **av) { method1(input_image, process_image, iterations, gen); break; } + case 2: { + method2(input_image, process_image, iterations, gen); + break; + } default: spdlog::error("Requested method {} is not implemented."); std::exit(-1); diff --git a/src/method1.cc b/src/method1.cc index 9499192..62a4ba5 100644 --- a/src/method1.cc +++ b/src/method1.cc @@ -2,12 +2,21 @@ #include "common.hh" #include "drawing.hh" #include +#include +#include +#include + +const auto thread_nbr = std::thread::hardware_concurrency(); +std::mutex numbers_mutex; using randint = std::uniform_int_distribution<>; +using Color = std::array; +using ColorSet = std::vector; -void newSquare(cv::Mat &t_process_img, std::mt19937 &t_gen, randint &t_dist) { - const int square_size = t_dist(t_gen); - auto square_top_left = cv::Point{t_dist(t_gen), t_dist(t_gen)}; +void newSquare1(cv::Mat &t_process_img, std::mt19937 &t_gen, + randint &t_rand_pos) { + const int square_size = t_rand_pos(t_gen); + auto square_top_left = cv::Point{t_rand_pos(t_gen), t_rand_pos(t_gen)}; draw_shape(t_process_img, square_top_left, square_size, random_color(t_gen), Shapes::Square); } @@ -21,7 +30,75 @@ void method1(cv::Mat &t_reference, cv::Mat &t_output, int t_iterations, spdlog::info("Beginning method1, initial difference: {}", diff); while (t_iterations > 0) { auto temp_image = t_output.clone(); - newSquare(temp_image, t_gen, dist); + newSquare1(temp_image, t_gen, dist); + if (auto new_diff = euclidian_distance(t_reference, temp_image); + new_diff < diff) { + diff = new_diff; + temp_image.copyTo(t_output); + --t_iterations; + spdlog::info("Iteration {}: diff {}", t_iterations, diff); + } + } +} + +void threadedGetColor(cv::Mat &t_reference, ColorSet &t_colors, int t_h) { + if (t_h > t_reference.size().height) + return; + for (int w = 0; w < t_reference.size().width; w += 3) { + Color temp = {t_reference.at(t_h, w), + t_reference.at(t_h, w + 1), + t_reference.at(t_h, w + 2)}; + auto pos = std::find(std::begin(t_colors), std::end(t_colors), temp); + if (pos == std::end(t_colors)) { + numbers_mutex.lock(); + t_colors.push_back(temp); + numbers_mutex.unlock(); + } + } +} + +ColorSet getColorSet(cv::Mat &t_reference) { + ColorSet res{}; + for (int h = 0; h < t_reference.size().height; h += thread_nbr) { + std::vector thread_list{}; + for (int i = 0; i < thread_nbr; ++i) { + thread_list.push_back(std::thread(threadedGetColor, std::ref(t_reference), + std::ref(res), h + i)); + } + for (auto &th : thread_list) + th.join(); + } + res.shrink_to_fit(); + return res; +} + +void newSquare2(cv::Mat &t_process_img, std::mt19937 &t_gen, + ColorSet const &t_colors, randint &t_rand_pos, + randint &t_rand_color) { + int const square_size = t_rand_pos(t_gen); + auto square_top_left = cv::Point{t_rand_pos(t_gen), t_rand_pos(t_gen)}; + const auto color = t_colors[t_rand_color(t_gen)]; + draw_shape(t_process_img, square_top_left, square_size, + cv::Scalar{static_cast(color[0]), + static_cast(color[1]), + static_cast(color[2])}, + Shapes::Square); +} + +void method2(cv::Mat &t_reference, cv::Mat &t_output, int t_iterations, + std::mt19937 &t_gen) { + auto diff = euclidian_distance(t_reference, t_output); + auto const max_size = + std::max(t_reference.size().width, t_reference.size().height); + randint dist(0, max_size); + spdlog::info("Beginning method2, initial difference: {}", diff); + auto const colors = getColorSet(t_reference); + spdlog::info("Running {} threads.", thread_nbr); + spdlog::info("{} colors detected.", colors.size()); + randint rand_color(0, colors.size()); + while (t_iterations > 0) { + auto temp_image = t_output.clone(); + newSquare2(temp_image, t_gen, colors, dist, rand_color); if (auto new_diff = euclidian_distance(t_reference, temp_image); new_diff < diff) { diff = new_diff;