changed program options, individual tiles load
This commit is contained in:
parent
67626b346d
commit
caf4c42169
@ -13,24 +13,34 @@
|
||||
class ImageManipulator {
|
||||
public:
|
||||
ImageManipulator() = delete;
|
||||
ImageManipulator(const ImageManipulator& other) = delete;
|
||||
ImageManipulator(ImageManipulator&& other) noexcept = delete;
|
||||
ImageManipulator& operator=(const ImageManipulator& other) = delete;
|
||||
ImageManipulator& operator=(ImageManipulator&& other) noexcept = delete;
|
||||
ImageManipulator(const ImageManipulator& other);
|
||||
ImageManipulator(ImageManipulator&& other) noexcept;
|
||||
[[nodiscard]] auto operator=(const ImageManipulator& other)
|
||||
-> ImageManipulator;
|
||||
[[nodiscard]] auto operator=(ImageManipulator&& other) noexcept
|
||||
-> ImageManipulator;
|
||||
|
||||
// Load image from input, and prepare for output
|
||||
ImageManipulator(std::filesystem::path const t_input_path,
|
||||
std::filesystem::path const t_output_path,
|
||||
int const iterations);
|
||||
// ImageManipulator(cv::Mat const& t_origin_image,
|
||||
// int const iterations,
|
||||
// int const t_x,
|
||||
// int const t_y,
|
||||
// int const t_width,
|
||||
// int const t_height);
|
||||
ImageManipulator(cv::Mat const& t_origin_image,
|
||||
int const iterations,
|
||||
int const t_x,
|
||||
int const t_y,
|
||||
int const t_width,
|
||||
int const t_height);
|
||||
|
||||
void exec_method(int const t_nb_method, bool const t_controlled_size);
|
||||
void exec_method(int const t_nb_method,
|
||||
bool const t_controlled_size,
|
||||
int const t_cols,
|
||||
int const t_rows,
|
||||
int const t_submethod);
|
||||
void write_file() const;
|
||||
[[nodiscard]] auto const& get_generated_image() const noexcept
|
||||
{
|
||||
return generated_image_;
|
||||
}
|
||||
|
||||
//! Destructor
|
||||
virtual ~ImageManipulator() noexcept = default;
|
||||
@ -51,21 +61,27 @@ class ImageManipulator {
|
||||
cv::Point const& t_top_left,
|
||||
int const t_size,
|
||||
cv::Scalar const& t_color) const;
|
||||
void update_gen_image(cv::Mat const& t_img, double const t_diff);
|
||||
void update_gen_image(cv::Mat const& t_img, double const t_diff);
|
||||
void method1();
|
||||
void method2();
|
||||
void method3();
|
||||
void method4(bool const t_controlled_size);
|
||||
void method5(bool const t_controlled_size,
|
||||
int cols,
|
||||
int const rows,
|
||||
int const submethod);
|
||||
|
||||
std::vector<std::array<uchar, 3>> colors_
|
||||
= std::vector<std::array<uchar, 3>>{};
|
||||
cv::Mat const reference_;
|
||||
cv::Mat generated_image_;
|
||||
std::mutex colors_mutex_ = std::mutex{};
|
||||
std::string const output_path_;
|
||||
cv::Mat generated_image_
|
||||
= cv::Mat{reference_.size().height, reference_.size().width, CV_8UC3,
|
||||
cv::Scalar(0, 0, 0)};
|
||||
mutable std::mutex colors_mutex_ = std::mutex{};
|
||||
std::string const output_path_{""};
|
||||
double diff_ = 0.0;
|
||||
int const total_iterations_ = 0;
|
||||
int remaining_iter_ = 0;
|
||||
int const width_;
|
||||
int const height_;
|
||||
int remaining_iter_ = total_iterations_;
|
||||
int const width_ = reference_.size().width;
|
||||
int const height_ = reference_.size().height;
|
||||
};
|
||||
|
@ -1,5 +1,4 @@
|
||||
#ifndef GENETIC_IMAGE_INCLUDE_GENIMG_PARSEARGS_HH_
|
||||
#define GENETIC_IMAGE_INCLUDE_GENIMG_PARSEARGS_HH_
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
#include <tuple>
|
||||
@ -10,7 +9,6 @@
|
||||
int,
|
||||
int,
|
||||
int,
|
||||
int,
|
||||
bool,
|
||||
bool>;
|
||||
|
||||
#endif /* GENETIC_IMAGE_INCLUDE_GENIMG_PARSEARGS_HH_ */
|
||||
|
11
src/main.cc
11
src/main.cc
@ -7,19 +7,16 @@
|
||||
int main(int ac, char** av)
|
||||
{
|
||||
std::srand(std::time(nullptr));
|
||||
auto [input_file, output_file, iterations, method, columns, rows,
|
||||
controlled_size, verbose]
|
||||
auto const [input_file, output_file, iterations, method, cols, rows,
|
||||
submethod, controlled_size, verbose]
|
||||
= parse_args(ac, av);
|
||||
if (rows == 0) {
|
||||
rows = columns;
|
||||
}
|
||||
spdlog::set_level(verbose ? spdlog::level::debug : spdlog::level::info);
|
||||
spdlog::set_pattern("[thread %t] %+");
|
||||
spdlog::set_pattern("[thread %t] %+");
|
||||
spdlog::debug("Input file:\t{}", input_file.native());
|
||||
spdlog::debug("Output file:\t{}", output_file.native());
|
||||
spdlog::debug("Iterations:\t{}", iterations);
|
||||
|
||||
ImageManipulator image_process{input_file, output_file, iterations};
|
||||
image_process.exec_method(method, controlled_size);
|
||||
image_process.exec_method(method, controlled_size, cols, rows, submethod);
|
||||
image_process.write_file();
|
||||
}
|
||||
|
158
src/methods.cc
158
src/methods.cc
@ -8,7 +8,6 @@
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
std::mutex colors_mutex;
|
||||
auto const thread_nbr = std::thread::hardware_concurrency();
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -20,15 +19,9 @@ ImageManipulator::ImageManipulator(std::filesystem::path const t_input_path,
|
||||
std::filesystem::path const t_output_path,
|
||||
int const t_iterations)
|
||||
: reference_{cv::imread(t_input_path.native(), cv::IMREAD_COLOR)},
|
||||
generated_image_{cv::Mat{reference_.size().height,
|
||||
reference_.size().width, CV_8UC3,
|
||||
cv::Scalar(0, 0, 0)}},
|
||||
output_path_{t_output_path.native()},
|
||||
diff_{euclidian_distance(generated_image_)},
|
||||
total_iterations_{t_iterations},
|
||||
remaining_iter_{t_iterations},
|
||||
width_{reference_.size().width},
|
||||
height_{reference_.size().height}
|
||||
total_iterations_{t_iterations}
|
||||
{
|
||||
if (!reference_.data) {
|
||||
spdlog::critical("Could not open or find image!\n");
|
||||
@ -39,9 +32,72 @@ ImageManipulator::ImageManipulator(std::filesystem::path const t_input_path,
|
||||
spdlog::debug("Height:\t{}", reference_.size().height);
|
||||
}
|
||||
|
||||
ImageManipulator::ImageManipulator(cv::Mat const& t_origin_image,
|
||||
int const t_iterations,
|
||||
int const t_x,
|
||||
int const t_y,
|
||||
int const t_width,
|
||||
int const t_height)
|
||||
: reference_{t_origin_image(
|
||||
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)})},
|
||||
diff_{euclidian_distance(generated_image_)},
|
||||
total_iterations_{t_iterations}
|
||||
{
|
||||
if (!reference_.data) {
|
||||
spdlog::critical("Could not open or find image!\n");
|
||||
exit(-1);
|
||||
}
|
||||
spdlog::debug("Image loaded!");
|
||||
spdlog::debug("Width:\t{}", reference_.size().width);
|
||||
spdlog::debug("Height:\t{}", reference_.size().height);
|
||||
}
|
||||
|
||||
ImageManipulator::ImageManipulator(const ImageManipulator& other)
|
||||
: colors_{other.colors_},
|
||||
reference_{other.reference_},
|
||||
generated_image_{other.generated_image_},
|
||||
output_path_{other.output_path_},
|
||||
diff_{other.diff_},
|
||||
total_iterations_{other.total_iterations_},
|
||||
remaining_iter_{other.remaining_iter_},
|
||||
width_{other.width_},
|
||||
height_{other.height_}
|
||||
{
|
||||
}
|
||||
|
||||
ImageManipulator::ImageManipulator(ImageManipulator&& other) noexcept
|
||||
: colors_{std::move(other.colors_)},
|
||||
reference_{std::move(other.reference_)},
|
||||
generated_image_{std::move(other.generated_image_)},
|
||||
output_path_{std::move(other.output_path_)},
|
||||
diff_{std::move(other.diff_)},
|
||||
total_iterations_{other.total_iterations_},
|
||||
remaining_iter_{other.remaining_iter_},
|
||||
width_{other.width_},
|
||||
height_{other.height_}
|
||||
{
|
||||
}
|
||||
|
||||
// operators //////////////////////////////////////////////////////////////////
|
||||
[[nodiscard]] auto ImageManipulator::operator=(const ImageManipulator& other)
|
||||
-> ImageManipulator
|
||||
{
|
||||
return ImageManipulator(other);
|
||||
}
|
||||
|
||||
[[nodiscard]] auto ImageManipulator::operator=(
|
||||
ImageManipulator&& other) noexcept -> ImageManipulator
|
||||
{
|
||||
return ImageManipulator{std::move(other)};
|
||||
}
|
||||
|
||||
// public methods /////////////////////////////////////////////////////////////
|
||||
void ImageManipulator::exec_method(int const t_nb_method,
|
||||
bool const t_controlled_size = false)
|
||||
bool const t_controlled_size = false,
|
||||
int const cols = 1,
|
||||
int const rows = 0,
|
||||
int const submethod = 1)
|
||||
{
|
||||
switch (t_nb_method) {
|
||||
case 1: {
|
||||
@ -60,6 +116,10 @@ void ImageManipulator::exec_method(int const t_nb_method,
|
||||
method4(t_controlled_size);
|
||||
break;
|
||||
}
|
||||
case 5: {
|
||||
method5(t_controlled_size, cols, rows, submethod);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
spdlog::error("Requested method {} is not implemented.", t_nb_method);
|
||||
std::exit(-1);
|
||||
@ -138,10 +198,9 @@ void ImageManipulator::write_file() const
|
||||
|
||||
void ImageManipulator::get_color_set()
|
||||
{
|
||||
for (int h = 0; h < reference_.size().height;
|
||||
h += std::thread::hardware_concurrency()) {
|
||||
for (int h = 0; h < reference_.size().height; h += thread_nbr) {
|
||||
std::vector<std::thread> thread_list{};
|
||||
for (auto i = 0u; i < std::thread::hardware_concurrency(); ++i) {
|
||||
for (auto i = 0u; i < thread_nbr; ++i) {
|
||||
thread_list.push_back(
|
||||
std::thread(&ImageManipulator::threaded_get_color, this, h + i));
|
||||
}
|
||||
@ -226,7 +285,7 @@ void ImageManipulator::method2()
|
||||
spdlog::debug("Beginning method2, initial difference: {}", diff_);
|
||||
spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_,
|
||||
remaining_iter_);
|
||||
spdlog::debug("Running on {} threads", std::thread::hardware_concurrency());
|
||||
spdlog::debug("Running on {} threads", thread_nbr);
|
||||
get_color_set();
|
||||
spdlog::debug("{} colors detected", colors_.size());
|
||||
while (remaining_iter_ > 0 && diff_ > 0.0) {
|
||||
@ -238,10 +297,10 @@ void ImageManipulator::method2()
|
||||
|
||||
void ImageManipulator::method3()
|
||||
{
|
||||
spdlog::debug("Beginning method2, initial difference: {}", diff_);
|
||||
spdlog::debug("Beginning method3, initial difference: {}", diff_);
|
||||
spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_,
|
||||
remaining_iter_);
|
||||
spdlog::debug("Running on {} threads", std::thread::hardware_concurrency());
|
||||
spdlog::debug("Running on {} threads", thread_nbr);
|
||||
get_color_set();
|
||||
spdlog::debug("{} colors detected", colors_.size());
|
||||
while (remaining_iter_ > 0 && diff_ > 0.0) {
|
||||
@ -254,35 +313,66 @@ void ImageManipulator::method3()
|
||||
|
||||
void ImageManipulator::method4(bool const t_controlled_size)
|
||||
{
|
||||
spdlog::debug("Beginning method2, initial difference: {}", diff_);
|
||||
spdlog::debug("Beginning method4, initial difference: {}", diff_);
|
||||
spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_,
|
||||
remaining_iter_);
|
||||
spdlog::debug("Running on {} threads", std::thread::hardware_concurrency());
|
||||
spdlog::debug("Running on {} threads", thread_nbr);
|
||||
get_color_set();
|
||||
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>>>>
|
||||
results{};
|
||||
std::vector<std::pair<cv::Mat, double>> values{};
|
||||
for (size_t i = 0; i < std::thread::hardware_concurrency(); ++i) {
|
||||
for (size_t i = 0; i < thread_nbr; ++i) {
|
||||
results.push_back(std::async(std::launch::async,
|
||||
&ImageManipulator::create_candidate, this,
|
||||
t_controlled_size));
|
||||
}
|
||||
for (auto& elem : results) {
|
||||
if(auto res = elem.get(); res.has_value() && res->second < diff_) {
|
||||
values.push_back(*res);
|
||||
}
|
||||
}
|
||||
if(values.size() > 0) {
|
||||
size_t best = 0;
|
||||
for(size_t i = 0; i < values.size(); ++i) {
|
||||
if(values[i].second < values[best].second) {
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
update_gen_image(values[best].first, values[best].second);
|
||||
}
|
||||
for (auto& elem : results) {
|
||||
if (auto res = elem.get(); res.has_value() && res->second < diff_) {
|
||||
values.push_back(*res);
|
||||
}
|
||||
}
|
||||
if (values.size() > 0) {
|
||||
size_t best = 0;
|
||||
for (size_t i = 0; i < values.size(); ++i) {
|
||||
if (values[i].second < values[best].second) {
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
update_gen_image(values[best].first, values[best].second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ImageManipulator::method5(bool const t_controlled_size,
|
||||
int cols,
|
||||
int const rows,
|
||||
int const submethod)
|
||||
{
|
||||
spdlog::debug("Beginning method5, initial difference: {}", diff_);
|
||||
spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_,
|
||||
remaining_iter_);
|
||||
spdlog::debug("Running on {} threads", thread_nbr);
|
||||
if (cols == 0) {
|
||||
cols = rows;
|
||||
}
|
||||
std::vector<std::vector<ImageManipulator>> tiles{};
|
||||
int const tile_width = reference_.cols / cols;
|
||||
int const tile_height = reference_.rows / rows;
|
||||
spdlog::debug("tile: width:{}\theight:{}", tile_width, tile_height);
|
||||
spdlog::debug("image: width:{}\theight:{}", reference_.cols, reference_.rows);
|
||||
for (int i = 0; i < rows; ++i) {
|
||||
std::vector<ImageManipulator> tile_row{};
|
||||
for (int j = 0; j < cols; ++j) {
|
||||
tile_row.emplace_back(
|
||||
reference_, total_iterations_, i * tile_height, j * tile_width,
|
||||
(i != rows - 1) ? tile_height
|
||||
: tile_height + reference_.cols % tile_height,
|
||||
(j != cols - 1) ? tile_width
|
||||
: tile_width + reference_.cols % tile_width);
|
||||
}
|
||||
tiles.push_back(tile_row);
|
||||
}
|
||||
spdlog::debug("{} tiles", tiles.size());
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ void processFilenames(po::variables_map const& vm,
|
||||
}
|
||||
|
||||
[[nodiscard]] auto parse_args(int t_ac, char** t_av)
|
||||
-> std::tuple<path, path, int, int, int, int, bool, bool>
|
||||
-> std::tuple<path, path, int, int, int, int, int, bool, bool>
|
||||
{
|
||||
po::options_description desc("Allowed options");
|
||||
desc.add_options()
|
||||
@ -32,13 +32,16 @@ void processFilenames(po::variables_map const& vm,
|
||||
"Image output path (default: \"output_\" + input path)")
|
||||
("iterations,n", po::value<int>(), "Number of iterations (default: 2000)")
|
||||
("method,m", po::value<int>(), "Method number to be used (default: 1)")
|
||||
("columns,c", po::value<int>(),
|
||||
("cols,c", po::value<int>(),
|
||||
"For method 5 only, number of columns the reference image should be "
|
||||
"divided into. (default: 1)")
|
||||
("rows,r", po::value<int>(),
|
||||
"For method 5 only, number of rows the reference image should be "
|
||||
"divided into. If the value is equal to 0, then it will be assumed "
|
||||
"there will be as many rows as there are collumns. (default: 0)")
|
||||
("rows,r", po::value<int>(),
|
||||
"For method 5 only, number of rows the reference image should be "
|
||||
"divided into. (default: 1)")
|
||||
("submethod,S", po::value<int>(),
|
||||
"Sub-method that will be used to generate the individual tiles from "
|
||||
"method 5. (default: 1)")
|
||||
("size,s", "Enables controlled size of the random shapes")
|
||||
("verbose,v", "Enables verbosity");
|
||||
po::variables_map vm;
|
||||
@ -58,7 +61,9 @@ void processFilenames(po::variables_map const& vm,
|
||||
input_path, output_path,
|
||||
vm.count("iterations") ? vm["iterations"].as<int>() : DEFAULT_ITERATIONS,
|
||||
vm.count("method") ? vm["method"].as<int>() : 1,
|
||||
vm.count("column") ? vm["column"].as<int>() : 1,
|
||||
vm.count("rows") ? vm["rows"].as<int>() : 0, vm.count("size"),
|
||||
vm.count("cols") ? vm["cols"].as<int>() : 0,
|
||||
vm.count("rows") ? vm["rows"].as<int>() : 1,
|
||||
vm.count("submethod") ? vm["submethod"].as<int>() : 1,
|
||||
vm.count("size"),
|
||||
vm.count("verbose"));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user