diff --git a/TODO b/TODO index e69de29..c83e8ef 100644 --- a/TODO +++ b/TODO @@ -0,0 +1,3 @@ +- Proper parsing of the CLI, adding filter according to it. +- Moar filters ! +- Kikoo stuff. diff --git a/src/encoder/video_reader.cc b/src/encoder/video_reader.cc index 9afc030..f0d6d98 100644 --- a/src/encoder/video_reader.cc +++ b/src/encoder/video_reader.cc @@ -4,20 +4,32 @@ VideoReader::VideoReader(std::string filename) : filter(tbb::filter::serial_in_order), capture_(filename) { - this->remaining_ = framecount_get(); + this->frames_ = framecount_get(); + this->remaining_ = this->frames_; } VideoReader::VideoReader(const VideoReader& vr) : filter(tbb::filter::serial_in_order) { this->capture_ = vr.capture_; - this->remaining_ = framecount_get(); + this->frames_ = framecount_get(); + this->remaining_ = this->frames_; } void* VideoReader::operator()(void* ign) { (void)ign; + static int curr_perc = 0; + + int perc = (this->frames_ - this->remaining_) * 100 / this->frames_; + if (perc % 10 == 0 && perc > curr_perc) + { + curr_perc = perc; + std::cout << perc << "%... "; + std::flush(std::cout); + } + cv::Mat retrieved; if (this->remaining_ > 0) { diff --git a/src/encoder/video_reader.hh b/src/encoder/video_reader.hh index 6e31f51..c70f7e9 100644 --- a/src/encoder/video_reader.hh +++ b/src/encoder/video_reader.hh @@ -18,6 +18,7 @@ class VideoReader: public tbb::filter private: cv::VideoCapture capture_; int remaining_; + int frames_; }; #endif /* !VIDEO_READER_HH_ */ diff --git a/src/filterSample/Makefile.am b/src/filterSample/Makefile.am index e2c381d..387a426 100644 --- a/src/filterSample/Makefile.am +++ b/src/filterSample/Makefile.am @@ -6,4 +6,5 @@ AM_CXXFLAGS = \ $(BOOST_CPPFLAGS) \ $(DEBUG_CXXFLAGS) -______lib_libfilterSample_a_SOURCES = grey.cc reverse.cc merge.cc interlace.cc +______lib_libfilterSample_a_SOURCES = grey.cc reverse.cc merge.cc \ + interlace.cc inlay.cc blur.cc cartoon.cc count.cc diff --git a/src/filterSample/blur.cc b/src/filterSample/blur.cc new file mode 100644 index 0000000..b24d7ff --- /dev/null +++ b/src/filterSample/blur.cc @@ -0,0 +1,15 @@ +#include "blur.hh" + +#include "opencv2/opencv.hpp" + +void* Blur::operator()(void* para) +{ + cv::Mat* mat = (cv::Mat*)para; + + if (mat == nullptr) + return nullptr; + + cv::blur(*mat, *mat, cv::Size { this->size_, this->size_ }); + + return mat; +} diff --git a/src/filterSample/blur.hh b/src/filterSample/blur.hh new file mode 100644 index 0000000..72538ac --- /dev/null +++ b/src/filterSample/blur.hh @@ -0,0 +1,15 @@ +#ifndef BLUR_HH_ +# define BLUR_HH_ + +# include "tbb/pipeline.h" + +class Blur: public tbb::filter +{ + public: + Blur(int size = 15): filter(tbb::filter::parallel), size_(size) {} + void* operator()(void*); + private: + int size_; +}; + +#endif /* !BLUR_HH_ */ diff --git a/src/filterSample/cartoon.cc b/src/filterSample/cartoon.cc new file mode 100644 index 0000000..5a68bff --- /dev/null +++ b/src/filterSample/cartoon.cc @@ -0,0 +1,16 @@ +#include "cartoon.hh" +#include "opencv2/opencv.hpp" + +void* Cartoon::operator()(void* para) +{ + cv::Mat* mat = (cv::Mat*)para; + cv::Mat tmp = mat->clone(); + + if (mat == nullptr) + return nullptr; + + cv::bilateralFilter(*mat, tmp, -1, 20, 20); + + *mat = tmp; + return mat; +} diff --git a/src/filterSample/cartoon.hh b/src/filterSample/cartoon.hh new file mode 100644 index 0000000..98b6d58 --- /dev/null +++ b/src/filterSample/cartoon.hh @@ -0,0 +1,13 @@ +#ifndef CARTOON_HH_ +# define CARTOON_HH_ + +# include "tbb/pipeline.h" + +class Cartoon: public tbb::filter +{ + public: + Cartoon(): filter(tbb::filter::parallel) {} + void* operator()(void*); +}; + +#endif /* !CARTOON_HH_ */ diff --git a/src/filterSample/count.cc b/src/filterSample/count.cc new file mode 100644 index 0000000..f1cea02 --- /dev/null +++ b/src/filterSample/count.cc @@ -0,0 +1,18 @@ +#include +#include "count.hh" +#include "opencv2/opencv.hpp" + +void* Count::operator()(void* para) +{ + static int count = 1; + cv::Mat* mat = (cv::Mat*)para; + + if (mat == nullptr) + return nullptr; + + cv::putText(*mat, std::to_string(count), cv::Point { 5, 25 }, + cv::FONT_HERSHEY_TRIPLEX, 1, cv::Scalar { 0, 255, 0 }, 1); + count++; + + return mat; +} diff --git a/src/filterSample/count.hh b/src/filterSample/count.hh new file mode 100644 index 0000000..09db7ea --- /dev/null +++ b/src/filterSample/count.hh @@ -0,0 +1,13 @@ +#ifndef COUNT_HH_ +# define COUNT_HH_ + +# include "tbb/pipeline.h" + +class Count: public tbb::filter +{ + public: + Count(): filter(tbb::filter::parallel) {} + void* operator()(void*); +}; + +#endif /* !COUNT_HH_ */ diff --git a/src/filterSample/inlay.cc b/src/filterSample/inlay.cc new file mode 100644 index 0000000..c9b5022 --- /dev/null +++ b/src/filterSample/inlay.cc @@ -0,0 +1,32 @@ +#include "inlay.hh" +#include "opencv2/opencv.hpp" + +static inline bool is_inlay(int strict, cv::Vec3b ref, cv::Vec3b pix) +{ + return (strict && ref == pix) || (!strict && + ((ref[0] > 0 && pix[0] > 127 && pix[0] > pix[1] && pix[0] > pix[2]) + || (ref[1] > 0 && pix[1] > 127 && pix[1] > pix[0] && pix[1] > pix[2]) + || (ref[2] > 0 && pix[2] > 127 && pix[2] > pix[0] && pix[2] > pix[1]))); +} + +void* Inlay::operator()(void* para) +{ + std::pair* pair = (std::pair*)para; + cv::Mat* mat = pair->first; + + if (mat == nullptr) + return nullptr; + + if (pair->second != nullptr) + { + for (size_t i = 0; i < mat->rows; ++i) + for (size_t j = 0; j < mat->cols; ++j) + if (i < pair->second->rows && j < pair->second->cols + && is_inlay(this->strict_, this->ref_, mat->at(i, j))) + mat->at(i, j) = pair->second->at(i, j); + } + + delete pair->second; + delete pair; + return mat; +} diff --git a/src/filterSample/inlay.hh b/src/filterSample/inlay.hh new file mode 100644 index 0000000..5b348f4 --- /dev/null +++ b/src/filterSample/inlay.hh @@ -0,0 +1,18 @@ +#ifndef INLAY_HH_ +# define INLAY_HH_ + +# include "tbb/pipeline.h" +# include "opencv2/opencv.hpp" + +class Inlay: public tbb::filter +{ + public: + Inlay(cv::Vec3b ref, int strict) + : filter(tbb::filter::parallel), ref_(ref), strict_(strict) {} + void* operator()(void*); + private: + cv::Vec3b ref_; + int strict_; +}; + +#endif /* !INLAY_HH_ */ diff --git a/src/main.cc b/src/main.cc index f3491de..754ea5b 100644 --- a/src/main.cc +++ b/src/main.cc @@ -94,18 +94,23 @@ int main (int argc, char** argv) if (!parse_cli(conf, argc, argv)) return 1; - VideoReader vr(conf.input.front()); - auto it = conf.input.begin(); - it++; + std::list input_vr = std::list(); + for (auto it = conf.input.begin(); it != conf.input.end(); ++it) + input_vr.push_back(VideoReader(*it)); VideoWriter vw = VideoWriter(); - vw.open(conf.output, conf.codec, vr.fps_get(), vr.width_get(), vr.height_get()); + vw.open(conf.output, conf.codec, input_vr.front().fps_get(), + input_vr.front().width_get(), input_vr.front().height_get()); - Pipeline pipe(std::list { vr, VideoReader(*it) }, vw); + Pipeline pipe(input_vr, vw); // add filters here - //pipe.add_filter("grey"); - //pipe.add_filter("reverse"); - //pipe.add_filter("interlace"); - //pipe.add_filter("merge"); + //pipe.add_filter("grey", std::vector()); + //pipe.add_filter("count", std::vector()); + //pipe.add_filter("cartoon", std::vector()); + //pipe.add_filter("blur", std::vector { 30 }); + //pipe.add_filter("reverse", std::vector()); + //pipe.add_filter("interlace", std::vector()); + //pipe.add_filter("merge", std::vector()); + //pipe.add_filter("inlay", std::vector { 0, 0, 255 }); pipe.run(); return 0; diff --git a/src/pipeline.cc b/src/pipeline.cc index 1313acd..697e51f 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -1,11 +1,19 @@ +#include +#include +#include +#include #include "tbb/pipeline.h" #include "pipeline.hh" #include "compose.hh" #include "filterSample/grey.hh" +#include "filterSample/cartoon.hh" +#include "filterSample/blur.hh" #include "filterSample/reverse.hh" #include "filterSample/merge.hh" #include "filterSample/interlace.hh" +#include "filterSample/inlay.hh" +#include "filterSample/count.hh" Pipeline::Pipeline(std::list input, VideoWriter output) : input_(input), output_(output) @@ -15,12 +23,23 @@ Pipeline::Pipeline(std::list input, VideoWriter output) this->input_it_++; } -bool Pipeline::add_filter(std::string filter) +bool Pipeline::add_filter(std::string filter, std::vector args) { if (filter == "grey" || filter == "gray") this->pipeline_.add_filter(*(new Grey())); else if (filter == "reverse" || filter == "inverse") this->pipeline_.add_filter(*(new Reverse())); + else if (filter == "cartoon") + this->pipeline_.add_filter(*(new Cartoon())); + else if (filter == "count") + this->pipeline_.add_filter(*(new Count())); + else if (filter == "blur") + { + if (args.size() >= 1) + this->pipeline_.add_filter(*(new Blur(args[0]))); + else + this->pipeline_.add_filter(*(new Blur())); + } else if (filter == "merge" && this->input_it_ != this->input_.end()) { this->pipeline_.add_filter(*(new Compose(*this->input_it_))); @@ -33,6 +52,22 @@ bool Pipeline::add_filter(std::string filter) this->input_it_++; this->pipeline_.add_filter(*(new Interlace())); } + else if (filter == "inlay" && this->input_it_ != this->input_.end() + && args.size() >= 3) + { + this->pipeline_.add_filter(*(new Compose(*this->input_it_))); + this->input_it_++; + this->pipeline_.add_filter( + *(new Inlay(cv::Vec3b { args[0], args[1], args[2] }, 0))); + } + else if (filter == "strictinlay" && this->input_it_ != this->input_.end() + && args.size() >= 3) + { + this->pipeline_.add_filter(*(new Compose(*this->input_it_))); + this->input_it_++; + this->pipeline_.add_filter( + *(new Inlay(cv::Vec3b { args[0], args[1], args[2] }, 1))); + } else return false; @@ -41,6 +76,9 @@ bool Pipeline::add_filter(std::string filter) void Pipeline::run() { + std::cout << "Applying video filter chain: "; + std::flush(std::cout); this->pipeline_.add_filter(this->output_); this->pipeline_.run(CHUNK_SIZE); + std::cout << "Done!" << std::endl; } diff --git a/src/pipeline.hh b/src/pipeline.hh index 4e9047c..2a6085e 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -1,7 +1,9 @@ #ifndef PIPELINE_HH_ # define PIPELINE_HH_ +# include # include +# include # include "opencv2/opencv.hpp" # include "tbb/pipeline.h" @@ -15,7 +17,7 @@ class Pipeline { public: Pipeline(std::list input, VideoWriter output); - bool add_filter(std::string filter); + bool add_filter(std::string filter, std::vector args); void run(); private: std::list> filters_;