Visual Servoing Platform  version 3.0.1
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
testKeyPoint-3.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Test keypoint matching with mostly OpenCV functions calls
32  * to detect potential memory leaks in testKeyPoint.cpp.
33  *
34  * Authors:
35  * Souriya Trinh
36  *
37  *****************************************************************************/
38 
39 #include <iostream>
40 
41 #include <visp3/core/vpConfig.h>
42 
43 #if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020301)
44 
45 #include <opencv2/core/core.hpp>
46 #include <opencv2/features2d/features2d.hpp>
47 #include <visp3/core/vpImage.h>
48 #include <visp3/io/vpImageIo.h>
49 #include <visp3/gui/vpDisplayX.h>
50 #include <visp3/gui/vpDisplayGTK.h>
51 #include <visp3/gui/vpDisplayGDI.h>
52 #include <visp3/gui/vpDisplayOpenCV.h>
53 #include <visp3/io/vpVideoReader.h>
54 #include <visp3/core/vpIoTools.h>
55 #include <visp3/io/vpParseArgv.h>
56 
57 // List of allowed command line options
58 #define GETOPTARGS "cdh"
59 
60 void usage(const char *name, const char *badparam);
61 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display);
62 
70 void usage(const char *name, const char *badparam)
71 {
72  fprintf(stdout, "\n\
73 Test keypoints matching.\n\
74 \n\
75 SYNOPSIS\n\
76  %s [-c] [-d] [-h]\n", name);
77 
78  fprintf(stdout, "\n\
79 OPTIONS: \n\
80 \n\
81  -c\n\
82  Disable the mouse click. Useful to automate the \n\
83  execution of this program without human intervention.\n\
84 \n\
85  -d \n\
86  Turn off the display.\n\
87 \n\
88  -h\n\
89  Print the help.\n");
90 
91  if (badparam)
92  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
93 }
94 
106 bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display)
107 {
108  const char *optarg_;
109  int c;
110  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
111 
112  switch (c) {
113  case 'c': click_allowed = false; break;
114  case 'd': display = false; break;
115  case 'h': usage(argv[0], NULL); return false; break;
116 
117  default:
118  usage(argv[0], optarg_);
119  return false; break;
120  }
121  }
122 
123  if ((c == 1) || (c == -1)) {
124  // standalone param or error
125  usage(argv[0], NULL);
126  std::cerr << "ERROR: " << std::endl;
127  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
128  return false;
129  }
130 
131  return true;
132 }
133 
140 int main(int argc, const char ** argv) {
141  try {
142  std::string env_ipath;
143  bool opt_click_allowed = true;
144  bool opt_display = true;
145 
146  // Read the command line options
147  if (getOptions(argc, argv, opt_click_allowed, opt_display) == false) {
148  exit (-1);
149  }
150 
151  //Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH environment variable value
152  env_ipath = vpIoTools::getViSPImagesDataPath();
153 
154  if(env_ipath.empty()) {
155  std::cerr << "Please set the VISP_INPUT_IMAGE_PATH environment variable value." << std::endl;
156  return -1;
157  }
158 
159  vpImage<unsigned char> Iref, Icur, Imatch;
160 
161  //Set the path location of the image sequence
162  std::string dirname = vpIoTools::createFilePath(env_ipath, "ViSP-images/mbt/cube");
163 
164  //Build the name of the image files
165  std::string filenameRef = vpIoTools::createFilePath(dirname, "image0000.pgm");
166  vpImageIo::read(Iref, filenameRef);
167  std::string filenameCur = vpIoTools::createFilePath(dirname, "image%04d.pgm");
168 
169  //Init keypoints
170  cv::Ptr<cv::FeatureDetector> detector;
171  cv::Ptr<cv::DescriptorExtractor> extractor;
172  cv::Ptr<cv::DescriptorMatcher> matcher;
173 
174 #if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
175  detector = cv::ORB::create();
176  extractor = cv::ORB::create();
177 #else
178  detector = cv::FeatureDetector::create("ORB");
179  extractor = cv::DescriptorExtractor::create("ORB");
180 #endif
181  matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");
182 
183  std::vector<cv::KeyPoint> trainKeyPoints;
184  cv::Mat matImg, trainDescriptors;
185  vpImageConvert::convert(Iref, matImg);
186  detector->detect(matImg, trainKeyPoints);
187  extractor->compute(matImg, trainKeyPoints, trainDescriptors);
188 
189  vpVideoReader g;
190  g.setFileName(filenameCur);
191  g.open(Icur);
192  g.acquire(Icur);
193 
194  Imatch.resize(Icur.getHeight(), 2*Icur.getWidth());
195  Imatch.insert(Iref, vpImagePoint(0,0));
196 
197 #if defined VISP_HAVE_X11
198  vpDisplayX display;
199 #elif defined VISP_HAVE_GTK
200  vpDisplayGTK display;
201 #elif defined VISP_HAVE_GDI
202  vpDisplayGDI display;
203 #else
204  vpDisplayOpenCV display;
205 #endif
206 
207  if (opt_display) {
209  display.init(Imatch, 0, 0, "ORB keypoints matching");
210  }
211 
212  bool opt_click = false;
214  while(!g.end()) {
215  g.acquire(Icur);
216  Imatch.insert(Icur, vpImagePoint(0, Icur.getWidth()));
217 
218  if(opt_display) {
219  vpDisplay::display(Imatch);
220  }
221 
222  vpImageConvert::convert(Icur, matImg);
223  std::vector<cv::KeyPoint> queryKeyPoints;
224  detector->detect(matImg, queryKeyPoints);
225 
226  cv::Mat queryDescriptors;
227  extractor->compute(matImg, queryKeyPoints, queryDescriptors);
228 
229  std::vector<std::vector<cv::DMatch> > knn_matches;
230  std::vector<cv::DMatch> matches;
231  matcher->knnMatch(queryDescriptors, trainDescriptors, knn_matches, 2);
232  for(std::vector<std::vector<cv::DMatch> >::const_iterator it = knn_matches.begin(); it != knn_matches.end(); ++it) {
233  if(it->size() > 1) {
234  double ratio = (*it)[0].distance / (*it)[1].distance;
235  if(ratio < 0.85) {
236  matches.push_back((*it)[0]);
237  }
238  }
239  }
240 
241  if(opt_display) {
242  for(std::vector<cv::DMatch>::const_iterator it = matches.begin(); it != matches.end(); ++it) {
243  vpImagePoint leftPt(trainKeyPoints[(size_t) it->trainIdx].pt.y, trainKeyPoints[(size_t) it->trainIdx].pt.x);
244  vpImagePoint rightPt(queryKeyPoints[(size_t) it->queryIdx].pt.y, queryKeyPoints[(size_t) it->queryIdx].pt.x
245  + Iref.getWidth());
246  vpDisplay::displayLine(Imatch, leftPt, rightPt, vpColor::green);
247  }
248 
249  vpDisplay::flush(Imatch);
250  }
251 
252  //Click requested to process next image
253  if (opt_click_allowed && opt_display) {
254  if(opt_click) {
255  vpDisplay::getClick(Imatch, button, true);
256  if(button == vpMouseButton::button3) {
257  opt_click = false;
258  }
259  } else {
260  //Use right click to enable/disable step by step tracking
261  if(vpDisplay::getClick(Imatch, button, false)) {
262  if (button == vpMouseButton::button3) {
263  opt_click = true;
264  }
265  else if(button == vpMouseButton::button1) {
266  break;
267  }
268  }
269  }
270  }
271  }
272 
273  } catch(vpException &e) {
274  std::cerr << e.what() << std::endl;
275  return -1;
276  }
277 
278  std::cout << "testKeyPoint-3 is ok !" << std::endl;
279  return 0;
280 }
281 #else
282 int main() {
283  std::cerr << "You need OpenCV library." << std::endl;
284 
285  return 0;
286 }
287 
288 #endif
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1157
unsigned int getWidth() const
Definition: vpImage.h:226
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
virtual void setDownScalingFactor(unsigned int scale)
Definition: vpDisplay.cpp:248
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:153
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
error that can be emited by ViSP classes.
Definition: vpException.h:73
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
static const vpColor green
Definition: vpColor.h:166
static void flush(const vpImage< unsigned char > &I)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:76
void open(vpImage< vpRGBa > &I)
const char * what() const
static std::string createFilePath(const std::string &parent, const std::string child)
Definition: vpIoTools.cpp:1366
static void display(const vpImage< unsigned char > &I)
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:138
void acquire(vpImage< vpRGBa > &I)
void resize(const unsigned int h, const unsigned int w)
resize the image : Image initialization
Definition: vpImage.h:903
void setFileName(const char *filename)
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:205
void insert(const vpImage< Type > &src, const vpImagePoint topLeft)
Definition: vpImage.h:1226
unsigned int getHeight() const
Definition: vpImage.h:175
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)