Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
testSurfKeyPoint.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Test auto detection of dots.
33  *
34  * Authors:
35  * Nicolas Melchior
36  *
37  *****************************************************************************/
38 
39 #include <iomanip>
40 #include <iostream>
41 #include <sstream>
42 #include <stdio.h>
43 #include <stdlib.h>
44 
45 #include <visp3/core/vpConfig.h>
46 
47 #if (defined(VISP_HAVE_OPENCV_NONFREE) && (VISP_HAVE_OPENCV_VERSION < 0x030000)) // Require opencv >= 1.1.0 < 3.0.0
48 
49 #include <visp3/core/vpCameraParameters.h>
50 #include <visp3/core/vpImage.h>
51 #include <visp3/core/vpIoTools.h>
52 #include <visp3/gui/vpDisplayGDI.h>
53 #include <visp3/gui/vpDisplayGTK.h>
54 #include <visp3/gui/vpDisplayOpenCV.h>
55 #include <visp3/gui/vpDisplayX.h>
56 #include <visp3/io/vpImageIo.h>
57 #include <visp3/io/vpParseArgv.h>
59 
66 // List of allowed command line options
67 #define GETOPTARGS "cdi:h"
68 
69 void usage(const char *name, const char *badparam, std::string ipath);
70 bool getOptions(int argc, const char **argv, std::string &ipath, bool &click_allowed, bool &display);
71 
81 void usage(const char *name, const char *badparam, std::string ipath)
82 {
83  fprintf(stdout, "\n\
84 Test dot tracking.\n\
85 \n\
86 SYNOPSIS\n\
87  %s [-i <input image path>] [-c] [-d] [-h]\n", name);
88 
89  fprintf(stdout, "\n\
90 OPTIONS: Default\n\
91  -i <input image path> %s\n\
92  Set image input path.\n\
93  From this path read image \n\
94  \"ellipse/ellipse.pgm\"\n\
95  Setting the VISP_INPUT_IMAGE_PATH environment\n\
96  variable produces the same behaviour than using\n\
97  this option.\n\
98 \n\
99  -c\n\
100  Disable the mouse click. Useful to automaze the \n\
101  execution of this program without humain intervention.\n\
102 \n\
103  -d \n\
104  Turn off the display.\n\
105 \n\
106  -h\n\
107  Print the help.\n", ipath.c_str());
108 
109  if (badparam)
110  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
111 }
124 bool getOptions(int argc, const char **argv, std::string &ipath, bool &click_allowed, bool &display)
125 {
126  const char *optarg_;
127  int c;
128  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
129 
130  switch (c) {
131  case 'c':
132  click_allowed = false;
133  break;
134  case 'd':
135  display = false;
136  break;
137  case 'i':
138  ipath = optarg_;
139  break;
140  case 'h':
141  usage(argv[0], NULL, ipath);
142  return false;
143  break;
144 
145  default:
146  usage(argv[0], optarg_, ipath);
147  return false;
148  break;
149  }
150  }
151 
152  if ((c == 1) || (c == -1)) {
153  // standalone param or error
154  usage(argv[0], NULL, ipath);
155  std::cerr << "ERROR: " << std::endl;
156  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
157  return false;
158  }
159 
160  return true;
161 }
162 
163 int main(int argc, const char **argv)
164 {
165  try {
166  std::string env_ipath;
167  std::string opt_ipath;
168  std::string ipath;
169  std::string dirname;
170  std::string filenameRef;
171  std::string filenameCur;
172  bool opt_click_allowed = true;
173  bool opt_display = true;
174 
175  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
176  // environment variable value
177  env_ipath = vpIoTools::getViSPImagesDataPath();
178 
179  // Set the default input path
180  if (!env_ipath.empty())
181  ipath = env_ipath;
182 
183  // Read the command line options
184  if (getOptions(argc, argv, opt_ipath, opt_click_allowed, opt_display) == false) {
185  exit(-1);
186  }
187 
188  // Get the option values
189  if (!opt_ipath.empty())
190  ipath = opt_ipath;
191 
192  // Compare ipath and env_ipath. If they differ, we take into account
193  // the input path comming from the command line option
194  if (!opt_ipath.empty() && !env_ipath.empty()) {
195  if (ipath != env_ipath) {
196  std::cout << std::endl << "WARNING: " << std::endl;
197  std::cout << " Since -i <visp image path=" << ipath << "> "
198  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
199  << " we skip the environment variable." << std::endl;
200  }
201  }
202 
203  // Test if an input path is set
204  if (opt_ipath.empty() && env_ipath.empty()) {
205  usage(argv[0], NULL, ipath);
206  std::cerr << std::endl << "ERROR:" << std::endl;
207  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
208  << " environment variable to specify the location of the " << std::endl
209  << " image path where test images are located." << std::endl
210  << std::endl;
211  exit(-1);
212  }
213 
214  // Declare an image, this is a gray level image (unsigned char)
215  // it size is not defined yet, it will be defined when the image will
216  // read on the disk
219 
220  // Set the path location of the image sequence
221  dirname = vpIoTools::createFilePath(ipath, "cube");
222 
223  // Build the name of the image file
224  filenameRef = vpIoTools::createFilePath(dirname, "image.0000.pgm");
225  filenameCur = vpIoTools::createFilePath(dirname, "image.0079.pgm");
226 
227  // Read the PGM image named "filename" on the disk, and put the
228  // bitmap into the image structure I. I is initialized to the
229  // correct size
230  //
231  // exception readPGM may throw various exception if, for example,
232  // the file does not exist, or if the memory cannot be allocated
233  try {
234  std::cout << "Load: " << filenameRef << std::endl;
235 
236  vpImageIo::read(Iref, filenameRef);
237 
238  std::cout << "Load: " << filenameCur << std::endl;
239 
240  vpImageIo::read(Icur, filenameCur);
241  } catch (...) {
242  // an exception is throwned if an exception from readPGM has been
243  // catched here this will result in the end of the program Note that
244  // another error message has been printed from readPGM to give more
245  // information about the error
246  std::cerr << std::endl << "ERROR:" << std::endl;
247  std::cerr << " Cannot read " << filenameRef << "or" << filenameCur << std::endl;
248  std::cerr << " Check your -i " << ipath << " option " << std::endl
249  << " or VISP_INPUT_IMAGE_PATH environment variable." << std::endl;
250  exit(-1);
251  }
252 
253 // We open a window using either X11, GTK or GDI.
254 #if defined VISP_HAVE_X11
255  vpDisplayX display[2];
256 #elif defined VISP_HAVE_GTK
257  vpDisplayGTK display[2];
258 #elif defined VISP_HAVE_GDI
259  vpDisplayGDI display[2];
260 #else
261  vpDisplayOpenCV display[2];
262 #endif
263 
264  if (opt_display) {
265  // Display size is automatically defined by the image (I) size
266  display[0].init(Iref, 100, 100, "Reference image");
267  // Display the image
268  // The image class has a member that specify a pointer toward
269  // the display that has been initialized in the display declaration
270  // therefore is is no longuer necessary to make a reference to the
271  // display variable.
272  vpDisplay::display(Iref);
273  // Flush the display
274  vpDisplay::flush(Iref);
275  }
276 
277  vpKeyPointSurf surf;
278  unsigned int nbrRef;
279 
280  if (opt_click_allowed && opt_display) {
281  std::cout << "Select a part of the image where the reference points "
282  "will be computed. This part is a rectangle."
283  << std::endl;
284  std::cout << "Click first on the top left corner and then on the "
285  "bottom right corner."
286  << std::endl;
287  vpImagePoint corners[2];
288  for (int i = 0; i < 2; i++) {
289  vpDisplay::getClick(Iref, corners[i]);
290  }
291 
292  vpDisplay::displayRectangle(Iref, corners[0], corners[1], vpColor::red);
293  vpDisplay::flush(Iref);
294  unsigned int height, width;
295  height = (unsigned int)(corners[1].get_i() - corners[0].get_i());
296  width = (unsigned int)(corners[1].get_j() - corners[0].get_j());
297 
298  // Computes the reference points
299  nbrRef = surf.buildReference(Iref, corners[0], height, width);
300  }
301 
302  else {
303  nbrRef = surf.buildReference(Iref);
304  }
305 
306  if (nbrRef < 1) {
307  std::cerr << "No reference point" << std::endl;
308  exit(-1);
309  }
310 
311  unsigned int nbrPair;
312  if (opt_display) {
313  display[1].init(Icur, (int)(100 + Iref.getWidth()), 100, "Current image");
314  // display variable.
315  vpDisplay::display(Icur);
316  // Flush the display
317  vpDisplay::flush(Icur);
318  }
319 
320  if (opt_click_allowed && opt_display) {
321  std::cout << "Select a part of the current image where the reference "
322  "will be search. This part is a rectangle."
323  << std::endl;
324  std::cout << "Click first on the top left corner and then on the "
325  "bottom right corner."
326  << std::endl;
327  vpImagePoint corners[2];
328  for (int i = 0; i < 2; i++) {
329  vpDisplay::getClick(Icur, corners[i]);
330  }
331  vpDisplay::displayRectangle(Icur, corners[0], corners[1], vpColor::green);
332  vpDisplay::flush(Icur);
333  unsigned int height, width;
334  height = (unsigned int)(corners[1].get_i() - corners[0].get_i());
335  width = (unsigned int)(corners[1].get_j() - corners[0].get_j());
336 
337  // Computes the reference points
338  nbrPair = surf.matchPoint(Icur, corners[0], height, width);
339  }
340 
341  else {
342  nbrPair = surf.matchPoint(Icur);
343  }
344 
345  if (nbrPair < 1) {
346  std::cout << "No point matched" << std::endl;
347  }
348 
349  if (opt_display) {
350  surf.display(Iref, Icur, 7);
351  vpDisplay::flush(Iref);
352  vpDisplay::flush(Icur);
353  if (opt_click_allowed) {
354  std::cout << "A click on the reference image to exit..." << std::endl;
355  vpDisplay::getClick(Iref);
356  }
357  }
358  return (0);
359  } catch (const vpException &e) {
360  std::cout << "Catch an exception: " << e << std::endl;
361  return (1);
362  }
363 }
364 #else
365 int main()
366 {
367  std::cerr << "You do not have 1.1.0 <= OpenCV < 2.3.0 that contains "
368  "opencv_nonfree component..."
369  << std::endl;
370 }
371 
372 #endif
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:149
double get_i() const
Definition: vpImagePoint.h:203
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1365
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:134
error that can be emited by ViSP classes.
Definition: vpException.h:71
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
static const vpColor green
Definition: vpColor.h:220
static void flush(const vpImage< unsigned char > &I)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
Class that implements the SURF key points and technics thanks to the OpenCV library.
static const vpColor red
Definition: vpColor.h:217
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1670
static void display(const vpImage< unsigned char > &I)
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
double get_j() const
Definition: vpImagePoint.h:214
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:134
static void displayRectangle(const vpImage< unsigned char > &I, const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
unsigned int getWidth() const
Definition: vpImage.h:246