updated documentation

pull/3471/head
kallaballa 2 years ago
parent 1d89af628a
commit eb6e2f564a
  1. 98
      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<Viz2D> v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "GL viewport");
v2d->setVisible(true);
Ptr<Viz2D> 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<Viz2D> v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "Show image");
Ptr<Viz2D> 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<Viz2D> v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "GL Tetrahedron");
v2d->setVisible(true);
Ptr<Viz2D> 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<Viz2D> v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "Manipulate Framebuffer");
v2d->setVisible(true);
Ptr<Viz2D> 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<Viz2D> v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "Vector Graphics");
v2d->setVisible(true);
Ptr<Viz2D> 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<Viz2D> v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "Vector Graphics");
v2d->setVisible(true);
Ptr<Viz2D> 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<Viz2D> v2d = Viz2D::make(cv::Size(WIDTH, HEIGHT), cv::Size(WIDTH, HEIGHT), false, "Vector Graphics");
v2d->setVisible(true);
Ptr<Viz2D> 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<Viz2D> v2d = Viz2D::make(Size(WIDTH, HEIGHT), Size(WIDTH, HEIGHT), false, "Video Editing");
v2d->setVisible(true);
//Setup video source and sink
Ptr<Viz2D> 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());
});

Loading…
Cancel
Save