From cbad530d4ae9b034cc51802aa54fb56300ed7a44 Mon Sep 17 00:00:00 2001 From: Phuntsok Drak-pa Date: Sat, 13 Apr 2019 14:26:01 +0200 Subject: [PATCH] Big code refactor, now the interface is easier to use --- include/genimg/common.hh | 15 -- include/genimg/drawing.hh | 15 -- include/genimg/methods.hh | 95 +++++---- src/common.cc | 33 --- src/drawing.cc | 35 ---- src/main.cc | 34 +-- src/methods.cc | 424 ++++++++++++++++++++------------------ 7 files changed, 291 insertions(+), 360 deletions(-) delete mode 100644 include/genimg/common.hh delete mode 100644 include/genimg/drawing.hh delete mode 100644 src/common.cc delete mode 100644 src/drawing.cc diff --git a/include/genimg/common.hh b/include/genimg/common.hh deleted file mode 100644 index 16f9003..0000000 --- a/include/genimg/common.hh +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef GENETIC_IMAGE_INCLUDE_GENIMG_COMMON_HH_ -#define GENETIC_IMAGE_INCLUDE_GENIMG_COMMON_HH_ - -#include -#include -#include -#include -#include - -[[nodiscard]] auto init_image(std::string const&) noexcept - -> std::pair; - -[[nodiscard]] auto euclidian_distance(cv::Mat const&, cv::Mat const&) -> double; - -#endif /* GENETIC_IMAGE_INCLUDE_GENIMG_COMMON_HH_ */ diff --git a/include/genimg/drawing.hh b/include/genimg/drawing.hh deleted file mode 100644 index e386268..0000000 --- a/include/genimg/drawing.hh +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef GENETIC_IMAGE_INCLUDE_GENIMG_DRAWING_HH_ -#define GENETIC_IMAGE_INCLUDE_GENIMG_DRAWING_HH_ - -#include -#include - -enum class Shapes { Square, Circle }; - -void draw_shape(cv::Mat&, - cv::Point const&, - int const, - cv::Scalar const&, - Shapes const&); - -#endif /* GENETIC_IMAGE_INCLUDE_GENIMG_DRAWING_HH_ */ diff --git a/include/genimg/methods.hh b/include/genimg/methods.hh index 1cf9f56..fde0c0b 100644 --- a/include/genimg/methods.hh +++ b/include/genimg/methods.hh @@ -1,50 +1,71 @@ -#ifndef GENETIC_IMAGE_INCLUDE_GENIMG_METHODS_HH_ -#define GENETIC_IMAGE_INCLUDE_GENIMG_METHODS_HH_ +#pragma once +#include #include #include +#include #include +#include +#include #include #include -namespace methods_private { +class ImageManipulator { + public: + ImageManipulator() = delete; + ImageManipulator(const ImageManipulator& other) = delete; + ImageManipulator(ImageManipulator&& other) noexcept = delete; + ImageManipulator& operator=(const ImageManipulator& other) = delete; + ImageManipulator& operator=(ImageManipulator&& other) noexcept = delete; -[[nodiscard]] auto randomColor(); -[[nodiscard]] auto getColorSet(cv::Mat const& t_reference); -[[nodiscard]] auto getSquareValues(cv::Mat const& t_img); -[[nodiscard]] auto getControlledSquareValues(cv::Mat const& t_img, - int const t_init_iter, - int const t_iter); -[[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, - int const t_init_iter, - int const t_iter); -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); + // Load image from input, and prepare for output + ImageManipulator(std::filesystem::path const t_input_path, + std::filesystem::path const t_output_path, + int const iterations); + // ImageManipulator(cv::Mat const& t_origin_image, + // int const iterations, + // int const t_x, + // int const t_y, + // int const t_width, + // int const t_height); -} // namespace methods_private + void exec_method(int const t_nb_method, bool const t_controlled_size); + void write_file() const; -void method1(cv::Mat const&, cv::Mat&, int); + //! Destructor + virtual ~ImageManipulator() noexcept = default; -void method2(cv::Mat const&, cv::Mat&, int); + protected: + private: + [[nodiscard]] auto euclidian_distance(cv::Mat const& t_img) const noexcept + -> double; + [[nodiscard]] auto random_color() const noexcept; + [[nodiscard]] auto get_square_values() const noexcept; + [[nodiscard]] auto get_controlled_square_values() const noexcept; + [[nodiscard]] auto create_candidate(bool const t_controlled_size) const; -void method3(cv::Mat const&, cv::Mat&, int); + void get_color_set(); + void threaded_get_color(int t_h); + void adjust_size(cv::Point& t_top_left, int const size) noexcept; + void draw_square(cv::Mat& t_img, + cv::Point const& t_top_left, + int const t_size, + cv::Scalar const& t_color) const; + void update_gen_image(cv::Mat const& t_img, double const t_diff); + void method1(); + void method2(); + void method3(); + void method4(bool const t_controlled_size); -void method4(cv::Mat const&, cv::Mat&, int, bool); - -void method5(cv::Mat const&, cv::Mat&, int, int, bool); - -#endif /* GENETIC_IMAGE_INCLUDE_GENIMG_METHODS_HH_ */ + std::vector> colors_ + = std::vector>{}; + cv::Mat const reference_; + cv::Mat generated_image_; + std::mutex colors_mutex_ = std::mutex{}; + std::string const output_path_; + double diff_ = 0.0; + int const total_iterations_ = 0; + int remaining_iter_ = 0; + int const width_; + int const height_; +}; diff --git a/src/common.cc b/src/common.cc deleted file mode 100644 index 23d1a10..0000000 --- a/src/common.cc +++ /dev/null @@ -1,33 +0,0 @@ -#include "common.hh" -#include -#include -#include - -[[nodiscard]] auto init_image(std::string const& t_input_file) noexcept - -> std::pair -{ - cv::Mat input_image = cv::imread(t_input_file, cv::IMREAD_COLOR); - if (!input_image.data) { - spdlog::critical("Could not open or find image!\n"); - exit(-1); - } - spdlog::debug("Image loaded!"); - spdlog::debug("Width:\t{}", input_image.size().width); - spdlog::debug("Height:\t{}", input_image.size().height); - cv::Mat process_image(input_image.size().height, input_image.size().width, - CV_8UC3, cv::Scalar(0, 0, 0)); - return std::make_pair(std::move(input_image), process_image); -} - -[[nodiscard]] auto euclidian_distance(cv::Mat const& t_img1, - cv::Mat const& t_img2) -> double -{ - double euclidian = 0.0; - for (auto itr1 = t_img1.begin(), itr2 = t_img2.begin(); - itr1 != t_img1.end() && itr2 != t_img2.end(); - ++itr1, ++itr2) { - euclidian += std::pow(*itr1 - *itr2, 2); - } - euclidian = std::sqrt(euclidian); - return euclidian; -} diff --git a/src/drawing.cc b/src/drawing.cc deleted file mode 100644 index e80c316..0000000 --- a/src/drawing.cc +++ /dev/null @@ -1,35 +0,0 @@ -#include "drawing.hh" -#include -#include -#include -#include - -void drawSquare(cv::Mat& t_img, - cv::Point const& t_top_left, - int const t_size, - cv::Scalar const& t_color) -{ - auto points = std::make_unique(4); - points.get()[0] = t_top_left; - points.get()[1] = cv::Point{t_top_left.x, t_top_left.y + t_size}; - points.get()[2] = cv::Point{t_top_left.x + t_size, t_top_left.y + t_size}; - points.get()[3] = cv::Point{t_top_left.x + t_size, t_top_left.y}; - fillConvexPoly(t_img, points.get(), 4, t_color); -} - -void draw_shape(cv::Mat& t_img, - cv::Point const& t_top_left, - int const t_size, - cv::Scalar const& t_color, - Shapes const& t_shape) -{ - switch (t_shape) { - case Shapes::Square: { - drawSquare(t_img, t_top_left, t_size, t_color); - break; - } - default: - spdlog::error("Shape does not exist. Aborting..."); - std::exit(1); - } -} diff --git a/src/main.cc b/src/main.cc index 938b3f9..b062385 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,4 +1,3 @@ -#include "common.hh" #include "methods.hh" #include "parseargs.hh" #include @@ -9,37 +8,16 @@ int main(int ac, char** av) { std::srand(std::time(nullptr)); auto const [input_file, output_file, iterations, method, division, - controlled_size, verbose - - ] = parse_args(ac, av); + controlled_size, verbose] + = parse_args(ac, av); spdlog::set_level(verbose ? spdlog::level::debug : spdlog::level::info); + spdlog::set_pattern("[thread %t] %+"); spdlog::debug("Input file:\t{}", input_file.native()); spdlog::debug("Output file:\t{}", output_file.native()); spdlog::debug("Iterations:\t{}", iterations); - auto [input_image, process_image] = init_image(input_file.native()); - switch (method) { - case 1: { - method1(input_image, process_image, iterations); - break; - } - case 2: { - method2(input_image, process_image, iterations); - break; - } - case 3: { - method3(input_image, process_image, iterations); - break; - } - case 4: { - method4(input_image, process_image, iterations, controlled_size); - break; - } - default: - spdlog::error("Requested method {} is not implemented.", method); - std::exit(-1); - } - - cv::imwrite(output_file.native(), process_image); + ImageManipulator image_process{input_file, output_file, iterations}; + image_process.exec_method(method, controlled_size); + image_process.write_file(); return 0; } diff --git a/src/methods.cc b/src/methods.cc index 9a1dc2b..fcd0bfd 100644 --- a/src/methods.cc +++ b/src/methods.cc @@ -1,258 +1,288 @@ #include "methods.hh" -#include "common.hh" -#include "drawing.hh" #include #include +#include #include #include #include #include -#include #include -#include +std::mutex colors_mutex; auto const thread_nbr = std::thread::hardware_concurrency(); -std::mutex numbers_mutex; -using randint = std::uniform_int_distribution<>; -using Color = std::array; -using ColorSet = std::vector; -using std::rand; +/////////////////////////////////////////////////////////////////////////////// +// class implementation // +/////////////////////////////////////////////////////////////////////////////// -namespace methods_private { - -[[nodiscard]] auto randomColor() +// constructors /////////////////////////////////////////////////////////////// +ImageManipulator::ImageManipulator(std::filesystem::path const t_input_path, + std::filesystem::path const t_output_path, + int const t_iterations) + : reference_{cv::imread(t_input_path.native(), cv::IMREAD_COLOR)}, + generated_image_{cv::Mat{reference_.size().height, + reference_.size().width, CV_8UC3, + cv::Scalar(0, 0, 0)}}, + output_path_{t_output_path.native()}, + diff_{euclidian_distance(generated_image_)}, + total_iterations_{t_iterations}, + remaining_iter_{t_iterations}, + width_{reference_.size().width}, + height_{reference_.size().height} +{ + if (!reference_.data) { + spdlog::critical("Could not open or find image!\n"); + exit(-1); + } + spdlog::debug("Image loaded!"); + spdlog::debug("Width:\t{}", reference_.size().width); + spdlog::debug("Height:\t{}", reference_.size().height); +} + +// public methods ///////////////////////////////////////////////////////////// +void ImageManipulator::exec_method(int const t_nb_method, + bool const t_controlled_size = false) +{ + switch (t_nb_method) { + case 1: { + method1(); + break; + } + case 2: { + method2(); + break; + } + case 3: { + method3(); + break; + } + case 4: { + method4(t_controlled_size); + break; + } + default: + spdlog::error("Requested method {} is not implemented.", t_nb_method); + std::exit(-1); + } +} + +void ImageManipulator::write_file() const +{ + cv::imwrite(output_path_, generated_image_); +} + +// private methods //////////////////////////////////////////////////////////// + +[[nodiscard]] auto ImageManipulator::euclidian_distance( + cv::Mat const& t_img) const noexcept -> double +{ + double euclidian = 0.0; + for (auto itr1 = reference_.begin(), itr2 = t_img.begin(); + itr1 != reference_.end() && itr2 != t_img.end(); + ++itr1, ++itr2) { + euclidian += std::pow(*itr1 - *itr2, 2); + } + return std::sqrt(euclidian); +} + +[[nodiscard]] auto ImageManipulator::random_color() const noexcept { - 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) +[[nodiscard]] auto ImageManipulator::get_square_values() const noexcept { - 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); + int rand_x = rand() % reference_.size().width; + int rand_y = rand() % reference_.size().height; + int size = rand() + % std::min(reference_.size().width - rand_x, + reference_.size().height - rand_y); return std::tuple(rand_x, rand_y, size); } -[[nodiscard]] auto getControlledSquareValues(cv::Mat const& t_img, - int const t_init_iter, - int const t_iter) +[[nodiscard]] auto ImageManipulator::get_controlled_square_values() const + noexcept { - int rand_x = rand() % t_img.size().width; - int rand_y = rand() % t_img.size().height; - float const coef - = static_cast(t_iter) / static_cast(t_init_iter); - int const min_size = static_cast( - (static_cast(std::min(t_img.size().width, t_img.size().height)) - / 2.0f) - * coef); + int rand_x = rand() % reference_.size().width; + int rand_y = rand() % reference_.size().height; + float const coef = static_cast(remaining_iter_) + / static_cast(total_iterations_); + int const min_size + = static_cast((static_cast(std::min(reference_.size().width, + reference_.size().height)) + / 2.0f) + * coef); int const max_size = min_size * 2 + 1; int size = rand() % (max_size - min_size) + min_size; 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 = false, - int const t_init_iter = 0, - int const t_iter = 0) +[[nodiscard]] auto ImageManipulator::create_candidate( + bool const t_controlled_size = false) const { - auto temp_image = t_base.clone(); - auto const [rand_x, rand_y, size] - = t_controlled_size ? methods_private::getControlledSquareValues( - temp_image, t_init_iter, t_iter) - : 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) + auto temp_image = generated_image_.clone(); + auto const [rand_x, rand_y, size] = t_controlled_size + ? get_controlled_square_values() + : get_square_values(); + auto const& color = colors_[rand() % colors_.size()]; + draw_square( + temp_image, cv::Point{rand_x, rand_y}, size, + cv::Scalar{static_cast(color[0]), static_cast(color[1]), + static_cast(color[2])}); + auto new_diff = euclidian_distance(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) +void ImageManipulator::get_color_set() +{ + for (int h = 0; h < reference_.size().height; + h += std::thread::hardware_concurrency()) { + std::vector thread_list{}; + for (auto i = 0u; i < std::thread::hardware_concurrency(); ++i) { + thread_list.push_back( + std::thread(&ImageManipulator::threaded_get_color, this, h + i)); + } + for (auto& th : thread_list) { + th.join(); + } + } + colors_.shrink_to_fit(); +} + +void ImageManipulator::threaded_get_color(int t_h) +{ + if (t_h > reference_.size().height) { + return; + } + for (int w = 0; w < reference_.size().width; w += 3) { + std::array temp + = {reference_.at(t_h, w), reference_.at(t_h, w + 1), + reference_.at(t_h, w + 2)}; + auto pos = std::find(std::begin(colors_), std::end(colors_), temp); + if (pos == std::end(colors_)) { + colors_mutex_.lock(); + colors_.push_back(std::move(temp)); + colors_mutex_.unlock(); + } + } +} + +void ImageManipulator::adjust_size(cv::Point& t_top_left, + int const size) noexcept { - int const height = t_process_img.size().height; - int const width = t_process_img.size().width; int const shape_total_width = t_top_left.x + size; int const shape_total_height = t_top_left.y + size; - if (int const diff = shape_total_height - height; diff > 0) { - t_top_left.y -= diff + 1; + if (int const diff = shape_total_height + height_; diff > 0) { + t_top_left.x += diff + 1; } - if (int const diff = shape_total_width - width; diff > 0) { - t_top_left.x -= diff + 1; + if (int const diff = shape_total_width + width_; diff > 0) { + t_top_left.x += diff + 1; } } -void threadedGetColor(cv::Mat const& t_reference, ColorSet& t_colors, int t_h) +void ImageManipulator::draw_square(cv::Mat& t_img, + cv::Point const& t_top_left, + int const t_size, + cv::Scalar const& t_color) const { - 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(); + auto points = std::make_unique(4); + points[0] = t_top_left; + points[1] = cv::Point{t_top_left.x, t_top_left.y + t_size}; + points[2] = cv::Point{t_top_left.x + t_size, t_top_left.y + t_size}; + points[3] = cv::Point{t_top_left.x + t_size, t_top_left.y}; + fillConvexPoly(t_img, points.get(), 4, t_color); +} + +void ImageManipulator::update_gen_image(cv::Mat const& t_img, + double const t_diff) +{ + diff_ = t_diff; + t_img.copyTo(generated_image_); + --remaining_iter_; + spdlog::debug("remaining iter: {}\tdiff: {}", remaining_iter_, diff_); +} + +void ImageManipulator::method1() +{ + spdlog::debug("Beginning method1, initial difference: {}", diff_); + spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_, + remaining_iter_); + while (remaining_iter_ > 0 && diff_ > 0.0) { + auto temp_image = generated_image_.clone(); + auto const [rand_x, rand_y, size] = get_square_values(); + draw_square(temp_image, cv::Point{rand_x, rand_y}, size, random_color()); + if (auto const new_diff = euclidian_distance(temp_image); + new_diff < diff_) { + update_gen_image(temp_image, new_diff); } } } -void newSquare1(cv::Mat& t_process_img, cv::Point&& t_top_left, int t_size) +void ImageManipulator::method2() { - 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, - cv::Point&& t_top_left, - int t_size, - Color const& t_color) -{ - draw_shape(t_process_img, t_top_left, t_size, - cv::Scalar{static_cast(t_color[0]), - static_cast(t_color[1]), - static_cast(t_color[2])}, - Shapes::Square); -} - -} // namespace methods_private - -void method1(cv::Mat const& t_reference, cv::Mat& t_output, int t_iterations) -{ - auto diff = euclidian_distance(t_reference, t_output); - spdlog::debug("Beginning method1, initial difference: {}", diff); - while (t_iterations > 0 && diff >= 0) { - auto temp_image = t_output.clone(); - 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) { - diff = new_diff; - temp_image.copyTo(t_output); - --t_iterations; - spdlog::debug("iteration:{} diff:{}", t_iterations, diff); + spdlog::debug("Beginning method2, initial difference: {}", diff_); + spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_, + remaining_iter_); + spdlog::debug("Running on {} threads", std::thread::hardware_concurrency()); + get_color_set(); + spdlog::debug("{} colors detected", colors_.size()); + while (remaining_iter_ > 0 && diff_ > 0.0) { + if (auto result = create_candidate(); result.has_value()) { + update_gen_image(result->first, result->second); } } } -void method2(cv::Mat const& t_reference, cv::Mat& t_output, int t_iterations) +void ImageManipulator::method3() { - spdlog::debug("Running on {} thread(s).", thread_nbr); - auto diff = euclidian_distance(t_reference, t_output); - spdlog::debug("Beginning method2, initial difference: {}", diff); - auto const colors = methods_private::getColorSet(t_reference); - spdlog::debug("{} colors detected.", colors.size()); - while (t_iterations > 0) { - if (auto result - = methods_private::createCandidate(t_output, t_reference, colors, diff); - result.has_value()) { - diff = result->second; - result->first.copyTo(t_output); - --t_iterations; - spdlog::debug("iteration:{} diff:{}", t_iterations, diff); + spdlog::debug("Beginning method2, initial difference: {}", diff_); + spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_, + remaining_iter_); + spdlog::debug("Running on {} threads", std::thread::hardware_concurrency()); + get_color_set(); + spdlog::debug("{} colors detected", colors_.size()); + while (remaining_iter_ > 0 && diff_ > 0.0) { + auto temp_image = generated_image_.clone(); + if (auto result = create_candidate(true); result.has_value()) { + update_gen_image(result->first, result->second); } } } -void method3(cv::Mat const& t_reference, cv::Mat& t_output, int t_iterations) +void ImageManipulator::method4(bool const t_controlled_size) { - auto const init_iter = t_iterations; - 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(); - if (auto result = methods_private::createCandidate( - t_output, t_reference, colors, diff, true, init_iter, t_iterations); - result.has_value()) { - diff = result->second; - result->first.copyTo(t_output); - --t_iterations; - spdlog::debug("iteration:{} diff:{}", t_iterations, diff); - } - } -} - -void method4(cv::Mat const& t_reference, - cv::Mat& t_output, - int t_iterations, - bool controlled_size) -{ - auto const init_iter = t_iterations; - 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) { + spdlog::debug("Beginning method2, initial difference: {}", diff_); + spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_, + remaining_iter_); + spdlog::debug("Running on {} threads", std::thread::hardware_concurrency()); + get_color_set(); + spdlog::debug("{} colors detected", colors_.size()); + while(remaining_iter_ > 0 && diff_ > 0.0) + { std::vector>>> results{}; std::vector> values{}; - for (unsigned i = 0; i < thread_nbr; ++i) { - results.push_back(std::async( - std::launch::async, methods_private::createCandidate, - std::ref(t_output), std::ref(t_reference), std::ref(colors), diff, - controlled_size, init_iter, t_iterations)); - } - for (auto& elem : results) { - if (auto res = elem.get(); res.has_value() && res->second < diff) { - values.push_back(*res); - } - } - if (values.size() > 0) { - unsigned best = 0; - for (unsigned i = 0; i < values.size(); ++i) { - if (values[i].second < values[best].second) { - best = i; - } - } - diff = values[best].second; - values[best].first.copyTo(t_output); - --t_iterations; - spdlog::debug("iteration:{} diff:{}", t_iterations, diff); + for (size_t i = 0; i < std::thread::hardware_concurrency(); ++i) { + results.push_back(std::async(std::launch::async, + &ImageManipulator::create_candidate, this, + t_controlled_size)); } + for (auto& elem : results) { + if(auto res = elem.get(); res.has_value() && res->second < diff_) { + values.push_back(*res); + } + } + if(values.size() > 0) { + size_t best = 0; + for(size_t i = 0; i < values.size(); ++i) { + if(values[i].second < values[best].second) { + best = i; + } + } + update_gen_image(values[best].first, values[best].second); + } } } - -void method5(cv::Mat const& t_reference, - cv::Mat& t_output, - int t_iterations, - int t_nb_tiles, - bool t_controlled_size = false) -{ - std::vector tiles{static_cast(t_nb_tiles * t_nb_tiles)}; - int col_width = t_reference.cols / t_nb_tiles; - spdlog::info("collumns of {}px", col_width); -}