Drawing in OpenCV with OpenGL - c++

OpenCV library, when compiled with GPU and OpenGL support, allows for displaying images with OpenGL. For example, video_reader.cpp (located in gpu samples) uses OpenGL to render display graphics directly from cv::gpu::GpuMat.
cv::gpu::GpuMat d_frame;
namedWindow("OpenGL", WINDOW_OPENGL);
cv::gpu::VideoReader_GPU d_reader(fname);
d_reader.dumpFormat(std::cout);
if (!d_reader.read(d_frame))
break;
cv::imshow("GPU", d_frame);
This is a very useful feature. However, it is not documented in the documentation on-line. For example, for namedWindow the flag WINDOW_OPENGL is not listed in the docs. Where can I find the documentation for OpenGL -related functionality of OpenCV?

The documentation is not very complete for 2.4.5. I don't think there is any more documentation than what you see on http://docs.opencv.org.
There are older documentation, such as http://opencv.willowgarage.com/documentation/cpp/ for 2.1, but I didn't find it having the documentation for the flag that you wanted.

OpenCV/OpenGL interop documentation
https://docs.opencv.org/4.x/d2/d3c/group__core__opengl.html
Highgui/OpenGL documentation
https://docs.opencv.org/4.x/df/d24/group__highgui__opengl.html
Especially the second link gives you two easy options for rendering.
imshow with a Texture2D object
setOpenGlDrawCallback() (https://docs.opencv.org/4.x/df/d24/group__highgui__opengl.html#gaf80dcbc168a6ce40f6d1ad9d79a10bb8) which allows you to draw on top of a nameWindow("OpenGL Window", WINDOW_OPENGL) using OpenGL.

The function
cv::imshow(const & string, cv::InputArray)
does not natively support gpu matrices, but supports GPU matrices by casting.
i.e. anything which supports a cv::Mat on its input should also support cv::gpu::GpuMat. I presume this means that when you call the function, it will automatically download the matrix to a cv::Mat and go from there, i.e. your imshow function call is not drawing directly gpu->gpu, but going gpu->cpu->gpu.

Related

CUDA how to get pixels from screen?

Good afternoon.
I found this article, but it shows how to take pixels from the image that is in the folder. Is it possible to take pixels straight from the desktop?
How to get image pixel value and image height and width in CUDA C?
It's not possible to use CUDA to get pixels from the screen/desktop/application window. You would have to use some sort of graphics API, like some X extension or DirectX (or OpenGL if the window you are working on is under control of OpenGL).
Once you have acquired the pixels via your graphics API, you can pass that to CUDA using CUDA/Graphics interop.
There are many resources for screen capture. Here is one example. There are many others.
One possible suggestion is to use NVIDIA capture SDK. However this is not formally part of CUDA. It is one possible method to get the screen pixels into a resource accessible to CUDA. (And, the functionality is deprecated on Windows.)

Does OpenGL display image faster than OpenCV?

I am using OpenCV to show image on the projector. But it seems the cv::imshow is not fast enough or maybe the data transfer is slow from my CPU to GPU then to projector, so I wonder if there is a faster way to display than OpenCV?
I considered OpenGL, since OpenGL directly uses GPU, the command may be faster than from CPU which is used by OpenCV. Correct me if I am wrong.
OpenCV already supports OpenGL for image output by itself. No need to write this yourself!
See the documentation:
http://docs.opencv.org/modules/highgui/doc/user_interface.html#imshow
http://docs.opencv.org/modules/highgui/doc/user_interface.html#namedwindow
Create the window first with namedWindow, where you can pass the WINDOW_OPENGL flag.
Then you can even use OpenGL buffers or GPU matrices as input to imshow (the data never leaves the GPU). But it will also use OpenGL to show regular matrix data.
Please note:
To enable OpenGL support, configure OpenCV using CMake with
WITH_OPENGL=ON . Currently OpenGL is supported only with WIN32, GTK
and Qt backends on Windows and Linux (MacOS and Android are not
supported). For GTK backend gtkglext-1.0 library is required.
Note that this is OpenCV 2.4.8 and this functionality has changed quite recently. I know there was OpenGL support in earlier versions in conjunction with the Qt backend, but I don't remember when it was introduced.
About the performance: It is a quite popular optimization in the CV community to output images using OpenGL, especially when outputting video sequences.
OpenGL is optimised for rendering images, so it's likely faster. It really depends if the OpenCV implementation uses any GPU acceleration AND if the bottleneck is on rendering side of things.
Have you tried GPU accelerated OpenCV? - http://opencv.org/platforms/cuda.html
How big is the image you are displaying? How long does it take to display the image using cv::imshow now?
I know it's an old question, but I happened to have exactly the same problem. And from my observations I've concluded that the root of the problem is the projector's own latency, especially if one is using an older model.
How have I concluded it?
I displayed the same video sequence with cv::imshow() on the laptop monitor and on the projector. Then I waved my hand. It was obvious, that projector introduces significant latency.
To double-check, I've opended a webcam video, waved my hand in front of it and observed the difference on the monitor and on the projector. Webcam does no processing, no opencv operations, so in my understanding the only thing that would explain the latency would be the projector itself.

What is the use case of cudaGraphicsRegisterFlagsWriteDiscard in cudaGraphicsGLRegisterImage?

I'm fairly new to CUDA, but I've managed to display something generated by a kernel on the screen using OpenGL. I've tried several approach :
Using a PBO and an OpenGL texture (old style);
Using a OpenGL texture as a CUDA surface and rendering on a quad (new style);
Using a renderbuffer as a CUDA surface and rendering using glBlitFramebuffer.
All of them worked, but, while implementing #2, I erroneously set the hint as cudaGraphicsRegisterFlagsWriteDiscard. Since all of the data will be generated by CUDA, I thought this was the correct option. However, later I realized that I needed a CUDA surface to write to an OpenGL texture, and when you use a surface, you are requested to use the LoadStore flag.
So basically my question is this : Since I absolutely need a CUDA surface to write to an OpenGL texture in CUDA, what is the use case of cudaGraphicsRegisterFlagsWriteDiscard in cudaGraphicsGLRegisterImage?
The documentation description seems pretty straightforward. It is for one-way delivery of data from CUDA to OpenGL.
This online book excerpt provides a similar explanation:
Applications where CUDA is the producer and OpenGL is the consumer should register the objects with a write-discard flag...
If you want to see an example, take a look at the postProcessGL cuda sample. In that case, OpenGL is rendering an image, and it's being post-processed (blur added) by cuda, before display. In this case, there are two separate pathways for data flow. In the OpenGL->CUDA case, the data is handled by the createTextureSrc function, and the flag specified is read-only. For the CUDA->OpenGL case (delivery of the post-processed frame) the function is handled in createTextureDst, where a call is made to cudaGraphicsGLRegisterImage with the cudaGraphicsMapFlagsWriteDiscard flag specified, since on this path, CUDA is producing and OpenGL is consuming.
To understand how the textures are handled (populated with data from the cuda operations via a cudaArray) you probably want to study the sequence of operations in processImage().

Cinder: How to get a pointer to data\frame generated but never shown on screen?

There is that grate lib I want to use called libCinder, I looked thru its docs but do not get if it is possible and how to render something with out showing it first?
Say we want to create a simple random color 640x480 canvas with 3 red white blue circles on it, and get RGB\HSL\any char * to raw image data out of it with out ever showing any windows to user. (say we have console application project type). I want to use such feaure for server side live video stream generation and for video streaming I would prefer to use ffmpeg so that is why I want a pointer to some RGB\HSV or what ever buffer with actuall image data. How to do such thing with libCInder?
You will have to use off-screen rendering. libcinder seems to be just a wrapper for OpenGL, as far as graphics go, so you can use OpenGL code to achieve this.
Since OpenGL does not have a native mechanism for off-screen rendering, you'll have to use an extension. A tutorial for using such an extension, called Framebuffer Rendering, can be found here. You will have to modify renderer.cpp to use this extension's commands.
An alternative to using such an extension is to use Mesa 3D, which is an open-source implementation of OpenGL. Mesa has a software rendering engine which allows it to render into memory without using a video card. This means you don't need a video card, but on the other hand the rendering might be slow. Mesa has an example of rendering to a memory buffer at src/osdemos/ in the Demos zip file. This solution will probably require you to write a complete Renderer class, similar to Renderer2d and RendererGl which will use Mesa's intrusctions instead of Windows's or Mac's.

Blitting zoomed images using SDL

Is there any way to Blit a zoomed (in) version of a certain image/sprite using SDL? (Besides manually saving a zoomed version of the image..)
Thanks :-)
Not with the SDL API itself.
I think there exist libraries (for SDL) who support zooming (so called resizing).
EDIT: http://www.ferzkopp.net/joomla/content/view/19/14/
Generally speaking, SDL isn't suitable for graphics that require real-time rotations and zooming. For that, you'd need an library based around an accelerated API such as DirectX or OpenGL. I understand that SFML meets this requirement.