clang format update
This commit is contained in:
parent
bc9dcf4142
commit
b962d50996
@ -1,150 +1,142 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "shapes.hh"
|
#include "shapes.hh"
|
||||||
#include <array>
|
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class ImageManipulator {
|
class ImageManipulator
|
||||||
public:
|
{
|
||||||
ImageManipulator() = delete;
|
public:
|
||||||
|
ImageManipulator() = delete;
|
||||||
|
|
||||||
/// \brief Copy contructor
|
/// \brief Copy contructor
|
||||||
ImageManipulator(const ImageManipulator& other);
|
ImageManipulator(const ImageManipulator &other);
|
||||||
|
|
||||||
/// \brief Move constructor
|
/// \brief Move constructor
|
||||||
ImageManipulator(ImageManipulator&& other) noexcept;
|
ImageManipulator(ImageManipulator &&other) noexcept;
|
||||||
|
|
||||||
/// \brief Load image from input, and prepare for output
|
/// \brief Load image from input, and prepare for output
|
||||||
ImageManipulator(std::string const t_input_path,
|
ImageManipulator(std::string const t_input_path,
|
||||||
std::string const t_output_path,
|
std::string const t_output_path, int const iterations,
|
||||||
int const iterations,
|
Shape::ShapeType const t_shape);
|
||||||
Shape::ShapeType const t_shape);
|
|
||||||
|
|
||||||
/// \brief Basically makes views from image
|
/// \brief Basically makes views from image
|
||||||
ImageManipulator(cv::Mat const& t_origin_image,
|
ImageManipulator(cv::Mat const &t_origin_image, int const t_iterations,
|
||||||
int const t_iterations,
|
Shape::ShapeType const t_shape, int const t_x, int const t_y,
|
||||||
Shape::ShapeType const t_shape,
|
int const t_width, int const t_height);
|
||||||
int const t_x,
|
|
||||||
int const t_y,
|
|
||||||
int const t_width,
|
|
||||||
int const t_height);
|
|
||||||
|
|
||||||
[[nodiscard]] auto operator=(ImageManipulator& other) = delete;
|
[[nodiscard]] auto operator=(ImageManipulator &other) = delete;
|
||||||
|
|
||||||
[[nodiscard]] auto operator=(ImageManipulator&& other) noexcept = delete;
|
[[nodiscard]] auto operator=(ImageManipulator &&other) noexcept = delete;
|
||||||
|
|
||||||
/// \brief Execute the nth method on the current object
|
/// \brief Execute the nth method on the current object
|
||||||
void exec_method(int const t_nb_method,
|
void exec_method(int const t_nb_method, bool const t_controlled_size,
|
||||||
bool const t_controlled_size,
|
int const t_cols, int const t_rows, int const t_submethod);
|
||||||
int const t_cols,
|
|
||||||
int const t_rows,
|
|
||||||
int const t_submethod);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Write the generated image to the output path
|
* \brief Write the generated image to the output path
|
||||||
*
|
*
|
||||||
* Write the generated image as a file to the specified path stored in the
|
* Write the generated image as a file to the specified path stored in the
|
||||||
* object
|
* object
|
||||||
*/
|
*/
|
||||||
inline void write_file() const
|
inline void write_file() const
|
||||||
{
|
{
|
||||||
cv::imwrite(output_path_, generated_image_);
|
cv::imwrite(output_path_, generated_image_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Returns a reference to the generated image
|
/// \brief Returns a reference to the generated image
|
||||||
[[nodiscard]] inline auto const& get_generated_image() const noexcept
|
[[nodiscard]] inline auto const &get_generated_image() const noexcept
|
||||||
{
|
{
|
||||||
return generated_image_;
|
return generated_image_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Destructor
|
/// \brief Destructor
|
||||||
virtual ~ImageManipulator() noexcept = default;
|
virtual ~ImageManipulator() noexcept = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
// methods //////////////////////////////////////////////////////////////////
|
// methods //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/// \brief Calculates the euclidian distance between two images
|
/// \brief Calculates the euclidian distance between two images
|
||||||
[[nodiscard]] auto euclidian_distance(cv::Mat const& t_img) const noexcept
|
[[nodiscard]] auto euclidian_distance(cv::Mat const &t_img) const noexcept
|
||||||
-> double;
|
-> double;
|
||||||
|
|
||||||
/// \brief Creates and returns a random color
|
/// \brief Creates and returns a random color
|
||||||
[[nodiscard]] auto random_color() const noexcept;
|
[[nodiscard]] auto random_color() const noexcept;
|
||||||
|
|
||||||
/// \brief Generates random square coordinates
|
/// \brief Generates random square coordinates
|
||||||
[[deprecated]] [[nodiscard]] auto get_square_values() const noexcept;
|
[[deprecated]] [[nodiscard]] auto get_square_values() const noexcept;
|
||||||
|
|
||||||
/// \brief Generates controlled random square coordinates
|
/// \brief Generates controlled random square coordinates
|
||||||
[[deprecated]] [[nodiscard]] auto get_controlled_square_values() const
|
[[deprecated]] [[nodiscard]] auto get_controlled_square_values() const
|
||||||
noexcept;
|
noexcept;
|
||||||
|
|
||||||
/// \brief Generates a candidate for image generation improvement
|
/// \brief Generates a candidate for image generation improvement
|
||||||
[[nodiscard]] auto create_candidate(bool const t_controlled_size);
|
[[nodiscard]] auto create_candidate(bool const t_controlled_size);
|
||||||
|
|
||||||
/// \brief Generates organized views of the reference image for method 5
|
/// \brief Generates organized views of the reference image for method 5
|
||||||
[[nodiscard]] auto generate_tiles(int const t_cols, int const t_rows) const;
|
[[nodiscard]] auto generate_tiles(int const t_cols, int const t_rows) const;
|
||||||
|
|
||||||
/// \brief Gets all colors from the reference image
|
/// \brief Gets all colors from the reference image
|
||||||
void get_color_set();
|
void get_color_set();
|
||||||
|
|
||||||
/// \brief Threaded helper for \ref get_color_set
|
/// \brief Threaded helper for \ref get_color_set
|
||||||
void threaded_get_color(int const t_h);
|
void threaded_get_color(int const t_h);
|
||||||
|
|
||||||
/// \brief Draw a square on an image
|
/// \brief Draw a square on an image
|
||||||
[[deprecated]] void draw_square(cv::Mat& t_img,
|
[[deprecated]] void draw_square(cv::Mat &t_img, cv::Point const &t_top_left,
|
||||||
cv::Point const& t_top_left,
|
int const t_size,
|
||||||
int const t_size,
|
cv::Scalar const &t_color) const;
|
||||||
cv::Scalar const& t_color) const;
|
|
||||||
|
|
||||||
void draw_shape(cv::Mat& t_img, cv::Scalar&& t_color);
|
void draw_shape(cv::Mat &t_img, cv::Scalar &&t_color);
|
||||||
|
void create_shape() noexcept;
|
||||||
|
void create_controlled_shape() noexcept;
|
||||||
|
|
||||||
/// \brief Update this object’s generated image
|
/// \brief Update this object’s generated image
|
||||||
void update_gen_image(cv::Mat const& t_img, double const t_diff);
|
void update_gen_image(cv::Mat const &t_img, double const t_diff);
|
||||||
|
|
||||||
/// \brief Merges tiles generated by method5
|
/// \brief Merges tiles generated by method5
|
||||||
void merge_tiles(std::vector<std::vector<ImageManipulator>> const& t_tiles);
|
void merge_tiles(std::vector<std::vector<ImageManipulator>> const &t_tiles);
|
||||||
|
|
||||||
/// \brief First method as described in the
|
/// \brief First method as described in the
|
||||||
/// [report](https://labs.phundrak.fr/phundrak/genetic-images/blob/master/report/report.pdf)
|
/// [report](https://labs.phundrak.fr/phundrak/genetic-images/blob/master/report/report.pdf)
|
||||||
void method1();
|
void method1();
|
||||||
|
|
||||||
/// \brief Second method as described in the
|
/// \brief Second method as described in the
|
||||||
/// [report](https://labs.phundrak.fr/phundrak/genetic-images/blob/master/report/report.pdf)
|
/// [report](https://labs.phundrak.fr/phundrak/genetic-images/blob/master/report/report.pdf)
|
||||||
void method2();
|
void method2();
|
||||||
|
|
||||||
/// \brief Third method as described in the
|
/// \brief Third method as described in the
|
||||||
/// [report](https://labs.phundrak.fr/phundrak/genetic-images/blob/master/report/report.pdf)
|
/// [report](https://labs.phundrak.fr/phundrak/genetic-images/blob/master/report/report.pdf)
|
||||||
void method3();
|
void method3();
|
||||||
|
|
||||||
/// \brief Fourth method as described in the
|
/// \brief Fourth method as described in the
|
||||||
/// [report](https://labs.phundrak.fr/phundrak/genetic-images/blob/master/report/report.pdf)
|
/// [report](https://labs.phundrak.fr/phundrak/genetic-images/blob/master/report/report.pdf)
|
||||||
void method4(bool const t_controlled_size);
|
void method4(bool const t_controlled_size);
|
||||||
|
|
||||||
/// \brief Fifth method as described in the
|
/// \brief Fifth method as described in the
|
||||||
/// [report](https://labs.phundrak.fr/phundrak/genetic-images/blob/master/report/report.pdf)
|
/// [report](https://labs.phundrak.fr/phundrak/genetic-images/blob/master/report/report.pdf)
|
||||||
void method5(bool const t_controlled_size,
|
void method5(bool const t_controlled_size, int const cols, int const rows,
|
||||||
int const cols,
|
int const submethod);
|
||||||
int const rows,
|
|
||||||
int const submethod);
|
|
||||||
|
|
||||||
// members //////////////////////////////////////////////////////////////////
|
// members //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
std::vector<std::array<uchar, 3>> colors_{}; /*!< Color set from reference */
|
std::vector<std::array<uchar, 3>> colors_{}; /*!< Color set from reference */
|
||||||
cv::Mat const reference_{}; /*!< Reference image */
|
cv::Mat const reference_{}; /*!< Reference image */
|
||||||
cv::Mat generated_image_{
|
cv::Mat generated_image_{
|
||||||
reference_.size().height, reference_.size().width, CV_8UC3,
|
reference_.size().height, reference_.size().width, CV_8UC3,
|
||||||
cv::Scalar(0, 0, 0)}; /*!< Working, generated image */
|
cv::Scalar(0, 0, 0)}; /*!< Working, generated image */
|
||||||
Shape shape_{Shape::ShapeType::Square};
|
Shape shape_{Shape::ShapeType::Square};
|
||||||
mutable std::mutex
|
mutable std::mutex
|
||||||
colors_mutex_{}; /*!< Thread mutex for color set generation */
|
colors_mutex_{}; /*!< Thread mutex for color set generation */
|
||||||
std::string const output_path_{}; /*!< Write path for the generated image */
|
std::string const output_path_{}; /*!< Write path for the generated image */
|
||||||
double diff_{euclidian_distance(generated_image_)}; /*!< Euclidian difference
|
double diff_{euclidian_distance(generated_image_)}; /*!< Euclidian difference
|
||||||
between \ref reference_ and \ref generated_image_ */
|
between \ref reference_ and \ref generated_image_ */
|
||||||
int const total_iterations_{0}; /*!< Number of iterations to perform */
|
int const total_iterations_{0}; /*!< Number of iterations to perform */
|
||||||
int remaining_iter_{
|
int remaining_iter_{
|
||||||
total_iterations_}; /*!< Remaining iterations to perform */
|
total_iterations_}; /*!< Remaining iterations to perform */
|
||||||
int const width_{reference_.size().width}; /*!< Width of the image */
|
int const width_{reference_.size().width}; /*!< Width of the image */
|
||||||
int const height_{reference_.size().height}; /*!< Height of the image */
|
int const height_{reference_.size().height}; /*!< Height of the image */
|
||||||
};
|
};
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include "shapes.hh"
|
#include "shapes.hh"
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
struct ParsedArgs {
|
struct ParsedArgs {
|
||||||
std::filesystem::path input_path;
|
std::filesystem::path input_path;
|
||||||
std::filesystem::path output_path;
|
std::filesystem::path output_path;
|
||||||
Shape::ShapeType shape;
|
Shape::ShapeType shape;
|
||||||
int iterations;
|
int iterations;
|
||||||
int method;
|
int method;
|
||||||
int cols;
|
int cols;
|
||||||
int rows;
|
int rows;
|
||||||
int submethod;
|
int submethod;
|
||||||
bool controlled_size;
|
bool controlled_size;
|
||||||
bool verbose;
|
bool verbose;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Parses the arguments passed to the program
|
/// \brief Parses the arguments passed to the program
|
||||||
[[nodiscard]] auto parse_args(int, char**) -> ParsedArgs;
|
[[nodiscard]] auto parse_args(int, char **) -> ParsedArgs;
|
||||||
|
@ -4,60 +4,62 @@
|
|||||||
#include <opencv2/highgui/highgui.hpp>
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
#include <opencv2/imgproc.hpp>
|
#include <opencv2/imgproc.hpp>
|
||||||
|
|
||||||
class Shape {
|
class Shape
|
||||||
public:
|
{
|
||||||
static constexpr int MAX_POINTS{4};
|
public:
|
||||||
enum class ShapeType { Square, Triangle };
|
static constexpr int MAX_POINTS{4};
|
||||||
|
enum class ShapeType { Square, Triangle };
|
||||||
|
|
||||||
/// \brief Default constructor
|
/// \brief Default constructor
|
||||||
Shape() = delete;
|
Shape() = delete;
|
||||||
|
|
||||||
Shape(Shape::ShapeType const t_type);
|
Shape(Shape::ShapeType const t_type);
|
||||||
|
|
||||||
/// \brief Copy constructor
|
/// \brief Copy constructor
|
||||||
Shape(const Shape& other) = default;
|
Shape(const Shape &other) = default;
|
||||||
|
|
||||||
/// \brief Move constructor
|
/// \brief Move constructor
|
||||||
Shape(Shape&& other) noexcept;
|
Shape(Shape &&other) noexcept;
|
||||||
|
|
||||||
/// \brief Destructor
|
/// \brief Destructor
|
||||||
virtual ~Shape() noexcept = default;
|
virtual ~Shape() noexcept = default;
|
||||||
|
|
||||||
/// \brief Copy assignment operator
|
/// \brief Copy assignment operator
|
||||||
Shape& operator=(const Shape& other) = delete;
|
Shape &operator=(const Shape &other) = delete;
|
||||||
|
|
||||||
/// \brief Move assignment operator
|
/// \brief Move assignment operator
|
||||||
Shape& operator=(Shape&& other) noexcept = delete;
|
Shape &operator=(Shape &&other) noexcept = delete;
|
||||||
|
|
||||||
/// \brief Generates a shape's points
|
/// \brief Generates a shape's points
|
||||||
void operator()(cv::Point&& t_max_pos,
|
void operator()(cv::Point &&t_max_pos, int const t_max_size,
|
||||||
int const t_max_size,
|
int const t_min_size = 0) noexcept;
|
||||||
int const t_min_size = 0) noexcept;
|
|
||||||
|
|
||||||
[[nodiscard]] auto get_points() const noexcept
|
[[nodiscard]] auto get_points() const noexcept
|
||||||
-> std::array<cv::Point, Shape::MAX_POINTS> const&
|
-> std::array<cv::Point, Shape::MAX_POINTS> const &
|
||||||
{
|
{
|
||||||
return points_;
|
return points_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Returns the type of shape described by the object
|
/// \brief Returns the type of shape described by the object
|
||||||
[[nodiscard]] auto get_type() const noexcept -> ShapeType const&
|
[[nodiscard]] auto get_type() const noexcept -> ShapeType const &
|
||||||
{
|
{
|
||||||
return type_;
|
return type_;
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] auto get_nb_points() const noexcept { return nb_points_; }
|
[[nodiscard]] auto get_nb_points() const noexcept
|
||||||
|
{
|
||||||
|
return nb_points_;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
private:
|
private:
|
||||||
void create_square_points(cv::Point const& t_top_left,
|
void create_square_points(cv::Point const &t_top_left,
|
||||||
int const t_size) noexcept;
|
int const t_size) noexcept;
|
||||||
void create_triangle_points(cv::Point const& t_top_left,
|
void create_triangle_points(cv::Point const &t_top_left,
|
||||||
int const t_size) noexcept;
|
int const t_size) noexcept;
|
||||||
|
|
||||||
|
ShapeType const type_{ShapeType::Square};
|
||||||
ShapeType const type_{ShapeType::Square};
|
std::array<cv::Point, Shape::MAX_POINTS> points_{
|
||||||
std::array<cv::Point, Shape::MAX_POINTS> points_{
|
cv::Point{0, 0}, cv::Point{0, 0}, cv::Point{0, 0}, cv::Point{0, 0}};
|
||||||
cv::Point{0, 0}, cv::Point{0, 0}, cv::Point{0, 0}, cv::Point{0, 0}};
|
int nb_points_{Shape::MAX_POINTS};
|
||||||
int nb_points_{Shape::MAX_POINTS};
|
|
||||||
};
|
};
|
||||||
|
31
src/main.cc
31
src/main.cc
@ -1,24 +1,25 @@
|
|||||||
#include "methods.hh"
|
#include "methods.hh"
|
||||||
#include "parseargs.hh"
|
#include "parseargs.hh"
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
int main(int ac, char** av)
|
int main(int ac, char **av)
|
||||||
{
|
{
|
||||||
std::srand(std::time(nullptr));
|
std::srand(std::time(nullptr));
|
||||||
auto const arguments = parse_args(ac, av);
|
auto const arguments = parse_args(ac, av);
|
||||||
spdlog::set_level(arguments.verbose ? spdlog::level::debug
|
spdlog::set_level(arguments.verbose ? spdlog::level::debug
|
||||||
: spdlog::level::info);
|
: spdlog::level::info);
|
||||||
spdlog::set_pattern("[thread %t] %+");
|
spdlog::set_pattern("[thread %t] %+");
|
||||||
spdlog::debug("Input file:\t{}", arguments.input_path.native());
|
spdlog::debug("Input file:\t{}", arguments.input_path.native());
|
||||||
spdlog::debug("Output file:\t{}", arguments.output_path.native());
|
spdlog::debug("Output file:\t{}", arguments.output_path.native());
|
||||||
spdlog::debug("Iterations:\t{}", arguments.iterations);
|
spdlog::debug("Iterations:\t{}", arguments.iterations);
|
||||||
|
|
||||||
ImageManipulator image_process{arguments.input_path, arguments.output_path,
|
ImageManipulator image_process{arguments.input_path, arguments.output_path,
|
||||||
arguments.iterations, arguments.shape};
|
arguments.iterations, arguments.shape};
|
||||||
image_process.exec_method(arguments.method, arguments.controlled_size,
|
image_process.exec_method(arguments.method, arguments.controlled_size,
|
||||||
arguments.cols, arguments.rows,
|
arguments.cols, arguments.rows,
|
||||||
arguments.submethod);
|
arguments.submethod);
|
||||||
image_process.write_file();
|
image_process.write_file();
|
||||||
}
|
}
|
||||||
|
524
src/methods.cc
524
src/methods.cc
@ -1,4 +1,5 @@
|
|||||||
#include "methods.hh"
|
#include "methods.hh"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@ -17,16 +18,12 @@ static auto const thread_nbr = std::thread::hardware_concurrency();
|
|||||||
*
|
*
|
||||||
* \param[in] other Element to copy
|
* \param[in] other Element to copy
|
||||||
*/
|
*/
|
||||||
ImageManipulator::ImageManipulator(const ImageManipulator& other)
|
ImageManipulator::ImageManipulator(const ImageManipulator &other)
|
||||||
: colors_{other.colors_},
|
: colors_{other.colors_}, reference_{other.reference_},
|
||||||
reference_{other.reference_},
|
generated_image_{other.generated_image_}, shape_{other.shape_},
|
||||||
generated_image_{other.generated_image_},
|
output_path_{other.output_path_}, diff_{other.diff_},
|
||||||
shape_{other.shape_},
|
|
||||||
output_path_{other.output_path_},
|
|
||||||
diff_{other.diff_},
|
|
||||||
total_iterations_{other.total_iterations_},
|
total_iterations_{other.total_iterations_},
|
||||||
remaining_iter_{other.remaining_iter_},
|
remaining_iter_{other.remaining_iter_}, width_{other.width_},
|
||||||
width_{other.width_},
|
|
||||||
height_{other.height_}
|
height_{other.height_}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -37,16 +34,14 @@ ImageManipulator::ImageManipulator(const ImageManipulator& other)
|
|||||||
*
|
*
|
||||||
* \param[in] other Element to move
|
* \param[in] other Element to move
|
||||||
*/
|
*/
|
||||||
ImageManipulator::ImageManipulator(ImageManipulator&& other) noexcept
|
ImageManipulator::ImageManipulator(ImageManipulator &&other) noexcept
|
||||||
: colors_{std::move(other.colors_)},
|
: colors_{std::move(other.colors_)}, reference_{std::move(
|
||||||
reference_{std::move(other.reference_)},
|
other.reference_)},
|
||||||
generated_image_{std::move(other.generated_image_)},
|
generated_image_{std::move(other.generated_image_)}, shape_{std::move(
|
||||||
shape_{std::move(other.shape_)},
|
other.shape_)},
|
||||||
output_path_{std::move(other.output_path_)},
|
output_path_{std::move(other.output_path_)},
|
||||||
diff_{std::move(other.diff_)},
|
diff_{std::move(other.diff_)}, total_iterations_{other.total_iterations_},
|
||||||
total_iterations_{other.total_iterations_},
|
remaining_iter_{other.remaining_iter_}, width_{other.width_},
|
||||||
remaining_iter_{other.remaining_iter_},
|
|
||||||
width_{other.width_},
|
|
||||||
height_{other.height_}
|
height_{other.height_}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -63,15 +58,14 @@ ImageManipulator::ImageManipulator(std::string const t_input_path,
|
|||||||
std::string const t_output_path,
|
std::string const t_output_path,
|
||||||
int const t_iterations,
|
int const t_iterations,
|
||||||
Shape::ShapeType const t_shape)
|
Shape::ShapeType const t_shape)
|
||||||
: reference_{cv::imread(t_input_path, cv::IMREAD_COLOR)},
|
: reference_{cv::imread(t_input_path, cv::IMREAD_COLOR)}, shape_{Shape{
|
||||||
shape_{Shape{t_shape}},
|
t_shape}},
|
||||||
output_path_{t_output_path},
|
output_path_{t_output_path}, total_iterations_{t_iterations}
|
||||||
total_iterations_{t_iterations}
|
|
||||||
{
|
{
|
||||||
if (!reference_.data) {
|
if (!reference_.data) {
|
||||||
spdlog::critical("Could not open or find image!\n");
|
spdlog::critical("Could not open or find image!\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -85,23 +79,20 @@ ImageManipulator::ImageManipulator(std::string const t_input_path,
|
|||||||
* \param[in] t_width Width of the view from its origin
|
* \param[in] t_width Width of the view from its origin
|
||||||
* \param[in] t_height Height of the view from its origin
|
* \param[in] t_height Height of the view from its origin
|
||||||
*/
|
*/
|
||||||
ImageManipulator::ImageManipulator(cv::Mat const& t_origin_image,
|
ImageManipulator::ImageManipulator(cv::Mat const &t_origin_image,
|
||||||
int const t_iterations,
|
int const t_iterations,
|
||||||
Shape::ShapeType const t_shape,
|
Shape::ShapeType const t_shape,
|
||||||
int const t_x,
|
int const t_x, int const t_y,
|
||||||
int const t_y,
|
int const t_width, int const t_height)
|
||||||
int const t_width,
|
|
||||||
int const t_height)
|
|
||||||
: reference_{t_origin_image(
|
: reference_{t_origin_image(
|
||||||
cv::Range{t_y, std::min(t_y + t_height, t_origin_image.rows)},
|
cv::Range{t_y, std::min(t_y + t_height, t_origin_image.rows)},
|
||||||
cv::Range{t_x, std::min(t_x + t_width, t_origin_image.cols)})},
|
cv::Range{t_x, std::min(t_x + t_width, t_origin_image.cols)})},
|
||||||
shape_{Shape{t_shape}},
|
shape_{Shape{t_shape}}, total_iterations_{t_iterations}
|
||||||
total_iterations_{t_iterations}
|
|
||||||
{
|
{
|
||||||
if (!reference_.data) {
|
if (!reference_.data) {
|
||||||
spdlog::critical("Could not open or find image!\n");
|
spdlog::critical("Could not open or find image!\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// public methods /////////////////////////////////////////////////////////////
|
// public methods /////////////////////////////////////////////////////////////
|
||||||
@ -121,35 +112,19 @@ ImageManipulator::ImageManipulator(cv::Mat const& t_origin_image,
|
|||||||
*/
|
*/
|
||||||
void ImageManipulator::exec_method(int const t_nb_method,
|
void ImageManipulator::exec_method(int const t_nb_method,
|
||||||
bool const t_controlled_size = false,
|
bool const t_controlled_size = false,
|
||||||
int const t_cols = 1,
|
int const t_cols = 1, int const t_rows = 0,
|
||||||
int const t_rows = 0,
|
|
||||||
int const t_submethod = 1)
|
int const t_submethod = 1)
|
||||||
{
|
{
|
||||||
switch (t_nb_method) {
|
switch (t_nb_method) {
|
||||||
case 1: {
|
case 1: method1(); break;
|
||||||
method1();
|
case 2: method2(); break;
|
||||||
break;
|
case 3: method3(); break;
|
||||||
}
|
case 4: method4(t_controlled_size); break;
|
||||||
case 2: {
|
case 5: method5(t_controlled_size, t_cols, t_rows, t_submethod); break;
|
||||||
method2();
|
default:
|
||||||
break;
|
spdlog::error("Requested method {} is not implemented.", t_nb_method);
|
||||||
}
|
std::exit(-1);
|
||||||
case 3: {
|
}
|
||||||
method3();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: {
|
|
||||||
method4(t_controlled_size);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 5: {
|
|
||||||
method5(t_controlled_size, t_cols, t_rows, t_submethod);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
spdlog::error("Requested method {} is not implemented.", t_nb_method);
|
|
||||||
std::exit(-1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -165,16 +140,17 @@ void ImageManipulator::exec_method(int const t_nb_method,
|
|||||||
* \param t_img Image with which the distance is computed
|
* \param t_img Image with which the distance is computed
|
||||||
* \return double
|
* \return double
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] auto ImageManipulator::euclidian_distance(
|
[[nodiscard]] auto
|
||||||
cv::Mat const& t_img) const noexcept -> double
|
ImageManipulator::euclidian_distance(cv::Mat const &t_img) const noexcept
|
||||||
|
-> double
|
||||||
{
|
{
|
||||||
double euclidian = 0.0;
|
double euclidian = 0.0;
|
||||||
for (auto itr1 = reference_.begin<uchar>(), itr2 = t_img.begin<uchar>();
|
for (auto itr1 = reference_.begin<uchar>(), itr2 = t_img.begin<uchar>();
|
||||||
itr1 != reference_.end<uchar>() && itr2 != t_img.end<uchar>();
|
itr1 != reference_.end<uchar>() && itr2 != t_img.end<uchar>();
|
||||||
++itr1, ++itr2) {
|
++itr1, ++itr2) {
|
||||||
euclidian += std::pow(*itr1 - *itr2, 2);
|
euclidian += std::pow(*itr1 - *itr2, 2);
|
||||||
}
|
}
|
||||||
return std::sqrt(euclidian);
|
return std::sqrt(euclidian);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -182,7 +158,7 @@ void ImageManipulator::exec_method(int const t_nb_method,
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] auto ImageManipulator::random_color() const noexcept
|
[[nodiscard]] auto ImageManipulator::random_color() const noexcept
|
||||||
{
|
{
|
||||||
return cv::Scalar(rand() % 255, rand() % 255, rand() % 255);
|
return cv::Scalar(rand() % 255, rand() % 255, rand() % 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -192,12 +168,12 @@ void ImageManipulator::exec_method(int const t_nb_method,
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] auto ImageManipulator::get_square_values() const noexcept
|
[[nodiscard]] auto ImageManipulator::get_square_values() const noexcept
|
||||||
{
|
{
|
||||||
int rand_x = rand() % reference_.size().width;
|
int rand_x = rand() % reference_.size().width;
|
||||||
int rand_y = rand() % reference_.size().height;
|
int rand_y = rand() % reference_.size().height;
|
||||||
int size = rand()
|
int size = rand()
|
||||||
% std::min(reference_.size().width - rand_x,
|
% std::min(reference_.size().width - rand_x,
|
||||||
reference_.size().height - rand_y);
|
reference_.size().height - rand_y);
|
||||||
return std::tuple<int, int, int>(rand_x, rand_y, size);
|
return std::tuple<int, int, int>(rand_x, rand_y, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -210,18 +186,38 @@ void ImageManipulator::exec_method(int const t_nb_method,
|
|||||||
[[nodiscard]] auto ImageManipulator::get_controlled_square_values() const
|
[[nodiscard]] auto ImageManipulator::get_controlled_square_values() const
|
||||||
noexcept
|
noexcept
|
||||||
{
|
{
|
||||||
int rand_x = rand() % reference_.size().width;
|
int rand_x = rand() % reference_.size().width;
|
||||||
int rand_y = rand() % reference_.size().height;
|
int rand_y = rand() % reference_.size().height;
|
||||||
float const coef = static_cast<float>(remaining_iter_)
|
float const coef = static_cast<float>(remaining_iter_)
|
||||||
/ static_cast<float>(total_iterations_);
|
/ static_cast<float>(total_iterations_);
|
||||||
int const min_size
|
int const min_size
|
||||||
= static_cast<int>((static_cast<float>(std::min(reference_.size().width,
|
= static_cast<int>((static_cast<float>(std::min(reference_.size().width,
|
||||||
reference_.size().height))
|
reference_.size().height))
|
||||||
/ 2.0f)
|
/ 2.0f)
|
||||||
* coef);
|
* coef);
|
||||||
int const max_size = min_size * 2 + 1;
|
int const max_size = min_size * 2 + 1;
|
||||||
int size = rand() % (max_size - min_size) + min_size;
|
int size = rand() % (max_size - min_size) + min_size;
|
||||||
return std::tuple<int, int, int>(rand_x, rand_y, size);
|
return std::tuple<int, int, int>(rand_x, rand_y, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageManipulator::create_shape() noexcept
|
||||||
|
{
|
||||||
|
shape_(cv::Point{reference_.size().width, reference_.size().height},
|
||||||
|
std::min(reference_.size().width, reference_.size().height));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageManipulator::create_controlled_shape() noexcept
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
shape_(cv::Point{reference_.size().width, reference_.size().height}, max_size,
|
||||||
|
min_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -233,41 +229,24 @@ void ImageManipulator::exec_method(int const t_nb_method,
|
|||||||
* \param[in] t_controlled_size Enables controlled square size
|
* \param[in] t_controlled_size Enables controlled square size
|
||||||
* \return Optional pair of cv::Mat and double
|
* \return Optional pair of cv::Mat and double
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] auto ImageManipulator::create_candidate(
|
[[nodiscard]] auto
|
||||||
bool const t_controlled_size = false)
|
ImageManipulator::create_candidate(bool const t_controlled_size = false)
|
||||||
{
|
{
|
||||||
auto temp_img = generated_image_.clone();
|
auto temp_img = generated_image_.clone();
|
||||||
auto create_shape = [&]() {
|
auto const &color = colors_[rand() % colors_.size()];
|
||||||
return shape_(cv::Point{reference_.size().width, reference_.size().height},
|
if (t_controlled_size) {
|
||||||
std::min(reference_.size().width, reference_.size().height));
|
create_shape();
|
||||||
};
|
} else {
|
||||||
auto create_controlled_shape = [&]() {
|
create_controlled_shape();
|
||||||
float const coef = static_cast<float>(remaining_iter_)
|
}
|
||||||
/ static_cast<float>(total_iterations_);
|
draw_shape(temp_img, cv::Scalar{static_cast<double>(color[0]),
|
||||||
int const min_size = static_cast<int>(
|
static_cast<double>(color[1]),
|
||||||
(static_cast<float>(
|
static_cast<double>(color[2])});
|
||||||
std::min(reference_.size().width, reference_.size().height))
|
auto new_diff = euclidian_distance(temp_img);
|
||||||
/ 2.0f)
|
return (new_diff < diff_)
|
||||||
* coef);
|
? std::optional<std::pair<cv::Mat, double>>{std::make_pair(
|
||||||
int const max_size = min_size * 2 + 1;
|
std::move(temp_img), new_diff)}
|
||||||
return shape_(cv::Point{reference_.size().width, reference_.size().height},
|
: std::nullopt;
|
||||||
max_size, min_size);
|
|
||||||
};
|
|
||||||
auto const& color = colors_[rand() % colors_.size()];
|
|
||||||
if (t_controlled_size) {
|
|
||||||
create_shape();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
create_controlled_shape();
|
|
||||||
}
|
|
||||||
draw_shape(temp_img, cv::Scalar{static_cast<double>(color[0]),
|
|
||||||
static_cast<double>(color[1]),
|
|
||||||
static_cast<double>(color[2])});
|
|
||||||
auto new_diff = euclidian_distance(temp_img);
|
|
||||||
return (new_diff < diff_)
|
|
||||||
? std::optional<std::pair<cv::Mat, double>>{std::make_pair(
|
|
||||||
std::move(temp_img), new_diff)}
|
|
||||||
: std::nullopt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -281,25 +260,25 @@ void ImageManipulator::exec_method(int const t_nb_method,
|
|||||||
[[nodiscard]] auto ImageManipulator::generate_tiles(int const t_cols,
|
[[nodiscard]] auto ImageManipulator::generate_tiles(int const t_cols,
|
||||||
int const t_rows) const
|
int const t_rows) const
|
||||||
{
|
{
|
||||||
std::vector<std::vector<ImageManipulator>> tiles{};
|
std::vector<std::vector<ImageManipulator>> tiles{};
|
||||||
int const tile_width = reference_.cols / t_cols;
|
int const tile_width = reference_.cols / t_cols;
|
||||||
int const tile_height = reference_.rows / t_rows;
|
int const tile_height = reference_.rows / t_rows;
|
||||||
for (int index_x = 0; index_x < t_cols; ++index_x) {
|
for (int index_x = 0; index_x < t_cols; ++index_x) {
|
||||||
std::vector<ImageManipulator> tile_col{};
|
std::vector<ImageManipulator> tile_col{};
|
||||||
for (int index_y = 0; index_y < t_rows; ++index_y) {
|
for (int index_y = 0; index_y < t_rows; ++index_y) {
|
||||||
int const width = (index_x != t_cols - 1)
|
int const width = (index_x != t_cols - 1)
|
||||||
? tile_width
|
? tile_width
|
||||||
: tile_width + reference_.cols % tile_width;
|
: tile_width + reference_.cols % tile_width;
|
||||||
int const height = (index_y != t_rows - 1)
|
int const height = (index_y != t_rows - 1)
|
||||||
? tile_height
|
? tile_height
|
||||||
: tile_height + reference_.rows % tile_height;
|
: tile_height + reference_.rows % tile_height;
|
||||||
tile_col.emplace_back(reference_, total_iterations_, shape_.get_type(),
|
tile_col.emplace_back(reference_, total_iterations_, shape_.get_type(),
|
||||||
index_x * tile_width, index_y * tile_height, width,
|
index_x * tile_width, index_y * tile_height, width,
|
||||||
height);
|
height);
|
||||||
}
|
}
|
||||||
tiles.push_back(tile_col);
|
tiles.push_back(tile_col);
|
||||||
}
|
}
|
||||||
return tiles;
|
return tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -308,16 +287,16 @@ void ImageManipulator::exec_method(int const t_nb_method,
|
|||||||
*/
|
*/
|
||||||
void ImageManipulator::get_color_set()
|
void ImageManipulator::get_color_set()
|
||||||
{
|
{
|
||||||
for (int h = 0; h < reference_.size().height; h += thread_nbr) {
|
for (int h = 0; h < reference_.size().height; h += thread_nbr) {
|
||||||
std::vector<std::thread> thread_list{};
|
std::vector<std::thread> thread_list{};
|
||||||
for (auto i = 0u; i < thread_nbr; ++i) {
|
for (auto i = 0u; i < thread_nbr; ++i) {
|
||||||
thread_list.push_back(
|
thread_list.push_back(
|
||||||
std::thread(&ImageManipulator::threaded_get_color, this, h + i));
|
std::thread(&ImageManipulator::threaded_get_color, this, h + i));
|
||||||
}
|
}
|
||||||
std::for_each(thread_list.begin(), thread_list.end(),
|
std::for_each(thread_list.begin(), thread_list.end(),
|
||||||
[](auto& th) { th.join(); });
|
[](auto &th) { th.join(); });
|
||||||
}
|
}
|
||||||
colors_.shrink_to_fit();
|
colors_.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -328,20 +307,20 @@ void ImageManipulator::get_color_set()
|
|||||||
*/
|
*/
|
||||||
void ImageManipulator::threaded_get_color(int const t_h)
|
void ImageManipulator::threaded_get_color(int const t_h)
|
||||||
{
|
{
|
||||||
if (t_h > reference_.size().height) {
|
if (t_h > reference_.size().height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int w = 0; w < reference_.size().width; w += 3) {
|
for (int w = 0; w < reference_.size().width; w += 3) {
|
||||||
std::array<uchar, 3> temp
|
std::array<uchar, 3> temp
|
||||||
= {reference_.at<uchar>(t_h, w), reference_.at<uchar>(t_h, w + 1),
|
= {reference_.at<uchar>(t_h, w), reference_.at<uchar>(t_h, w + 1),
|
||||||
reference_.at<uchar>(t_h, w + 2)};
|
reference_.at<uchar>(t_h, w + 2)};
|
||||||
auto pos = std::find(std::begin(colors_), std::end(colors_), temp);
|
auto pos = std::find(std::begin(colors_), std::end(colors_), temp);
|
||||||
if (pos == std::end(colors_)) {
|
if (pos == std::end(colors_)) {
|
||||||
colors_mutex_.lock();
|
colors_mutex_.lock();
|
||||||
colors_.push_back(std::move(temp));
|
colors_.push_back(std::move(temp));
|
||||||
colors_mutex_.unlock();
|
colors_mutex_.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -353,22 +332,21 @@ void ImageManipulator::threaded_get_color(int const t_h)
|
|||||||
* \param[in] t_size Size of the square
|
* \param[in] t_size Size of the square
|
||||||
* \param[in] t_color Color of the square
|
* \param[in] t_color Color of the square
|
||||||
*/
|
*/
|
||||||
void ImageManipulator::draw_square(cv::Mat& t_img,
|
void ImageManipulator::draw_square(cv::Mat &t_img, cv::Point const &t_top_left,
|
||||||
cv::Point const& t_top_left,
|
|
||||||
int const t_size,
|
int const t_size,
|
||||||
cv::Scalar const& t_color) const
|
cv::Scalar const &t_color) const
|
||||||
{
|
{
|
||||||
std::array<cv::Point, 4> points
|
std::array<cv::Point, 4> points
|
||||||
= {t_top_left, cv::Point{t_top_left.x, t_top_left.y + t_size},
|
= {t_top_left, cv::Point{t_top_left.x, t_top_left.y + t_size},
|
||||||
cv::Point{t_top_left.x + t_size, t_top_left.y + t_size},
|
cv::Point{t_top_left.x + t_size, t_top_left.y + t_size},
|
||||||
cv::Point{t_top_left.x + t_size, t_top_left.y}};
|
cv::Point{t_top_left.x + t_size, t_top_left.y}};
|
||||||
fillConvexPoly(t_img, points.data(), 4, t_color);
|
fillConvexPoly(t_img, points.data(), 4, t_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageManipulator::draw_shape(cv::Mat& t_img, cv::Scalar&& t_color)
|
void ImageManipulator::draw_shape(cv::Mat &t_img, cv::Scalar &&t_color)
|
||||||
{
|
{
|
||||||
fillConvexPoly(t_img, shape_.get_points().data(), shape_.get_nb_points(),
|
fillConvexPoly(t_img, shape_.get_points().data(), shape_.get_nb_points(),
|
||||||
t_color);
|
t_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -381,13 +359,13 @@ void ImageManipulator::draw_shape(cv::Mat& t_img, cv::Scalar&& t_color)
|
|||||||
* \param[in] t_img Image to replace \ref generated_image_
|
* \param[in] t_img Image to replace \ref generated_image_
|
||||||
* \param[in] t_diff New euclidian distance
|
* \param[in] t_diff New euclidian distance
|
||||||
*/
|
*/
|
||||||
void ImageManipulator::update_gen_image(cv::Mat const& t_img,
|
void ImageManipulator::update_gen_image(cv::Mat const &t_img,
|
||||||
double const t_diff)
|
double const t_diff)
|
||||||
{
|
{
|
||||||
diff_ = t_diff;
|
diff_ = t_diff;
|
||||||
t_img.copyTo(generated_image_);
|
t_img.copyTo(generated_image_);
|
||||||
--remaining_iter_;
|
--remaining_iter_;
|
||||||
spdlog::debug("remaining iter: {}\tdiff: {}", remaining_iter_, diff_);
|
spdlog::debug("remaining iter: {}\tdiff: {}", remaining_iter_, diff_);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -398,60 +376,60 @@ void ImageManipulator::update_gen_image(cv::Mat const& t_img,
|
|||||||
* \param t_tiles Collection of tiles to be merged together
|
* \param t_tiles Collection of tiles to be merged together
|
||||||
*/
|
*/
|
||||||
void ImageManipulator::merge_tiles(
|
void ImageManipulator::merge_tiles(
|
||||||
std::vector<std::vector<ImageManipulator>> const& t_tiles)
|
std::vector<std::vector<ImageManipulator>> const &t_tiles)
|
||||||
{
|
{
|
||||||
std::vector<cv::Mat> columns{};
|
std::vector<cv::Mat> columns{};
|
||||||
std::for_each(t_tiles.begin(), t_tiles.end(), [&columns](auto const& col) {
|
std::for_each(t_tiles.begin(), t_tiles.end(), [&columns](auto const &col) {
|
||||||
std::vector<cv::Mat> column_arr{};
|
std::vector<cv::Mat> column_arr{};
|
||||||
cv::Mat column_img{};
|
cv::Mat column_img{};
|
||||||
std::for_each(col.begin(), col.end(), [&column_arr](auto const& tile) {
|
std::for_each(col.begin(), col.end(), [&column_arr](auto const &tile) {
|
||||||
column_arr.push_back(tile.get_generated_image());
|
column_arr.push_back(tile.get_generated_image());
|
||||||
});
|
});
|
||||||
vconcat(column_arr, column_img);
|
vconcat(column_arr, column_img);
|
||||||
columns.push_back(std::move(column_img));
|
columns.push_back(std::move(column_img));
|
||||||
});
|
});
|
||||||
hconcat(columns, generated_image_);
|
hconcat(columns, generated_image_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageManipulator::method1()
|
void ImageManipulator::method1()
|
||||||
{
|
{
|
||||||
spdlog::debug("Beginning method1, initial difference: {}", diff_);
|
spdlog::debug("Beginning method1, initial difference: {}", diff_);
|
||||||
while (remaining_iter_ > 0 && diff_ > 0.0) {
|
while (remaining_iter_ > 0 && diff_ > 0.0) {
|
||||||
auto temp_image = generated_image_.clone();
|
auto temp_image = generated_image_.clone();
|
||||||
auto const [rand_x, rand_y, size] = get_square_values();
|
create_shape();
|
||||||
draw_square(temp_image, cv::Point{rand_x, rand_y}, size, random_color());
|
draw_shape(temp_image, random_color());
|
||||||
if (auto const new_diff = euclidian_distance(temp_image);
|
if (auto const new_diff = euclidian_distance(temp_image);
|
||||||
new_diff < diff_) {
|
new_diff < diff_) {
|
||||||
update_gen_image(temp_image, new_diff);
|
update_gen_image(temp_image, new_diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageManipulator::method2()
|
void ImageManipulator::method2()
|
||||||
{
|
{
|
||||||
spdlog::debug("Beginning method2, initial difference: {}", diff_);
|
spdlog::debug("Beginning method2, initial difference: {}", diff_);
|
||||||
spdlog::debug("Running on {} threads", thread_nbr);
|
spdlog::debug("Running on {} threads", thread_nbr);
|
||||||
get_color_set();
|
get_color_set();
|
||||||
spdlog::debug("{} colors detected", colors_.size());
|
spdlog::debug("{} colors detected", colors_.size());
|
||||||
while (remaining_iter_ > 0 && diff_ > 0.0) {
|
while (remaining_iter_ > 0 && diff_ > 0.0) {
|
||||||
if (auto result = create_candidate(); result.has_value()) {
|
if (auto result = create_candidate(); result.has_value()) {
|
||||||
update_gen_image(result->first, result->second);
|
update_gen_image(result->first, result->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageManipulator::method3()
|
void ImageManipulator::method3()
|
||||||
{
|
{
|
||||||
spdlog::debug("Beginning method3, initial difference: {}", diff_);
|
spdlog::debug("Beginning method3, initial difference: {}", diff_);
|
||||||
spdlog::debug("Running on {} threads", thread_nbr);
|
spdlog::debug("Running on {} threads", thread_nbr);
|
||||||
get_color_set();
|
get_color_set();
|
||||||
spdlog::debug("{} colors detected", colors_.size());
|
spdlog::debug("{} colors detected", colors_.size());
|
||||||
while (remaining_iter_ > 0 && diff_ > 0.0) {
|
while (remaining_iter_ > 0 && diff_ > 0.0) {
|
||||||
auto temp_image = generated_image_.clone();
|
auto temp_image = generated_image_.clone();
|
||||||
if (auto result = create_candidate(true); result.has_value()) {
|
if (auto result = create_candidate(true); result.has_value()) {
|
||||||
update_gen_image(result->first, result->second);
|
update_gen_image(result->first, result->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -459,36 +437,36 @@ void ImageManipulator::method3()
|
|||||||
*/
|
*/
|
||||||
void ImageManipulator::method4(bool const t_controlled_size)
|
void ImageManipulator::method4(bool const t_controlled_size)
|
||||||
{
|
{
|
||||||
spdlog::debug("Beginning method4, initial difference: {}", diff_);
|
spdlog::debug("Beginning method4, initial difference: {}", diff_);
|
||||||
spdlog::debug("Running on {} threads", thread_nbr);
|
spdlog::debug("Running on {} threads", thread_nbr);
|
||||||
get_color_set();
|
get_color_set();
|
||||||
spdlog::debug("{} colors detected", colors_.size());
|
spdlog::debug("{} colors detected", colors_.size());
|
||||||
while (remaining_iter_ > 0 && diff_ > 0.0) {
|
while (remaining_iter_ > 0 && diff_ > 0.0) {
|
||||||
std::vector<std::future<std::optional<std::pair<cv::Mat, double>>>>
|
std::vector<std::future<std::optional<std::pair<cv::Mat, double>>>>
|
||||||
results{};
|
results{};
|
||||||
std::vector<std::pair<cv::Mat, double>> values{};
|
std::vector<std::pair<cv::Mat, double>> values{};
|
||||||
// launch asynchronously candidate image generation
|
// launch asynchronously candidate image generation
|
||||||
for (size_t i = 0; i < thread_nbr; ++i) {
|
for (size_t i = 0; i < thread_nbr; ++i) {
|
||||||
results.push_back(std::async(std::launch::async,
|
results.push_back(std::async(std::launch::async,
|
||||||
&ImageManipulator::create_candidate, this,
|
&ImageManipulator::create_candidate, this,
|
||||||
t_controlled_size));
|
t_controlled_size));
|
||||||
}
|
}
|
||||||
// if candidate is a success, store it
|
// if candidate is a success, store it
|
||||||
std::for_each(results.begin(), results.end(), [&values, this](auto& elem) {
|
std::for_each(results.begin(), results.end(), [&values, this](auto &elem) {
|
||||||
if (auto res = elem.get(); res.has_value() && res->second < this->diff_) {
|
if (auto res = elem.get(); res.has_value() && res->second < this->diff_) {
|
||||||
values.push_back(*res);
|
values.push_back(*res);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// apply best candidate
|
// apply best candidate
|
||||||
if (values.size() > 0) {
|
if (values.size() > 0) {
|
||||||
auto const pos
|
auto const pos
|
||||||
= std::min_element(std::begin(values), std::end(values),
|
= std::min_element(std::begin(values), std::end(values),
|
||||||
[](const auto& elem1, const auto& elem2) {
|
[](const auto &elem1, const auto &elem2) {
|
||||||
return elem1.second < elem2.second;
|
return elem1.second < elem2.second;
|
||||||
});
|
});
|
||||||
update_gen_image(pos->first, pos->second);
|
update_gen_image(pos->first, pos->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -497,25 +475,23 @@ void ImageManipulator::method4(bool const t_controlled_size)
|
|||||||
* \param[in] t_rows Number of rows the reference should be divided into
|
* \param[in] t_rows Number of rows the reference should be divided into
|
||||||
* \param[in] t_submethod Method to be used on each tile
|
* \param[in] t_submethod Method to be used on each tile
|
||||||
*/
|
*/
|
||||||
void ImageManipulator::method5(bool const t_controlled_size,
|
void ImageManipulator::method5(bool const t_controlled_size, int const t_cols,
|
||||||
int const t_cols,
|
int const t_rows, int const t_submethod)
|
||||||
int const t_rows,
|
|
||||||
int const t_submethod)
|
|
||||||
{
|
{
|
||||||
spdlog::debug("Beginning method5, initial difference: {}", diff_);
|
spdlog::debug("Beginning method5, initial difference: {}", diff_);
|
||||||
spdlog::debug("Running on {} threads", thread_nbr);
|
spdlog::debug("Running on {} threads", thread_nbr);
|
||||||
|
|
||||||
auto tiles = generate_tiles((t_cols != 0) ? t_cols : t_rows, t_rows);
|
auto tiles = generate_tiles((t_cols != 0) ? t_cols : t_rows, t_rows);
|
||||||
spdlog::debug("{} tiles", tiles.size());
|
spdlog::debug("{} tiles", tiles.size());
|
||||||
|
|
||||||
std::vector<std::thread> thread_list{};
|
std::vector<std::thread> thread_list{};
|
||||||
std::for_each(tiles.begin(), tiles.end(), [&](auto& row) {
|
std::for_each(tiles.begin(), tiles.end(), [&](auto &row) {
|
||||||
std::for_each(row.begin(), row.end(), [&](auto& tile) {
|
std::for_each(row.begin(), row.end(), [&](auto &tile) {
|
||||||
thread_list.emplace_back(
|
thread_list.emplace_back(
|
||||||
[&]() { tile.exec_method(t_submethod, t_controlled_size); });
|
[&]() { tile.exec_method(t_submethod, t_controlled_size); });
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
std::for_each(thread_list.begin(), thread_list.end(),
|
std::for_each(thread_list.begin(), thread_list.end(),
|
||||||
[](auto& th) { th.join(); });
|
[](auto &th) { th.join(); });
|
||||||
merge_tiles(tiles);
|
merge_tiles(tiles);
|
||||||
}
|
}
|
||||||
|
125
src/parseargs.cc
125
src/parseargs.cc
@ -1,10 +1,11 @@
|
|||||||
#include "parseargs.hh"
|
#include "parseargs.hh"
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
constexpr int DEFAULT_ITERATIONS = 2000;
|
constexpr int DEFAULT_ITERATIONS = 2000;
|
||||||
|
|
||||||
using path = std::filesystem::path;
|
using path = std::filesystem::path;
|
||||||
namespace po = boost::program_options;
|
namespace po = boost::program_options;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -19,17 +20,15 @@ namespace po = boost::program_options;
|
|||||||
* \param[out] t_input Input path
|
* \param[out] t_input Input path
|
||||||
* \param[out] t_output Output path
|
* \param[out] t_output Output path
|
||||||
*/
|
*/
|
||||||
void processFilenames(po::variables_map const& t_vm,
|
void processFilenames(po::variables_map const &t_vm, path const &t_input,
|
||||||
path const& t_input,
|
path &t_output)
|
||||||
path& t_output)
|
|
||||||
{
|
{
|
||||||
if (!t_vm.count("output")) {
|
if (!t_vm.count("output")) {
|
||||||
t_output.replace_filename("output_"
|
t_output.replace_filename("output_"
|
||||||
+ std::string{t_input.filename().string()});
|
+ std::string{t_input.filename().string()});
|
||||||
}
|
} else if (!t_output.has_extension()) {
|
||||||
else if (!t_output.has_extension()) {
|
t_output.replace_extension(".png");
|
||||||
t_output.replace_extension(".png");
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,62 +41,58 @@ void processFilenames(po::variables_map const& t_vm,
|
|||||||
* \param[in] t_av Arguments passed to the program
|
* \param[in] t_av Arguments passed to the program
|
||||||
* \return Tuple of path, path, int, int, int, int, int, bool and bool
|
* \return Tuple of path, path, int, int, int, int, int, bool and bool
|
||||||
*/
|
*/
|
||||||
[[nodiscard]] auto parse_args(int t_ac, char** t_av) -> ParsedArgs
|
[[nodiscard]] auto parse_args(int t_ac, char **t_av) -> ParsedArgs
|
||||||
{
|
{
|
||||||
ParsedArgs ret{};
|
ParsedArgs ret{};
|
||||||
po::options_description desc("Allowed options");
|
po::options_description desc("Allowed options");
|
||||||
desc.add_options()("help,h", "Display this help message")(
|
desc.add_options()
|
||||||
"input,i", po::value<path>(), "Input image")(
|
("help,h", "Display this help message")
|
||||||
"output,o", po::value<path>(),
|
("input,i", po::value<path>(), "Input image")
|
||||||
"Image output path (default: \"output_\" + input path)")(
|
("output,o", po::value<path>(),
|
||||||
"iterations,n", po::value<int>(), "Number of iterations (default: 2000)")(
|
"Image output path (default: \"output_\" + input path)")
|
||||||
"method,m", po::value<int>(), "Method number to be used (default: 1)")(
|
("iterations,n", po::value<int>(), "Number of iterations (default: 2000)")
|
||||||
"form,f", po::value<int>(), "Select shape (1:square, 2:triangle)")(
|
("method,m", po::value<int>(), "Method number to be used (default: 1)")
|
||||||
"cols,c", po::value<int>(),
|
("form,f", po::value<int>(), "Select shape (1:square, 2:triangle)")
|
||||||
"For method 5 only, number of columns the reference image should be "
|
("cols,c", po::value<int>(),
|
||||||
"divided into. If the value is equal to 0, then it will be assumed "
|
"For method 5 only, number of columns the reference image should be "
|
||||||
"there will be as many rows as there are collumns. (default: 0)")(
|
"divided into. If the value is equal to 0, then it will be assumed "
|
||||||
"rows,r", po::value<int>(),
|
"there will be as many rows as there are collumns. (default: 0)")
|
||||||
"For method 5 only, number of rows the reference image should be "
|
("rows,r", po::value<int>(),
|
||||||
"divided into. (default: 1)")(
|
"For method 5 only, number of rows the reference image should be "
|
||||||
"submethod,S", po::value<int>(),
|
"divided into. (default: 1)")
|
||||||
"Sub-method that will be used to generate the individual tiles from "
|
("submethod,S", po::value<int>(),
|
||||||
"method 5. (default: 1)")("size,s",
|
"Sub-method that will be used to generate the individual tiles from "
|
||||||
"Enables controlled size of the random shapes")(
|
"method 5. (default: 1)")
|
||||||
"verbose,v", "Enables verbosity");
|
("size,s", "Enables controlled size of the random shapes")
|
||||||
po::variables_map vm;
|
("verbose,v", "Enables verbosity");
|
||||||
po::store(po::parse_command_line(t_ac, t_av, desc), vm);
|
po::variables_map vm;
|
||||||
po::notify(vm);
|
po::store(po::parse_command_line(t_ac, t_av, desc), vm);
|
||||||
if (vm.count("help") || !vm.count("input")) {
|
po::notify(vm);
|
||||||
std::cout << desc << "\n";
|
if (vm.count("help") || !vm.count("input")) {
|
||||||
std::exit(!vm.count("help"));
|
std::cout << desc << "\n";
|
||||||
}
|
std::exit(!vm.count("help"));
|
||||||
|
}
|
||||||
|
|
||||||
auto const input_path = vm["input"].as<path>();
|
auto const input_path = vm["input"].as<path>();
|
||||||
auto output_path
|
auto output_path
|
||||||
= vm.count("output") ? vm["output"].as<path>() : input_path.filename();
|
= vm.count("output") ? vm["output"].as<path>() : input_path.filename();
|
||||||
processFilenames(vm, input_path, output_path);
|
processFilenames(vm, input_path, output_path);
|
||||||
|
|
||||||
ret.input_path = input_path;
|
ret.input_path = input_path;
|
||||||
ret.output_path = output_path;
|
ret.output_path = output_path;
|
||||||
ret.iterations = vm.count("iterations") ? vm["iterations"].as<int>()
|
ret.iterations = vm.count("iterations") ? vm["iterations"].as<int>()
|
||||||
: DEFAULT_ITERATIONS;
|
: DEFAULT_ITERATIONS;
|
||||||
ret.method = vm.count("method") ? vm["method"].as<int>() : 1;
|
ret.method = vm.count("method") ? vm["method"].as<int>() : 1;
|
||||||
switch (vm.count("form") ? vm["form"].as<int>() : 1) {
|
switch (vm.count("form") ? vm["form"].as<int>() : 1) {
|
||||||
case 2:
|
case 2: ret.shape = Shape::ShapeType::Triangle; break;
|
||||||
ret.shape= Shape::ShapeType::Triangle;
|
case 1: [[fallthrough]];
|
||||||
break;
|
default: ret.shape = Shape::ShapeType::Square; break;
|
||||||
case 1:
|
}
|
||||||
[[fallthrough]];
|
|
||||||
default:
|
|
||||||
ret.shape = Shape::ShapeType::Square;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret.cols = vm.count("cols") ? vm["cols"].as<int>() : 0;
|
ret.cols = vm.count("cols") ? vm["cols"].as<int>() : 0;
|
||||||
ret.rows = vm.count("rows") ? vm["rows"].as<int>() : 1;
|
ret.rows = vm.count("rows") ? vm["rows"].as<int>() : 1;
|
||||||
ret.submethod = vm.count("submethod") ? vm["submethod"].as<int>() : 1;
|
ret.submethod = vm.count("submethod") ? vm["submethod"].as<int>() : 1;
|
||||||
ret.controlled_size = vm.count("size");
|
ret.controlled_size = vm.count("size");
|
||||||
ret.verbose = vm.count("verbose");
|
ret.verbose = vm.count("verbose");
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "shapes.hh"
|
#include "shapes.hh"
|
||||||
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -6,22 +7,18 @@ using point_arr = std::array<cv::Point, 4>;
|
|||||||
|
|
||||||
Shape::Shape(Shape::ShapeType const t_type) : type_{t_type}
|
Shape::Shape(Shape::ShapeType const t_type) : type_{t_type}
|
||||||
{
|
{
|
||||||
switch (t_type) {
|
switch (t_type) {
|
||||||
case ShapeType::Triangle: {
|
case ShapeType::Triangle: {
|
||||||
nb_points_ = 3;
|
nb_points_ = 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ShapeType::Square:
|
case ShapeType::Square: [[fallthrough]];
|
||||||
[[fallthrough]];
|
default: nb_points_ = 4; break;
|
||||||
default:
|
}
|
||||||
nb_points_ = 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape::Shape(Shape&& other) noexcept
|
Shape::Shape(Shape &&other) noexcept
|
||||||
: type_{std::move(other.type_)},
|
: type_{std::move(other.type_)}, points_{std::move(other.points_)},
|
||||||
points_{std::move(other.points_)},
|
|
||||||
nb_points_{std::move(other.nb_points_)}
|
nb_points_{std::move(other.nb_points_)}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -34,39 +31,36 @@ Shape::Shape(Shape&& other) noexcept
|
|||||||
* for
|
* for
|
||||||
* \return Array of points describing the shape
|
* \return Array of points describing the shape
|
||||||
*/
|
*/
|
||||||
void Shape::operator()(cv::Point&& t_max_pos,
|
void Shape::operator()(cv::Point &&t_max_pos, int const t_max_size,
|
||||||
int const t_max_size,
|
|
||||||
int const t_min_size) noexcept
|
int const t_min_size) noexcept
|
||||||
{
|
{
|
||||||
int const size = (rand() % (t_max_size - t_min_size)) + t_min_size;
|
int const size = (rand() % (t_max_size - t_min_size)) + t_min_size;
|
||||||
cv::Point const top_left
|
cv::Point const top_left
|
||||||
= {rand() % (t_max_pos.x - size), rand() % (t_max_pos.y - size)};
|
= {rand() % (t_max_pos.x - size), rand() % (t_max_pos.y - size)};
|
||||||
if (type_ == ShapeType::Triangle) {
|
if (type_ == ShapeType::Triangle) {
|
||||||
create_triangle_points(top_left, size);
|
create_triangle_points(top_left, size);
|
||||||
}
|
} else { // ShapeType::Square
|
||||||
else { // ShapeType::Square
|
create_square_points(top_left, size);
|
||||||
create_square_points(top_left, size);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shape::create_triangle_points(cv::Point const &t_top_left,
|
||||||
void Shape::create_triangle_points(cv::Point const& t_top_left,
|
|
||||||
int const t_size) noexcept
|
int const t_size) noexcept
|
||||||
{
|
{
|
||||||
bool top_left = rand() % 1 == 0;
|
bool top_left = rand() % 1 == 0;
|
||||||
points_ = {
|
points_ = {
|
||||||
cv::Point{top_left ? t_top_left.x : t_top_left.x + t_size, t_top_left.y},
|
cv::Point{top_left ? t_top_left.x : t_top_left.x + t_size, t_top_left.y},
|
||||||
cv::Point{top_left ? t_top_left.x + t_size : t_top_left.x,
|
cv::Point{top_left ? t_top_left.x + t_size : t_top_left.x,
|
||||||
t_top_left.y + t_size},
|
t_top_left.y + t_size},
|
||||||
cv::Point{t_top_left.x + rand() % t_size, t_top_left.y + t_size},
|
cv::Point{t_top_left.x + rand() % t_size, t_top_left.y + t_size},
|
||||||
cv::Point{0, 0}};
|
cv::Point{0, 0}};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shape::create_square_points(cv::Point const& t_top_left,
|
void Shape::create_square_points(cv::Point const &t_top_left,
|
||||||
int const t_size) noexcept
|
int const t_size) noexcept
|
||||||
{
|
{
|
||||||
points_ = {cv::Point{t_top_left.x, t_top_left.y},
|
points_ = {cv::Point{t_top_left.x, t_top_left.y},
|
||||||
cv::Point{t_top_left.x, t_top_left.y + t_size},
|
cv::Point{t_top_left.x, t_top_left.y + t_size},
|
||||||
cv::Point{t_top_left.x + t_size, t_top_left.y},
|
cv::Point{t_top_left.x + t_size, t_top_left.y},
|
||||||
cv::Point{t_top_left.x + t_size, t_top_left.y}};
|
cv::Point{t_top_left.x + t_size, t_top_left.y}};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user