Visual Servoing Platform version 3.6.0
Loading...
Searching...
No Matches
testKeyPoint-3.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 keypoint matching with mostly OpenCV functions calls
32 * to detect potential memory leaks in testKeyPoint.cpp.
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)
40
41#include <opencv2/features2d/features2d.hpp>
42
43#include <visp3/core/vpImage.h>
44#include <visp3/core/vpIoTools.h>
45#include <visp3/gui/vpDisplayGDI.h>
46#include <visp3/gui/vpDisplayGTK.h>
47#include <visp3/gui/vpDisplayOpenCV.h>
48#include <visp3/gui/vpDisplayX.h>
49#include <visp3/io/vpImageIo.h>
50#include <visp3/io/vpParseArgv.h>
51#include <visp3/io/vpVideoReader.h>
52
53// List of allowed command line options
54#define GETOPTARGS "cdh"
55
56void usage(const char *name, const char *badparam);
57bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display);
58
66void usage(const char *name, const char *badparam)
67{
68 fprintf(stdout, "\n\
69Test keypoints matching.\n\
70\n\
71SYNOPSIS\n\
72 %s [-c] [-d] [-h]\n",
73 name);
74
75 fprintf(stdout, "\n\
76OPTIONS: \n\
77\n\
78 -c\n\
79 Disable the mouse click. Useful to automate the \n\
80 execution of this program without human intervention.\n\
81\n\
82 -d \n\
83 Turn off the display.\n\
84\n\
85 -h\n\
86 Print the help.\n");
87
88 if (badparam)
89 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
90}
91
103bool getOptions(int argc, const char **argv, bool &click_allowed, bool &display)
104{
105 const char *optarg_;
106 int c;
107 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
108
109 switch (c) {
110 case 'c':
111 click_allowed = false;
112 break;
113 case 'd':
114 display = false;
115 break;
116 case 'h':
117 usage(argv[0], NULL);
118 return false;
119 break;
120
121 default:
122 usage(argv[0], optarg_);
123 return false;
124 break;
125 }
126 }
127
128 if ((c == 1) || (c == -1)) {
129 // standalone param or error
130 usage(argv[0], NULL);
131 std::cerr << "ERROR: " << std::endl;
132 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
133 return false;
134 }
135
136 return true;
137}
138
139template <typename Type>
140void run_test(const std::string &env_ipath, bool opt_click_allowed, bool opt_display, vpImage<Type> &Iref,
141 vpImage<Type> &Icur, vpImage<Type> &Imatch)
142{
143#if VISP_HAVE_DATASET_VERSION >= 0x030600
144 std::string ext("png");
145#else
146 std::string ext("pgm");
147#endif
148 // Set the path location of the image sequence
149 std::string dirname = vpIoTools::createFilePath(env_ipath, "mbt/cube");
150
151 // Build the name of the image files
152 std::string filenameRef = vpIoTools::createFilePath(dirname, "image0000." + ext);
153 vpImageIo::read(Iref, filenameRef);
154 std::string filenameCur = vpIoTools::createFilePath(dirname, "image%04d." + ext);
155
156 // Init keypoints
157 cv::Ptr<cv::FeatureDetector> detector;
158 cv::Ptr<cv::DescriptorExtractor> extractor;
159 cv::Ptr<cv::DescriptorMatcher> matcher;
160
161#if (VISP_HAVE_OPENCV_VERSION >= 0x030000)
162 detector = cv::ORB::create();
163 extractor = cv::ORB::create();
164#else
165 detector = cv::FeatureDetector::create("ORB");
166 extractor = cv::DescriptorExtractor::create("ORB");
167#endif
168 matcher = cv::DescriptorMatcher::create("BruteForce-Hamming");
169
170 std::vector<cv::KeyPoint> trainKeyPoints;
171 cv::Mat matImg, trainDescriptors;
172 vpImageConvert::convert(Iref, matImg);
173 detector->detect(matImg, trainKeyPoints);
174 extractor->compute(matImg, trainKeyPoints, trainDescriptors);
175
177 g.setFileName(filenameCur);
178 g.open(Icur);
179 g.acquire(Icur);
180
181 Imatch.resize(Icur.getHeight(), 2 * Icur.getWidth());
182 Imatch.insert(Iref, vpImagePoint(0, 0));
183
184#if defined(VISP_HAVE_X11)
185 vpDisplayX display;
186#elif defined(VISP_HAVE_GTK)
187 vpDisplayGTK display;
188#elif defined(VISP_HAVE_GDI)
189 vpDisplayGDI display;
190#elif defined(HAVE_OPENCV_HIGHGUI)
191 vpDisplayOpenCV display;
192#endif
193
194 if (opt_display) {
195 display.setDownScalingFactor(vpDisplay::SCALE_AUTO);
196 display.init(Imatch, 0, 0, "ORB keypoints matching");
197 }
198
199 bool opt_click = false;
201 while (!g.end()) {
202 g.acquire(Icur);
203 Imatch.insert(Icur, vpImagePoint(0, Icur.getWidth()));
204
205 if (opt_display) {
206 vpDisplay::display(Imatch);
207 }
208
209 vpImageConvert::convert(Icur, matImg);
210 std::vector<cv::KeyPoint> queryKeyPoints;
211 detector->detect(matImg, queryKeyPoints);
212
213 cv::Mat queryDescriptors;
214 extractor->compute(matImg, queryKeyPoints, queryDescriptors);
215
216 std::vector<std::vector<cv::DMatch> > knn_matches;
217 std::vector<cv::DMatch> matches;
218 matcher->knnMatch(queryDescriptors, trainDescriptors, knn_matches, 2);
219 for (std::vector<std::vector<cv::DMatch> >::const_iterator it = knn_matches.begin(); it != knn_matches.end();
220 ++it) {
221 if (it->size() > 1) {
222 double ratio = (*it)[0].distance / (*it)[1].distance;
223 if (ratio < 0.85) {
224 matches.push_back((*it)[0]);
225 }
226 }
227 }
228
229 if (opt_display) {
230 for (std::vector<cv::DMatch>::const_iterator it = matches.begin(); it != matches.end(); ++it) {
231 vpImagePoint leftPt(trainKeyPoints[(size_t)it->trainIdx].pt.y, trainKeyPoints[(size_t)it->trainIdx].pt.x);
232 vpImagePoint rightPt(queryKeyPoints[(size_t)it->queryIdx].pt.y,
233 queryKeyPoints[(size_t)it->queryIdx].pt.x + Iref.getWidth());
234 vpDisplay::displayLine(Imatch, leftPt, rightPt, vpColor::green);
235 }
236
237 vpDisplay::flush(Imatch);
238 }
239
240 // Click requested to process next image
241 if (opt_click_allowed && opt_display) {
242 if (opt_click) {
243 vpDisplay::getClick(Imatch, button, true);
244 if (button == vpMouseButton::button3) {
245 opt_click = false;
246 }
247 } else {
248 // Use right click to enable/disable step by step tracking
249 if (vpDisplay::getClick(Imatch, button, false)) {
250 if (button == vpMouseButton::button3) {
251 opt_click = true;
252 } else if (button == vpMouseButton::button1) {
253 break;
254 }
255 }
256 }
257 }
258 }
259}
260
267int main(int argc, const char **argv)
268{
269 try {
270 std::string env_ipath;
271 bool opt_click_allowed = true;
272 bool opt_display = true;
273
274 // Read the command line options
275 if (getOptions(argc, argv, opt_click_allowed, opt_display) == false) {
276 return EXIT_FAILURE;
277 }
278
279 // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
280 // environment variable value
282
283 if (env_ipath.empty()) {
284 std::cerr << "Please set the VISP_INPUT_IMAGE_PATH environment "
285 "variable value."
286 << std::endl;
287 return EXIT_FAILURE;
288 }
289
290 {
291 vpImage<unsigned char> Iref, Icur, Imatch;
292
293 std::cout << "-- Test on gray level images" << std::endl;
294 run_test(env_ipath, opt_click_allowed, opt_display, Iref, Icur, Imatch);
295 }
296
297 {
298 vpImage<vpRGBa> Iref, Icur, Imatch;
299
300 std::cout << "-- Test on color images" << std::endl;
301 run_test(env_ipath, opt_click_allowed, opt_display, Iref, Icur, Imatch);
302 }
303
304 } catch (const vpException &e) {
305 std::cerr << e.what() << std::endl;
306 return EXIT_FAILURE;
307 }
308
309 std::cout << "testKeyPoint-3 is ok !" << std::endl;
310 return EXIT_SUCCESS;
311}
312
313#else
314int main()
315{
316 std::cerr << "You need OpenCV library." << std::endl;
317
318 return EXIT_SUCCESS;
319}
320
321#endif
static const vpColor green
Definition vpColor.h:214
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 displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void flush(const vpImage< unsigned char > &I)
error that can be emitted by ViSP classes.
Definition vpException.h:59
const char * what() const
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
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 ...
Definition of the vpImage class member functions.
Definition vpImage.h:135
unsigned int getWidth() const
Definition vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:795
void insert(const vpImage< Type > &src, const vpImagePoint &topLeft)
Definition vpImage.h:1361
unsigned int getHeight() const
Definition vpImage.h:184
static std::string getViSPImagesDataPath()
static std::string createFilePath(const std::string &parent, const std::string &child)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
void acquire(vpImage< vpRGBa > &I)
void open(vpImage< vpRGBa > &I)
void setFileName(const std::string &filename)