39 #include <visp3/core/vpConfig.h>
41 #if defined(HAVE_OPENCV_HIGHGUI)
50 #include <visp3/core/vpDisplay.h>
51 #include <visp3/core/vpImageTools.h>
52 #include <visp3/core/vpIoTools.h>
53 #include <visp3/core/vpMath.h>
54 #include <visp3/gui/vpDisplayOpenCV.h>
57 #include <visp3/core/vpDisplayException.h>
59 #include <opencv2/core/core.hpp>
60 #include <opencv2/highgui/highgui.hpp>
61 #include <opencv2/core/core_c.h>
63 #if defined(HAVE_OPENCV_IMGPROC)
64 #include <opencv2/imgproc/imgproc.hpp>
68 #define CV_RGB(r, g, b) cv::Scalar((b), (g), (r), 0)
72 #include <visp3/gui/vpDisplayX.h>
79 #ifndef DOXYGEN_SHOULD_SKIP_THIS
80 class vpDisplayOpenCV::Impl
88 static std::vector<std::string> m_listTitles;
89 static unsigned int m_nbWindows;
117 m_background(), col(nullptr), cvcolor(), font(cv::FONT_HERSHEY_PLAIN), fontScale(0.8f),
118 fontHeight(10), x_move(0), y_move(0), move(false), x_lbuttondown(0), y_lbuttondown(0), lbuttondown(false),
119 x_mbuttondown(0), y_mbuttondown(0), mbuttondown(false), x_rbuttondown(0), y_rbuttondown(0), rbuttondown(false),
120 x_lbuttonup(0), y_lbuttonup(0), lbuttonup(false), x_mbuttonup(0), y_mbuttonup(0), mbuttonup(false), x_rbuttonup(0),
121 y_rbuttonup(0), rbuttonup(false)
126 if (col !=
nullptr) {
138 std::string
init(
const std::string &title,
const int &windowXPosition,
const int &windowYPosition)
140 int flags = cv::WINDOW_AUTOSIZE;
141 std::string outTitle = title;
142 if (outTitle.empty()) {
143 std::ostringstream s;
145 outTitle = std::string(
"Window ") + s.str();
152 while (i < m_listTitles.size() && !isInList) {
153 if (m_listTitles[i] == outTitle) {
154 std::ostringstream s;
156 outTitle = std::string(
"Window ") + s.str();
163 m_listTitles.push_back(outTitle);
167 cv::namedWindow(outTitle, flags);
168 cv::moveWindow(outTitle.c_str(), windowXPosition, windowYPosition);
178 cv::setMouseCallback(outTitle, on_mouse,
this);
223 fontSize = cv::getTextSize(
"A", font, fontScale, thickness, &baseline);
225 fontHeight = fontSize.height + baseline;
231 if (col !=
nullptr) {
236 cv::destroyWindow(title);
237 for (
size_t i = 0; i < m_listTitles.size(); i++) {
238 if (title == m_listTitles[i]) {
239 m_listTitles.erase(m_listTitles.begin() + (
long int)i);
246 const unsigned int &w,
const unsigned int &h,
const unsigned int &thickness,
const unsigned int &scale)
252 if ((std::fabs(a) <= std::numeric_limits<double>::epsilon()) &&
253 (std::fabs(b) <= std::numeric_limits<double>::epsilon())) {
281 const unsigned int &thickness,
const unsigned int &scale)
285 int r =
static_cast<int>(radius / scale);
288 cv_color = col[color.
id];
291 cv_color = CV_RGB(color.
R, color.
G, color.
B);
295 int cv_thickness =
static_cast<int>(thickness);
296 cv::circle(m_background, cv::Point(x, y), r, cv_color, cv_thickness);
299 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
300 int filled = cv::FILLED;
302 int filled = CV_FILLED;
304 double opacity =
static_cast<double>(color.
A) / 255.0;
305 overlay([x, y, r, cv_color, filled](cv::Mat image) { cv::circle(image, cv::Point(x, y), r, cv_color, filled); },
326 const unsigned int &thickness,
const unsigned int &scale)
331 double size = 10. * scale;
333 bool vertical_line = (int)ip2_.
get_j() == (int)ip1_.
get_j();
336 std::swap(ip1_, ip2_);
340 std::swap(ip1_, ip2_);
343 double diff_j = vertical_line ? 1 : ip2_.
get_j() - ip1_.
get_j();
344 double deltaj = size / length * diff_j;
345 double deltai = size / length * (ip2_.
get_i() - ip1_.
get_i());
346 double slope = (ip2_.
get_i() - ip1_.
get_i()) / diff_j;
347 double orig = ip1_.
get_i() - slope * ip1_.
get_j();
350 for (
unsigned int i = (
unsigned int)ip1_.
get_i(); i < ip2_.
get_i(); i += (
unsigned int)(2 * deltai)) {
351 double j = ip1_.
get_j();
356 for (
unsigned int j = (
unsigned int)ip1_.
get_j(); j < ip2_.
get_j(); j += (
unsigned int)(2 * deltaj)) {
357 double i = slope * j + orig;
367 cv::Size size((
int)width, (
int)height);
368 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (
int)height ||
369 m_background.cols != (
int)width) {
370 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
374 for (
unsigned int i = 0; i < height; i++) {
375 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 * width);
376 for (
unsigned int j = 0; j < width; j++) {
377 unsigned char val = I[i][j];
385 for (
unsigned int i = 0; i < height; i++) {
386 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 * width);
387 for (
unsigned int j = 0; j < width; j++) {
388 unsigned char val = I[i * scale][j * scale];
401 cv::Size size((
int)width, (
int)height);
402 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (
int)height ||
403 m_background.cols != (
int)width) {
404 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
408 for (
unsigned int i = 0; i < height; i++) {
409 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 * width);
410 for (
unsigned int j = 0; j < width; j++) {
419 for (
unsigned int i = 0; i < height; i++) {
420 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 * width);
421 for (
unsigned int j = 0; j < width; j++) {
422 vpRGBa val = I[i * scale][j * scale];
432 const unsigned int &h,
const unsigned int &imgWidth,
const unsigned int &imgHeight,
const unsigned int &scale)
436 cv::Size size((
int)imgWidth, (
int)imgHeight);
437 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (
int)imgHeight ||
438 m_background.cols != (
int)imgWidth) {
439 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
443 unsigned int i_min = (
unsigned int)iP.
get_i();
444 unsigned int j_min = (
unsigned int)iP.
get_j();
445 unsigned int i_max = std::min<unsigned int>(i_min + h, imgHeight);
446 unsigned int j_max = std::min<unsigned int>(j_min + w, imgWidth);
447 for (
unsigned int i = i_min; i < i_max; i++) {
448 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 * imgWidth + j_min * 3);
449 for (
unsigned int j = j_min; j < j_max; j++) {
450 unsigned char val = I[i][j];
458 int i_min = std::max<int>((
int)ceil(iP.
get_i() / scale), 0);
459 int j_min = std::max<int>((
int)ceil(iP.
get_j() / scale), 0);
460 int i_max = std::min<int>((
int)ceil((iP.
get_i() + h) / scale), (
int)imgHeight);
461 int j_max = std::min<int>((
int)ceil((iP.
get_j() + w) / scale), (
int)imgWidth);
462 for (
int i = i_min; i < i_max; i++) {
463 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 * imgWidth + j_min * 3);
464 for (
int j = j_min; j < j_max; j++) {
465 unsigned char val = I[i * scale][j * scale];
478 cv::Size size((
int)imgWidth, (
int)imgHeight);
479 if (m_background.channels() != channels || m_background.depth() != depth || m_background.rows != (
int)imgHeight ||
480 m_background.cols != (
int)imgWidth) {
481 m_background = cv::Mat(size, CV_MAKETYPE(depth, channels));
485 unsigned int i_min = (
unsigned int)iP.
get_i();
486 unsigned int j_min = (
unsigned int)iP.
get_j();
487 unsigned int i_max = std::min<unsigned int>(i_min + h, imgHeight);
488 unsigned int j_max = std::min<unsigned int>(j_min + w, imgWidth);
489 for (
unsigned int i = i_min; i < i_max; i++) {
490 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 * imgWidth + j_min * 3);
491 for (
unsigned int j = j_min; j < j_max; j++) {
500 int i_min = std::max<int>((
int)ceil(iP.
get_i() / scale), 0);
501 int j_min = std::max<int>((
int)ceil(iP.
get_j() / scale), 0);
502 int i_max = std::min<int>((
int)ceil((iP.
get_i() + h) / scale), (
int)imgHeight);
503 int j_max = std::min<int>((
int)ceil((iP.
get_j() + w) / scale), (
int)imgWidth);
504 for (
int i = i_min; i < i_max; i++) {
505 unsigned char *dst_24 = (
unsigned char *)m_background.data + (
int)(i * 3 * imgWidth + j_min * 3);
506 for (
int j = j_min; j < j_max; j++) {
507 vpRGBa val = I[i * scale][j * scale];
524 cvcolor = CV_RGB(color.
R, color.
G, color.
B);
533 for (
unsigned int i = 0; i < thickness; i++) {
537 col[color.
id], (
int)thickness);
540 cvcolor = CV_RGB(color.
R, color.
G, color.
B);
543 cvcolor, (
int)thickness);
549 const bool &fill,
const unsigned int &thickness,
const unsigned int &scale)
557 cv_color = col[color.
id];
560 cv_color = CV_RGB(color.
R, color.
G, color.
B);
564 int cv_thickness =
static_cast<int>(thickness);
565 cv::rectangle(m_background, cv::Point(left, top), cv::Point(right, bottom), cv_color, cv_thickness);
568 #if VISP_HAVE_OPENCV_VERSION >= 0x030000
569 int filled = cv::FILLED;
571 int filled = CV_FILLED;
573 double opacity =
static_cast<double>(color.
A) / 255.0;
574 overlay([left, top, right, bottom, cv_color, filled](cv::Mat image) {
575 cv::rectangle(image, cv::Point(left, top), cv::Point(right, bottom), cv_color, filled);
584 cv::putText(m_background, text,
586 font, fontScale, col[color.
id]);
589 cvcolor = CV_RGB(color.
R, color.
G, color.
B);
590 cv::putText(m_background, text,
592 font, fontScale, cvcolor);
598 cv::imshow(title, m_background);
604 cv::imshow(title.c_str(), m_background);
621 u = (
unsigned int)x_lbuttondown * scale;
622 v = (
unsigned int)y_lbuttondown * scale;
630 u = (
unsigned int)x_mbuttondown * scale;
631 v = (
unsigned int)y_mbuttondown * scale;
639 u = (
unsigned int)x_rbuttondown * scale;
640 v = (
unsigned int)y_rbuttondown * scale;
649 }
while (ret ==
false && blocking ==
true);
665 u = (
unsigned int)x_lbuttonup * scale;
666 v = (
unsigned int)y_lbuttonup * scale;
674 u = (
unsigned int)x_mbuttonup * scale;
675 v = (
unsigned int)y_mbuttonup * scale;
683 u = (
unsigned int)x_rbuttonup * scale;
684 v = (
unsigned int)y_rbuttonup * scale;
693 }
while (ret ==
false && blocking ==
true);
702 double u = (
unsigned int)x_move / scale;
703 double v = (
unsigned int)y_move / scale;
716 u = (
unsigned int)x_move / scale;
717 v = (
unsigned int)y_move / scale;
723 static void on_mouse(
int event,
int x,
int y,
int ,
void *
display)
725 Impl *disp =
static_cast<Impl *
>(
display);
728 case cv::EVENT_MOUSEMOVE:
735 case cv::EVENT_LBUTTONDOWN:
737 disp->lbuttondown =
true;
738 disp->x_lbuttondown = x;
739 disp->y_lbuttondown = y;
742 case cv::EVENT_MBUTTONDOWN:
744 disp->mbuttondown =
true;
745 disp->x_mbuttondown = x;
746 disp->y_mbuttondown = y;
749 case cv::EVENT_RBUTTONDOWN:
751 disp->rbuttondown =
true;
752 disp->x_rbuttondown = x;
753 disp->y_rbuttondown = y;
756 case cv::EVENT_LBUTTONUP:
758 disp->lbuttonup =
true;
759 disp->x_lbuttonup = x;
760 disp->y_lbuttonup = y;
763 case cv::EVENT_MBUTTONUP:
765 disp->mbuttonup =
true;
766 disp->x_mbuttonup = x;
767 disp->y_mbuttonup = y;
770 case cv::EVENT_RBUTTONUP:
772 disp->rbuttonup =
true;
773 disp->x_rbuttonup = x;
774 disp->y_rbuttonup = y;
783 void overlay(std::function<
void(cv::Mat &)> overlay_function,
const double &opacity)
789 overlay = m_background.clone();
793 overlay = m_background;
796 overlay_function(overlay);
800 cv::addWeighted(overlay, opacity, m_background, 1.0 - opacity, 0.0, m_background);
805 std::vector<std::string> vpDisplayOpenCV::Impl::m_listTitles = std::vector<std::string>();
806 unsigned int vpDisplayOpenCV::Impl::m_nbWindows = 0;
867 init(I, x, y, title);
921 init(I, x, y, title);
957 if (!title.empty()) {
961 std::ostringstream s;
962 s << vpDisplayOpenCV::Impl::m_nbWindows++;
963 m_title = std::string(
"Window ") + s.str();
969 for (
size_t i = 0; i < vpDisplayOpenCV::Impl::m_listTitles.size(); i++) {
970 if (vpDisplayOpenCV::Impl::m_listTitles[i] ==
m_title) {
971 std::ostringstream s;
972 s << vpDisplayOpenCV::Impl::m_nbWindows++;
973 m_title = std::string(
"Window ") + s.str();
980 vpDisplayOpenCV::Impl::m_listTitles.push_back(
m_title);
1008 , m_impl(new Impl())
1085 if (!title.empty()) {
1140 cv::moveWindow(this->
m_title.c_str(), winx, winy);
1261 m_impl->closeDisplay(
m_title);
1277 m_impl->flushDisplay(
m_title);
1290 const unsigned int )
1293 m_impl->flushDisplayROI(
m_title);
1316 unsigned int w,
unsigned int h,
unsigned int thickness)
1319 m_impl->displayArrow(ip1, ip2, color, w, h, thickness,
m_scale);
1340 m_impl->displayText(ip, text, color,
m_scale);
1360 unsigned int thickness)
1363 m_impl->displayCircle(center, radius, color, fill, thickness,
m_scale);
1378 unsigned int thickness)
1381 m_impl->displayCross(ip, size, color, thickness,
m_scale);
1396 unsigned int thickness)
1399 m_impl->displayDotLine(ip1, ip2, color, thickness,
m_scale);
1413 unsigned int thickness)
1416 m_impl->displayLine(ip1, ip2, color, thickness,
m_scale);
1432 m_impl->displayPoint(ip, color, thickness,
m_scale);
1455 const vpColor &color,
bool fill,
unsigned int thickness)
1458 m_impl->displayRectangle(topLeft, w, h, color, fill, thickness,
m_scale);
1479 const vpColor &color,
bool fill,
unsigned int thickness)
1482 unsigned int w = bottomRight.
get_u() - topLeft.
get_u() + 1;
1483 unsigned int h = bottomRight.
get_v() - topLeft.
get_v() + 1;
1535 ret =
getClick(ip, button, blocking);
1564 ret =
getClick(ip, button, blocking);
1628 ret = m_impl->getClickUp(ip, button, blocking,
m_scale);
1642 m_impl->getImage(I);
1670 int key_pressed = cv::waitKey(delay);
1672 if (key_pressed == -1)
1710 int key_pressed = cv::waitKey(delay);
1711 if (key_pressed == -1)
1715 std::stringstream ss;
1742 ret = m_impl->getPointerMotionEvent(ip,
m_scale);
1764 m_impl->getPointerPosition(ip,
m_scale);
1780 #if defined(VISP_HAVE_X11)
1783 #elif defined(VISP_HAVE_XRANDR)
1784 std::string command =
"xrandr | grep '*'";
1785 FILE *fpipe = (FILE *)popen(command.c_str(),
"r");
1787 while (fgets(line,
sizeof(line), fpipe)) {
1788 std::string str(line);
1789 std::size_t found = str.find(
"Failed");
1791 if (found == std::string::npos) {
1792 std::vector<std::string> elm;
1794 for (
size_t i = 0; i < elm.size(); i++) {
1795 if (!elm[i].empty()) {
1797 if (resolution.size() == 2) {
1798 std::istringstream sswidth(resolution[0]), ssheight(resolution[1]);
1808 #elif defined(_WIN32)
1810 w = GetSystemMetrics(SM_CXSCREEN);
1811 h = GetSystemMetrics(SM_CYSCREEN);
1814 "implemented on winrt"));
1824 unsigned int width, height;
1834 unsigned int width, height;
1841 #elif !defined(VISP_BUILD_SHARED_LIBS)
1843 void dummy_vpDisplayOpenCV() { };
Class to define RGB colors available for display functionalities.
static const vpColor white
static const vpColor darkGray
static const vpColor cyan
static const vpColor orange
static const vpColor darkRed
static const vpColor blue
static const vpColor lightGray
static const vpColor lightBlue
static const vpColor darkGreen
static const vpColor darkBlue
static const vpColor purple
static const vpColor lightGreen
static const vpColor yellow
static const vpColor lightRed
static const vpColor black
static const vpColor green
static const vpColor gray
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 displayRectangle(const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1) VP_OVERRIDE
void flushDisplayROI(const vpImagePoint &iP, unsigned int width, unsigned int height) VP_OVERRIDE
virtual ~vpDisplayOpenCV() VP_OVERRIDE
bool getKeyboardEvent(bool blocking=true) VP_OVERRIDE
void displayPoint(const vpImagePoint &ip, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
void setFont(const std::string &font) VP_OVERRIDE
void getImage(vpImage< vpRGBa > &I) VP_OVERRIDE
Get the window pixmap and put it in vpRGBa image.
void flushDisplay() VP_OVERRIDE
void getScreenSize(unsigned int &width, unsigned int &height) VP_OVERRIDE
void clearDisplay(const vpColor &color=vpColor::white) VP_OVERRIDE
bool getPointerMotionEvent(vpImagePoint &ip) VP_OVERRIDE
void displayDotLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) 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
unsigned int getScreenWidth() VP_OVERRIDE
void setTitle(const std::string &title) VP_OVERRIDE
void setWindowPosition(int winx, int winy) VP_OVERRIDE
void displayCircle(const vpImagePoint ¢er, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1) VP_OVERRIDE
void closeDisplay() VP_OVERRIDE
void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
void displayImage(const vpImage< unsigned char > &I) VP_OVERRIDE
bool getPointerPosition(vpImagePoint &ip) 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
bool getClickUp(vpImagePoint &ip, vpMouseButton::vpMouseButtonType &button, bool blocking=true) VP_OVERRIDE
bool getClick(bool blocking=true) VP_OVERRIDE
void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1) VP_OVERRIDE
unsigned int getScreenHeight() VP_OVERRIDE
void displayImageROI(const vpImage< unsigned char > &I, const vpImagePoint &iP, unsigned int width, unsigned int height) VP_OVERRIDE
void getScreenSize(unsigned int &width, unsigned int &height) VP_OVERRIDE
Class that defines generic functionalities for display.
static void display(const vpImage< unsigned char > &I)
int m_windowXPosition
display position
int m_windowYPosition
display position
bool m_displayHasBeenInitialized
display has been initialized
void setScale(vpScaleType scaleType, unsigned int width, unsigned int height)
error that can be emitted by ViSP classes.
@ functionNotImplementedError
Function not implemented.
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 ...
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
unsigned int getWidth() const
unsigned int getHeight() const
static double sqr(double x)
static int round(double x)
unsigned char B
Blue component.
unsigned char R
Red component.
unsigned char G
Green component.
unsigned char A
Additionnal component.
Defines a rectangle in the plane.
vpImagePoint getTopLeft() const