Big code refactor, now the interface is easier to use
This commit is contained in:
parent
4201e5476e
commit
cbad530d4a
@ -1,15 +0,0 @@
|
||||
#ifndef GENETIC_IMAGE_INCLUDE_GENIMG_COMMON_HH_
|
||||
#define GENETIC_IMAGE_INCLUDE_GENIMG_COMMON_HH_
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
[[nodiscard]] auto init_image(std::string const&) noexcept
|
||||
-> std::pair<cv::Mat, cv::Mat>;
|
||||
|
||||
[[nodiscard]] auto euclidian_distance(cv::Mat const&, cv::Mat const&) -> double;
|
||||
|
||||
#endif /* GENETIC_IMAGE_INCLUDE_GENIMG_COMMON_HH_ */
|
@ -1,15 +0,0 @@
|
||||
#ifndef GENETIC_IMAGE_INCLUDE_GENIMG_DRAWING_HH_
|
||||
#define GENETIC_IMAGE_INCLUDE_GENIMG_DRAWING_HH_
|
||||
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
|
||||
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_ */
|
@ -1,50 +1,71 @@
|
||||
#ifndef GENETIC_IMAGE_INCLUDE_GENIMG_METHODS_HH_
|
||||
#define GENETIC_IMAGE_INCLUDE_GENIMG_METHODS_HH_
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
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<std::array<uchar, 3>> 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<std::array<uchar, 3>>& 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<uchar, 3> 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<std::array<uchar, 3>> colors_
|
||||
= std::vector<std::array<uchar, 3>>{};
|
||||
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_;
|
||||
};
|
||||
|
@ -1,33 +0,0 @@
|
||||
#include "common.hh"
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
|
||||
[[nodiscard]] auto init_image(std::string const& t_input_file) noexcept
|
||||
-> std::pair<cv::Mat, cv::Mat>
|
||||
{
|
||||
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<uchar>(), itr2 = t_img2.begin<uchar>();
|
||||
itr1 != t_img1.end<uchar>() && itr2 != t_img2.end<uchar>();
|
||||
++itr1, ++itr2) {
|
||||
euclidian += std::pow(*itr1 - *itr2, 2);
|
||||
}
|
||||
euclidian = std::sqrt(euclidian);
|
||||
return euclidian;
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
#include "drawing.hh"
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
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<cv::Point[]>(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);
|
||||
}
|
||||
}
|
34
src/main.cc
34
src/main.cc
@ -1,4 +1,3 @@
|
||||
#include "common.hh"
|
||||
#include "methods.hh"
|
||||
#include "parseargs.hh"
|
||||
#include <cstdlib>
|
||||
@ -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;
|
||||
}
|
||||
|
424
src/methods.cc
424
src/methods.cc
@ -1,258 +1,288 @@
|
||||
#include "methods.hh"
|
||||
#include "common.hh"
|
||||
#include "drawing.hh"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <future>
|
||||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
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<uchar, 3>;
|
||||
using ColorSet = std::vector<Color>;
|
||||
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<uchar>(), itr2 = t_img.begin<uchar>();
|
||||
itr1 != reference_.end<uchar>() && itr2 != t_img.end<uchar>();
|
||||
++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<std::thread> 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<int, int, int>(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<float>(t_iter) / static_cast<float>(t_init_iter);
|
||||
int const min_size = static_cast<int>(
|
||||
(static_cast<float>(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<float>(remaining_iter_)
|
||||
/ static_cast<float>(total_iterations_);
|
||||
int const min_size
|
||||
= static_cast<int>((static_cast<float>(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<int, int, int>(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<double>(color[0]), static_cast<double>(color[1]),
|
||||
static_cast<double>(color[2])});
|
||||
auto new_diff = euclidian_distance(temp_image);
|
||||
return (new_diff < diff_)
|
||||
? std::optional<std::pair<cv::Mat, double>>{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<std::thread> 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<uchar, 3> temp
|
||||
= {reference_.at<uchar>(t_h, w), reference_.at<uchar>(t_h, w + 1),
|
||||
reference_.at<uchar>(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<uchar>(t_h, w), t_reference.at<uchar>(t_h, w + 1),
|
||||
t_reference.at<uchar>(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<cv::Point[]>(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<double>(t_color[0]),
|
||||
static_cast<double>(t_color[1]),
|
||||
static_cast<double>(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<std::future<std::optional<std::pair<cv::Mat, double>>>>
|
||||
results{};
|
||||
std::vector<std::pair<cv::Mat, double>> 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<cv::Mat> tiles{static_cast<size_t>(t_nb_tiles * t_nb_tiles)};
|
||||
int col_width = t_reference.cols / t_nb_tiles;
|
||||
spdlog::info("collumns of {}px", col_width);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user