From 321510a21afb38a12e6d3b06054a79f4016b0ccb Mon Sep 17 00:00:00 2001 From: kallaballa Date: Sat, 15 Apr 2023 20:09:21 +0200 Subject: [PATCH] added tutorial on custom sources and sinks --- modules/viz2d/doc/custom_source_and_sink.png | Bin 0 -> 3707 bytes .../samples/cpp/custom_source_and_sink.cpp | 69 ++++++++++++++++++ .../06-custom_source_and_sink.markdown | 4 +- 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 modules/viz2d/doc/custom_source_and_sink.png create mode 100644 modules/viz2d/samples/cpp/custom_source_and_sink.cpp diff --git a/modules/viz2d/doc/custom_source_and_sink.png b/modules/viz2d/doc/custom_source_and_sink.png new file mode 100644 index 0000000000000000000000000000000000000000..475f3751dc23a463719aba23544fa8ed2d555b1e GIT binary patch literal 3707 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 +#include +#include + +using namespace cv; +using namespace cv::viz; + +constexpr int WIDTH = 1280; +constexpr int HEIGHT = 720; + +int main(int argc, char** argv) { + string hv = "Hello Rainbow!"; + Ptr v2d = Viz2D::make(Size(WIDTH, HEIGHT), "Video Editing"); + //Make a Source that generates rainbow frames. + Source src([=](cv::UMat& frame){ + static long cnt = 0; + + if(frame.empty()) + frame.create(v2d->getFrameBufferSize(), CV_8UC3); + frame = colorConvert(Scalar(cnt % 180, 128, 128, 255), COLOR_HLS2BGR); + + ++cnt; + if(cnt > std::numeric_limits().max() / 2.0) + cnt = 0; + return true; + }, 60.0f); + + //Make a Sink the saves each frame to a PNG file. + Sink sink([](const cv::UMat& frame){ + static long cnt = 0; + + try { + imwrite(std::to_string(cnt) + ".png", frame); + } catch(std::exception& ex) { + cerr << "Unable to write frame: " << ex.what() << endl; + return false; + } + + ++cnt; + if(cnt > std::numeric_limits().max() / 2.0) + cnt = 0; + + return true; + }); + + //Attach source and sink + v2d->setSource(src); + v2d->setSink(sink); + + v2d->run([=]() { + //Capture video from the Source + if(!v2d->capture()) + return false; //end of input video + + //Render "Hello Rainbow!" over the frame + v2d->nvg([=](const Size& sz) { + using namespace cv::viz::nvg; + + fontSize(40.0f); + fontFace("sans-bold"); + fillColor(Scalar(255, 0, 0, 255)); + textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP); + text(sz.width / 2.0, sz.height / 2.0, hv.c_str(), hv.c_str() + hv.size()); + }); + v2d->write(); //Write video to the Sink + return v2d->display(); //Display the framebuffer in the native window + }); +} + diff --git a/modules/viz2d/tutorials/06-custom_source_and_sink.markdown b/modules/viz2d/tutorials/06-custom_source_and_sink.markdown index d08aae235..41b187278 100644 --- a/modules/viz2d/tutorials/06-custom_source_and_sink.markdown +++ b/modules/viz2d/tutorials/06-custom_source_and_sink.markdown @@ -9,9 +9,9 @@ | Compatibility | OpenCV >= 4.7 | ## Reading and writing to Viz2D using custom Sources and Sinks -In the previous tutorial we used a default video source and a video sink to stream a video through Viz2D's framebuffer which can be manipulated using OpenGL or NanoVG - hence video editing. +In the previous tutorial we used a default video source and a video sink to stream a video through Viz2D which can be manipulated using OpenGL or NanoVG. In this example we are creating a custom Source that generates rainbow frames. For each time the Source is invoked the frame is colored a slightly different color. Additionally the custom Sink saves individual images instead of a video. @include samples/cpp/custom_source_and_sink.cpp -![The result](doc/video_editing.png) +![The result](doc/custom_source_and_sink.png)