Visual Servoing Platform  version 3.6.1 under development (2024-11-21)
tutorial-munkres-assignment.cpp
1 
3 #include <functional>
4 
5 #include <visp3/core/vpConfig.h>
6 // Display
7 #include <visp3/gui/vpDisplayD3D.h>
8 #include <visp3/gui/vpDisplayGDI.h>
9 #include <visp3/gui/vpDisplayGTK.h>
10 #include <visp3/gui/vpDisplayOpenCV.h>
11 #include <visp3/gui/vpDisplayX.h>
12 
13 #include <visp3/core/vpColor.h>
14 
15 // Munkres
16 #include <visp3/core/vpMunkres.h>
17 
18 // Math
19 #include <visp3/core/vpUniRand.h>
20 
21 int main()
22 {
23  // Check if std:c++17 or higher
24 #if ((__cplusplus >= 201703L) || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
25 
26 #if defined(VISP_HAVE_DISPLAY)
27 #ifdef ENABLE_VISP_NAMESPACE
28  using namespace VISP_NAMESPACE_NAME;
29 #endif
30  // Create base img
31  vpImage<unsigned char> I(480, 640, 255);
32 
33  // Generate random points
35  vpUniRand rand {};
36  std::vector<vpImagePoint> rand_ips {};
37  while (rand_ips.size() < 10) {
38  rand_ips.emplace_back(rand.uniform(10, I.getHeight() - 10), rand.uniform(10, I.getWidth() - 10));
39  }
41 
42  try {
43  // Init display
44  const auto disp_scale_type = vpDisplay::SCALE_AUTO;
45 #if defined(VISP_HAVE_X11)
46  vpDisplayX d(I, disp_scale_type);
47 #elif defined(VISP_HAVE_GDI)
48  vpDisplayGDI d(I, disp_scale_type);
49 #elif defined(HAVE_OPENCV_HIGHGUI)
50  vpDisplayOpenCV d(I, disp_scale_type);
51 #elif defined(VISP_HAVE_GTK)
52  vpDisplayGTK d(I, disp_scale_type);
53 #elif defined(VISP_HAVE_D3D9)
54  vpDisplayD3D d(I, disp_scale_type);
55 #else
56  std::cout << "No image viewer is available..." << std::endl;
57 #endif
58  vpDisplay::setTitle(I, "Munkres Assignment Algorithm");
59 
60  // Local helper to display a point in the image
61  auto display_point = [&I](const vpImagePoint &ip, const vpColor &color) {
62  I.display->displayCircle(ip, 5, color, true, 1);
63  };
64 
66 
67  auto disp_lane { 0 };
68  vpDisplay::displayText(I, 15 * ++disp_lane, 15, "Left click to add a point", vpColor::black);
69  vpDisplay::displayText(I, 15 * ++disp_lane, 15, "Middle click to continue (run Munkres)", vpColor::black);
70  vpDisplay::displayText(I, 15 * ++disp_lane, 15, "Right click to quit", vpColor::black);
71 
72  std::for_each(begin(rand_ips), end(rand_ips), std::bind(display_point, std::placeholders::_1, vpColor::red));
74 
75  // Ask user to clic on point
77  std::vector<vpImagePoint> user_ips {};
79  while (button != vpMouseButton::button2) {
80  vpImagePoint ip {};
81  vpDisplay::getClick(I, ip, button, true);
82  if (button == vpMouseButton::button1) {
83  user_ips.push_back(ip);
84  }
85  else if (button == vpMouseButton::button3) {
86  return EXIT_SUCCESS;
87  }
88 
89  std::for_each(begin(user_ips), end(user_ips), std::bind(display_point, std::placeholders::_1, vpColor::green));
90 
92  }
94 
95  // Prepare Munkres (init cost matrix with random ip / user ip distances)
97  std::vector<std::vector<double> > cost_matrix(rand_ips.size(), std::vector<double>(user_ips.size()));
98  for (auto i = 0u; i < rand_ips.size(); i++) {
99  for (auto j = 0u; j < user_ips.size(); j++) {
100  cost_matrix.at(i).at(j) = vpImagePoint::distance(rand_ips.at(i), user_ips.at(j));
101  }
102  }
104 
105  // Display results
107  std::for_each(begin(rand_ips), end(rand_ips), std::bind(display_point, std::placeholders::_1, vpColor::red));
108  std::for_each(begin(user_ips), end(user_ips), std::bind(display_point, std::placeholders::_1, vpColor::green));
109 
111  for (const auto &[i, j] : vpMunkres::run(cost_matrix)) {
112  I.display->displayLine(rand_ips.at(i), user_ips.at(j), vpColor::blue, 1);
113  }
115 
116  vpDisplay::displayText(I, 15, 15, "Click to quit", vpColor::black);
117  vpDisplay::flush(I);
119 
120  }
121  catch (const vpException &e) {
122  std::cout << "Catch an exception: " << e << std::endl;
123  }
124 #endif // defined(VISP_HAVE_DISPLAY)
125 #endif
126  return EXIT_SUCCESS;
127 }
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:157
static const vpColor red
Definition: vpColor.h:217
static const vpColor blue
Definition: vpColor.h:223
static const vpColor black
Definition: vpColor.h:211
static const vpColor green
Definition: vpColor.h:220
Display for windows using Direct3D 3rd party. Thus to enable this class Direct3D should be installed....
Definition: vpDisplayD3D.h:106
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:130
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:133
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void displayCircle(const vpImage< unsigned char > &I, const vpImageCircle &circle, const vpColor &color, bool fill=false, unsigned int thickness=1)
static void display(const vpImage< unsigned char > &I)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void setTitle(const vpImage< unsigned char > &I, const std::string &windowtitle)
static void flush(const vpImage< unsigned char > &I)
@ SCALE_AUTO
Definition: vpDisplay.h:184
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Definition: vpException.h:60
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:82
static double distance(const vpImagePoint &iP1, const vpImagePoint &iP2)
unsigned int getWidth() const
Definition: vpImage.h:242
unsigned int getHeight() const
Definition: vpImage.h:181
vpDisplay * display
Definition: vpImage.h:136
Class for generating random numbers with uniform probability density.
Definition: vpUniRand.h:127