From 72b91ab1b108e7b16b2496611bfb412454bc3f7c Mon Sep 17 00:00:00 2001 From: Phuntsok Drak-pa Date: Tue, 2 Apr 2019 10:37:14 +0200 Subject: [PATCH] less duplicate code --- include/genimg/methods.hh | 27 ++++++++++ src/methods.cc | 109 ++++++++++++++++++++++---------------- 2 files changed, 91 insertions(+), 45 deletions(-) diff --git a/include/genimg/methods.hh b/include/genimg/methods.hh index f727876..9c8771d 100644 --- a/include/genimg/methods.hh +++ b/include/genimg/methods.hh @@ -4,6 +4,33 @@ #include #include #include +#include +#include + +namespace methods_private { + +[[nodiscard]] auto randomColor(); +[[nodiscard]] auto getColorSet(cv::Mat const& t_reference); +[[nodiscard]] auto getSquareValues(cv::Mat const& t_img); +[[nodiscard]] auto createCandidate( + cv::Mat const& t_base, + cv::Mat const& t_ref, + std::vector> const& t_colors, + double const diff, + bool const t_controlled_size); +void adjustSize(cv::Mat const& t_process_img, + cv::Point& t_top_left, + int t_size); +void threadedGetColor(cv::Mat const& t_reference, + std::vector>& t_colors, + int t_h); +void newSquare1(cv::Mat& t_process_img, cv::Point&& t_top_left, int t_size); +void newSquare2(cv::Mat& t_process_img, + cv::Point&& t_top_left, + int t_size, + std::array const& t_color); + +} // namespace methods_private void method1(cv::Mat const&, cv::Mat&, int); diff --git a/src/methods.cc b/src/methods.cc index c332959..0252692 100644 --- a/src/methods.cc +++ b/src/methods.cc @@ -4,7 +4,9 @@ #include #include #include +#include #include +#include #include auto const thread_nbr = std::thread::hardware_concurrency(); @@ -17,6 +19,57 @@ using std::rand; namespace methods_private { +[[nodiscard]] auto randomColor() +{ + static std::uniform_int_distribution<> dis(0, 255); + return cv::Scalar(rand() % 255, rand() % 255, rand() % 255); +} + +[[nodiscard]] auto getColorSet(cv::Mat const& t_reference) +{ + ColorSet res{}; + for (int h = 0; h < t_reference.size().height; h += thread_nbr) { + std::vector thread_list{}; + for (auto i = 0u; i < thread_nbr; ++i) { + thread_list.push_back(std::thread(methods_private::threadedGetColor, + std::ref(t_reference), std::ref(res), + h + i)); + } + for (auto& th : thread_list) + th.join(); + } + res.shrink_to_fit(); + return res; +} + +[[nodiscard]] auto getSquareValues(cv::Mat const& t_img) +{ + int rand_x = rand() % t_img.size().width; + int rand_y = rand() % t_img.size().height; + int size + = rand() + % std::min(t_img.size().width - rand_x, t_img.size().height - rand_y); + return std::tuple(rand_x, rand_y, size); +} + +[[nodiscard]] auto createCandidate(cv::Mat const& t_base, + cv::Mat const& t_ref, + ColorSet const& t_colors, + double const diff, + bool const t_controlled_size) +{ + auto temp_image = t_base.clone(); + auto const [rand_x, rand_y, size] + = methods_private::getSquareValues(temp_image); + methods_private::newSquare2(temp_image, cv::Point{rand_x, rand_y}, size, + t_colors[rand() % t_colors.size()]); + auto new_diff = euclidian_distance(t_ref, temp_image); + return (new_diff < diff) + ? std::optional>{std::make_pair( + std::move(temp_image), new_diff)} + : std::nullopt; +} + void adjustSize(cv::Mat const& t_process_img, cv::Point& t_top_left, int size) { int const height = t_process_img.size().height; @@ -31,18 +84,6 @@ void adjustSize(cv::Mat const& t_process_img, cv::Point& t_top_left, int size) } } -[[nodiscard]] auto randomColor() -> cv::Scalar -{ - static std::uniform_int_distribution<> dis(0, 255); - return cv::Scalar(rand() % 255, rand() % 255, rand() % 255); -} - -void newSquare1(cv::Mat& t_process_img, cv::Point&& t_top_left, int t_size) -{ - adjustSize(t_process_img, t_top_left, t_size); - draw_shape(t_process_img, t_top_left, t_size, randomColor(), Shapes::Square); -} - void threadedGetColor(cv::Mat const& t_reference, ColorSet& t_colors, int t_h) { if (t_h > t_reference.size().height) @@ -60,21 +101,10 @@ void threadedGetColor(cv::Mat const& t_reference, ColorSet& t_colors, int t_h) } } -[[nodiscard]] auto getColorSet(cv::Mat const& t_reference) -> ColorSet +void newSquare1(cv::Mat& t_process_img, cv::Point&& t_top_left, int t_size) { - ColorSet res{}; - for (int h = 0; h < t_reference.size().height; h += thread_nbr) { - std::vector thread_list{}; - for (auto i = 0u; i < thread_nbr; ++i) { - thread_list.push_back(std::thread(methods_private::threadedGetColor, - std::ref(t_reference), std::ref(res), - h + i)); - } - for (auto& th : thread_list) - th.join(); - } - res.shrink_to_fit(); - return res; + adjustSize(t_process_img, t_top_left, t_size); + draw_shape(t_process_img, t_top_left, t_size, randomColor(), Shapes::Square); } void newSquare2(cv::Mat& t_process_img, @@ -97,11 +127,8 @@ void method1(cv::Mat const& t_reference, cv::Mat& t_output, int t_iterations) spdlog::debug("Beginning method1, initial difference: {}", diff); while (t_iterations > 0 && diff >= 0) { auto temp_image = t_output.clone(); - int const rand_x = rand() % temp_image.size().width; - int const rand_y = rand() % temp_image.size().height; - int const size = rand() - % std::min(t_reference.size().width - rand_x, - t_reference.size().height - rand_y); + auto const [rand_x, rand_y, size] + = methods_private::getSquareValues(temp_image); methods_private::newSquare1(temp_image, cv::Point{rand_x, rand_y}, size); if (auto const new_diff = euclidian_distance(t_reference, temp_image); new_diff < diff) { @@ -115,25 +142,17 @@ void method1(cv::Mat const& t_reference, cv::Mat& t_output, int t_iterations) void method2(cv::Mat const& t_reference, cv::Mat& t_output, int t_iterations) { + spdlog::debug("Running on {} thread(s).", thread_nbr); auto diff = euclidian_distance(t_reference, t_output); spdlog::debug("Beginning method2, initial difference: {}", diff); - spdlog::debug("Running {} threads.", thread_nbr); auto const colors = methods_private::getColorSet(t_reference); spdlog::debug("{} colors detected.", colors.size()); - while (t_iterations > 0) { - auto temp_image = t_output.clone(); - int const rand_x = rand() % temp_image.size().width; - int const rand_y = rand() % temp_image.size().height; - int const size = rand() - % std::min(t_reference.size().width - rand_x, - t_reference.size().height - rand_y); - methods_private::newSquare2(temp_image, cv::Point{rand_x, rand_y}, size, - colors[rand() % colors.size()]); - if (auto new_diff = euclidian_distance(t_reference, temp_image); - new_diff < diff) { - diff = new_diff; - temp_image.copyTo(t_output); + if (auto result = methods_private::createCandidate(t_output, t_reference, + colors, diff, false); + result.has_value()) { + diff = result->second; + result->first.copyTo(t_output); --t_iterations; spdlog::debug("iteration:{} diff:{}", t_iterations, diff); }