ViSP  3.0.0
testKeyPoint-3.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2015 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) {
208  display.init(Imatch, 0, 0, "ORB keypoints matching");
209  }
210 
211  bool opt_click = false;
213  while(!g.end()) {
214  g.acquire(Icur);
215  Imatch.insert(Icur, vpImagePoint(0, Icur.getWidth()));
216 
217  if(opt_display) {
218  vpDisplay::display(Imatch);
219  }
220 
221  vpImageConvert::convert(Icur, matImg);
222  std::vector<cv::KeyPoint> queryKeyPoints;
223  detector->detect(matImg, queryKeyPoints);
224 
225  cv::Mat queryDescriptors;
226  extractor->compute(matImg, queryKeyPoints, queryDescriptors);
227 
228  std::vector<std::vector<cv::DMatch> > knn_matches;
229  std::vector<cv::DMatch> matches;
230  matcher->knnMatch(queryDescriptors, trainDescriptors, knn_matches, 2);
231  for(std::vector<std::vector<cv::DMatch> >::const_iterator it = knn_matches.begin(); it != knn_matches.end(); ++it) {
232  if(it->size() > 1) {
233  double ratio = (*it)[0].distance / (*it)[1].distance;
234  if(ratio < 0.85) {
235  matches.push_back((*it)[0]);
236  }
237  }
238  }
239 
240  if(opt_display) {
241  for(std::vector<cv::DMatch>::const_iterator it = matches.begin(); it != matches.end(); ++it) {
242  vpImagePoint leftPt(trainKeyPoints[(size_t) it->trainIdx].pt.y, trainKeyPoints[(size_t) it->trainIdx].pt.x);
243  vpImagePoint rightPt(queryKeyPoints[(size_t) it->queryIdx].pt.y, queryKeyPoints[(size_t) it->queryIdx].pt.x
244  + Iref.getWidth());
245  vpDisplay::displayLine(Imatch, leftPt, rightPt, vpColor::green);
246  }
247 
248  vpDisplay::flush(Imatch);
249  }
250 
251  //Click requested to process next image
252  if (opt_click_allowed && opt_display) {
253  if(opt_click) {
254  vpDisplay::getClick(Imatch, button, true);
255  if(button == vpMouseButton::button3) {
256  opt_click = false;
257  }
258  } else {
259  //Use right click to enable/disable step by step tracking
260  if(vpDisplay::getClick(Imatch, button, false)) {
261  if (button == vpMouseButton::button3) {
262  opt_click = true;
263  }
264  else if(button == vpMouseButton::button1) {
265  break;
266  }
267  }
268  }
269  }
270  }
271 
272  } catch(vpException &e) {
273  std::cerr << e.what() << std::endl;
274  return -1;
275  }
276 
277  std::cout << "testKeyPoint-3 is ok !" << std::endl;
278  return 0;
279 }
280 #else
281 int main() {
282  std::cerr << "You need OpenCV library." << std::endl;
283 
284  return 0;
285 }
286 
287 #endif
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const char *title=NULL)
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1091
unsigned int getWidth() const
Definition: vpImage.h:161
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:128
Define the X11 console to display images.
Definition: vpDisplayX.h:148
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
static const vpColor green
Definition: vpColor.h:166
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:2233
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:1265
static void display(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:206
The vpDisplayOpenCV allows to display image using the opencv library.
The vpDisplayGTK allows to display image using the GTK+ library version 1.2.
Definition: vpDisplayGTK.h:141
void acquire(vpImage< vpRGBa > &I)
void resize(const unsigned int h, const unsigned int w)
set the size of the image without initializing it.
Definition: vpImage.h:616
void setFileName(const char *filename)
void insert(const vpImage< Type > &src, const vpImagePoint topLeft)
Definition: vpImage.h:935
unsigned int getHeight() const
Definition: vpImage.h:152
virtual bool getClick(bool blocking=true)=0
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:88
virtual void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)=0
static void read(vpImage< unsigned char > &I, const char *filename)
Definition: vpImageIo.cpp:274