Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
testKeyPoint-5.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
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 https://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 keypoints detection with OpenCV, specially the Pyramid implementation
32 * feature misssing in OpenCV 3.0.
33 */
34
35#include <iostream>
36
37#include <visp3/core/vpConfig.h>
38
39#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_FEATURES2D) && defined(HAVE_OPENCV_VIDEO)
40
41#include <visp3/core/vpImage.h>
42#include <visp3/core/vpIoTools.h>
43#include <visp3/gui/vpDisplayGDI.h>
44#include <visp3/gui/vpDisplayGTK.h>
45#include <visp3/gui/vpDisplayOpenCV.h>
46#include <visp3/gui/vpDisplayX.h>
47#include <visp3/io/vpImageIo.h>
48#include <visp3/io/vpParseArgv.h>
49#include <visp3/vision/vpKeyPoint.h>
50
51// List of allowed command line options
52#define GETOPTARGS "cdh"
53
54void usage(const char *name, const char *badparam);
55bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display);
56
65void usage(const char *name, const char *badparam)
66{
67 fprintf(stdout, "\n\
68Test keypoints detection.\n\
69\n\
70SYNOPSIS\n\
71 %s [-c] [-d] [-h]\n",
72 name);
73
74 fprintf(stdout, "\n\
75OPTIONS: \n\
76\n\
77 -c\n\
78 Disable the mouse click. Useful to automate the \n\
79 execution of this program without human intervention.\n\
80\n\
81 -d \n\
82 Turn off the display.\n\
83\n\
84 -h\n\
85 Print the help.\n");
86
87 if (badparam)
88 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
89}
90
102bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display)
103{
104 const char *optarg_;
105 int c;
106 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
107
108 switch (c) {
109 case 'c':
110 click_allowed = false;
111 break;
112 case 'd':
113 display = false;
114 break;
115 case 'h':
116 usage(argv[0], NULL);
117 return false;
118 break;
119
120 default:
121 usage(argv[0], optarg_);
122 return false;
123 break;
124 }
125 }
126
127 if ((c == 1) || (c == -1)) {
128 // standalone param or error
129 usage(argv[0], NULL);
130 std::cerr << "ERROR: " << std::endl;
131 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
132 return false;
133 }
134
135 return true;
136}
137
138template <typename Type>
139void run_test(const std::string &env_ipath, bool opt_click_allowed, bool opt_display, vpImage<Type> &Iinput,
140 vpImage<Type> &I)
141{
142 // Set the path location of the image sequence
143 std::string dirname = vpIoTools::createFilePath(env_ipath, "Klimt");
144
145 // Build the name of the image files
146 std::string filename = vpIoTools::createFilePath(dirname, "/Klimt.png");
147 vpImageIo::read(Iinput, filename);
148 Iinput.halfSizeImage(I);
149
150#if defined(VISP_HAVE_X11)
151 vpDisplayX display;
152#elif defined(VISP_HAVE_GTK)
153 vpDisplayGTK display;
154#elif defined(VISP_HAVE_GDI)
155 vpDisplayGDI display;
156#elif defined(HAVE_OPENCV_HIGHGUI)
157 vpDisplayOpenCV display;
158#endif
159
160 if (opt_display) {
161 display.init(I, 0, 0, "KeyPoints detection.");
162 }
163
164 // Here, we want to test feature detection on a pyramid of images even for
165 // features that are scale invariant to detect potential problem in ViSP.
166 std::cout << "INFORMATION: " << std::endl;
167 std::cout << "Here, we want to test feature detection on a pyramid of images even for features "
168 "that are scale invariant to detect potential problem in ViSP."
169 << std::endl
170 << std::endl;
171 vpKeyPoint keyPoints;
172
173 // Will test the different types of keypoints detection to see if there is
174 // a problem between OpenCV versions, modules or constructors
175 std::vector<std::string> detectorNames;
176 detectorNames.push_back("PyramidFAST");
177 detectorNames.push_back("FAST");
178 detectorNames.push_back("PyramidMSER");
179 detectorNames.push_back("MSER");
180 detectorNames.push_back("PyramidGFTT");
181 detectorNames.push_back("GFTT");
182 detectorNames.push_back("PyramidSimpleBlob");
183 detectorNames.push_back("SimpleBlob");
184// In contrib modules
185#if (VISP_HAVE_OPENCV_VERSION < 0x030000) || defined(VISP_HAVE_OPENCV_XFEATURES2D)
186 detectorNames.push_back("PyramidSTAR");
187 detectorNames.push_back("STAR");
188#endif
189#if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
190 detectorNames.push_back("PyramidAGAST");
191 detectorNames.push_back("AGAST");
192#endif
193 detectorNames.push_back("PyramidORB");
194 detectorNames.push_back("ORB");
195#if (VISP_HAVE_OPENCV_VERSION >= 0x020403)
196 detectorNames.push_back("PyramidBRISK");
197 detectorNames.push_back("BRISK");
198#endif
199#if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
200 detectorNames.push_back("PyramidKAZE");
201 detectorNames.push_back("KAZE");
202 detectorNames.push_back("PyramidAKAZE");
203 detectorNames.push_back("AKAZE");
204#endif
205
206#if defined(VISP_HAVE_OPENCV_NONFREE) || defined(VISP_HAVE_OPENCV_XFEATURES2D) || \
207 (VISP_HAVE_OPENCV_VERSION >= 0x030411 && CV_MAJOR_VERSION < 4) || (VISP_HAVE_OPENCV_VERSION >= 0x040400)
208#if (VISP_HAVE_OPENCV_VERSION != 0x040504) && (VISP_HAVE_OPENCV_VERSION != 0x040505) && \
209 (VISP_HAVE_OPENCV_VERSION != 0x040600) && (VISP_HAVE_OPENCV_VERSION != 0x040700) && \
210 (defined(__APPLE__) && defined(__MACH__))
211 // SIFT is known to be unstable with OpenCV 4.5.4 and 4.5.5 on macOS (see #1048)
212 // Same for OpenCV 4.6.0 (see #1106) where it produces an Illegal Instruction error when OpenCV 4.6.0 is
213 // installed with brew. It seems working when OpenCV is build from source
214 detectorNames.push_back("PyramidSIFT");
215 detectorNames.push_back("SIFT");
216#endif
217#endif
218#if defined(VISP_HAVE_OPENCV_NONFREE) || defined(VISP_HAVE_OPENCV_XFEATURES2D)
219 detectorNames.push_back("PyramidSURF");
220 detectorNames.push_back("SURF");
221#endif
222
223 for (std::vector<std::string>::const_iterator itd = detectorNames.begin(); itd != detectorNames.end(); ++itd) {
224 keyPoints.setDetector(*itd);
225
226 std::vector<cv::KeyPoint> kpts;
227
228 keyPoints.detect(I, kpts);
229 std::cout << "Nb keypoints detected: " << kpts.size() << " for " << *itd << " method." << std::endl;
230 if (kpts.empty()) {
231 std::stringstream ss;
232 ss << "No keypoints detected with " << *itd << " and image: " << filename << "." << std::endl;
233 throw(vpException(vpException::fatalError, ss.str()));
234 }
235
236 if (opt_display) {
238
239 for (std::vector<cv::KeyPoint>::const_iterator it = kpts.begin(); it != kpts.end(); ++it) {
240 vpImagePoint imPt;
241 imPt.set_uv(it->pt.x, it->pt.y);
242
244 }
245
247
248 if (opt_click_allowed) {
250 }
251 }
252 }
253
254 std::cout << "\n\n";
255
256 std::map<vpKeyPoint::vpFeatureDetectorType, std::string> mapOfDetectorNames = keyPoints.getDetectorNames();
257 for (int i = 0; i < vpKeyPoint::DETECTOR_TYPE_SIZE; i++) {
258#if defined(VISP_HAVE_OPENCV_NONFREE) || defined(VISP_HAVE_OPENCV_XFEATURES2D) || \
259 (VISP_HAVE_OPENCV_VERSION >= 0x030411 && CV_MAJOR_VERSION < 4) || (VISP_HAVE_OPENCV_VERSION >= 0x040400)
260#if ((VISP_HAVE_OPENCV_VERSION == 0x040504) || (VISP_HAVE_OPENCV_VERSION == 0x040505) || \
261 (VISP_HAVE_OPENCV_VERSION == 0x040600) || (VISP_HAVE_OPENCV_VERSION == 0x040700)) && \
262 (defined(__APPLE__) && defined(__MACH__))
263 // SIFT is known to be unstable with OpenCV 4.5.4 and 4.5.5 on macOS (see #1048)
264 // Same for OpenCV 4.6.0 (see #1106) where it produces an Illegal Instruction error when OpenCV 4.6.0 is
265 // installed with brew. It seems working when OpenCV is build from source
266 if (i == vpKeyPoint::DETECTOR_SIFT) {
267 continue;
268 }
269#endif
270#endif
272
273 std::vector<cv::KeyPoint> kpts;
274
275 keyPoints.detect(I, kpts);
276 std::cout << "Nb keypoints detected: " << kpts.size() << " for "
277 << mapOfDetectorNames[(vpKeyPoint::vpFeatureDetectorType)i] << " method." << std::endl;
278 if (kpts.empty()) {
279 std::stringstream ss;
280 ss << "No keypoints detected with " << mapOfDetectorNames[(vpKeyPoint::vpFeatureDetectorType)i]
281 << " method and image: " << filename << "." << std::endl;
282 throw(vpException(vpException::fatalError, ss.str()));
283 }
284
285 if (opt_display) {
287
288 for (std::vector<cv::KeyPoint>::const_iterator it = kpts.begin(); it != kpts.end(); ++it) {
289 vpImagePoint imPt;
290 imPt.set_uv(it->pt.x, it->pt.y);
291
293 }
294
296
297 if (opt_click_allowed) {
299 }
300 }
301 }
302}
303
310int main(int argc, const char **argv)
311{
312 try {
313 std::string env_ipath;
314 bool opt_click_allowed = true;
315 bool opt_display = true;
316
317 // Read the command line options
318 if (getOptions(argc, argv, opt_click_allowed, opt_display) == false) {
319 exit(EXIT_FAILURE);
320 }
321
322 // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
323 // environment variable value
325
326 if (env_ipath.empty()) {
327 std::cerr << "Please set the VISP_INPUT_IMAGE_PATH environment "
328 "variable value."
329 << std::endl;
330 return EXIT_FAILURE;
331 }
332
333 {
334 vpImage<unsigned char> Iinput, I;
335
336 std::cout << "-- Test on gray level images" << std::endl;
337 run_test(env_ipath, opt_click_allowed, opt_display, Iinput, I);
338 }
339
340 {
341 vpImage<vpRGBa> Iinput, I;
342
343 std::cout << "-- Test on color images" << std::endl;
344 run_test(env_ipath, opt_click_allowed, opt_display, Iinput, I);
345 }
346
347 } catch (const vpException &e) {
348 std::cerr << e.what() << std::endl;
349 return EXIT_FAILURE;
350 }
351
352 std::cout << "testKeyPoint-5 is ok !" << std::endl;
353 return EXIT_SUCCESS;
354}
355#else
356#include <cstdlib>
357
358int main()
359{
360 std::cerr << "You need OpenCV library." << std::endl;
361
362 return EXIT_SUCCESS;
363}
364
365#endif
static const vpColor red
Definition vpColor.h:211
Display for windows using GDI (available on any windows 32 platform).
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition vpDisplayX.h:132
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
static void flush(const vpImage< unsigned char > &I)
error that can be emitted by ViSP classes.
Definition vpException.h:59
@ fatalError
Fatal error.
Definition vpException.h:84
const char * what() const
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void set_uv(double u, double v)
Definition of the vpImage class member functions.
Definition vpImage.h:135
void halfSizeImage(vpImage< Type > &res) const
Definition vpImage.h:1438
static std::string getViSPImagesDataPath()
static std::string createFilePath(const std::string &parent, const std::string &child)
Class that allows keypoints detection (and descriptors extraction) and matching thanks to OpenCV libr...
Definition vpKeyPoint.h:212
@ DETECTOR_TYPE_SIZE
Definition vpKeyPoint.h:274
void detect(const vpImage< unsigned char > &I, std::vector< cv::KeyPoint > &keyPoints, const vpRect &rectangle=vpRect())
std::map< vpFeatureDetectorType, std::string > getDetectorNames() const
Definition vpKeyPoint.h:520
void setDetector(const vpFeatureDetectorType &detectorType)
Definition vpKeyPoint.h:765
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)