changed program options, individual tiles load

This commit is contained in:
Phuntsok Drak-pa 2019-04-13 19:46:04 +02:00
parent 67626b346d
commit caf4c42169
5 changed files with 176 additions and 70 deletions

View File

@ -13,24 +13,34 @@
class ImageManipulator { class ImageManipulator {
public: public:
ImageManipulator() = delete; ImageManipulator() = delete;
ImageManipulator(const ImageManipulator& other) = delete; ImageManipulator(const ImageManipulator& other);
ImageManipulator(ImageManipulator&& other) noexcept = delete; ImageManipulator(ImageManipulator&& other) noexcept;
ImageManipulator& operator=(const ImageManipulator& other) = delete; [[nodiscard]] auto operator=(const ImageManipulator& other)
ImageManipulator& operator=(ImageManipulator&& other) noexcept = delete; -> ImageManipulator;
[[nodiscard]] auto operator=(ImageManipulator&& other) noexcept
-> ImageManipulator;
// Load image from input, and prepare for output // Load image from input, and prepare for output
ImageManipulator(std::filesystem::path const t_input_path, ImageManipulator(std::filesystem::path const t_input_path,
std::filesystem::path const t_output_path, std::filesystem::path const t_output_path,
int const iterations); int const iterations);
// ImageManipulator(cv::Mat const& t_origin_image, ImageManipulator(cv::Mat const& t_origin_image,
// int const iterations, int const iterations,
// int const t_x, int const t_x,
// int const t_y, int const t_y,
// int const t_width, int const t_width,
// int const t_height); 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; void write_file() const;
[[nodiscard]] auto const& get_generated_image() const noexcept
{
return generated_image_;
}
//! Destructor //! Destructor
virtual ~ImageManipulator() noexcept = default; virtual ~ImageManipulator() noexcept = default;
@ -51,21 +61,27 @@ class ImageManipulator {
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 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 method1();
void method2(); void method2();
void method3(); void method3();
void method4(bool const t_controlled_size); 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>> colors_
= std::vector<std::array<uchar, 3>>{}; = std::vector<std::array<uchar, 3>>{};
cv::Mat const reference_; cv::Mat const reference_;
cv::Mat generated_image_; cv::Mat generated_image_
std::mutex colors_mutex_ = std::mutex{}; = cv::Mat{reference_.size().height, reference_.size().width, CV_8UC3,
std::string const output_path_; cv::Scalar(0, 0, 0)};
mutable std::mutex colors_mutex_ = std::mutex{};
std::string const output_path_{""};
double diff_ = 0.0; double diff_ = 0.0;
int const total_iterations_ = 0; int const total_iterations_ = 0;
int remaining_iter_ = 0; int remaining_iter_ = total_iterations_;
int const width_; int const width_ = reference_.size().width;
int const height_; int const height_ = reference_.size().height;
}; };

View File

@ -1,5 +1,4 @@
#ifndef GENETIC_IMAGE_INCLUDE_GENIMG_PARSEARGS_HH_ #pragma once
#define GENETIC_IMAGE_INCLUDE_GENIMG_PARSEARGS_HH_
#include <filesystem> #include <filesystem>
#include <tuple> #include <tuple>
@ -10,7 +9,6 @@
int, int,
int, int,
int, int,
int,
bool, bool,
bool>; bool>;
#endif /* GENETIC_IMAGE_INCLUDE_GENIMG_PARSEARGS_HH_ */

View File

@ -7,19 +7,16 @@
int main(int ac, char** av) int main(int ac, char** av)
{ {
std::srand(std::time(nullptr)); std::srand(std::time(nullptr));
auto [input_file, output_file, iterations, method, columns, rows, auto const [input_file, output_file, iterations, method, cols, rows,
controlled_size, verbose] submethod, controlled_size, verbose]
= parse_args(ac, av); = parse_args(ac, av);
if (rows == 0) {
rows = columns;
}
spdlog::set_level(verbose ? spdlog::level::debug : spdlog::level::info); 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("Input file:\t{}", input_file.native());
spdlog::debug("Output file:\t{}", output_file.native()); spdlog::debug("Output file:\t{}", output_file.native());
spdlog::debug("Iterations:\t{}", iterations); spdlog::debug("Iterations:\t{}", iterations);
ImageManipulator image_process{input_file, output_file, 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(); image_process.write_file();
} }

View File

@ -8,7 +8,6 @@
#include <optional> #include <optional>
#include <utility> #include <utility>
std::mutex colors_mutex;
auto const thread_nbr = std::thread::hardware_concurrency(); 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, std::filesystem::path const t_output_path,
int const t_iterations) int const t_iterations)
: reference_{cv::imread(t_input_path.native(), cv::IMREAD_COLOR)}, : 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()}, output_path_{t_output_path.native()},
diff_{euclidian_distance(generated_image_)}, diff_{euclidian_distance(generated_image_)},
total_iterations_{t_iterations}, total_iterations_{t_iterations}
remaining_iter_{t_iterations},
width_{reference_.size().width},
height_{reference_.size().height}
{ {
if (!reference_.data) { if (!reference_.data) {
spdlog::critical("Could not open or find image!\n"); 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); 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 ///////////////////////////////////////////////////////////// // public methods /////////////////////////////////////////////////////////////
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 cols = 1,
int const rows = 0,
int const submethod = 1)
{ {
switch (t_nb_method) { switch (t_nb_method) {
case 1: { case 1: {
@ -60,6 +116,10 @@ void ImageManipulator::exec_method(int const t_nb_method,
method4(t_controlled_size); method4(t_controlled_size);
break; break;
} }
case 5: {
method5(t_controlled_size, cols, rows, submethod);
break;
}
default: default:
spdlog::error("Requested method {} is not implemented.", t_nb_method); spdlog::error("Requested method {} is not implemented.", t_nb_method);
std::exit(-1); std::exit(-1);
@ -138,10 +198,9 @@ void ImageManipulator::write_file() const
void ImageManipulator::get_color_set() void ImageManipulator::get_color_set()
{ {
for (int h = 0; h < reference_.size().height; for (int h = 0; h < reference_.size().height; h += thread_nbr) {
h += std::thread::hardware_concurrency()) {
std::vector<std::thread> thread_list{}; 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( thread_list.push_back(
std::thread(&ImageManipulator::threaded_get_color, this, h + i)); 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("Beginning method2, initial difference: {}", diff_);
spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_, spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_,
remaining_iter_); remaining_iter_);
spdlog::debug("Running on {} threads", std::thread::hardware_concurrency()); 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) {
@ -238,10 +297,10 @@ void ImageManipulator::method2()
void ImageManipulator::method3() 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_, spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_,
remaining_iter_); remaining_iter_);
spdlog::debug("Running on {} threads", std::thread::hardware_concurrency()); 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) {
@ -254,35 +313,66 @@ void ImageManipulator::method3()
void ImageManipulator::method4(bool const t_controlled_size) 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_, spdlog::debug("nb_total_iter: {}, nb_remaining_iter: {}", total_iterations_,
remaining_iter_); remaining_iter_);
spdlog::debug("Running on {} threads", std::thread::hardware_concurrency()); 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{};
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, results.push_back(std::async(std::launch::async,
&ImageManipulator::create_candidate, this, &ImageManipulator::create_candidate, this,
t_controlled_size)); t_controlled_size));
} }
for (auto& elem : results) { for (auto& elem : results) {
if(auto res = elem.get(); res.has_value() && res->second < diff_) { if (auto res = elem.get(); res.has_value() && res->second < diff_) {
values.push_back(*res); values.push_back(*res);
} }
} }
if(values.size() > 0) { if (values.size() > 0) {
size_t best = 0; size_t best = 0;
for(size_t i = 0; i < values.size(); ++i) { for (size_t i = 0; i < values.size(); ++i) {
if(values[i].second < values[best].second) { if (values[i].second < values[best].second) {
best = i; best = i;
} }
} }
update_gen_image(values[best].first, values[best].second); 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());
}

View File

@ -22,7 +22,7 @@ void processFilenames(po::variables_map const& vm,
} }
[[nodiscard]] auto parse_args(int t_ac, char** t_av) [[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"); po::options_description desc("Allowed options");
desc.add_options() desc.add_options()
@ -32,13 +32,16 @@ void processFilenames(po::variables_map const& vm,
"Image output path (default: \"output_\" + input path)") "Image output path (default: \"output_\" + input path)")
("iterations,n", po::value<int>(), "Number of iterations (default: 2000)") ("iterations,n", po::value<int>(), "Number of iterations (default: 2000)")
("method,m", po::value<int>(), "Method number to be used (default: 1)") ("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 " "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 " "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)") "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") ("size,s", "Enables controlled size of the random shapes")
("verbose,v", "Enables verbosity"); ("verbose,v", "Enables verbosity");
po::variables_map vm; po::variables_map vm;
@ -58,7 +61,9 @@ void processFilenames(po::variables_map const& vm,
input_path, output_path, input_path, output_path,
vm.count("iterations") ? vm["iterations"].as<int>() : DEFAULT_ITERATIONS, vm.count("iterations") ? vm["iterations"].as<int>() : DEFAULT_ITERATIONS,
vm.count("method") ? vm["method"].as<int>() : 1, vm.count("method") ? vm["method"].as<int>() : 1,
vm.count("column") ? vm["column"].as<int>() : 1, vm.count("cols") ? vm["cols"].as<int>() : 0,
vm.count("rows") ? vm["rows"].as<int>() : 0, vm.count("size"), vm.count("rows") ? vm["rows"].as<int>() : 1,
vm.count("submethod") ? vm["submethod"].as<int>() : 1,
vm.count("size"),
vm.count("verbose")); vm.count("verbose"));
} }