Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
Tutorial: How to display an image and basic drawings in a window

1. Introduction

In this tutorial you will learn how to display basic drawings with ViSP either on Unix-like systems (including OSX, Fedora, Ubuntu, Debian, ...) or on Windows.

Note that all the material (source code and images) described in this tutorial is part of ViSP source code (in tutorial/image folder) and could be found in https://github.com/lagadic/visp/tree/master/tutorial/image.

2. Load and display an image

ViSP gui module provides Graphical User Interfaces capabilities. To this end you may use several optional third-party libraries which are: X11, GDI, OpenCV, GTK, Direct3D. In the next example, we will use the first 3rd party that is available from the previous list.

The following example also available in tutorial-viewer.cpp shows how to read and display an image.

#include <visp3/core/vpConfig.h>
#include <visp3/core/vpFont.h>
#include <visp3/core/vpIoTools.h>
#include <visp3/core/vpTime.h>
#include <visp3/gui/vpDisplayFactory.h>
#include <visp3/io/vpImageIo.h>
#ifdef ENABLE_VISP_NAMESPACE
using namespace VISP_NAMESPACE_NAME;
#endif
int main(int argc, char **argv)
{
#ifdef VISP_HAVE_DISPLAY
if (argc != 2) {
printf("Usage: %s <image name.[pgm,ppm,jpeg,png,tiff,bmp,ras,jp2]>\n", argv[0]);
return EXIT_FAILURE;
}
try {
vpImageIo::read(I, argv[1]);
}
catch (...) {
std::cout << "Cannot read image \"" << argv[1] << "\"" << std::endl;
return EXIT_FAILURE;
}
try {
#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
std::shared_ptr<vpDisplay> pdisp = vpDisplayFactory::createDisplay(I, 10, 10, vpIoTools::getName(argv[1]), vpDisplay::SCALE_AUTO);
#else
#endif
std::cout << "Right click to quit" << std::endl;
std::cout << "Left click to inspect pixel position (i,j) and RGBa values\n" << std::endl;
bool quit = false;
unsigned int scale_factor = vpDisplay::getDownScalingFactor(I);
while (!quit) {
if (vpDisplay::getClick(I, ip, button, false)) {
if (button == vpMouseButton::button3) {
quit = true;
}
else {
std::stringstream ss;
unsigned int i = static_cast<unsigned int>(ip.get_i());
unsigned int j = static_cast<unsigned int>(ip.get_j());
ss << i << " " << j << ": " << I[i][j];
std::cout << ss.str() << std::endl;
font.drawText(I, ss.str(), vpImagePoint(I.getHeight() - 20*scale_factor, 10), vpColor::red, vpColor::white);
}
}
}
#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
delete pdisp;
#endif
}
catch (const vpException &e) {
std::cout << "Catch an exception: " << e << std::endl;
}
#else
(void)argc;
(void)argv;
std::cout << "No display available!" << std::endl;
#endif
}
static const vpColor white
Definition vpColor.h:193
static const vpColor red
Definition vpColor.h:198
Class that defines generic functionalities for display.
Definition vpDisplay.h:171
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void setTitle(const vpImage< unsigned char > &I, const std::string &windowtitle)
static void flush(const vpImage< unsigned char > &I)
unsigned int getDownScalingFactor()
Definition vpDisplay.h:218
error that can be emitted by ViSP classes.
Definition vpException.h:60
Font drawing functions for image.
Definition vpFont.h:55
@ GENERIC_MONOSPACE
Definition vpFont.h:57
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
double get_j() const
double get_i() const
Definition of the vpImage class member functions.
Definition vpImage.h:131
static std::string getName(const std::string &pathname)
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.
vpDisplay * allocateDisplay()
Return a newly allocated vpDisplay specialization if a GUI library is available or nullptr otherwise.
VISP_EXPORT void sleepMs(double t)

Once build, if you run the corresponding binary loading monkey.jpeg image:

$ cd $VISP_WS/visp-build/tutorial/image
$ ./tutorial-viewer monkey.jpeg

It will open a window containing monkey.jpeg image:

A detailed explanation of the source is available following 2.2. Get tutorial-viewer.cpp file section.

3. Display basic drawings in window overlay

There are a lot of examples in ViSP that show how to display drawings in window overlay. There is testDisplays.cpp that gives an overview.

If you run the corresponding binary:

$ cd $VISP_WS/visp-build/modules/gui
$ ./testDisplays

it will open a window like the following:

3.1. Display a point in overlay

As shown in tutorial-draw-point.cpp which source code is given below we use vpDisplay::displayPoint() function to draw a point in the overlay of a windows that displays a 3840 by 2160 grey image that has all the pixels set to 128 gray level.

#include <visp3/core/vpConfig.h>
#include <visp3/gui/vpDisplayFactory.h>
#ifdef ENABLE_VISP_NAMESPACE
using namespace VISP_NAMESPACE_NAME;
#endif
int main()
{
#if defined(VISP_HAVE_DISPLAY)
vpImage<unsigned char> I(2160, 3840, 128);
#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
std::shared_ptr<vpDisplay> d = vpDisplayFactory::createDisplay(I, -1, -1, "Point drawing", vpDisplay::SCALE_AUTO);
#else
#endif
vpDisplay::displayPoint(I, I.getHeight() / 2, I.getWidth() / 2, vpColor::red, 2);
std::cout << "A click to quit..." << std::endl;
#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
delete d;
#endif
#else
std::cout << "No gui available to display an image..." << std::endl;
#endif
return EXIT_SUCCESS;
}
static void displayPoint(const vpImage< unsigned char > &I, const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1)

Here we draw a point at the center of a grey image with red color and thickness 2.

3.2. Display a line between 2 points in overlay

As given in tutorial-draw-line.cpp we use vpDisplay::displayLine() function to draw a line segment on the screen.

vpDisplay::displayLine(I, I.getHeight() / 4, I.getWidth() / 4, (3 * I.getHeight()) / 4, (3 * I.getWidth()) / 4,

Here we draw a red coloured line segment with the specified initial and final coordinates and thickness 10.

3.3. Display a circle in overlay

As given in tutorial-image-display-scaled-auto.cpp we use vpDisplay::displayCircle() function to draw a circle on the screen.

vpDisplay::displayCircle(I, I.getHeight() / 2, I.getWidth() / 2, 200, vpColor::red, true);

Here we draw a red coloured filled circle at the center with radius of 200.

3.4. Display a rectangle in overlay

As given in tutorial-draw-rectangle.cpp we use vpDisplay::displayRectangle() function to draw a rectangle on the screen.

vpDisplay::displayRectangle(I, I.getHeight() / 4, I.getWidth() / 4, I.getWidth() / 2, I.getHeight() / 2,
vpColor::red, true);

Here we draw a red coloured filled rectangle with specified top-left coordinates and width and height.

3.5. Display a cross in overlay

As given in tutorial-draw-cross.cpp we use vpDisplay::displayCross() function to draw a rectangle on the screen.

vpDisplay::displayCross(I, I.getHeight() / 2, I.getWidth() / 2, I.getWidth() / 2, vpColor::red, 2);

Here we draw a red coloured cross on the center with speicfied size and thickness 2.

3.6. Display text in window overlay

As given in tutorial-draw-text.cpp we use vpDisplay::displayText() function to add text in the window overlay.

vpDisplay::displayText(I, I.getHeight() / 2, I.getWidth() / 2, "Hello World!", vpColor::yellow);

Here Hello world is displayed in the middle of the image.

4. Export and save the content of a window as an image

As given in tutorial-export-image.cpp which source code is given below, we use vpDisplay::getImage() function to export the image with the whole drawings in overlay. Then we use vpImageIo::write() to save the image in png format.

#include <visp3/core/vpConfig.h>
#include <visp3/gui/vpDisplayFactory.h>
#include <visp3/io/vpImageIo.h>
#ifdef ENABLE_VISP_NAMESPACE
using namespace VISP_NAMESPACE_NAME;
#endif
int main()
{
#if defined(VISP_HAVE_DISPLAY)
vpImage<unsigned char> I(240, 320, 255); // Create a black grey level image
vpImage<vpRGBa> Ioverlay;
// Initialize the display with the image I. Display and image are now linked together
#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
std::shared_ptr<vpDisplay> d = vpDisplayFactory::createDisplay(I, -1, -1, "Save overlayed image", vpDisplay::SCALE_AUTO);
#else
vpDisplay *d = vpDisplayFactory::allocateDisplay(I, -1, -1, "Save overlayed image", vpDisplay::SCALE_AUTO);
#endif
// Set the display background with image I content
// Draw a red rectangle in the display overlay (foreground)
vpDisplay::displayRectangle(I, 10, 10, 100, 20, vpColor::red, true);
// Flush the foreground and background display
// Updates the color image with the original loaded image and the overlay
vpDisplay::getImage(I, Ioverlay);
// Write the color image on the disk
std::string ofilename("overlay.png");
std::cout << "Save overlayed image in: " << ofilename << std::endl;
vpImageIo::write(Ioverlay, ofilename);
// Wait for a click in the display window
std::cout << "A click to quit..." << std::endl;
#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
delete d;
#endif
#else
std::cout << "No gui available to display an image..." << std::endl;
#endif
}
static void getImage(const vpImage< unsigned char > &Is, vpImage< vpRGBa > &Id)
static void displayRectangle(const vpImage< unsigned char > &I, const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)

5. Handle keyboard events in a window

As given in tutorial-event-keyboard.cpp which code is given below, we use vpDisplay::getKeyboardEvent() function to get the value of the key pressed.

#include <visp3/core/vpConfig.h>
#include <visp3/gui/vpDisplayFactory.h>
#ifdef ENABLE_VISP_NAMESPACE
using namespace VISP_NAMESPACE_NAME;
#endif
int main()
{
#if defined(VISP_HAVE_DISPLAY)
vpImage<unsigned char> I(240, 320); // Create a black image
// Initialize the display with the image I. Display and image are now linked together
#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
std::shared_ptr<vpDisplay> d = vpDisplayFactory::createDisplay(I, -1, -1, "Keyboard event example", vpDisplay::SCALE_AUTO);
#else
vpDisplay *d = vpDisplayFactory::allocateDisplay(I, -1, -1, "Keyboard event example", vpDisplay::SCALE_AUTO);
#endif
// Set the display background with image I content
// Flush the foreground and background display
// Wait for keyboard event
std::cout << "Waiting a keyboard event..." << std::endl;
std::cout << "A keyboard event was detected" << std::endl;
// Non blocking keyboard event loop
int cpt_event = 0;
char key[10];
std::cout << "Enter a non blocking keyboard event detection loop..." << std::endl;
do {
bool event = vpDisplay::getKeyboardEvent(I, &key[0], false);
if (event) {
std::cout << "Key detected: " << key << std::endl;
cpt_event++;
}
vpTime::wait(5); // wait 5 ms
} while (cpt_event < 5);
#if (VISP_CXX_STANDARD < VISP_CXX_STANDARD_11)
delete d;
#endif
#else
std::cout << "No gui available to display an image..." << std::endl;
#endif
return EXIT_SUCCESS;
}
static bool getKeyboardEvent(const vpImage< unsigned char > &I, bool blocking=true)
VISP_EXPORT int wait(double t0, double t)

6. Next tutorial

You are now ready to see how to continue with Tutorial: How to modify an image to insert basic drawings.