From eb6e2f564aae43e18f8a8367f3d4e1e393a06171 Mon Sep 17 00:00:00 2001 From: kallaballa Date: Mon, 10 Apr 2023 20:38:27 +0200 Subject: [PATCH] updated documentation --- README.md | 98 +++++++++++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 91bac1f59..daf555e11 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Viz2D -Viz2D is a visualization module for OpenCV. It features OpenCL/OpenGL, OpenCL/VAAPI interoperability, vector graphics using NanoVG and a GUI based on NanoGUI. It should be included in OpenCV-contrib once it is ready. +Viz2D is a visualization module for OpenCV. It features vector graphics using [NanoVG](https://github.com/memononen/nanovg) a GUI based on [NanoGUI](https://github.com/wjakob/nanogui) and (on supported systems) OpenCL/OpenGL and OpenCL/VAAPI interoperability, . It should be included in OpenCV-contrib once it is ready. # What is Viz2D? -Viz2D is a new way of writing graphical (on- and offscreen) applications with OpenCV. It is light-weight and unencumbered by problematic licenses. +Viz2D is a way of writing graphical (on- and offscreen) high performance applications with OpenCV. It is light-weight and unencumbered by QT or GTK licenses. # Why Viz2D? Please refere to the [online demos](https://github.com/kallaballa/Viz2D/blob/main/README.md#online-demos) to see at a glance what it can do for you. @@ -21,16 +21,16 @@ API documentation is available [here](https://viel-zu.org/opencv/apidoc/) ## Basics * Viz2D is not thread safe. Though it is possible to have several Viz2D objects in one or more threads and synchronize them using ```Viz2D::makeNonCurrent()``` and ```Viz2D::makeCurrent()```. This is a limitation of GLFW3. That said, OpenCV algorithms are multi-threaded as usual. -* Viz2D uses InputArray/OutputArray/InputOutputArray which gives you the option to work with cv::Mat, std::vector and cv::UMat. Anyway, you should prefer to use cv::UMat whenever possible to automatically use hardware capabilities where available. +* Viz2D uses InputArray/OutputArray/InputOutputArray which gives you the option to work with Mat, std::vector and UMat. Anyway, you should prefer to use UMat whenever possible to automatically use hardware capabilities where available. * Access to different subsystems (opengl, opencl, nanovg and nanogui) is provided through "contexts". A context is simply a function that takes a functor, sets up the subsystem, executes the functor and tears-down the subsystem. * Contexts ***may not*** be nested. For example, to create an OpenGL context and set the GL viewport: ```C++ -Ptr v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "GL viewport"); -v2d->setVisible(true); +Ptr v2d = Viz2D::make(Size(WIDTH, HEIGHT), "GL viewport"); + //takes care of OpenGL states in the background -v2d->gl([](const cv::Size sz) { +v2d->gl([](const Size sz) { glViewPort(0, 0, sz.width, sz.height); }); ``` @@ -43,10 +43,9 @@ Actually there are several ways to display an image but for now we focus on the ```C++ //Create a Viz2D object for on screen rendering -Ptr v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "Show image"); +Ptr v2d = Viz2D::make(Size(WIDTH, HEIGHT), "Show image"); //An image -cv::UMat image = cv::imread("sample.png"); -v2d->setVisible(true); +UMat image = imread("sample.png"); //Feeds the image to the video pipeline v2d->feed(image); //Display the framebuffer in the native window @@ -59,10 +58,9 @@ This will create a window with size WIDTHxHEIGHT for on-screen rendering with th This example renders a rotating tetrahedron using legacy OpenGL for brevity. ```C++ -Ptr v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "GL Tetrahedron"); -v2d->setVisible(true); +Ptr v2d = Viz2D::make(Size(WIDTH, HEIGHT), "GL Tetrahedron"); -v2d->gl([](const cv::Size sz) { +v2d->gl([](const Size sz) { //Initialize the OpenGL scene glViewport(0, 0, sz.width, sz.height); glColor3f(1.0, 1.0, 1.0); @@ -82,7 +80,7 @@ v2d->gl([](const cv::Size sz) { }); while (keepRunning()) { - v2d->gl([](const cv::Size sz) { + v2d->gl([](const Size sz) { //Render a tetrahedron using immediate mode because the code is more concise glViewport(0, 0, sz.width, sz.height); glRotatef(1, 0, 1, 0); @@ -117,16 +115,14 @@ All contexts operate on the same framebuffer through different means. That means ```C++ //Create a Viz2D object for on screen rendering -Ptr v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "Manipulate Framebuffer"); -v2d->setVisible(true); +Ptr v2d = Viz2D::make(Size(WIDTH, HEIGHT), "Manipulate Framebuffer"); //An image -cv::UMat image = cv::imread("sample.png"); +UMat image = imread("sample.png"); //Feeds the image to the video pipeline v2d->feed(image); - //directly accesses the framebuffer using OpenCV (and using OpenCL if available) -v2d->fb([](cv::UMat& framebuffer) { - cv::flip(framebuffer,framebuffer,0); //Flip the framebuffer +v2d->fb([](UMat& framebuffer) { + flip(framebuffer,framebuffer,0); //Flip the framebuffer }); //Display the upside-down image in the native window v2d->display(); @@ -137,16 +133,14 @@ v2d->display(); Through the nvg context javascript-like canvas-rendering is possible. ```C++ //Create a Viz2D object for on screen rendering -Ptr v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "Vector Graphics"); -v2d->setVisible(true); - +Ptr v2d = Viz2D::make(Size(WIDTH, HEIGHT), "Vector Graphics"); //create a NanoVG context and draws a cross-hair on the framebuffer -v2d->nvg([](const cv::Size sz) { +v2d->nvg([](const Size sz) { //calls from this namespace may only be used inside a nvg context - namespace cv::viz::nvg; + namespace viz::nvg; beginPath(); strokeWidth(3.0); - strokeColor(cv::Scalar(0,0,255,255)); //BGRA + strokeColor(Scalar(0,0,255,255)); //BGRA moveTo(0, WIDTH/2.0); lineTo(HEIGHT, WIDTH/2.0); moveTo(HEIGHT/2.0, 0); @@ -160,27 +154,24 @@ The framebuffer can be accessed directly to manipulate data created in other con ```C++ //Create a Viz2D object for on screen rendering -Ptr v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "Vector Graphics"); -v2d->setVisible(true); - +Ptr v2d = Viz2D::make(Size(WIDTH, HEIGHT), "Vector Graphics"); //create a NanoVG context and draws a cross-hair on the framebuffer -v2d->nvg([](const cv::Size sz) { +v2d->nvg([](const Size sz) { //calls from this namespace may only be used inside a nvg context - namespace cv::viz::nvg; + namespace viz::nvg; beginPath(); strokeWidth(3.0); - strokeColor(cv::Scalar(0,0,255,255)); //BGRA + strokeColor(Scalar(0,0,255,255)); //BGRA moveTo(0, WIDTH/2.0); lineTo(HEIGHT, WIDTH/2.0); moveTo(HEIGHT/2.0, 0); lineTo(HEIGHT/2.0, WIDTH); stroke(); }); - //directly accesses the framebuffer using OpenCV (and using OpenCL if available) -v2d->fb([](cv::UMat& framebuffer) { +v2d->fb([](UMat& framebuffer) { //blurs the crosshair using a cheap boxFilter - cv::boxFilter(framebuffer, framebuffer, -1, cv::Size(5, 5), cv::Point(-1,-1), true, cv::BORDER_REPLICATE); + boxFilter(framebuffer, framebuffer, -1, Size(5, 5), Point(-1,-1), true, BORDER_REPLICATE); }); ``` @@ -188,49 +179,48 @@ v2d->fb([](cv::UMat& framebuffer) { ### Font rendering Draws "hello world" to the screen. ```C++ +string hw = "hello world"; //Create a Viz2D object for on screen rendering -Ptr v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "Vector Graphics"); -v2d->setVisible(true); +Ptr v2d = Viz2D::make(Size(WIDTH, HEIGHT), "Vector Graphics"); +//Clear with black v2d->clear(); - -string hw = "hello world"; - -v2d->nvg([&](const cv::Size& sz) { - using namespace cv::viz::nvg; - +//render the text at the center of the screen +v2d->nvg([&](const Size& sz) { + using namespace viz::nvg; fontSize(font_size); fontFace("sans-bold"); - fillColor(cv::Scalar(255, 0, 0, 255)); + fillColor(Scalar(255, 0, 0, 255)); textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP); text(WIDTH / 2.0, HEIGHT / 2.0, hw.c_str(), hw.c_str() + hw.size()); }); ``` ### Video editing -Through adding a Source and a Sink v2d becomes capable of video editing. +Through adding a Source and a Sink v2d becomes capable of video editing. Reads a video, renders text on top and writes the result. ```C++ +string hw = "hello video!"; //Create a Viz2D object for on screen rendering -Ptr v2d = Viz2D::make(Size(WIDTH, HEIGHT), Size(WIDTH, HEIGHT), false, "Video Editing"); -v2d->setVisible(true); - -//Setup video source and sink +Ptr v2d = Viz2D::make(Size(WIDTH, HEIGHT), "Video Editing"); +//Setup source and sink +//Input file Source src = make_capture_source("input.webm"); -v2d->setSource(src); +//Output file Sink sink = make_writer_sink("output.webm", VideoWriter::fourcc('V', 'P', '9', '0'), src.fps(), Size(WIDTH, HEIGHT)); -v2d->setSink(sink); -std::string hw = "hello video!"; +//Attach source and sink +v2d->setSource(src); +v2d->setSink(sink); while(keepRunning()) { if(!v2d->capture()) break; - v2d->nvg([&](const cv::Size& sz) { - using namespace cv::viz::nvg; + v2d->nvg([&](const Size& sz) { + using namespace viz::nvg; fontSize(font_size); fontFace("sans-bold"); - fillColor(cv::Scalar(255, 0, 0, 255)); + fillColor(Scalar(255, 0, 0, 255)); textAlign(NVG_ALIGN_CENTER | NVG_ALIGN_TOP); text(WIDTH / 2.0, y, hw.c_str(), hw.c_str() + hw.size()); });