1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Image display.
33  *
34  * Authors:
35  * Christophe Collewet
36  * Eric Marchand
37  * Fabien Spindler
38  *
39  *****************************************************************************/
40 
41 /*!
42   \file vpDisplayOpenCV.cpp
43   \brief Define the OpenCV console to display images.
44 */
45 
46 #include <visp3/core/vpConfig.h>
47 
48 #if defined(VISP_HAVE_OPENCV)
49 
50 #include <cmath> // std::fabs
51 #include <iostream>
52 #include <limits> // numeric_limits
53 #include <stdio.h>
54 #include <stdlib.h>
55 
56 // Display stuff
57 #include <visp3/core/vpDisplay.h>
58 #include <visp3/core/vpImageTools.h>
59 #include <visp3/core/vpIoTools.h>
60 #include <visp3/core/vpMath.h>
61 #include <visp3/gui/vpDisplayOpenCV.h>
62 
63 // debug / exception
64 #include <visp3/core/vpDebug.h>
65 #include <visp3/core/vpDisplayException.h>
66 
67 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
68 
69 #include <opencv2/core/core_c.h> // for CV_FILLED versus cv::FILLED
70 #include <opencv2/imgproc/imgproc.hpp>
71 
72 #ifndef CV_RGB
73 #define CV_RGB(r, g, b) cv::Scalar((b), (g), (r), 0)
74 #endif
75 #endif
76 
77 #ifdef VISP_HAVE_X11
78 #include <visp3/gui/vpDisplayX.h> // to get screen resolution
79 #elif defined(_WIN32)
80 #include <windows.h>
81 #endif
82 
83 std::vector<std::string> vpDisplayOpenCV::m_listTitles = std::vector<std::string>();
84 unsigned int vpDisplayOpenCV::m_nbWindows = 0;
85 
86 /*!
87 
88   Constructor. Initialize a display to visualize a gray level image
89   (8 bits).
90 
91   \param I : Image to be displayed (not that image has to be initialized)
92   \param scaleType : If this parameter is set to:
93   - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
94     is fully displayed in the screen;
95   - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
96   same than the image size.
97   - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
98   and the columns.
99   - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
100   and the columns.
101   - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
102   and the columns.
103   - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
104   and the columns.
105 
106 */
vpDisplayOpenCV(vpImage<unsigned char> & I,vpScaleType scaleType)107 vpDisplayOpenCV::vpDisplayOpenCV(vpImage<unsigned char> &I, vpScaleType scaleType)
108   : vpDisplay(),
109 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
110     m_background(NULL), col(NULL), cvcolor(), font(NULL),
111 #else
112     m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
113 #endif
114     fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
115     x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
116     x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
117     y_rbuttonup(0), rbuttonup(false)
118 {
119   setScale(scaleType, I.getWidth(), I.getHeight());
120   init(I);
121 }
122 
123 /*!
124 
125   Constructor. Initialize a display to visualize a gray level image
126   (8 bits).
127 
128   \param I : Image to be displayed (not that image has to be initialized)
129   \param x, y : The window is set at position x,y (column index, row index).
130   \param title : Window title.
131   \param scaleType : If this parameter is set to:
132   - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
133     is fully displayed in the screen;
134   - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
135   same than the image size.
136   - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
137   and the columns.
138   - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
139   and the columns.
140   - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
141   and the columns.
142   - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
143   and the columns.
144 
145 */
vpDisplayOpenCV(vpImage<unsigned char> & I,int x,int y,const std::string & title,vpScaleType scaleType)146 vpDisplayOpenCV::vpDisplayOpenCV(vpImage<unsigned char> &I, int x, int y, const std::string &title,
147                                  vpScaleType scaleType)
148   : vpDisplay(),
149 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
150     m_background(NULL), col(NULL), cvcolor(), font(NULL),
151 #else
152     m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
153 #endif
154     fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
155     x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
156     x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
157     y_rbuttonup(0), rbuttonup(false)
158 {
159   setScale(scaleType, I.getWidth(), I.getHeight());
160   init(I, x, y, title);
161 }
162 
163 /*!
164   Constructor. Initialize a display to visualize a RGBa image (32 bits).
165 
166   \param I : Image to be displayed (not that image has to be initialized)
167   \param scaleType : If this parameter is set to:
168   - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
169     is fully displayed in the screen;
170   - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
171   same than the image size.
172   - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
173   and the columns.
174   - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
175   and the columns.
176   - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
177   and the columns.
178   - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
179   and the columns.
180 */
vpDisplayOpenCV(vpImage<vpRGBa> & I,vpScaleType scaleType)181 vpDisplayOpenCV::vpDisplayOpenCV(vpImage<vpRGBa> &I, vpScaleType scaleType)
182   :
183 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
184     m_background(NULL), col(NULL), cvcolor(), font(NULL),
185 #else
186     m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
187 #endif
188     fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
189     x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
190     x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
191     y_rbuttonup(0), rbuttonup(false)
192 {
193   setScale(scaleType, I.getWidth(), I.getHeight());
194   init(I);
195 }
196 
197 /*!
198   Constructor. Initialize a display to visualize a RGBa image (32 bits).
199 
200   \param I : Image to be displayed (not that image has to be initialized)
201   \param x, y : The window is set at position x,y (column index, row index).
202   \param title : Window title.
203   \param scaleType : If this parameter is set to:
204   - vpDisplay::SCALE_AUTO, the display size is adapted to ensure the image
205     is fully displayed in the screen;
206   - vpDisplay::SCALE_DEFAULT or vpDisplay::SCALE_1, the display size is the
207   same than the image size.
208   - vpDisplay::SCALE_2, the display size is downscaled by 2 along the lines
209   and the columns.
210   - vpDisplay::SCALE_3, the display size is downscaled by 3 along the lines
211   and the columns.
212   - vpDisplay::SCALE_4, the display size is downscaled by 4 along the lines
213   and the columns.
214   - vpDisplay::SCALE_5, the display size is downscaled by 5 along the lines
215   and the columns.
216 */
vpDisplayOpenCV(vpImage<vpRGBa> & I,int x,int y,const std::string & title,vpScaleType scaleType)217 vpDisplayOpenCV::vpDisplayOpenCV(vpImage<vpRGBa> &I, int x, int y, const std::string &title, vpScaleType scaleType)
218   :
219 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
220     m_background(NULL), col(NULL), cvcolor(), font(NULL),
221 #else
222     m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
223 #endif
224     fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
225     x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
226     x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
227     y_rbuttonup(0), rbuttonup(false)
228 {
229   setScale(scaleType, I.getWidth(), I.getHeight());
230   init(I, x, y, title);
231 }
232 
233 /*!
234 
235   Constructor that just initialize the display position in the screen
236   and the display title.
237 
238   \param x, y : The window is set at position x,y (column index, row index).
239   \param title : Window title.
240 
241   To initialize the display size, you need to call init().
242 
243   \code
244 #include <visp3/core/vpImage.h>
245 #include <visp3/gui/vpDisplayOpenCV.h>
246 
247 int main()
248 {
249   vpDisplayOpenCV d(100, 200, "My display");
250   vpImage<unsigned char> I(240, 384);
251   d.init(I);
252 }
253   \endcode
254 */
vpDisplayOpenCV(int x,int y,const std::string & title)255 vpDisplayOpenCV::vpDisplayOpenCV(int x, int y, const std::string &title)
256   :
257 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
258     m_background(NULL), col(NULL), cvcolor(), font(NULL),
259 #else
260     m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
261 #endif
262     fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
263     x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
264     x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
265     y_rbuttonup(0), rbuttonup(false)
266 {
267   m_windowXPosition = x;
268   m_windowYPosition = y;
269 
270   if (!title.empty()) {
271     m_title = title;
272   } else {
273     std::ostringstream s;
274     s << m_nbWindows++;
275     m_title = std::string("Window ") + s.str();
276   }
277 
278   bool isInList;
279   do {
280     isInList = false;
281     for (size_t i = 0; i < m_listTitles.size(); i++) {
282       if (m_listTitles[i] == m_title) {
283         std::ostringstream s;
284         s << m_nbWindows++;
285         m_title = std::string("Window ") + s.str();
286         isInList = true;
287         break;
288       }
289     }
290   } while (isInList);
291 
292   m_listTitles.push_back(m_title);
293 }
294 
295 /*!
296   Basic constructor.
297 
298   To initialize the window position, title and size you may call
299   init(vpImage<unsigned char> &, int, int, const std::string &) or
300   init(vpImage<vpRGBa> &, int, int, const std::string &).
301 
302   \code
303 #include <visp3/core/vpImage.h>
304 #include <visp3/gui/vpDisplayOpenCV.h>
305 
306 int main()
307 {
308   vpDisplayOpenCV d;
309   vpImage<unsigned char> I(240, 384);
310   d.init(I, 100, 200, "My display");
311 }
312   \endcode
313 */
vpDisplayOpenCV()314 vpDisplayOpenCV::vpDisplayOpenCV()
315   :
316 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
317     m_background(NULL), col(NULL), cvcolor(), font(NULL),
318 #else
319     m_background(), col(NULL), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
320 #endif
321     fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
322     x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
323     x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
324     y_rbuttonup(0), rbuttonup(false)
325 {
326 }
327 
328 /*!
329   Destructor.
330 */
~vpDisplayOpenCV()331 vpDisplayOpenCV::~vpDisplayOpenCV()
332 {
333   closeDisplay();
334 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
335   cvReleaseImage(&m_background);
336 #endif
337 }
338 
339 /*!
340   Initialize the display (size, position and title) of a gray level image.
341 
342   \param I : Image to be displayed (not that image has to be initialized)
343   \param x, y : The window is set at position x,y (column index, row index).
344   \param title : Window title.
345 
346 */
init(vpImage<unsigned char> & I,int x,int y,const std::string & title)347 void vpDisplayOpenCV::init(vpImage<unsigned char> &I, int x, int y, const std::string &title)
348 {
349   if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
350     throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
351   }
352   setScale(m_scaleType, I.getWidth(), I.getHeight());
353   init(I.getWidth(), I.getHeight(), x, y, title);
354   I.display = this;
355   m_displayHasBeenInitialized = true;
356 }
357 
358 /*!
359   Initialize the display (size, position and title) of a color
360   image in RGBa format.
361 
362   \param I : Image to be displayed (not that image has to be initialized)
363   \param x, y : The window is set at position x,y (column index, row index).
364   \param title : Window title.
365 
366 */
init(vpImage<vpRGBa> & I,int x,int y,const std::string & title)367 void vpDisplayOpenCV::init(vpImage<vpRGBa> &I, int x, int y, const std::string &title)
368 {
369   if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
370     throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
371   }
372 
373   setScale(m_scaleType, I.getWidth(), I.getHeight());
374   init(I.getWidth(), I.getHeight(), x, y, title);
375   I.display = this;
376   m_displayHasBeenInitialized = true;
377 }
378 
379 /*!
380   Initialize the display size, position and title.
381 
382   \param w, h : Width and height of the window.
383   \param x, y : The window is set at position x,y (column index, row index).
384   \param title : Window title.
385 
386   \exception vpDisplayException::notInitializedError If OpenCV was not build
387   with an available display device suach as Gtk, Cocoa, Carbon, Qt.
388 */
init(unsigned int w,unsigned int h,int x,int y,const std::string & title)389 void vpDisplayOpenCV::init(unsigned int w, unsigned int h, int x, int y, const std::string &title)
390 {
391   setScale(m_scaleType, w, h);
392 
393   this->m_width = w / m_scale;
394   this->m_height = h / m_scale;
395 
396   if (x != -1)
397     this->m_windowXPosition = x;
398   if (y != -1)
399     this->m_windowYPosition = y;
400 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
401   int flags = CV_WINDOW_AUTOSIZE;
402 #else
403   int flags = cv::WINDOW_AUTOSIZE;
404 #endif
405 
406   if (m_title.empty()) {
407     if (!title.empty()) {
408       m_title = std::string(title);
409     } else {
410 
411       std::ostringstream s;
412       s << m_nbWindows++;
413       m_title = std::string("Window ") + s.str();
414     }
415 
416     bool isInList;
417     do {
418       isInList = false;
419       for (size_t i = 0; i < m_listTitles.size(); i++) {
420         if (m_listTitles[i] == m_title) {
421           std::ostringstream s;
422           s << m_nbWindows++;
423           m_title = std::string("Window ") + s.str();
424           isInList = true;
425           break;
426         }
427       }
428     } while (isInList);
429 
430     m_listTitles.push_back(m_title);
431   }
432 
433 /* Create the window*/
434 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
435   if (cvNamedWindow(this->m_title.c_str(), flags) < 0) {
436     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV was not built with a display device"));
437   }
438 #else
439   cv::namedWindow(this->m_title, flags);
440 #endif
441 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
442   cvMoveWindow(this->m_title.c_str(), this->m_windowXPosition, this->m_windowYPosition);
443 #else
444   cv::moveWindow(this->m_title.c_str(), this->m_windowXPosition, this->m_windowYPosition);
445 #endif
446   move = false;
447   lbuttondown = false;
448   mbuttondown = false;
449   rbuttondown = false;
450   lbuttonup = false;
451   mbuttonup = false;
452   rbuttonup = false;
453 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
454   cvSetMouseCallback(this->m_title.c_str(), on_mouse, this);
455   col = new CvScalar[vpColor::id_unknown];
456 #else
457   cv::setMouseCallback(this->m_title, on_mouse, this);
458   col = new cv::Scalar[vpColor::id_unknown];
459 #endif
460 
461   /* Create color */
462   vpColor pcolor; // Predefined colors
463   pcolor = vpColor::lightBlue;
464   col[vpColor::id_lightBlue] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
465   pcolor = vpColor::blue;
466   col[vpColor::id_blue] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
467   pcolor = vpColor::darkBlue;
468   col[vpColor::id_darkBlue] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
469   pcolor = vpColor::lightRed;
470   col[vpColor::id_lightRed] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
471   pcolor = vpColor::red;
472   col[vpColor::id_red] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
473   pcolor = vpColor::darkRed;
474   col[vpColor::id_darkRed] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
475   pcolor = vpColor::lightGreen;
476   col[vpColor::id_lightGreen] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
477   pcolor = vpColor::green;
478   col[vpColor::id_green] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
479   pcolor = vpColor::darkGreen;
480   col[vpColor::id_darkGreen] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
481   pcolor = vpColor::yellow;
482   col[vpColor::id_yellow] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
483   pcolor = vpColor::cyan;
484   col[vpColor::id_cyan] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
485   pcolor = vpColor::orange;
486   col[vpColor::id_orange] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
487   pcolor = vpColor::purple;
488   col[vpColor::id_purple] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
489   pcolor = vpColor::white;
490   col[vpColor::id_white] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
491   pcolor = vpColor::black;
492   col[vpColor::id_black] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
493   pcolor = vpColor::lightGray;
494   col[vpColor::id_lightGray] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
495   pcolor = vpColor::gray;
496   col[vpColor::id_gray] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
497   pcolor = vpColor::darkGray;
498   col[vpColor::id_darkGray] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
499 
500 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
501   font = new CvFont;
502   cvInitFont(font, CV_FONT_HERSHEY_PLAIN, 0.70f, 0.70f);
503   CvSize fontSize;
504   int baseline;
505   cvGetTextSize("A", font, &fontSize, &baseline);
506 #else
507   int thickness = 1;
508   cv::Size fontSize;
509   int baseline;
510   fontSize = cv::getTextSize("A", font, fontScale, thickness, &baseline);
511 #endif
512 
513   fontHeight = fontSize.height + baseline;
514   m_displayHasBeenInitialized = true;
515 }
516 
517 /*!
518   \warning This method is not yet implemented.
519 
520   Set the font used to display a text in overlay. The display is
521   performed using displayCharString().
522 
523   \param font : The expected font name. The available fonts are given by
524   the "xlsfonts" binary. To choose a font you can also use the
525   "xfontsel" binary.
526 
527   \note Under UNIX, to know all the available fonts, use the
528   "xlsfonts" binary in a terminal. You can also use the "xfontsel" binary.
529 
530   \sa displayCharString()
531 */
setFont(const std::string &)532 void vpDisplayOpenCV::setFont(const std::string & /* font */) { vpERROR_TRACE("Not yet implemented"); }
533 
534 /*!
535   Set the window title.
536 
537   \warning This method is not implemented yet.
538 
539   \param title : Window title.
540  */
setTitle(const std::string &)541 void vpDisplayOpenCV::setTitle(const std::string & /* title */)
542 {
543   //  static bool warn_displayed = false;
544   //  if (! warn_displayed) {
545   //    vpTRACE("Not implemented");
546   //    warn_displayed = true;
547   //  }
548 }
549 
550 /*!
551   Set the window position in the screen.
552 
553   \param winx, winy : Position of the upper-left window's border in the
554   screen.
555 
556   \exception vpDisplayException::notInitializedError : If the video
557   device is not initialized.
558 */
setWindowPosition(int winx,int winy)559 void vpDisplayOpenCV::setWindowPosition(int winx, int winy)
560 {
561   if (m_displayHasBeenInitialized) {
562     this->m_windowXPosition = winx;
563     this->m_windowYPosition = winy;
564 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
565     cvMoveWindow(this->m_title.c_str(), winx, winy);
566 #else
567     cv::moveWindow(this->m_title.c_str(), winx, winy);
568 #endif
569   } else {
570     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
571   }
572 }
573 /*!
574   Display the gray level image \e I (8bits).
575 
576   \warning Display has to be initialized.
577 
578   \warning suppres the overlay drawing
579 
580   \param I : Image to display.
581 
582   \sa init(), closeDisplay()
583 */
displayImage(const vpImage<unsigned char> & I)584 void vpDisplayOpenCV::displayImage(const vpImage<unsigned char> &I)
585 {
586   if (m_displayHasBeenInitialized) {
587 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
588     int depth = 8;
589     int channels = 3;
590     CvSize size = cvSize((int)this->m_width, (int)this->m_height);
591     if (m_background != NULL) {
592       if (m_background->nChannels != channels || m_background->depth != depth ||
593           m_background->height != (int)m_height || m_background->width != (int)m_width) {
594         if (m_background->nChannels != 0)
595           cvReleaseImage(&m_background);
596         m_background = cvCreateImage(size, depth, channels);
597       }
598     } else {
599       m_background = cvCreateImage(size, depth, channels);
600     }
601 
602     if (m_scale == 1) {
603       for (unsigned int i = 0; i < m_height; i++) {
604         unsigned char *dst_24 = (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep);
605         for (unsigned int j = 0; j < m_width; j++) {
606           unsigned char val = I[i][j];
607           *(dst_24++) = val;
608           *(dst_24++) = val;
609           *(dst_24++) = val;
610         }
611       }
612     } else {
613       for (unsigned int i = 0; i < m_height; i++) {
614         unsigned char *dst_24 = (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep);
615         for (unsigned int j = 0; j < m_width; j++) {
616           unsigned char val = I[i * m_scale][j * m_scale];
617           *(dst_24++) = val;
618           *(dst_24++) = val;
619           *(dst_24++) = val;
620         }
621       }
622     }
623 
624 #else
625     int depth = CV_8U;
626     int channels = 3;
627     cv::Size size((int)m_width, (int)m_height);
628     if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
629         m_background.cols != (int)m_width) {
630       m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
631     }
632 
633     if (m_scale == 1) {
634       for (unsigned int i = 0; i < m_height; i++) {
635         unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
636         for (unsigned int j = 0; j < m_width; j++) {
637           unsigned char val = I[i][j];
638           *(dst_24++) = val;
639           *(dst_24++) = val;
640           *(dst_24++) = val;
641         }
642       }
643     } else {
644       for (unsigned int i = 0; i < m_height; i++) {
645         unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
646         for (unsigned int j = 0; j < m_width; j++) {
647           unsigned char val = I[i * m_scale][j * m_scale];
648           *(dst_24++) = val;
649           *(dst_24++) = val;
650           *(dst_24++) = val;
651         }
652       }
653     }
654 #endif
655 
656   } else {
657     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
658   }
659 }
660 
661 /*!
662   Display a selection of the gray level image \e I (8bits).
663 
664   \warning Display has to be initialized.
665 
666   \warning Suppress the overlay drawing in the region of interest.
667 
668   \param I : Image to display.
669 
670   \param iP : Top left corner of the region of interest
671 
672   \param w, h : Width and height of the region of interest
673 
674   \sa init(), closeDisplay()
675 */
displayImageROI(const vpImage<unsigned char> & I,const vpImagePoint & iP,unsigned int w,unsigned int h)676 void vpDisplayOpenCV::displayImageROI(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int w,
677                                       unsigned int h)
678 {
679   if (m_displayHasBeenInitialized) {
680 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
681     int depth = 8;
682     int channels = 3;
683     CvSize size = cvSize((int)this->m_width, (int)this->m_height);
684     if (m_background != NULL) {
685       if (m_background->nChannels != channels || m_background->depth != depth ||
686           m_background->height != (int)m_height || m_background->width != (int)m_width) {
687         if (m_background->nChannels != 0)
688           cvReleaseImage(&m_background);
689         m_background = cvCreateImage(size, depth, channels);
690       }
691     } else {
692       m_background = cvCreateImage(size, depth, channels);
693     }
694 
695     if (m_scale == 1) {
696       unsigned int i_min = (unsigned int)iP.get_i();
697       unsigned int j_min = (unsigned int)iP.get_j();
698       unsigned int i_max = (std::min)(i_min + h, m_height);
699       unsigned int j_max = (std::min)(j_min + w, m_width);
700       for (unsigned int i = i_min; i < i_max; i++) {
701         unsigned char *dst_24 =
702             (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep + j_min * 3);
703         for (unsigned int j = j_min; j < j_max; j++) {
704           unsigned char val = I[i][j];
705           *(dst_24++) = val;
706           *(dst_24++) = val;
707           *(dst_24++) = val;
708         }
709       }
710     } else {
711       int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
712       int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
713       int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
714       int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
715       for (int i = i_min; i < i_max; i++) {
716         unsigned char *dst_24 =
717             (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep + j_min * 3);
718         for (int j = j_min; j < j_max; j++) {
719           unsigned char val = I[i * m_scale][j * m_scale];
720           *(dst_24++) = val;
721           *(dst_24++) = val;
722           *(dst_24++) = val;
723         }
724       }
725     }
726 
727 #else
728     int depth = CV_8U;
729     int channels = 3;
730     cv::Size size((int)m_width, (int)m_height);
731     if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
732         m_background.cols != (int)m_width) {
733       m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
734     }
735 
736     if (m_scale == 1) {
737       unsigned int i_min = (unsigned int)iP.get_i();
738       unsigned int j_min = (unsigned int)iP.get_j();
739       unsigned int i_max = (std::min)(i_min + h, m_height);
740       unsigned int j_max = (std::min)(j_min + w, m_width);
741       for (unsigned int i = i_min; i < i_max; i++) {
742         unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
743         for (unsigned int j = j_min; j < j_max; j++) {
744           unsigned char val = I[i][j];
745           *(dst_24++) = val;
746           *(dst_24++) = val;
747           *(dst_24++) = val;
748         }
749       }
750     } else {
751       int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
752       int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
753       int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
754       int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
755       for (int i = i_min; i < i_max; i++) {
756         unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
757         for (int j = j_min; j < j_max; j++) {
758           unsigned char val = I[i * m_scale][j * m_scale];
759           *(dst_24++) = val;
760           *(dst_24++) = val;
761           *(dst_24++) = val;
762         }
763       }
764     }
765 #endif
766   } else {
767     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
768   }
769 }
770 
771 /*!
772   Display the color image \e I in RGBa format (32bits).
773 
774   \warning Display has to be initialized.
775 
776   \warning suppres the overlay drawing
777 
778   \param I : Image to display.
779 
780   \sa init(), closeDisplay()
781 */
displayImage(const vpImage<vpRGBa> & I)782 void vpDisplayOpenCV::displayImage(const vpImage<vpRGBa> &I)
783 {
784 
785   if (m_displayHasBeenInitialized) {
786 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
787     int depth = 8;
788     int channels = 3;
789     CvSize size = cvSize((int)this->m_width, (int)this->m_height);
790     if (m_background != NULL) {
791       if (m_background->nChannels != channels || m_background->depth != depth ||
792           m_background->height != (int)m_height || m_background->width != (int)m_width) {
793         if (m_background->nChannels != 0)
794           cvReleaseImage(&m_background);
795         m_background = cvCreateImage(size, depth, channels);
796       }
797     } else {
798       m_background = cvCreateImage(size, depth, channels);
799     }
800 
801     if (m_scale == 1) {
802       for (unsigned int i = 0; i < m_height; i++) {
803         unsigned char *dst_24 = (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep);
804         for (unsigned int j = 0; j < m_width; j++) {
805           vpRGBa val = I[i][j];
806           *(dst_24++) = val.B;
807           *(dst_24++) = val.G;
808           *(dst_24++) = val.R;
809         }
810       }
811     } else {
812       for (unsigned int i = 0; i < m_height; i++) {
813         unsigned char *dst_24 = (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep);
814         for (unsigned int j = 0; j < m_width; j++) {
815           vpRGBa val = I[i * m_scale][j * m_scale];
816           *(dst_24++) = val.B;
817           *(dst_24++) = val.G;
818           *(dst_24++) = val.R;
819         }
820       }
821     }
822 #else
823     int depth = CV_8U;
824     int channels = 3;
825     cv::Size size((int)this->m_width, (int)this->m_height);
826     if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
827         m_background.cols != (int)m_width) {
828       m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
829     }
830 
831     if (m_scale == 1) {
832       for (unsigned int i = 0; i < m_height; i++) {
833         unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
834         for (unsigned int j = 0; j < m_width; j++) {
835           vpRGBa val = I[i][j];
836           *(dst_24++) = val.B;
837           *(dst_24++) = val.G;
838           *(dst_24++) = val.R;
839         }
840       }
841     } else {
842       for (unsigned int i = 0; i < m_height; i++) {
843         unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
844         for (unsigned int j = 0; j < m_width; j++) {
845           vpRGBa val = I[i * m_scale][j * m_scale];
846           *(dst_24++) = val.B;
847           *(dst_24++) = val.G;
848           *(dst_24++) = val.R;
849         }
850       }
851     }
852 #endif
853   } else {
854     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
855   }
856 }
857 
858 /*!
859   Display a selection of the color image \e I in RGBa format (32bits).
860 
861   \warning Display has to be initialized.
862 
863   \warning Suppress the overlay drawing in the region of interest.
864 
865   \param I : Image to display.
866 
867   \param iP : Top left corner of the region of interest
868 
869   \param w, h : Width and height of the region of interest
870 
871   \sa init(), closeDisplay()
872 */
displayImageROI(const vpImage<vpRGBa> & I,const vpImagePoint & iP,unsigned int w,unsigned int h)873 void vpDisplayOpenCV::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w,
874                                       unsigned int h)
875 {
876   if (m_displayHasBeenInitialized) {
877 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
878     int depth = 8;
879     int channels = 3;
880     CvSize size = cvSize((int)this->m_width, (int)this->m_height);
881     if (m_background != NULL) {
882       if (m_background->nChannels != channels || m_background->depth != depth ||
883           m_background->height != (int)m_height || m_background->width != (int)m_width) {
884         if (m_background->nChannels != 0)
885           cvReleaseImage(&m_background);
886         m_background = cvCreateImage(size, depth, channels);
887       }
888     } else {
889       m_background = cvCreateImage(size, depth, channels);
890     }
891 
892     if (m_scale == 1) {
893       unsigned int i_min = (unsigned int)iP.get_i();
894       unsigned int j_min = (unsigned int)iP.get_j();
895       unsigned int i_max = (std::min)(i_min + h, m_height);
896       unsigned int j_max = (std::min)(j_min + w, m_width);
897       for (unsigned int i = i_min; i < i_max; i++) {
898         unsigned char *dst_24 =
899             (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep + j_min * 3);
900         for (unsigned int j = j_min; j < j_max; j++) {
901           vpRGBa val = I[i][j];
902           *(dst_24++) = val.B;
903           *(dst_24++) = val.G;
904           *(dst_24++) = val.R;
905         }
906       }
907     } else {
908       int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
909       int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
910       int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
911       int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
912       for (int i = i_min; i < i_max; i++) {
913         unsigned char *dst_24 =
914             (unsigned char *)m_background->imageData + (int)(i * m_background->widthStep + j_min * 3);
915         for (int j = j_min; j < j_max; j++) {
916           vpRGBa val = I[i * m_scale][j * m_scale];
917           *(dst_24++) = val.B;
918           *(dst_24++) = val.G;
919           *(dst_24++) = val.R;
920         }
921       }
922     }
923 #else
924     int depth = CV_8U;
925     int channels = 3;
926     cv::Size size((int)this->m_width, (int)this->m_height);
927     if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
928         m_background.cols != (int)m_width) {
929       m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
930     }
931 
932     if (m_scale == 1) {
933       unsigned int i_min = (unsigned int)iP.get_i();
934       unsigned int j_min = (unsigned int)iP.get_j();
935       unsigned int i_max = (std::min)(i_min + h, m_height);
936       unsigned int j_max = (std::min)(j_min + w, m_width);
937       for (unsigned int i = i_min; i < i_max; i++) {
938         unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
939         for (unsigned int j = j_min; j < j_max; j++) {
940           vpRGBa val = I[i][j];
941           *(dst_24++) = val.B;
942           *(dst_24++) = val.G;
943           *(dst_24++) = val.R;
944         }
945       }
946     } else {
947       int i_min = (std::max)((int)ceil(iP.get_i() / m_scale), 0);
948       int j_min = (std::max)((int)ceil(iP.get_j() / m_scale), 0);
949       int i_max = (std::min)((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
950       int j_max = (std::min)((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
951       for (int i = i_min; i < i_max; i++) {
952         unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
953         for (int j = j_min; j < j_max; j++) {
954           vpRGBa val = I[i * m_scale][j * m_scale];
955           *(dst_24++) = val.B;
956           *(dst_24++) = val.G;
957           *(dst_24++) = val.R;
958         }
959       }
960     }
961 #endif
962   } else {
963     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
964   }
965 }
966 
967 /*!
968   \warning ot implemented yet
969 
970   \sa init(), closeDisplay()
971 */
displayImage(const unsigned char *)972 void vpDisplayOpenCV::displayImage(const unsigned char * /* I */) { vpTRACE(" not implemented "); }
973 
974 /*!
975 
976   Close the window.
977 
978   \sa init()
979 
980 */
closeDisplay()981 void vpDisplayOpenCV::closeDisplay()
982 {
983   if (col != NULL) {
984     delete[] col;
985     col = NULL;
986   }
987 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
988   if (font != NULL) {
989     delete font;
990     font = NULL;
991   }
992 #endif
993   if (m_displayHasBeenInitialized) {
994 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
995     cvDestroyWindow(this->m_title.c_str());
996 #else
997     cv::destroyWindow(this->m_title);
998 #endif
999 
1000     for (size_t i = 0; i < m_listTitles.size(); i++) {
1001       if (m_title == m_listTitles[i]) {
1002         m_listTitles.erase(m_listTitles.begin() + (long int)i);
1003         break;
1004       }
1005     }
1006 
1007     m_title.clear();
1008 
1009     m_displayHasBeenInitialized = false;
1010   }
1011 }
1012 
1013 /*!
1014   Flushes the OpenCV buffer.
1015   It's necessary to use this function to see the results of any drawing.
1016 
1017 */
flushDisplay()1018 void vpDisplayOpenCV::flushDisplay()
1019 {
1020   if (m_displayHasBeenInitialized) {
1021 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1022     cvShowImage(this->m_title.c_str(), m_background);
1023     cvWaitKey(5);
1024 #else
1025     cv::imshow(this->m_title, m_background);
1026     cv::waitKey(5);
1027 #endif
1028   } else {
1029     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1030   }
1031 }
1032 
1033 /*!
1034   Flushes the OpenCV buffer.
1035   It's necessary to use this function to see the results of any drawing.
1036 
1037 */
flushDisplayROI(const vpImagePoint &,const unsigned int,const unsigned int)1038 void vpDisplayOpenCV::flushDisplayROI(const vpImagePoint & /*iP*/, const unsigned int /*width*/,
1039                                       const unsigned int /*height*/)
1040 {
1041   if (m_displayHasBeenInitialized) {
1042 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1043     cvShowImage(this->m_title.c_str(), m_background);
1044     cvWaitKey(5);
1045 #else
1046     cv::imshow(this->m_title.c_str(), m_background);
1047     cv::waitKey(5);
1048 #endif
1049   } else {
1050     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1051   }
1052 }
1053 
1054 /*!
1055   \warning Not implemented yet.
1056 */
clearDisplay(const vpColor &)1057 void vpDisplayOpenCV::clearDisplay(const vpColor & /* color */)
1058 {
1059   static bool warn_displayed = false;
1060   if (!warn_displayed) {
1061     vpTRACE("Not implemented");
1062     warn_displayed = true;
1063   }
1064 }
1065 
1066 /*!
1067   Display an arrow from image point \e ip1 to image point \e ip2.
1068   \param ip1,ip2 : Initial and final image point.
1069   \param color : Arrow color.
1070   \param w,h : Width and height of the arrow.
1071   \param thickness : Thickness of the lines used to display the arrow.
1072 */
displayArrow(const vpImagePoint & ip1,const vpImagePoint & ip2,const vpColor & color,unsigned int w,unsigned int h,unsigned int thickness)1073 void vpDisplayOpenCV::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1074                                    unsigned int w, unsigned int h, unsigned int thickness)
1075 {
1076   if (m_displayHasBeenInitialized) {
1077     double a = ip2.get_i() - ip1.get_i();
1078     double b = ip2.get_j() - ip1.get_j();
1079     double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
1080 
1081     // if ((a==0)&&(b==0))
1082     if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
1083         (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
1084       // DisplayCrossLarge(i1,j1,3,col) ;
1085     } else {
1086       a /= lg;
1087       b /= lg;
1088 
1089       vpImagePoint ip3;
1090       ip3.set_i(ip2.get_i() - w * a);
1091       ip3.set_j(ip2.get_j() - w * b);
1092 
1093       vpImagePoint ip4;
1094       ip4.set_i(ip3.get_i() - b * h);
1095       ip4.set_j(ip3.get_j() + a * h);
1096 
1097       if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1098         displayLine(ip2, ip4, color, thickness);
1099 
1100       ip4.set_i(ip3.get_i() + b * h);
1101       ip4.set_j(ip3.get_j() - a * h);
1102 
1103       if (lg > 2 * vpImagePoint::distance(ip2, ip4))
1104         displayLine(ip2, ip4, color, thickness);
1105 
1106       displayLine(ip1, ip2, color, thickness);
1107     }
1108   } else {
1109     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1110   }
1111 }
1112 
1113 /*!
1114   Display a string at the image point \e ip location.
1115 
1116   To select the font used to display the string, use setFont().
1117 
1118   \param ip : Upper left image point location of the string in the display.
1119   \param text : String to display in overlay.
1120   \param color : String color.
1121 
1122   \sa setFont()
1123 */
displayCharString(const vpImagePoint & ip,const char * text,const vpColor & color)1124 void vpDisplayOpenCV::displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color)
1125 {
1126   if (m_displayHasBeenInitialized) {
1127     if (color.id < vpColor::id_unknown) {
1128 #if VISP_HAVE_OPENCV_VERSION < 0x020408
1129       cvPutText(m_background, text,
1130                 cvPoint(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale + fontHeight)), font,
1131                 col[color.id]);
1132 #else
1133       cv::putText(m_background, text,
1134                   cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale + fontHeight)),
1135                   font, fontScale, col[color.id]);
1136 #endif
1137     } else {
1138       cvcolor = CV_RGB(color.R, color.G, color.B);
1139 #if VISP_HAVE_OPENCV_VERSION < 0x020408
1140       cvPutText(m_background, text,
1141                 cvPoint(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale + fontHeight)), font,
1142                 cvcolor);
1143 #else
1144       cv::putText(m_background, text,
1145                   cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale + fontHeight)),
1146                   font, fontScale, cvcolor);
1147 #endif
1148     }
1149   } else {
1150     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1151   }
1152 }
1153 /*!
1154   Display a circle.
1155   \param center : Circle center position.
1156   \param radius : Circle radius.
1157   \param color : RGB color used to display the rectangle.
1158   Alpha channel in color.A is here taken into account when cxx standard is set to cxx11 or higher.
1159   When alpha value is set to 255 (default) the rectangle is displayed without
1160   transparency. Closer is the alpha value to zero, more the rectangle is transparent.
1161   \param fill : When set to true fill the circle.
1162   \param thickness : Thickness of the circle. This parameter is only useful
1163   when \e fill is set to false.
1164 */
displayCircle(const vpImagePoint & center,unsigned int radius,const vpColor & color,bool fill,unsigned int thickness)1165 void vpDisplayOpenCV::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
1166                                     unsigned int thickness)
1167 {
1168   if (m_displayHasBeenInitialized) {
1169     int x = vpMath::round(center.get_u() / m_scale);
1170     int y = vpMath::round(center.get_v() / m_scale);
1171     int r = static_cast<int>(radius / m_scale);
1172     cv::Scalar cv_color;
1173     if (color.id < vpColor::id_unknown) {
1174       cv_color = col[color.id];
1175     }
1176     else{
1177       cv_color = CV_RGB(color.R, color.G, color.B);
1178     }
1179 
1180     if (fill == false) {
1181       int cv_thickness = static_cast<int>(thickness);
1182 #if VISP_HAVE_OPENCV_VERSION < 0x020408
1183       cvCircle(
1184         m_background,
1185         cvPoint(x, y),
1186         r,
1187         cv_color,
1188         cv_thickness);
1189 #else
1190       cv::circle(
1191         m_background,
1192         cv::Point(x, y),
1193         r,
1194         cv_color,
1195         cv_thickness);
1196 #endif
1197     } else {
1198 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
1199       int filled = cv::FILLED;
1200 #else
1201       int filled = CV_FILLED;
1202 #endif
1203 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
1204       double opacity = static_cast<double>(color.A) / 255.0;
1205 #  if VISP_HAVE_OPENCV_VERSION < 0x020408
1206       overlay(
1207         [x, y, r, cv_color, filled](cv::Mat image) {
1208           cvCircle(
1209             image,
1210             cvPoint(x, y),
1211             r,
1212             cv_color,
1213             filled);
1214         },
1215         opacity);
1216 #  else
1217       overlay(
1218         [x, y, r, cv_color, filled](cv::Mat image) {
1219           cv::circle(
1220             image,
1221             cv::Point(x, y),
1222             r,
1223             cv_color,
1224             filled);
1225         },
1226         opacity);
1227 #  endif
1228 #else
1229 #  if VISP_HAVE_OPENCV_VERSION < 0x020408
1230       cvCircle(
1231         m_background,
1232         cvPoint(x, y),
1233         r,
1234         cv_color,
1235         filled);
1236 #  else
1237       cv::circle(
1238         m_background,
1239         cv::Point(x, y),
1240         r,
1241         cv_color,
1242         filled);
1243 #  endif
1244 #endif
1245     }
1246   } else {
1247     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1248   }
1249 }
1250 
1251 /*!
1252   Display a cross at the image point \e ip location.
1253   \param ip : Cross location.
1254   \param size : Size (width and height) of the cross.
1255   \param color : Cross color.
1256   \param thickness : Thickness of the lines used to display the cross.
1257 */
displayCross(const vpImagePoint & ip,unsigned int size,const vpColor & color,unsigned int thickness)1258 void vpDisplayOpenCV::displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color,
1259                                    unsigned int thickness)
1260 {
1261   if (m_displayHasBeenInitialized) {
1262     vpImagePoint top, bottom, left, right;
1263     top.set_i(ip.get_i() - size / 2);
1264     top.set_j(ip.get_j());
1265     bottom.set_i(ip.get_i() + size / 2);
1266     bottom.set_j(ip.get_j());
1267     left.set_i(ip.get_i());
1268     left.set_j(ip.get_j() - size / 2);
1269     right.set_i(ip.get_i());
1270     right.set_j(ip.get_j() + size / 2);
1271     displayLine(top, bottom, color, thickness);
1272     displayLine(left, right, color, thickness);
1273   } else {
1274     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1275   }
1276 }
1277 
1278 /*!
1279   Display a dashed line from image point \e ip1 to image point \e ip2.
1280 
1281   \param ip1,ip2 : Initial and final image points.
1282   \param color : Line color.
1283   \param thickness : Line thickness.
1284 */
displayDotLine(const vpImagePoint & ip1,const vpImagePoint & ip2,const vpColor & color,unsigned int thickness)1285 void vpDisplayOpenCV::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1286                                      unsigned int thickness)
1287 {
1288   if (m_displayHasBeenInitialized) {
1289     vpImagePoint ip1_ = ip1;
1290     vpImagePoint ip2_ = ip2;
1291 
1292     double size = 10. * m_scale;
1293     double length = sqrt(vpMath::sqr(ip2_.get_i() - ip1_.get_i()) + vpMath::sqr(ip2_.get_j() - ip1_.get_j()));
1294     bool vertical_line = (int)ip2_.get_j() == (int)ip1_.get_j();
1295     if (vertical_line) {
1296       if (ip2_.get_i() < ip1_.get_i()) {
1297         std::swap(ip1_, ip2_);
1298       }
1299     } else if (ip2_.get_j() < ip1_.get_j()) {
1300       std::swap(ip1_, ip2_);
1301     }
1302 
1303     double diff_j = vertical_line ? 1 : ip2_.get_j() - ip1_.get_j();
1304     double deltaj = size / length * diff_j;
1305     double deltai = size / length * (ip2_.get_i() - ip1_.get_i());
1306     double slope = (ip2_.get_i() - ip1_.get_i()) / diff_j;
1307     double orig = ip1_.get_i() - slope * ip1_.get_j();
1308 
1309     if (vertical_line) {
1310       for (unsigned int i = (unsigned int)ip1_.get_i(); i < ip2_.get_i(); i += (unsigned int)(2 * deltai)) {
1311         double j = ip1_.get_j();
1312         displayLine(vpImagePoint(i, j), vpImagePoint(i + deltai, j), color, thickness);
1313       }
1314     } else {
1315       for (unsigned int j = (unsigned int)ip1_.get_j(); j < ip2_.get_j(); j += (unsigned int)(2 * deltaj)) {
1316         double i = slope * j + orig;
1317         displayLine(vpImagePoint(i, j), vpImagePoint(i + deltai, j + deltaj), color, thickness);
1318       }
1319     }
1320   } else {
1321     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1322   }
1323 }
1324 
1325 /*!
1326   Display a line from image point \e ip1 to image point \e ip2.
1327   \param ip1,ip2 : Initial and final image points.
1328   \param color : Line color.
1329   \param thickness : Line thickness.
1330 */
displayLine(const vpImagePoint & ip1,const vpImagePoint & ip2,const vpColor & color,unsigned int thickness)1331 void vpDisplayOpenCV::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1332                                   unsigned int thickness)
1333 {
1334   if (m_displayHasBeenInitialized) {
1335     if (color.id < vpColor::id_unknown) {
1336 #if VISP_HAVE_OPENCV_VERSION < 0x020408
1337       cvLine(m_background, cvPoint(vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale)),
1338              cvPoint(vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale)), col[color.id],
1339              (int)thickness);
1340 #else
1341       cv::line(m_background, cv::Point(vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale)),
1342                cv::Point(vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale)), col[color.id],
1343                (int)thickness);
1344 #endif
1345     } else {
1346       cvcolor = CV_RGB(color.R, color.G, color.B);
1347 #if VISP_HAVE_OPENCV_VERSION < 0x020408
1348       cvLine(m_background, cvPoint(vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale)),
1349              cvPoint(vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale)), cvcolor,
1350              (int)thickness);
1351 #else
1352       cv::line(m_background, cv::Point(vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale)),
1353                cv::Point(vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale)), cvcolor,
1354                (int)thickness);
1355 #endif
1356     }
1357   } else {
1358     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1359   }
1360 }
1361 
1362 /*!
1363   Display a point at the image point \e ip location.
1364   \param ip : Point location.
1365   \param color : Point color.
1366   \param thickness : point thickness.
1367 */
displayPoint(const vpImagePoint & ip,const vpColor & color,unsigned int thickness)1368 void vpDisplayOpenCV::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
1369 {
1370   if (m_displayHasBeenInitialized) {
1371     for (unsigned int i = 0; i < thickness; i++) {
1372       if (color.id < vpColor::id_unknown) {
1373 #if VISP_HAVE_OPENCV_VERSION < 0x020408
1374         cvLine(m_background, cvPoint(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale)),
1375                cvPoint(vpMath::round(ip.get_u() / m_scale + thickness - 1), vpMath::round(ip.get_v() / m_scale)),
1376                col[color.id], (int)thickness);
1377 #else
1378         cv::line(m_background, cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale)),
1379                  cv::Point(vpMath::round(ip.get_u() / m_scale + thickness - 1), vpMath::round(ip.get_v() / m_scale)),
1380                  col[color.id], (int)thickness);
1381 #endif
1382       } else {
1383         cvcolor = CV_RGB(color.R, color.G, color.B);
1384 #if VISP_HAVE_OPENCV_VERSION < 0x020408
1385         cvLine(m_background, cvPoint(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale)),
1386                cvPoint(vpMath::round(ip.get_u() / m_scale + thickness - 1), vpMath::round(ip.get_v() / m_scale)),
1387                cvcolor, (int)thickness);
1388 #else
1389         cv::line(m_background, cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale)),
1390                  cv::Point(vpMath::round(ip.get_u() / m_scale + thickness - 1), vpMath::round(ip.get_v() / m_scale)),
1391                  cvcolor, (int)thickness);
1392 #endif
1393       }
1394     }
1395   } else {
1396     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1397   }
1398 }
1399 
1400 /*!
1401   Display a rectangle with \e topLeft as the top-left corner and \e
1402   width and \e height the rectangle size.
1403 
1404   \param topLeft : Top-left corner of the rectangle.
1405   \param w,h : Rectangle size in terms of width and height.
1406   \param color : RGB color used to display the rectangle.
1407   Alpha channel in color.A is here taken into account when cxx standard is set to cxx11 or higher.
1408   When alpha value is set to 255 (default) the rectangle is displayed without
1409   transparency. Closer is the alpha value to zero, more the rectangle is transparent.
1410   \param fill : When set to true fill the rectangle.
1411   \param thickness : Thickness of the four lines used to display the
1412   rectangle. This parameter is only useful when \e fill is set to
1413   false.
1414 */
displayRectangle(const vpImagePoint & topLeft,unsigned int w,unsigned int h,const vpColor & color,bool fill,unsigned int thickness)1415 void vpDisplayOpenCV::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h,
1416                                        const vpColor &color, bool fill, unsigned int thickness)
1417 {
1418   if (m_displayHasBeenInitialized) {
1419     int left = vpMath::round(topLeft.get_u() / m_scale);
1420     int top = vpMath::round(topLeft.get_v() / m_scale);
1421     int right = vpMath::round((topLeft.get_u() + w) / m_scale);
1422     int bottom = vpMath::round((topLeft.get_v() + h) / m_scale);
1423     cv::Scalar cv_color;
1424     if (color.id < vpColor::id_unknown) {
1425       cv_color = col[color.id];
1426     }
1427     else {
1428       cv_color = CV_RGB(color.R, color.G, color.B);
1429     }
1430 
1431     if (fill == false) {
1432       int cv_thickness = static_cast<int>(thickness);
1433 #if VISP_HAVE_OPENCV_VERSION < 0x020408
1434       cvRectangle(
1435         m_background,
1436         cvPoint(left, top),
1437         cvPoint(right, bottom),
1438         cv_color,
1439         cv_thickness);
1440 #else
1441       cv::rectangle(
1442         m_background,
1443         cv::Point(left, top),
1444         cv::Point(right, bottom),
1445         cv_color,
1446         cv_thickness);
1447 #endif
1448     } else {
1449 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
1450       int filled = cv::FILLED;
1451 #else
1452       int filled = CV_FILLED;
1453 #endif
1454 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
1455       double opacity = static_cast<double>(color.A) / 255.0;
1456 #  if VISP_HAVE_OPENCV_VERSION < 0x020408
1457       overlay(
1458         [left, top, right, bottom, cv_color, filled](cv::Mat image) {
1459           cvRectangle(
1460               image,
1461               cvPoint(left, top),
1462               cvPoint(right, bottom),
1463               cv_color,
1464               filled);
1465         },
1466         opacity);
1467 #  else
1468       overlay(
1469         [left, top, right, bottom, cv_color, filled](cv::Mat image) {
1470           cv::rectangle(
1471             image,
1472             cv::Point(left, top),
1473             cv::Point(right, bottom),
1474             cv_color,
1475             filled);
1476         },
1477         opacity);
1478 #  endif
1479 #else
1480 #  if VISP_HAVE_OPENCV_VERSION < 0x020408
1481       cvRectangle(m_background,
1482                   cvPoint(left, top),
1483                   cvPoint(right, bottom),
1484                   cv_color,
1485                   filled);
1486 #  else
1487       cv::rectangle(m_background,
1488                     cv::Point(left, top),
1489                     cv::Point(right, bottom),
1490                     cv_color,
1491                     filled);
1492 #  endif
1493 #endif
1494     }
1495   } else {
1496     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1497   }
1498 }
1499 /*!
1500   Display a rectangle.
1501 
1502   \param topLeft : Top-left corner of the rectangle.
1503   \param bottomRight : Bottom-right corner of the rectangle.
1504   \param color : RGB color used to display the rectangle.
1505   Alpha channel in color.A is here taken into account when cxx standard is set to cxx11 or higher.
1506   When alpha value is set to 255 (default) the rectangle is displayed without
1507   transparency. Closer is the alpha value to zero, more the rectangle is transparent.
1508   \param fill : When set to true fill the rectangle.
1509   \param thickness : Thickness of the four lines used to display the
1510   rectangle. This parameter is only useful when \e fill is set to
1511   false.
1512 */
displayRectangle(const vpImagePoint & topLeft,const vpImagePoint & bottomRight,const vpColor & color,bool fill,unsigned int thickness)1513 void vpDisplayOpenCV::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight,
1514                                        const vpColor &color, bool fill, unsigned int thickness)
1515 {
1516   if (m_displayHasBeenInitialized) {
1517     int left = vpMath::round(topLeft.get_u() / m_scale);
1518     int top = vpMath::round(topLeft.get_v() / m_scale);
1519     int right = vpMath::round(bottomRight.get_u() / m_scale);
1520     int bottom = vpMath::round(bottomRight.get_v() / m_scale);
1521     cv::Scalar cv_color;
1522     if (color.id < vpColor::id_unknown) {
1523       cv_color = col[color.id];
1524     }
1525     else {
1526       cv_color = CV_RGB(color.R, color.G, color.B);
1527     }
1528 
1529     if (fill == false) {
1530       int cv_thickness = static_cast<int>(thickness);
1531 #if VISP_HAVE_OPENCV_VERSION < 0x020408
1532       cvRectangle(
1533         m_background,
1534         cvPoint(left, top),
1535         cvPoint(right, bottom),
1536         cv_color,
1537         cv_thickness);
1538 #else
1539       cv::rectangle(
1540         m_background,
1541         cv::Point(left, top),
1542         cv::Point(right, bottom),
1543         cv_color,
1544         cv_thickness);
1545 #endif
1546     } else {
1547 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
1548       int filled = cv::FILLED;
1549 #else
1550       int filled = CV_FILLED;
1551 #endif
1552 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
1553       double opacity = static_cast<double>(color.A) / 255.0;
1554 #  if VISP_HAVE_OPENCV_VERSION < 0x020408
1555       overlay(
1556         [left, top, right, bottom, cv_color, filled](cv::Mat image) {
1557           cvRectangle(
1558             image,
1559             cvPoint(left, top),
1560             cvPoint(right, bottom),
1561             cv_color,
1562             filled);
1563         },
1564         opacity);
1565 #  else
1566       overlay(
1567         [left, top, right, bottom, cv_color, filled](cv::Mat image) {
1568           cv::rectangle(
1569             image,
1570             cv::Point(left, top),
1571             cv::Point(right, bottom),
1572             cv_color,
1573             filled);
1574         },
1575         opacity);
1576 #  endif
1577 #else
1578 #  if VISP_HAVE_OPENCV_VERSION < 0x020408
1579       cvRectangle(m_background,
1580                   cvPoint(left, top),
1581                   cvPoint(right, bottom),
1582                   cv_color,
1583                   filled);
1584 #  else
1585       cv::rectangle(m_background,
1586                     cv::Point(left, top),
1587                     cv::Point(right, bottom),
1588                     cv_color,
1589                     filled);
1590 #  endif
1591 #endif
1592     }
1593   } else {
1594     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1595   }
1596 }
1597 
1598 /*!
1599   Display a rectangle.
1600 
1601   \param rectangle : Rectangle characteristics.
1602   \param color : RGB color used to display the rectangle.
1603   Alpha channel in color.A is here taken into account when cxx standard is set to cxx11 or higher.
1604   When alpha value is set to 255 (default) the rectangle is displayed without
1605   transparency. Closer is the alpha value to zero, more the rectangle is transparent.
1606   \param fill : When set to true fill the rectangle.
1607   \param thickness : Thickness of the four lines used to display the
1608   rectangle. This parameter is only useful when \e fill is set to
1609   false.
1610 */
displayRectangle(const vpRect & rectangle,const vpColor & color,bool fill,unsigned int thickness)1611 void vpDisplayOpenCV::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
1612 {
1613   if (m_displayHasBeenInitialized) {
1614     int left = vpMath::round(rectangle.getLeft() / m_scale);
1615     int top = vpMath::round(rectangle.getTop() / m_scale);
1616     int right = vpMath::round(rectangle.getRight() / m_scale);
1617     int bottom = vpMath::round(rectangle.getBottom() / m_scale);
1618     cv::Scalar cv_color;
1619     if (color.id < vpColor::id_unknown) {
1620       cv_color = col[color.id];
1621     }
1622     else {
1623       cv_color = CV_RGB(color.R, color.G, color.B);
1624     }
1625 
1626     if (fill == false) {
1627       int cv_thickness = static_cast<int>(thickness);
1628 #if VISP_HAVE_OPENCV_VERSION < 0x020408
1629       cvRectangle(
1630         m_background,
1631         cvPoint(left, top),
1632         cvPoint(right, bottom),
1633         cv_color,
1634         cv_thickness);
1635 #else
1636       cv::rectangle(
1637         m_background,
1638         cv::Point(left, top),
1639         cv::Point(right, bottom),
1640         cv_color,
1641         cv_thickness);
1642 #endif
1643     } else {
1644 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
1645       int filled = cv::FILLED;
1646 #else
1647       int filled = CV_FILLED;
1648 #endif
1649 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
1650       double opacity = static_cast<double>(color.A) / 255.0;
1651 #  if VISP_HAVE_OPENCV_VERSION < 0x020408
1652       overlay(
1653         [left, top, right, bottom, cv_color, filled](cv::Mat image) {
1654           cvRectangle(
1655               image,
1656               cvPoint(left, top),
1657               cvPoint(right, bottom),
1658               cv_color,
1659               filled);
1660         },
1661         opacity);
1662 #  else
1663       overlay(
1664         [left, top, right, bottom, cv_color, filled](cv::Mat image) {
1665           cv::rectangle(
1666               image,
1667               cv::Point(left, top),
1668               cv::Point(right, bottom),
1669               cv_color,
1670               filled);
1671         },
1672         opacity);
1673 #  endif
1674 #else
1675 #  if VISP_HAVE_OPENCV_VERSION < 0x020408
1676       cvRectangle(m_background,
1677                   cvPoint(left, top),
1678                   cvPoint(right, bottom),
1679                   cv_color,
1680                   filled);
1681 #  else
1682       cv::rectangle(m_background,
1683                     cv::Point(left, top),
1684                     cv::Point(right, bottom),
1685                     cv_color,
1686                     filled);
1687 #  endif
1688 #endif
1689       }
1690   } else {
1691     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1692   }
1693 }
1694 
1695 /*!
1696   Wait for a click from one of the mouse button.
1697 
1698   \param blocking [in] : Blocking behavior.
1699   - When set to true, this method waits until a mouse button is
1700     pressed and then returns always true.
1701   - When set to false, returns true only if a mouse button is
1702     pressed, otherwise returns false.
1703 
1704   \return
1705   - true if a button was clicked. This is always the case if blocking is set
1706     to \e true.
1707   - false if no button was clicked. This can occur if blocking is set
1708     to \e false.
1709 */
getClick(bool blocking)1710 bool vpDisplayOpenCV::getClick(bool blocking)
1711 {
1712   bool ret = false;
1713   if (m_displayHasBeenInitialized) {
1714     flushDisplay();
1715     if (blocking) {
1716       lbuttondown = false;
1717       mbuttondown = false;
1718       rbuttondown = false;
1719     }
1720     do {
1721       if (lbuttondown) {
1722         ret = true;
1723         lbuttondown = false;
1724       }
1725       if (mbuttondown) {
1726         ret = true;
1727         mbuttondown = false;
1728       }
1729       if (rbuttondown) {
1730         ret = true;
1731         rbuttondown = false;
1732       }
1733       if (blocking)
1734 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1735         cvWaitKey(10);
1736 #else
1737         cv::waitKey(10);
1738 #endif
1739     } while (ret == false && blocking == true);
1740   } else {
1741     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1742   }
1743   return ret;
1744 }
1745 
1746 /*!
1747   Wait for a click from one of the mouse button and get the position
1748   of the clicked image point.
1749 
1750   \param ip [out] : The coordinates of the clicked image point.
1751 
1752   \param blocking [in] : true for a blocking behaviour waiting a mouse
1753   button click, false for a non blocking behaviour.
1754 
1755   \return
1756   - true if a button was clicked. This is always the case if blocking is set
1757     to \e true.
1758   - false if no button was clicked. This can occur if blocking is set
1759     to \e false.
1760 */
getClick(vpImagePoint & ip,bool blocking)1761 bool vpDisplayOpenCV::getClick(vpImagePoint &ip, bool blocking)
1762 {
1763   bool ret = false;
1764 
1765   if (m_displayHasBeenInitialized) {
1766     flushDisplay();
1767 
1768     double u, v;
1769 
1770     if (blocking) {
1771       lbuttondown = false;
1772       mbuttondown = false;
1773       rbuttondown = false;
1774     }
1775     do {
1776       if (lbuttondown) {
1777         ret = true;
1778         u = (unsigned int)x_lbuttondown * m_scale;
1779         v = (unsigned int)y_lbuttondown * m_scale;
1780         ip.set_u(u);
1781         ip.set_v(v);
1782         lbuttondown = false;
1783       }
1784       if (mbuttondown) {
1785         ret = true;
1786         u = (unsigned int)x_mbuttondown * m_scale;
1787         v = (unsigned int)y_mbuttondown * m_scale;
1788         ip.set_u(u);
1789         ip.set_v(v);
1790         mbuttondown = false;
1791       }
1792       if (rbuttondown) {
1793         ret = true;
1794         u = (unsigned int)x_rbuttondown * m_scale;
1795         v = (unsigned int)y_rbuttondown * m_scale;
1796         ip.set_u(u);
1797         ip.set_v(v);
1798         rbuttondown = false;
1799       }
1800       if (blocking)
1801 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1802         cvWaitKey(10);
1803 #else
1804         cv::waitKey(10);
1805 #endif
1806     } while (ret == false && blocking == true);
1807   } else {
1808     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1809   }
1810   return ret;
1811 }
1812 
1813 /*!
1814   Wait for a mouse button click and get the position of the clicked
1815   pixel. The button used to click is also set.
1816 
1817   \param ip [out] : The coordinates of the clicked image point.
1818 
1819   \param button [out] : The button used to click.
1820 
1821   \param blocking [in] :
1822   - When set to true, this method waits until a mouse button is
1823     pressed and then returns always true.
1824   - When set to false, returns true only if a mouse button is
1825     pressed, otherwise returns false.
1826 
1827   \return true if a mouse button is pressed, false otherwise. If a
1828   button is pressed, the location of the mouse pointer is updated in
1829   \e ip.
1830 */
getClick(vpImagePoint & ip,vpMouseButton::vpMouseButtonType & button,bool blocking)1831 bool vpDisplayOpenCV::getClick(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking)
1832 {
1833   bool ret = false;
1834 
1835   if (m_displayHasBeenInitialized) {
1836     // flushDisplay() ;
1837     double u, v;
1838     if (blocking) {
1839       lbuttondown = false;
1840       mbuttondown = false;
1841       rbuttondown = false;
1842     }
1843     do {
1844       if (lbuttondown) {
1845         ret = true;
1846         u = (unsigned int)x_lbuttondown * m_scale;
1847         v = (unsigned int)y_lbuttondown * m_scale;
1848         ip.set_u(u);
1849         ip.set_v(v);
1850         button = vpMouseButton::button1;
1851         lbuttondown = false;
1852       }
1853       if (mbuttondown) {
1854         ret = true;
1855         u = (unsigned int)x_mbuttondown * m_scale;
1856         v = (unsigned int)y_mbuttondown * m_scale;
1857         ip.set_u(u);
1858         ip.set_v(v);
1859         button = vpMouseButton::button2;
1860         mbuttondown = false;
1861       }
1862       if (rbuttondown) {
1863         ret = true;
1864         u = (unsigned int)x_rbuttondown * m_scale;
1865         v = (unsigned int)y_rbuttondown * m_scale;
1866         ip.set_u(u);
1867         ip.set_v(v);
1868         button = vpMouseButton::button3;
1869         rbuttondown = false;
1870       }
1871       if (blocking)
1872 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1873         cvWaitKey(10);
1874 #else
1875         cv::waitKey(10);
1876 #endif
1877     } while (ret == false && blocking == true);
1878   } else {
1879     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1880   }
1881   return ret;
1882 }
1883 
1884 /*!
1885   Wait for a mouse button click release and get the position of the
1886   image point were the click release occurs.  The button used to click is
1887   also set. Same method as getClick(unsigned int&, unsigned int&,
1888   vpMouseButton::vpMouseButtonType &, bool).
1889 
1890   \param ip [out] : Position of the clicked image point.
1891 
1892   \param button [in] : Button used to click.
1893 
1894   \param blocking [in] : true for a blocking behaviour waiting a mouse
1895   button click, false for a non blocking behaviour.
1896 
1897   \return
1898   - true if a button was clicked. This is always the case if blocking is set
1899     to \e true.
1900   - false if no button was clicked. This can occur if blocking is set
1901     to \e false.
1902 
1903   \sa getClick(vpImagePoint &, vpMouseButton::vpMouseButtonType &, bool)
1904 */
getClickUp(vpImagePoint & ip,vpMouseButton::vpMouseButtonType & button,bool blocking)1905 bool vpDisplayOpenCV::getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking)
1906 {
1907   bool ret = false;
1908   if (m_displayHasBeenInitialized) {
1909     // flushDisplay() ;
1910     double u, v;
1911     if (blocking) {
1912       lbuttonup = false;
1913       mbuttonup = false;
1914       rbuttonup = false;
1915     }
1916     do {
1917       if (lbuttonup) {
1918         ret = true;
1919         u = (unsigned int)x_lbuttonup * m_scale;
1920         v = (unsigned int)y_lbuttonup * m_scale;
1921         ip.set_u(u);
1922         ip.set_v(v);
1923         button = vpMouseButton::button1;
1924         lbuttonup = false;
1925       }
1926       if (mbuttonup) {
1927         ret = true;
1928         u = (unsigned int)x_mbuttonup * m_scale;
1929         v = (unsigned int)y_mbuttonup * m_scale;
1930         ip.set_u(u);
1931         ip.set_v(v);
1932         button = vpMouseButton::button2;
1933         mbuttonup = false;
1934       }
1935       if (rbuttonup) {
1936         ret = true;
1937         u = (unsigned int)x_rbuttonup * m_scale;
1938         v = (unsigned int)y_rbuttonup * m_scale;
1939         ip.set_u(u);
1940         ip.set_v(v);
1941         button = vpMouseButton::button3;
1942         rbuttonup = false;
1943       }
1944       if (blocking)
1945 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1946         cvWaitKey(10);
1947 #else
1948         cv::waitKey(10);
1949 #endif
1950     } while (ret == false && blocking == true);
1951   } else {
1952     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1953   }
1954   return ret;
1955 }
1956 
1957 /*
1958   Gets the displayed image (including the overlay plane)
1959   and returns an RGBa image.
1960 */
getImage(vpImage<vpRGBa> & I)1961 void vpDisplayOpenCV::getImage(vpImage<vpRGBa> &I)
1962 {
1963   vpImageConvert::convert(m_background, I);
1964   // should certainly be optimized.
1965 }
1966 
on_mouse(int event,int x,int y,int,void * display)1967 void vpDisplayOpenCV::on_mouse(int event, int x, int y, int /*flags*/, void *display)
1968 {
1969   vpDisplayOpenCV *disp = static_cast<vpDisplayOpenCV *>(display);
1970   switch (event) {
1971 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1972   case CV_EVENT_MOUSEMOVE:
1973 #else
1974   case cv::EVENT_MOUSEMOVE:
1975 #endif
1976   {
1977     disp->move = true;
1978     disp->x_move = x;
1979     disp->y_move = y;
1980     break;
1981   }
1982 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1983   case CV_EVENT_LBUTTONDOWN:
1984 #else
1985   case cv::EVENT_LBUTTONDOWN:
1986 #endif
1987   {
1988     disp->lbuttondown = true;
1989     disp->x_lbuttondown = x;
1990     disp->y_lbuttondown = y;
1991     break;
1992   }
1993 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
1994   case CV_EVENT_MBUTTONDOWN:
1995 #else
1996   case cv::EVENT_MBUTTONDOWN:
1997 #endif
1998   {
1999     disp->mbuttondown = true;
2000     disp->x_mbuttondown = x;
2001     disp->y_mbuttondown = y;
2002     break;
2003   }
2004 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
2005   case CV_EVENT_RBUTTONDOWN:
2006 #else
2007   case cv::EVENT_RBUTTONDOWN:
2008 #endif
2009   {
2010     disp->rbuttondown = true;
2011     disp->x_rbuttondown = x;
2012     disp->y_rbuttondown = y;
2013     break;
2014   }
2015 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
2016   case CV_EVENT_LBUTTONUP:
2017 #else
2018   case cv::EVENT_LBUTTONUP:
2019 #endif
2020   {
2021     disp->lbuttonup = true;
2022     disp->x_lbuttonup = x;
2023     disp->y_lbuttonup = y;
2024     break;
2025   }
2026 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
2027   case CV_EVENT_MBUTTONUP:
2028 #else
2029   case cv::EVENT_MBUTTONUP:
2030 #endif
2031   {
2032     disp->mbuttonup = true;
2033     disp->x_mbuttonup = x;
2034     disp->y_mbuttonup = y;
2035     break;
2036   }
2037 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
2038   case CV_EVENT_RBUTTONUP:
2039 #else
2040   case cv::EVENT_RBUTTONUP:
2041 #endif
2042   {
2043     disp->rbuttonup = true;
2044     disp->x_rbuttonup = x;
2045     disp->y_rbuttonup = y;
2046     break;
2047   }
2048 
2049   default:
2050     break;
2051   }
2052 }
2053 
2054 /*!
2055   Get a keyboard event.
2056 
2057   \param blocking [in] : Blocking behavior.
2058   - When set to true, this method waits until a key is
2059     pressed and then returns always true.
2060   - When set to false, returns true only if a key is
2061     pressed, otherwise returns false.
2062 
2063   \return
2064   - true if a key was pressed. This is always the case if blocking is set
2065     to \e true.
2066   - false if no key was pressed. This can occur if blocking is set
2067     to \e false.
2068 */
getKeyboardEvent(bool blocking)2069 bool vpDisplayOpenCV::getKeyboardEvent(bool blocking)
2070 {
2071   if (m_displayHasBeenInitialized) {
2072     int delay;
2073     flushDisplay();
2074     if (blocking)
2075       delay = 0;
2076     else
2077       delay = 10;
2078 
2079 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
2080     int key_pressed = cvWaitKey(delay);
2081 #else
2082     int key_pressed = cv::waitKey(delay);
2083 #endif
2084 
2085     if (key_pressed == -1)
2086       return false;
2087     return true;
2088   } else {
2089     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
2090   }
2091   // return false; // Never reached after throw()
2092 }
2093 /*!
2094   Get a keyboard event.
2095 
2096   \param blocking [in] : Blocking behavior.
2097   - When set to true, this method waits until a key is
2098     pressed and then returns always true.
2099   - When set to false, returns true only if a key is
2100     pressed, otherwise returns false.
2101 
2102   \param key [out]: If possible, an ISO Latin-1 character
2103   corresponding to the keyboard key.
2104 
2105   \return
2106   - true if a key was pressed. This is always the case if blocking is set
2107     to \e true.
2108   - false if no key was pressed. This can occur if blocking is set
2109     to \e false.
2110 */
getKeyboardEvent(std::string & key,bool blocking)2111 bool vpDisplayOpenCV::getKeyboardEvent(std::string &key, bool blocking)
2112 {
2113   if (m_displayHasBeenInitialized) {
2114     int delay;
2115     flushDisplay();
2116     if (blocking)
2117       delay = 0;
2118     else
2119       delay = 10;
2120 
2121 #if (VISP_HAVE_OPENCV_VERSION < 0x020408)
2122     int key_pressed = cvWaitKey(delay);
2123 #else
2124     int key_pressed = cv::waitKey(delay);
2125 #endif
2126     if (key_pressed == -1)
2127       return false;
2128     else {
2129       // std::cout << "Key pressed: \"" << key_pressed << "\"" << std::endl;
2130       std::stringstream ss;
2131       ss << key_pressed;
2132       key = ss.str();
2133     }
2134     return true;
2135   } else {
2136     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
2137   }
2138   // return false; // Never reached after throw()
2139 }
2140 
2141 /*!
2142   Get the coordinates of the mouse pointer.
2143 
2144   \param ip [out] : The coordinates of the mouse pointer.
2145 
2146   \return true if a pointer motion event was received, false otherwise.
2147 
2148   \exception vpDisplayException::notInitializedError : If the display
2149   was not initialized.
2150 */
getPointerMotionEvent(vpImagePoint & ip)2151 bool vpDisplayOpenCV::getPointerMotionEvent(vpImagePoint &ip)
2152 {
2153   bool ret = false;
2154 
2155   if (m_displayHasBeenInitialized) {
2156     // flushDisplay() ;
2157     if (move) {
2158       ret = true;
2159       double u = (unsigned int)x_move / m_scale;
2160       double v = (unsigned int)y_move / m_scale;
2161       ip.set_u(u);
2162       ip.set_v(v);
2163       move = false;
2164     }
2165   }
2166 
2167   else {
2168     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
2169   }
2170   return ret;
2171 }
2172 
2173 /*!
2174   Get the coordinates of the mouse pointer.
2175 
2176   \param ip [out] : The coordinates of the mouse pointer.
2177 
2178   \return true.
2179 
2180   \exception vpDisplayException::notInitializedError : If the display
2181   was not initialized.
2182 */
getPointerPosition(vpImagePoint & ip)2183 bool vpDisplayOpenCV::getPointerPosition(vpImagePoint &ip)
2184 {
2185   if (m_displayHasBeenInitialized) {
2186     bool moved = getPointerMotionEvent(ip);
2187     if (!moved) {
2188       double u, v;
2189       u = (unsigned int)x_move / m_scale;
2190       v = (unsigned int)y_move / m_scale;
2191       ip.set_u(u);
2192       ip.set_v(v);
2193     }
2194     return false;
2195   } else {
2196     throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
2197   }
2198 }
2199 
2200 /*!
2201   Gets screen resolution in pixels.
2202   \param w, h : Horizontal and vertical screen resolution.
2203  */
getScreenSize(unsigned int & w,unsigned int & h)2204 void vpDisplayOpenCV::getScreenSize(unsigned int &w, unsigned int &h)
2205 {
2206   w = h = 0;
2207 
2208 #if defined(VISP_HAVE_X11)
2209   vpDisplayX d;
2210   d.getScreenSize(w, h);
2211 #elif defined(VISP_HAVE_XRANDR)
2212   std::string command = "xrandr | grep '*'";
2213   FILE *fpipe = (FILE *)popen(command.c_str(), "r");
2214   char line[256];
2215   while (fgets(line, sizeof(line), fpipe)) {
2216     std::string str(line);
2217     std::size_t found = str.find("Failed");
2218 
2219     if (found == std::string::npos) {
2220       std::vector<std::string> elm;
2221       elm = vpIoTools::splitChain(str, " ");
2222       for (size_t i = 0; i < elm.size(); i++) {
2223         if (!elm[i].empty()) {
2224           std::vector<std::string> resolution = vpIoTools::splitChain(elm[i], "x");
2225           if (resolution.size() == 2) {
2226             std::istringstream sswidth(resolution[0]), ssheight(resolution[1]);
2227             sswidth >> w;
2228             ssheight >> h;
2229             break;
2230           }
2231         }
2232       }
2233     }
2234   }
2235   pclose(fpipe);
2236 #elif defined(_WIN32)
2237 #if !defined(WINRT)
2238   w = GetSystemMetrics(SM_CXSCREEN);
2239   h = GetSystemMetrics(SM_CYSCREEN);
2240 #else
2241   throw(vpException(vpException::functionNotImplementedError, "The function vpDisplayOpenCV::getScreenSize() is not "
2242                                                               "implemented on winrt"));
2243 #endif
2244 #endif
2245 }
2246 
2247 /*!
2248   Gets the screen horizontal resolution in pixels.
2249  */
getScreenWidth()2250 unsigned int vpDisplayOpenCV::getScreenWidth()
2251 {
2252   unsigned int width, height;
2253   getScreenSize(width, height);
2254   return width;
2255 }
2256 
2257 /*!
2258   Gets the screen vertical resolution in pixels.
2259  */
getScreenHeight()2260 unsigned int vpDisplayOpenCV::getScreenHeight()
2261 {
2262   unsigned int width, height;
2263   getScreenSize(width, height);
2264   return height;
2265 }
2266 
2267 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
2268 /*!
2269  * Initialize display overlay layer for transparency.
2270  * \param overlay_function : Overlay function
2271  * \param opacity : Opacity between 0 and 1.
2272  */
overlay(std::function<void (cv::Mat &)> overlay_function,double opacity)2273 void vpDisplayOpenCV::overlay(std::function<void(cv::Mat&)> overlay_function, double opacity)
2274 {
2275   // Initialize overlay layer for transparency
2276   cv::Mat overlay;
2277   if (opacity < 1.0) {
2278     // Deep copy
2279     overlay = m_background.clone();
2280   }
2281   else {
2282     // Shallow copy
2283     overlay = m_background;
2284   }
2285 
2286   overlay_function(overlay);
2287 
2288   // Blend background and overlay
2289   if (opacity < 1.0) {
2290     cv::addWeighted(overlay, opacity, m_background, 1.0 - opacity, 0.0, m_background);
2291   }
2292 }
2293 #endif
2294 
2295 #elif !defined(VISP_BUILD_SHARED_LIBS)
2296 // Work arround to avoid warning: libvisp_core.a(vpDisplayOpenCV.cpp.o) has no
2297 // symbols
dummy_vpDisplayOpenCV()2298 void dummy_vpDisplayOpenCV(){};
2299 #endif
2300