File: tutorial-matching-keypoint-homography.cpp

package info (click to toggle)
visp 3.6.0-5
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 119,296 kB
  • sloc: cpp: 500,914; ansic: 52,904; xml: 22,642; python: 7,365; java: 4,247; sh: 482; makefile: 237; objc: 145
file content (143 lines) | stat: -rw-r--r-- 4,550 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
//! \example tutorial-matching-keypoint-homography.cpp
#include <visp3/core/vpPixelMeterConversion.h>
#include <visp3/gui/vpDisplayOpenCV.h>
#include <visp3/io/vpVideoReader.h>
#include <visp3/vision/vpHomography.h>
#include <visp3/vision/vpKeyPoint.h>

int main(int argc, const char **argv)
{
#if defined(HAVE_OPENCV_HIGHGUI) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_FEATURES2D)
  //! [Select method]
  int method = 0;

  if (argc > 1)
    method = atoi(argv[1]);

  if (method == 0)
    std::cout << "Uses Ransac to estimate the homography" << std::endl;
  else
    std::cout << "Uses a robust scheme to estimate the homography" << std::endl;
  //! [Select method]

  vpImage<unsigned char> I;

  vpVideoReader reader;
  reader.setFileName("video-postcard.mp4");
  reader.acquire(I);

  const std::string detectorName = "ORB";
  const std::string extractorName = "ORB";
  // Hamming distance must be used with ORB
  const std::string matcherName = "BruteForce-Hamming";
  vpKeyPoint::vpFilterMatchingType filterType = vpKeyPoint::ratioDistanceThreshold;
  vpKeyPoint keypoint(detectorName, extractorName, matcherName, filterType);
  keypoint.buildReference(I);

  vpImage<unsigned char> Idisp;
  Idisp.resize(I.getHeight(), 2 * I.getWidth());
  Idisp.insert(I, vpImagePoint(0, 0));
  Idisp.insert(I, vpImagePoint(0, I.getWidth()));

  vpDisplayOpenCV d(Idisp, 0, 0, "Homography from matched keypoints");
  vpDisplay::display(Idisp);
  vpDisplay::flush(Idisp);

  //! [Set coordinates]
  vpImagePoint corner_ref[4];
  corner_ref[0].set_ij(115, 64);
  corner_ref[1].set_ij(83, 253);
  corner_ref[2].set_ij(282, 307);
  corner_ref[3].set_ij(330, 72);
  //! [Set coordinates]
  //! [Display]
  for (unsigned int i = 0; i < 4; i++) {
    vpDisplay::displayCross(Idisp, corner_ref[i], 12, vpColor::red);
  }
  vpDisplay::flush(Idisp);
  //! [Display]

  //! [Camera]
  vpCameraParameters cam(840, 840, I.getWidth() / 2, I.getHeight() / 2);
  //! [Camera]

  vpHomography curHref;

  while (!reader.end()) {
    reader.acquire(I);
    Idisp.insert(I, vpImagePoint(0, I.getWidth()));
    vpDisplay::display(Idisp);
    vpDisplay::displayLine(Idisp, vpImagePoint(0, I.getWidth()), vpImagePoint(I.getHeight(), I.getWidth()),
                           vpColor::white, 2);

    //! [Matching]
    unsigned int nbMatch = keypoint.matchPoint(I);
    std::cout << "Nb matches: " << nbMatch << std::endl;
    //! [Matching]

    std::vector<vpImagePoint> iPref(nbMatch),
        iPcur(nbMatch); // Coordinates in pixels (for display only)
    //! [Allocation]
    std::vector<double> mPref_x(nbMatch), mPref_y(nbMatch);
    std::vector<double> mPcur_x(nbMatch), mPcur_y(nbMatch);
    std::vector<bool> inliers(nbMatch);
    //! [Allocation]

    for (unsigned int i = 0; i < nbMatch; i++) {
      keypoint.getMatchedPoints(i, iPref[i], iPcur[i]);
      //! [Pixel conversion]
      vpPixelMeterConversion::convertPoint(cam, iPref[i], mPref_x[i], mPref_y[i]);
      vpPixelMeterConversion::convertPoint(cam, iPcur[i], mPcur_x[i], mPcur_y[i]);
      //! [Pixel conversion]
    }

    //! [Homography estimation]
    try {
      double residual;
      if (method == 0)
        vpHomography::ransac(mPref_x, mPref_y, mPcur_x, mPcur_y, curHref, inliers, residual,
                             (unsigned int)(mPref_x.size() * 0.25), 2.0 / cam.get_px(), true);
      else
        vpHomography::robust(mPref_x, mPref_y, mPcur_x, mPcur_y, curHref, inliers, residual, 0.4, 4, true);
    } catch (...) {
      std::cout << "Cannot compute homography from matches..." << std::endl;
    }

    //! [Homography estimation]

    //! [Projection]
    vpImagePoint corner_cur[4];
    for (int i = 0; i < 4; i++) {
      corner_cur[i] = vpHomography::project(cam, curHref, corner_ref[i]);
    }
    //! [Projection]

    //! [Display contour]
    vpImagePoint offset(0, I.getWidth());
    for (int i = 0; i < 4; i++) {
      vpDisplay::displayLine(Idisp, corner_cur[i] + offset, corner_cur[(i + 1) % 4] + offset, vpColor::blue, 3);
    }
    //! [Display contour]

    //! [Display matches]
    for (unsigned int i = 0; i < nbMatch; i++) {
      if (inliers[i] == true)
        vpDisplay::displayLine(Idisp, iPref[i], iPcur[i] + offset, vpColor::green);
      else
        vpDisplay::displayLine(Idisp, iPref[i], iPcur[i] + offset, vpColor::red);
    }
    //! [Display matches]

    vpDisplay::flush(Idisp);

    if (vpDisplay::getClick(Idisp, false))
      break;
  }

  vpDisplay::getClick(Idisp);
#else
  (void)argc;
  (void)argv;
#endif
  return EXIT_SUCCESS;
}