clang format update

This commit is contained in:
Phuntsok Drak-pa 2019-04-27 16:27:22 +02:00
parent bc9dcf4142
commit b962d50996
7 changed files with 520 additions and 559 deletions

View File

@ -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 objects generated image /// \brief Update this objects 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 */
}; };

View File

@ -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;

View File

@ -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};
}; };

View File

@ -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();
} }

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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}};
} }