Visual Servoing Platform  version 3.6.1 under development (2024-04-25)
vpDisplayOpenCV.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 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 https://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 *****************************************************************************/
35 
41 #include <visp3/core/vpConfig.h>
42 
43 #if defined(HAVE_OPENCV_HIGHGUI)
44 
45 #include <cmath> // std::fabs
46 #include <iostream>
47 #include <limits> // numeric_limits
48 #include <stdio.h>
49 #include <stdlib.h>
50 
51 // Display stuff
52 #include <visp3/core/vpDisplay.h>
53 #include <visp3/core/vpImageTools.h>
54 #include <visp3/core/vpIoTools.h>
55 #include <visp3/core/vpMath.h>
56 #include <visp3/gui/vpDisplayOpenCV.h>
57 
58 // debug / exception
59 #include <visp3/core/vpDebug.h>
60 #include <visp3/core/vpDisplayException.h>
61 
62 #include <opencv2/core/core_c.h> // for CV_FILLED versus cv::FILLED
63 
64 #if defined(HAVE_OPENCV_IMGPROC)
65 #include <opencv2/imgproc/imgproc.hpp>
66 #endif
67 
68 #ifndef CV_RGB
69 #define CV_RGB(r, g, b) cv::Scalar((b), (g), (r), 0)
70 #endif
71 
72 #ifdef VISP_HAVE_X11
73 #include <visp3/gui/vpDisplayX.h> // to get screen resolution
74 #elif defined(_WIN32)
75 #include <windows.h>
76 #endif
77 
78 std::vector<std::string> vpDisplayOpenCV::m_listTitles = std::vector<std::string>();
79 unsigned int vpDisplayOpenCV::m_nbWindows = 0;
80 
103  : vpDisplay(),
104  m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
105  fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
106  x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
107  x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
108  y_rbuttonup(0), rbuttonup(false)
109 {
110  setScale(scaleType, I.getWidth(), I.getHeight());
111  init(I);
112 }
113 
137 vpDisplayOpenCV::vpDisplayOpenCV(vpImage<unsigned char> &I, int x, int y, const std::string &title,
138  vpScaleType scaleType)
139  : vpDisplay(),
140  m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
141  fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
142  x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
143  x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
144  y_rbuttonup(0), rbuttonup(false)
145 {
146  setScale(scaleType, I.getWidth(), I.getHeight());
147  init(I, x, y, title);
148 }
149 
169  :
170  m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
171  fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
172  x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
173  x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
174  y_rbuttonup(0), rbuttonup(false)
175 {
176  setScale(scaleType, I.getWidth(), I.getHeight());
177  init(I);
178 }
179 
200 vpDisplayOpenCV::vpDisplayOpenCV(vpImage<vpRGBa> &I, int x, int y, const std::string &title, vpScaleType scaleType)
201  :
202  m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
203  fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
204  x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
205  x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
206  y_rbuttonup(0), rbuttonup(false)
207 {
208  setScale(scaleType, I.getWidth(), I.getHeight());
209  init(I, x, y, title);
210 }
211 
234 vpDisplayOpenCV::vpDisplayOpenCV(int x, int y, const std::string &title)
235  :
236  m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
237  fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
238  x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
239  x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
240  y_rbuttonup(0), rbuttonup(false)
241 {
242  m_windowXPosition = x;
243  m_windowYPosition = y;
244 
245  if (!title.empty()) {
246  m_title = title;
247  }
248  else {
249  std::ostringstream s;
250  s << m_nbWindows++;
251  m_title = std::string("Window ") + s.str();
252  }
253 
254  bool isInList;
255  do {
256  isInList = false;
257  for (size_t i = 0; i < m_listTitles.size(); i++) {
258  if (m_listTitles[i] == m_title) {
259  std::ostringstream s;
260  s << m_nbWindows++;
261  m_title = std::string("Window ") + s.str();
262  isInList = true;
263  break;
264  }
265  }
266  } while (isInList);
267 
268  m_listTitles.push_back(m_title);
269 }
270 
291  :
292  m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
293  fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
294  x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
295  x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
296  y_rbuttonup(0), rbuttonup(false)
297 { }
298 
303 {
304  closeDisplay();
305 }
306 
315 void vpDisplayOpenCV::init(vpImage<unsigned char> &I, int x, int y, const std::string &title)
316 {
317  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
318  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
319  }
321  init(I.getWidth(), I.getHeight(), x, y, title);
322  I.display = this;
324 }
325 
335 void vpDisplayOpenCV::init(vpImage<vpRGBa> &I, int x, int y, const std::string &title)
336 {
337  if ((I.getHeight() == 0) || (I.getWidth() == 0)) {
338  throw(vpDisplayException(vpDisplayException::notInitializedError, "Image not initialized"));
339  }
340 
342  init(I.getWidth(), I.getHeight(), x, y, title);
343  I.display = this;
345 }
346 
357 void vpDisplayOpenCV::init(unsigned int w, unsigned int h, int x, int y, const std::string &title)
358 {
359  setScale(m_scaleType, w, h);
360 
361  this->m_width = w / m_scale;
362  this->m_height = h / m_scale;
363 
364  if (x != -1) {
365  this->m_windowXPosition = x;
366  }
367  if (y != -1) {
368  this->m_windowYPosition = y;
369  }
370  int flags = cv::WINDOW_AUTOSIZE;
371 
372  if (m_title.empty()) {
373  if (!title.empty()) {
374  m_title = std::string(title);
375  }
376  else {
377 
378  std::ostringstream s;
379  s << m_nbWindows++;
380  m_title = std::string("Window ") + s.str();
381  }
382 
383  bool isInList;
384  do {
385  isInList = false;
386  for (size_t i = 0; i < m_listTitles.size(); i++) {
387  if (m_listTitles[i] == m_title) {
388  std::ostringstream s;
389  s << m_nbWindows++;
390  m_title = std::string("Window ") + s.str();
391  isInList = true;
392  break;
393  }
394  }
395  } while (isInList);
396 
397  m_listTitles.push_back(m_title);
398  }
399 
400  /* Create the window*/
401  cv::namedWindow(this->m_title, flags);
402  cv::moveWindow(this->m_title.c_str(), this->m_windowXPosition, this->m_windowYPosition);
403 
404  move = false;
405  lbuttondown = false;
406  mbuttondown = false;
407  rbuttondown = false;
408  lbuttonup = false;
409  mbuttonup = false;
410  rbuttonup = false;
411 
412  cv::setMouseCallback(this->m_title, on_mouse, this);
413  col = new cv::Scalar[vpColor::id_unknown];
414 
415  /* Create color */
416  vpColor pcolor; // Predefined colors
417  pcolor = vpColor::lightBlue;
418  col[vpColor::id_lightBlue] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
419  pcolor = vpColor::blue;
420  col[vpColor::id_blue] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
421  pcolor = vpColor::darkBlue;
422  col[vpColor::id_darkBlue] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
423  pcolor = vpColor::lightRed;
424  col[vpColor::id_lightRed] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
425  pcolor = vpColor::red;
426  col[vpColor::id_red] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
427  pcolor = vpColor::darkRed;
428  col[vpColor::id_darkRed] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
429  pcolor = vpColor::lightGreen;
430  col[vpColor::id_lightGreen] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
431  pcolor = vpColor::green;
432  col[vpColor::id_green] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
433  pcolor = vpColor::darkGreen;
434  col[vpColor::id_darkGreen] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
435  pcolor = vpColor::yellow;
436  col[vpColor::id_yellow] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
437  pcolor = vpColor::cyan;
438  col[vpColor::id_cyan] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
439  pcolor = vpColor::orange;
440  col[vpColor::id_orange] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
441  pcolor = vpColor::purple;
442  col[vpColor::id_purple] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
443  pcolor = vpColor::white;
444  col[vpColor::id_white] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
445  pcolor = vpColor::black;
446  col[vpColor::id_black] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
447  pcolor = vpColor::lightGray;
448  col[vpColor::id_lightGray] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
449  pcolor = vpColor::gray;
450  col[vpColor::id_gray] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
451  pcolor = vpColor::darkGray;
452  col[vpColor::id_darkGray] = CV_RGB(pcolor.R, pcolor.G, pcolor.B);
453 
454  int thickness = 1;
455  cv::Size fontSize;
456  int baseline;
457  fontSize = cv::getTextSize("A", font, fontScale, thickness, &baseline);
458 
459  fontHeight = fontSize.height + baseline;
461 }
462 
478 void vpDisplayOpenCV::setFont(const std::string & /* font */) { vpERROR_TRACE("Not yet implemented"); }
479 
487 void vpDisplayOpenCV::setTitle(const std::string & /* title */)
488 {
489  // static bool warn_displayed = false;
490  // if (! warn_displayed) {
491  // vpTRACE("Not implemented");
492  // warn_displayed = true;
493  // }
494 }
495 
505 void vpDisplayOpenCV::setWindowPosition(int winx, int winy)
506 {
508  this->m_windowXPosition = winx;
509  this->m_windowYPosition = winy;
510  cv::moveWindow(this->m_title.c_str(), winx, winy);
511  }
512  else {
513  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
514  }
515 }
528 {
530  int depth = CV_8U;
531  int channels = 3;
532  cv::Size size((int)m_width, (int)m_height);
533  if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
534  m_background.cols != (int)m_width) {
535  m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
536  }
537 
538  if (m_scale == 1) {
539  for (unsigned int i = 0; i < m_height; i++) {
540  unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
541  for (unsigned int j = 0; j < m_width; j++) {
542  unsigned char val = I[i][j];
543  *(dst_24++) = val;
544  *(dst_24++) = val;
545  *(dst_24++) = val;
546  }
547  }
548  }
549  else {
550  for (unsigned int i = 0; i < m_height; i++) {
551  unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
552  for (unsigned int j = 0; j < m_width; j++) {
553  unsigned char val = I[i * m_scale][j * m_scale];
554  *(dst_24++) = val;
555  *(dst_24++) = val;
556  *(dst_24++) = val;
557  }
558  }
559  }
560  }
561  else {
562  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
563  }
564 }
565 
582  unsigned int h)
583 {
585  int depth = CV_8U;
586  int channels = 3;
587  cv::Size size((int)m_width, (int)m_height);
588  if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
589  m_background.cols != (int)m_width) {
590  m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
591  }
592 
593  if (m_scale == 1) {
594  unsigned int i_min = (unsigned int)iP.get_i();
595  unsigned int j_min = (unsigned int)iP.get_j();
596  unsigned int i_max = std::min<unsigned int>(i_min + h, m_height);
597  unsigned int j_max = std::min<unsigned int>(j_min + w, m_width);
598  for (unsigned int i = i_min; i < i_max; i++) {
599  unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
600  for (unsigned int j = j_min; j < j_max; j++) {
601  unsigned char val = I[i][j];
602  *(dst_24++) = val;
603  *(dst_24++) = val;
604  *(dst_24++) = val;
605  }
606  }
607  }
608  else {
609  int i_min = std::max<int>((int)ceil(iP.get_i() / m_scale), 0);
610  int j_min = std::max<int>((int)ceil(iP.get_j() / m_scale), 0);
611  int i_max = std::min<int>((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
612  int j_max = std::min<int>((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
613  for (int i = i_min; i < i_max; i++) {
614  unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
615  for (int j = j_min; j < j_max; 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  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
626  }
627 }
628 
641 {
642 
644  int depth = CV_8U;
645  int channels = 3;
646  cv::Size size((int)this->m_width, (int)this->m_height);
647  if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
648  m_background.cols != (int)m_width) {
649  m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
650  }
651 
652  if (m_scale == 1) {
653  for (unsigned int i = 0; i < m_height; i++) {
654  unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
655  for (unsigned int j = 0; j < m_width; j++) {
656  vpRGBa val = I[i][j];
657  *(dst_24++) = val.B;
658  *(dst_24++) = val.G;
659  *(dst_24++) = val.R;
660  }
661  }
662  }
663  else {
664  for (unsigned int i = 0; i < m_height; i++) {
665  unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width);
666  for (unsigned int j = 0; j < m_width; j++) {
667  vpRGBa val = I[i * m_scale][j * m_scale];
668  *(dst_24++) = val.B;
669  *(dst_24++) = val.G;
670  *(dst_24++) = val.R;
671  }
672  }
673  }
674  }
675  else {
676  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
677  }
678 }
679 
695 void vpDisplayOpenCV::displayImageROI(const vpImage<vpRGBa> &I, const vpImagePoint &iP, unsigned int w, unsigned int h)
696 {
698  int depth = CV_8U;
699  int channels = 3;
700  cv::Size size((int)this->m_width, (int)this->m_height);
701  if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (int)m_height ||
702  m_background.cols != (int)m_width) {
703  m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
704  }
705 
706  if (m_scale == 1) {
707  unsigned int i_min = (unsigned int)iP.get_i();
708  unsigned int j_min = (unsigned int)iP.get_j();
709  unsigned int i_max = std::min<unsigned int>(i_min + h, m_height);
710  unsigned int j_max = std::min<unsigned int>(j_min + w, m_width);
711  for (unsigned int i = i_min; i < i_max; i++) {
712  unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
713  for (unsigned int j = j_min; j < j_max; j++) {
714  vpRGBa val = I[i][j];
715  *(dst_24++) = val.B;
716  *(dst_24++) = val.G;
717  *(dst_24++) = val.R;
718  }
719  }
720  }
721  else {
722  int i_min = std::max<int>((int)ceil(iP.get_i() / m_scale), 0);
723  int j_min = std::max<int>((int)ceil(iP.get_j() / m_scale), 0);
724  int i_max = std::min<int>((int)ceil((iP.get_i() + h) / m_scale), (int)m_height);
725  int j_max = std::min<int>((int)ceil((iP.get_j() + w) / m_scale), (int)m_width);
726  for (int i = i_min; i < i_max; i++) {
727  unsigned char *dst_24 = (unsigned char *)m_background.data + (int)(i * 3 * m_width + j_min * 3);
728  for (int j = j_min; j < j_max; j++) {
729  vpRGBa val = I[i * m_scale][j * m_scale];
730  *(dst_24++) = val.B;
731  *(dst_24++) = val.G;
732  *(dst_24++) = val.R;
733  }
734  }
735  }
736  }
737  else {
738  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
739  }
740 }
741 
747 void vpDisplayOpenCV::displayImage(const unsigned char * /* I */) { vpTRACE(" not implemented "); }
748 
757 {
758  if (col != nullptr) {
759  delete[] col;
760  col = nullptr;
761  }
763  cv::destroyWindow(this->m_title);
764  for (size_t i = 0; i < m_listTitles.size(); i++) {
765  if (m_title == m_listTitles[i]) {
766  m_listTitles.erase(m_listTitles.begin() + (long int)i);
767  break;
768  }
769  }
770 
771  m_title.clear();
772 
774  }
775 }
776 
783 {
785  cv::imshow(this->m_title, m_background);
786  cv::waitKey(5);
787  }
788  else {
789  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
790  }
791 }
792 
798 void vpDisplayOpenCV::flushDisplayROI(const vpImagePoint & /*iP*/, const unsigned int /*width*/,
799  const unsigned int /*height*/)
800 {
802  cv::imshow(this->m_title.c_str(), m_background);
803  cv::waitKey(5);
804  }
805  else {
806  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
807  }
808 }
809 
813 void vpDisplayOpenCV::clearDisplay(const vpColor & /* color */)
814 {
815  static bool warn_displayed = false;
816  if (!warn_displayed) {
817  vpTRACE("Not implemented");
818  warn_displayed = true;
819  }
820 }
821 
829 void vpDisplayOpenCV::displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
830  unsigned int w, unsigned int h, unsigned int thickness)
831 {
833  double a = ip2.get_i() - ip1.get_i();
834  double b = ip2.get_j() - ip1.get_j();
835  double lg = sqrt(vpMath::sqr(a) + vpMath::sqr(b));
836 
837  // if ((a==0)&&(b==0))
838  if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
839  (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
840  // DisplayCrossLarge(i1,j1,3,col) ;
841  }
842  else {
843  a /= lg;
844  b /= lg;
845 
846  vpImagePoint ip3;
847  ip3.set_i(ip2.get_i() - w * a);
848  ip3.set_j(ip2.get_j() - w * b);
849 
850  vpImagePoint ip4;
851  ip4.set_i(ip3.get_i() - b * h);
852  ip4.set_j(ip3.get_j() + a * h);
853 
854  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
855  displayLine(ip2, ip4, color, thickness);
856 
857  ip4.set_i(ip3.get_i() + b * h);
858  ip4.set_j(ip3.get_j() - a * h);
859 
860  if (lg > 2 * vpImagePoint::distance(ip2, ip4))
861  displayLine(ip2, ip4, color, thickness);
862 
863  displayLine(ip1, ip2, color, thickness);
864  }
865  }
866  else {
867  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
868  }
869 }
870 
882 void vpDisplayOpenCV::displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color)
883 {
885  if (color.id < vpColor::id_unknown) {
886  cv::putText(m_background, text,
887  cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale + fontHeight)),
888  font, fontScale, col[color.id]);
889  }
890  else {
891  cvcolor = CV_RGB(color.R, color.G, color.B);
892  cv::putText(m_background, text,
893  cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale + fontHeight)),
894  font, fontScale, cvcolor);
895  }
896  }
897  else {
898  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
899  }
900 }
913 void vpDisplayOpenCV::displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill,
914  unsigned int thickness)
915 {
917  int x = vpMath::round(center.get_u() / m_scale);
918  int y = vpMath::round(center.get_v() / m_scale);
919  int r = static_cast<int>(radius / m_scale);
920  cv::Scalar cv_color;
921  if (color.id < vpColor::id_unknown) {
922  cv_color = col[color.id];
923  }
924  else {
925  cv_color = CV_RGB(color.R, color.G, color.B);
926  }
927 
928  if (fill == false) {
929  int cv_thickness = static_cast<int>(thickness);
930  cv::circle(m_background, cv::Point(x, y), r, cv_color, cv_thickness);
931  }
932  else {
933 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
934  int filled = cv::FILLED;
935 #else
936  int filled = CV_FILLED;
937 #endif
938  double opacity = static_cast<double>(color.A) / 255.0;
939  overlay([x, y, r, cv_color, filled](cv::Mat image) { cv::circle(image, cv::Point(x, y), r, cv_color, filled); },
940  opacity);
941  }
942  }
943  else {
944  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
945  }
946 }
947 
955 void vpDisplayOpenCV::displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color,
956  unsigned int thickness)
957 {
959  vpImagePoint top, bottom, left, right;
960  top.set_i(ip.get_i() - size / 2);
961  top.set_j(ip.get_j());
962  bottom.set_i(ip.get_i() + size / 2);
963  bottom.set_j(ip.get_j());
964  left.set_i(ip.get_i());
965  left.set_j(ip.get_j() - size / 2);
966  right.set_i(ip.get_i());
967  right.set_j(ip.get_j() + size / 2);
968  displayLine(top, bottom, color, thickness);
969  displayLine(left, right, color, thickness);
970  }
971  else {
972  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
973  }
974 }
975 
983 void vpDisplayOpenCV::displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
984  unsigned int thickness)
985 {
987  vpImagePoint ip1_ = ip1;
988  vpImagePoint ip2_ = ip2;
989 
990  double size = 10. * m_scale;
991  double length = sqrt(vpMath::sqr(ip2_.get_i() - ip1_.get_i()) + vpMath::sqr(ip2_.get_j() - ip1_.get_j()));
992  bool vertical_line = (int)ip2_.get_j() == (int)ip1_.get_j();
993  if (vertical_line) {
994  if (ip2_.get_i() < ip1_.get_i()) {
995  std::swap(ip1_, ip2_);
996  }
997  }
998  else if (ip2_.get_j() < ip1_.get_j()) {
999  std::swap(ip1_, ip2_);
1000  }
1001 
1002  double diff_j = vertical_line ? 1 : ip2_.get_j() - ip1_.get_j();
1003  double deltaj = size / length * diff_j;
1004  double deltai = size / length * (ip2_.get_i() - ip1_.get_i());
1005  double slope = (ip2_.get_i() - ip1_.get_i()) / diff_j;
1006  double orig = ip1_.get_i() - slope * ip1_.get_j();
1007 
1008  if (vertical_line) {
1009  for (unsigned int i = (unsigned int)ip1_.get_i(); i < ip2_.get_i(); i += (unsigned int)(2 * deltai)) {
1010  double j = ip1_.get_j();
1011  displayLine(vpImagePoint(i, j), vpImagePoint(i + deltai, j), color, thickness);
1012  }
1013  }
1014  else {
1015  for (unsigned int j = (unsigned int)ip1_.get_j(); j < ip2_.get_j(); j += (unsigned int)(2 * deltaj)) {
1016  double i = slope * j + orig;
1017  displayLine(vpImagePoint(i, j), vpImagePoint(i + deltai, j + deltaj), color, thickness);
1018  }
1019  }
1020  }
1021  else {
1022  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1023  }
1024 }
1025 
1032 void vpDisplayOpenCV::displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color,
1033  unsigned int thickness)
1034 {
1036  if (color.id < vpColor::id_unknown) {
1037  cv::line(m_background, cv::Point(vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale)),
1038  cv::Point(vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale)), col[color.id],
1039  (int)thickness);
1040  }
1041  else {
1042  cvcolor = CV_RGB(color.R, color.G, color.B);
1043  cv::line(m_background, cv::Point(vpMath::round(ip1.get_u() / m_scale), vpMath::round(ip1.get_v() / m_scale)),
1044  cv::Point(vpMath::round(ip2.get_u() / m_scale), vpMath::round(ip2.get_v() / m_scale)), cvcolor,
1045  (int)thickness);
1046  }
1047  }
1048  else {
1049  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1050  }
1051 }
1052 
1059 void vpDisplayOpenCV::displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness)
1060 {
1062  for (unsigned int i = 0; i < thickness; i++) {
1063  if (color.id < vpColor::id_unknown) {
1064  cv::line(m_background, cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale)),
1065  cv::Point(vpMath::round(ip.get_u() / m_scale + thickness - 1), vpMath::round(ip.get_v() / m_scale)),
1066  col[color.id], (int)thickness);
1067  }
1068  else {
1069  cvcolor = CV_RGB(color.R, color.G, color.B);
1070  cv::line(m_background, cv::Point(vpMath::round(ip.get_u() / m_scale), vpMath::round(ip.get_v() / m_scale)),
1071  cv::Point(vpMath::round(ip.get_u() / m_scale + thickness - 1), vpMath::round(ip.get_v() / m_scale)),
1072  cvcolor, (int)thickness);
1073  }
1074  }
1075  }
1076  else {
1077  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1078  }
1079 }
1080 
1096 void vpDisplayOpenCV::displayRectangle(const vpImagePoint &topLeft, unsigned int w, unsigned int h,
1097  const vpColor &color, bool fill, unsigned int thickness)
1098 {
1100  int left = vpMath::round(topLeft.get_u() / m_scale);
1101  int top = vpMath::round(topLeft.get_v() / m_scale);
1102  int right = vpMath::round((topLeft.get_u() + w) / m_scale);
1103  int bottom = vpMath::round((topLeft.get_v() + h) / m_scale);
1104  cv::Scalar cv_color;
1105  if (color.id < vpColor::id_unknown) {
1106  cv_color = col[color.id];
1107  }
1108  else {
1109  cv_color = CV_RGB(color.R, color.G, color.B);
1110  }
1111 
1112  if (fill == false) {
1113  int cv_thickness = static_cast<int>(thickness);
1114  cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, cv_thickness);
1115  }
1116  else {
1117 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
1118  int filled = cv::FILLED;
1119 #else
1120  int filled = CV_FILLED;
1121 #endif
1122  double opacity = static_cast<double>(color.A) / 255.0;
1123  overlay([left, top, right, bottom, cv_color, filled](cv::Mat image) {
1124  cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1125  },
1126  opacity);
1127  }
1128  }
1129  else {
1130  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1131  }
1132 }
1147 void vpDisplayOpenCV::displayRectangle(const vpImagePoint &topLeft, const vpImagePoint &bottomRight,
1148  const vpColor &color, bool fill, unsigned int thickness)
1149 {
1151  int left = vpMath::round(topLeft.get_u() / m_scale);
1152  int top = vpMath::round(topLeft.get_v() / m_scale);
1153  int right = vpMath::round(bottomRight.get_u() / m_scale);
1154  int bottom = vpMath::round(bottomRight.get_v() / m_scale);
1155  cv::Scalar cv_color;
1156  if (color.id < vpColor::id_unknown) {
1157  cv_color = col[color.id];
1158  }
1159  else {
1160  cv_color = CV_RGB(color.R, color.G, color.B);
1161  }
1162 
1163  if (fill == false) {
1164  int cv_thickness = static_cast<int>(thickness);
1165  cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, cv_thickness);
1166  }
1167  else {
1168 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
1169  int filled = cv::FILLED;
1170 #else
1171  int filled = CV_FILLED;
1172 #endif
1173  double opacity = static_cast<double>(color.A) / 255.0;
1174  overlay([left, top, right, bottom, cv_color, filled](cv::Mat image) {
1175  cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1176  },
1177  opacity);
1178  }
1179  }
1180  else {
1181  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1182  }
1183 }
1184 
1198 void vpDisplayOpenCV::displayRectangle(const vpRect &rectangle, const vpColor &color, bool fill, unsigned int thickness)
1199 {
1201  int left = vpMath::round(rectangle.getLeft() / m_scale);
1202  int top = vpMath::round(rectangle.getTop() / m_scale);
1203  int right = vpMath::round(rectangle.getRight() / m_scale);
1204  int bottom = vpMath::round(rectangle.getBottom() / m_scale);
1205  cv::Scalar cv_color;
1206  if (color.id < vpColor::id_unknown) {
1207  cv_color = col[color.id];
1208  }
1209  else {
1210  cv_color = CV_RGB(color.R, color.G, color.B);
1211  }
1212 
1213  if (fill == false) {
1214  int cv_thickness = static_cast<int>(thickness);
1215  cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, cv_thickness);
1216  }
1217  else {
1218 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
1219  int filled = cv::FILLED;
1220 #else
1221  int filled = CV_FILLED;
1222 #endif
1223  double opacity = static_cast<double>(color.A) / 255.0;
1224  overlay([left, top, right, bottom, cv_color, filled](cv::Mat image) {
1225  cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
1226  },
1227  opacity);
1228  }
1229  }
1230  else {
1231  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1232  }
1233 }
1234 
1250 bool vpDisplayOpenCV::getClick(bool blocking)
1251 {
1252  bool ret = false;
1254  flushDisplay();
1255  if (blocking) {
1256  lbuttondown = false;
1257  mbuttondown = false;
1258  rbuttondown = false;
1259  }
1260  do {
1261  if (lbuttondown) {
1262  ret = true;
1263  lbuttondown = false;
1264  }
1265  if (mbuttondown) {
1266  ret = true;
1267  mbuttondown = false;
1268  }
1269  if (rbuttondown) {
1270  ret = true;
1271  rbuttondown = false;
1272  }
1273  if (blocking) {
1274  cv::waitKey(10);
1275  }
1276  } while (ret == false && blocking == true);
1277  }
1278  else {
1279  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1280  }
1281  return ret;
1282 }
1283 
1299 bool vpDisplayOpenCV::getClick(vpImagePoint &ip, bool blocking)
1300 {
1301  bool ret = false;
1302 
1304  flushDisplay();
1305 
1306  double u, v;
1307 
1308  if (blocking) {
1309  lbuttondown = false;
1310  mbuttondown = false;
1311  rbuttondown = false;
1312  }
1313  do {
1314  if (lbuttondown) {
1315  ret = true;
1316  u = (unsigned int)x_lbuttondown * m_scale;
1317  v = (unsigned int)y_lbuttondown * m_scale;
1318  ip.set_u(u);
1319  ip.set_v(v);
1320  lbuttondown = false;
1321  }
1322  if (mbuttondown) {
1323  ret = true;
1324  u = (unsigned int)x_mbuttondown * m_scale;
1325  v = (unsigned int)y_mbuttondown * m_scale;
1326  ip.set_u(u);
1327  ip.set_v(v);
1328  mbuttondown = false;
1329  }
1330  if (rbuttondown) {
1331  ret = true;
1332  u = (unsigned int)x_rbuttondown * m_scale;
1333  v = (unsigned int)y_rbuttondown * m_scale;
1334  ip.set_u(u);
1335  ip.set_v(v);
1336  rbuttondown = false;
1337  }
1338  if (blocking) {
1339  cv::waitKey(10);
1340  }
1341  } while (ret == false && blocking == true);
1342  }
1343  else {
1344  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1345  }
1346  return ret;
1347 }
1348 
1368 {
1369  bool ret = false;
1370 
1372  // flushDisplay() ;
1373  double u, v;
1374  if (blocking) {
1375  lbuttondown = false;
1376  mbuttondown = false;
1377  rbuttondown = false;
1378  }
1379  do {
1380  if (lbuttondown) {
1381  ret = true;
1382  u = (unsigned int)x_lbuttondown * m_scale;
1383  v = (unsigned int)y_lbuttondown * m_scale;
1384  ip.set_u(u);
1385  ip.set_v(v);
1386  button = vpMouseButton::button1;
1387  lbuttondown = false;
1388  }
1389  if (mbuttondown) {
1390  ret = true;
1391  u = (unsigned int)x_mbuttondown * m_scale;
1392  v = (unsigned int)y_mbuttondown * m_scale;
1393  ip.set_u(u);
1394  ip.set_v(v);
1395  button = vpMouseButton::button2;
1396  mbuttondown = false;
1397  }
1398  if (rbuttondown) {
1399  ret = true;
1400  u = (unsigned int)x_rbuttondown * m_scale;
1401  v = (unsigned int)y_rbuttondown * m_scale;
1402  ip.set_u(u);
1403  ip.set_v(v);
1404  button = vpMouseButton::button3;
1405  rbuttondown = false;
1406  }
1407  if (blocking) {
1408  cv::waitKey(10);
1409  }
1410  } while (ret == false && blocking == true);
1411  }
1412  else {
1413  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1414  }
1415  return ret;
1416 }
1417 
1440 {
1441  bool ret = false;
1443  // flushDisplay() ;
1444  double u, v;
1445  if (blocking) {
1446  lbuttonup = false;
1447  mbuttonup = false;
1448  rbuttonup = false;
1449  }
1450  do {
1451  if (lbuttonup) {
1452  ret = true;
1453  u = (unsigned int)x_lbuttonup * m_scale;
1454  v = (unsigned int)y_lbuttonup * m_scale;
1455  ip.set_u(u);
1456  ip.set_v(v);
1457  button = vpMouseButton::button1;
1458  lbuttonup = false;
1459  }
1460  if (mbuttonup) {
1461  ret = true;
1462  u = (unsigned int)x_mbuttonup * m_scale;
1463  v = (unsigned int)y_mbuttonup * m_scale;
1464  ip.set_u(u);
1465  ip.set_v(v);
1466  button = vpMouseButton::button2;
1467  mbuttonup = false;
1468  }
1469  if (rbuttonup) {
1470  ret = true;
1471  u = (unsigned int)x_rbuttonup * m_scale;
1472  v = (unsigned int)y_rbuttonup * m_scale;
1473  ip.set_u(u);
1474  ip.set_v(v);
1475  button = vpMouseButton::button3;
1476  rbuttonup = false;
1477  }
1478  if (blocking) {
1479  cv::waitKey(10);
1480  }
1481  } while (ret == false && blocking == true);
1482  }
1483  else {
1484  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1485  }
1486  return ret;
1487 }
1488 
1489 /*
1490  Gets the displayed image (including the overlay plane)
1491  and returns an RGBa image.
1492 */
1494 {
1495  vpImageConvert::convert(m_background, I);
1496  // should certainly be optimized.
1497 }
1498 
1499 void vpDisplayOpenCV::on_mouse(int event, int x, int y, int /*flags*/, void *display)
1500 {
1501  vpDisplayOpenCV *disp = static_cast<vpDisplayOpenCV *>(display);
1502  switch (event) {
1503  case cv::EVENT_MOUSEMOVE:
1504  {
1505  disp->move = true;
1506  disp->x_move = x;
1507  disp->y_move = y;
1508  break;
1509  }
1510  case cv::EVENT_LBUTTONDOWN:
1511  {
1512  disp->lbuttondown = true;
1513  disp->x_lbuttondown = x;
1514  disp->y_lbuttondown = y;
1515  break;
1516  }
1517  case cv::EVENT_MBUTTONDOWN:
1518  {
1519  disp->mbuttondown = true;
1520  disp->x_mbuttondown = x;
1521  disp->y_mbuttondown = y;
1522  break;
1523  }
1524  case cv::EVENT_RBUTTONDOWN:
1525  {
1526  disp->rbuttondown = true;
1527  disp->x_rbuttondown = x;
1528  disp->y_rbuttondown = y;
1529  break;
1530  }
1531  case cv::EVENT_LBUTTONUP:
1532  {
1533  disp->lbuttonup = true;
1534  disp->x_lbuttonup = x;
1535  disp->y_lbuttonup = y;
1536  break;
1537  }
1538  case cv::EVENT_MBUTTONUP:
1539  {
1540  disp->mbuttonup = true;
1541  disp->x_mbuttonup = x;
1542  disp->y_mbuttonup = y;
1543  break;
1544  }
1545  case cv::EVENT_RBUTTONUP:
1546  {
1547  disp->rbuttonup = true;
1548  disp->x_rbuttonup = x;
1549  disp->y_rbuttonup = y;
1550  break;
1551  }
1552 
1553  default:
1554  break;
1555  }
1556 }
1557 
1574 {
1576  int delay;
1577  flushDisplay();
1578  if (blocking)
1579  delay = 0;
1580  else
1581  delay = 10;
1582 
1583  int key_pressed = cv::waitKey(delay);
1584 
1585  if (key_pressed == -1)
1586  return false;
1587  return true;
1588  }
1589  else {
1590  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1591  }
1592  // return false; // Never reached after throw()
1593 }
1612 bool vpDisplayOpenCV::getKeyboardEvent(std::string &key, bool blocking)
1613 {
1615  int delay;
1616  flushDisplay();
1617  if (blocking)
1618  delay = 0;
1619  else
1620  delay = 10;
1621 
1622  int key_pressed = cv::waitKey(delay);
1623  if (key_pressed == -1)
1624  return false;
1625  else {
1626  // std::cout << "Key pressed: \"" << key_pressed << "\"" << std::endl;
1627  std::stringstream ss;
1628  ss << key_pressed;
1629  key = ss.str();
1630  }
1631  return true;
1632  }
1633  else {
1634  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1635  }
1636  // return false; // Never reached after throw()
1637 }
1638 
1650 {
1651  bool ret = false;
1652 
1654  // flushDisplay() ;
1655  if (move) {
1656  ret = true;
1657  double u = (unsigned int)x_move / m_scale;
1658  double v = (unsigned int)y_move / m_scale;
1659  ip.set_u(u);
1660  ip.set_v(v);
1661  move = false;
1662  }
1663  }
1664 
1665  else {
1666  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1667  }
1668  return ret;
1669 }
1670 
1682 {
1684  bool moved = getPointerMotionEvent(ip);
1685  if (!moved) {
1686  double u, v;
1687  u = (unsigned int)x_move / m_scale;
1688  v = (unsigned int)y_move / m_scale;
1689  ip.set_u(u);
1690  ip.set_v(v);
1691  }
1692  return false;
1693  }
1694  else {
1695  throw(vpDisplayException(vpDisplayException::notInitializedError, "OpenCV not initialized"));
1696  }
1697 }
1698 
1703 void vpDisplayOpenCV::getScreenSize(unsigned int &w, unsigned int &h)
1704 {
1705  w = h = 0;
1706 
1707 #if defined(VISP_HAVE_X11)
1708  vpDisplayX d;
1709  d.getScreenSize(w, h);
1710 #elif defined(VISP_HAVE_XRANDR)
1711  std::string command = "xrandr | grep '*'";
1712  FILE *fpipe = (FILE *)popen(command.c_str(), "r");
1713  char line[256];
1714  while (fgets(line, sizeof(line), fpipe)) {
1715  std::string str(line);
1716  std::size_t found = str.find("Failed");
1717 
1718  if (found == std::string::npos) {
1719  std::vector<std::string> elm;
1720  elm = vpIoTools::splitChain(str, " ");
1721  for (size_t i = 0; i < elm.size(); i++) {
1722  if (!elm[i].empty()) {
1723  std::vector<std::string> resolution = vpIoTools::splitChain(elm[i], "x");
1724  if (resolution.size() == 2) {
1725  std::istringstream sswidth(resolution[0]), ssheight(resolution[1]);
1726  sswidth >> w;
1727  ssheight >> h;
1728  break;
1729  }
1730  }
1731  }
1732  }
1733  }
1734  pclose(fpipe);
1735 #elif defined(_WIN32)
1736 #if !defined(WINRT)
1737  w = GetSystemMetrics(SM_CXSCREEN);
1738  h = GetSystemMetrics(SM_CYSCREEN);
1739 #else
1740  throw(vpException(vpException::functionNotImplementedError, "The function vpDisplayOpenCV::getScreenSize() is not "
1741  "implemented on winrt"));
1742 #endif
1743 #endif
1744 }
1745 
1750 {
1751  unsigned int width, height;
1752  getScreenSize(width, height);
1753  return width;
1754 }
1755 
1760 {
1761  unsigned int width, height;
1762  getScreenSize(width, height);
1763  return height;
1764 }
1765 
1771 void vpDisplayOpenCV::overlay(std::function<void(cv::Mat &)> overlay_function, double opacity)
1772 {
1773  // Initialize overlay layer for transparency
1774  cv::Mat overlay;
1775  if (opacity < 1.0) {
1776  // Deep copy
1777  overlay = m_background.clone();
1778  }
1779  else {
1780  // Shallow copy
1781  overlay = m_background;
1782  }
1783 
1784  overlay_function(overlay);
1785 
1786  // Blend background and overlay
1787  if (opacity < 1.0) {
1788  cv::addWeighted(overlay, opacity, m_background, 1.0 - opacity, 0.0, m_background);
1789  }
1790 }
1791 
1792 #elif !defined(VISP_BUILD_SHARED_LIBS)
1793 // Work around to avoid warning: libvisp_core.a(vpDisplayOpenCV.cpp.o) has no symbols
1794 void dummy_vpDisplayOpenCV() { };
1795 #endif
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:152
static const vpColor white
Definition: vpColor.h:206
vpColorIdentifier id
Definition: vpColor.h:200
static const vpColor red
Definition: vpColor.h:211
static const vpColor darkGray
Definition: vpColor.h:209
static const vpColor black
Definition: vpColor.h:205
static const vpColor cyan
Definition: vpColor.h:220
static const vpColor orange
Definition: vpColor.h:221
static const vpColor darkRed
Definition: vpColor.h:212
static const vpColor blue
Definition: vpColor.h:217
static const vpColor lightGray
Definition: vpColor.h:207
static const vpColor lightBlue
Definition: vpColor.h:216
static const vpColor darkGreen
Definition: vpColor.h:215
static const vpColor darkBlue
Definition: vpColor.h:218
static const vpColor purple
Definition: vpColor.h:222
static const vpColor lightGreen
Definition: vpColor.h:213
static const vpColor yellow
Definition: vpColor.h:219
@ id_lightBlue
Definition: vpColor.h:178
@ id_yellow
Definition: vpColor.h:184
@ id_darkGray
Definition: vpColor.h:164
@ id_green
Definition: vpColor.h:174
@ id_darkRed
Definition: vpColor.h:170
@ id_lightGray
Definition: vpColor.h:160
@ id_red
Definition: vpColor.h:168
@ id_lightRed
Definition: vpColor.h:166
@ id_white
Definition: vpColor.h:158
@ id_black
Definition: vpColor.h:156
@ id_blue
Definition: vpColor.h:180
@ id_darkGreen
Definition: vpColor.h:176
@ id_gray
Definition: vpColor.h:162
@ id_lightGreen
Definition: vpColor.h:172
@ id_purple
Definition: vpColor.h:190
@ id_orange
Definition: vpColor.h:188
@ id_cyan
Definition: vpColor.h:186
@ id_darkBlue
Definition: vpColor.h:182
@ id_unknown
Definition: vpColor.h:193
static const vpColor lightRed
Definition: vpColor.h:210
static const vpColor green
Definition: vpColor.h:214
static const vpColor gray
Definition: vpColor.h:208
Error that can be emitted by the vpDisplay class and its derivatives.
@ notInitializedError
Display not initialized.
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
void setTitle(const std::string &title) vp_override
void displayArrow(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1) vp_override
void overlay(std::function< void(cv::Mat &)> overlay_function, double opacity)
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height) vp_override
unsigned int getScreenHeight() vp_override
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1) vp_override
void displayImage(const vpImage< unsigned char > &I) vp_override
bool getKeyboardEvent(bool blocking=true) vp_override
void closeDisplay() vp_override
void displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1) vp_override
void setFont(const std::string &font) vp_override
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="") vp_override
void displayText(const vpImagePoint &ip, const std::string &text, const vpColor &color=vpColor::green) vp_override
virtual ~vpDisplayOpenCV() vp_override
unsigned int getScreenWidth() vp_override
void getScreenSize(unsigned int &width, unsigned int &height) vp_override
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) vp_override
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) vp_override
static void on_mouse(int event, int x, int y, int flags, void *param)
bool getClick(bool blocking=true) vp_override
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1) vp_override
bool getPointerMotionEvent(vpImagePoint &ip) vp_override
void setWindowPosition(int winx, int winy) vp_override
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height) vp_override
bool getPointerPosition(vpImagePoint &ip) vp_override
void getImage(vpImage< vpRGBa > &I) vp_override
Get the window pixmap and put it in vpRGBa image.
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true) vp_override
void displayCircle(const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1) vp_override
void clearDisplay(const vpColor &color=vpColor::white) vp_override
void flushDisplay() vp_override
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:128
void getScreenSize(unsigned int &width, unsigned int &height) vp_override
Class that defines generic functionalities for display.
Definition: vpDisplay.h:173
unsigned int m_height
Definition: vpDisplay.h:212
vpScaleType m_scaleType
Definition: vpDisplay.h:215
unsigned int m_width
Definition: vpDisplay.h:211
static void display(const vpImage< unsigned char > &I)
int m_windowXPosition
display position
Definition: vpDisplay.h:208
std::string m_title
Definition: vpDisplay.h:213
int m_windowYPosition
display position
Definition: vpDisplay.h:210
unsigned int m_scale
Definition: vpDisplay.h:214
bool m_displayHasBeenInitialized
display has been initialized
Definition: vpDisplay.h:206
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
Definition: vpDisplay.cpp:256
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ functionNotImplementedError
Function not implemented.
Definition: vpException.h:78
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
void set_j(double jj)
Definition: vpImagePoint.h:304
double get_j() const
Definition: vpImagePoint.h:125
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
void set_i(double ii)
Definition: vpImagePoint.h:293
double get_u() const
Definition: vpImagePoint.h:136
void set_u(double u)
Definition: vpImagePoint.h:330
void set_v(double v)
Definition: vpImagePoint.h:341
double get_i() const
Definition: vpImagePoint.h:114
double get_v() const
Definition: vpImagePoint.h:147
unsigned int getWidth() const
Definition: vpImage.h:245
unsigned int getHeight() const
Definition: vpImage.h:184
vpDisplay * display
Definition: vpImage.h:140
static std::vector< std::string > splitChain(const std::string &chain, const std::string &sep)
Definition: vpIoTools.cpp:2425
static double sqr(double x)
Definition: vpMath.h:201
static int round(double x)
Definition: vpMath.h:403
Definition: vpRGBa.h:61
unsigned char B
Blue component.
Definition: vpRGBa.h:139
unsigned char R
Red component.
Definition: vpRGBa.h:137
unsigned char G
Green component.
Definition: vpRGBa.h:138
unsigned char A
Additionnal component.
Definition: vpRGBa.h:140
Defines a rectangle in the plane.
Definition: vpRect.h:76
double getLeft() const
Definition: vpRect.h:170
double getRight() const
Definition: vpRect.h:176
double getBottom() const
Definition: vpRect.h:94
double getTop() const
Definition: vpRect.h:189
#define vpTRACE
Definition: vpDebug.h:405
#define vpERROR_TRACE
Definition: vpDebug.h:382