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 ¢er, 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