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  * Key point Surf.
33  *
34  * Authors:
35  * Nicolas Melchior
36  *
37  *****************************************************************************/
38 
39 #ifndef vpKeyPointSurf_H
40 #define vpKeyPointSurf_H
41 
42 /*!
43   \file vpKeyPointSurf.h
44   \ingroup group_detection_keypoint
45 
46   \brief Class that implements the SURF key points and technics thanks
47   to the OpenCV library.
48 */
49 
50 #include <visp3/vision/vpBasicKeyPoint.h>
51 
52 #include <list>
53 #include <vector>
54 
55 #if defined(VISP_HAVE_OPENCV_NONFREE) && (VISP_HAVE_OPENCV_VERSION < 0x030000)
56 
57 #if (VISP_HAVE_OPENCV_VERSION >= 0x020400) // Require opencv >= 1.1.0 < 3.0.0
58 #include <opencv2/core/core.hpp>
59 #include <opencv2/features2d/features2d.hpp>
60 #include <opencv2/legacy/compat.hpp>
61 #include <opencv2/nonfree/nonfree.hpp>
62 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
63 #include <opencv2/features2d/features2d.hpp>
64 #elif (VISP_HAVE_OPENCV_VERSION >= 0x010100) // Require opencv >= 1.1.0
65 #include <cv.h>
66 #include <cxcore.h>
67 #endif
68 
69 /*!
70   \class vpKeyPointSurf
71   \ingroup group_vision_keypoints
72 
73   \brief Class that implements the SURF key points and technics thanks
74   to OpenCV library.
75 
76   \deprecated This class is deprecated with OpenCV 3.0.0 or more recent.
77   You should rather use vpKeyPoint class that is more generic.
78 
79   The goal of this class is to provide a tool to match points from a
80   model and points belonging to an image in which the model appears.
81   The coordinates of the different reference points and matched points
82   are given in pixel thanks to the class vpImagePoint. In this
83   documentation we do not explain the SURF technics. So if you want to
84   learn more about it you can refer to the following article :
85   Herbert Bay, Tinne Tuytelaars and Luc Van Gool "SURF: Speeded Up
86   Robust Features", Proceedings of the 9th European Conference on
87   Computer Vision, Springer LNCS volume 3951, part 1, pp 404--417,
88   2006.
89 
90   If you use this class the first things you have to do is to create
91   the reference thanks to a reference image which contains the
92   interesting object to detect. Then you have to grab other images
93   containing the object. After calling the specific method to match
94   points you can access to the lists of matched points thanks to the
95   methods getMatchedPointsInReferenceImage() and
96   getMatchedPointsInCurrentImage(). These two methods return a list of
97   matched points. The nth element of the first list is matched with
98   the nth element of the second list. The following small example show
99   how to use the class.
100 
101   \code
102 #include <visp3/core/vpConfig.h>
103 #include <visp3/core/vpImage.h>
104 #include <visp3/vision/vpKeyPointSurf.h>
105 
106 int main()
107 {
108 #if defined (VISP_HAVE_OPENCV_NONFREE) && (VISP_HAVE_OPENCV_VERSION < 0x030000)
109   vpImage<unsigned char> Ireference; vpImage<unsigned char> Icurrent;
110   vpKeyPointSurf surf;
111 
112   // First grab the reference image Ireference
113 
114   // Build the reference SURF points.
115   surf.buildReference(Ireference);
116 
117   // Then grab another image which represents the current image Icurrent
118 
119   // Match points between the reference points and the SURF points computed in the current image.
120   surf.matchPoint(Icurrent);
121 
122   // Display the matched points
123   surf.display(Ireference, Icurrent);
124 
125   return (0);
126 #endif
127 }
128   \endcode
129 
130   It is also possible to create the reference thanks to only a part of the
131   reference image (not the whole image) and find points to match in only a
132   part of the current image. The small following example shows how to this
133 
134   \code
135 #include <visp3/core/vpDisplay.h>
136 #include <visp3/core/vpImage.h>
137 #include <visp3/vision/vpKeyPointSurf.h>
138 
139 int main()
140 {
141 #if defined (VISP_HAVE_OPENCV_NONFREE) && (VISP_HAVE_OPENCV_VERSION < 0x030000)
142   vpImage<unsigned char> Ireference; vpImage<unsigned char> Icurrent;
143   vpKeyPointSurf surf;
144 
145   //First grab the reference image Ireference
146 
147   //Select a part of the image by clincking on two points which define a rectangle
148   vpImagePoint corners[2]; for (int i=0 ; i < 2 ; i++) {
149     vpDisplay::getClick(Ireference, corners[i]);
150   }
151 
152   //Build the reference SURF points.
153   int nbrRef;
154   unsigned int height, width;
155   height = (unsigned int)(corners[1].get_i() - corners[0].get_i());
156   width = (unsigned int)(corners[1].get_j() - corners[0].get_j());
157   nbrRef = surf.buildReference(Ireference, corners[0], height, width);
158 
159   //Then grab another image which represents the current image Icurrent
160 
161   //Select a part of the image by clincking on two points which define a rectangle
162   for (int i=0 ; i < 2 ; i++) {
163     vpDisplay::getClick(Icurrent, corners[i]);
164   }
165 
166   //Match points between the reference points and the SURF points computed in the current image.
167   int nbrMatched;
168   height = (unsigned int)(corners[1].get_i() - corners[0].get_i());
169   width = (unsigned int)(corners[1].get_j() - corners[0].get_j());
170   nbrMatched = surf.matchPoint(Icurrent, corners[0], height, width);
171 
172   //Display the matched points
173   surf.display(Ireference, Icurrent);
174 
175   return(0);
176 #endif
177 }
178   \endcode
179 
180   This class is also described in \ref tutorial-matching.
181 */
182 
183 class VISP_EXPORT vpKeyPointSurf : public vpBasicKeyPoint
184 {
185 public:
186   /*!
187     This enumerate enables to set the detail level of the
188     descriptors.
189   */
190   typedef enum {
191     basicDescriptor,   /*<! basicDescriptor means that the descriptors are
192                          composed by 64 elements floating-point vector. */
193     extendedDescriptor /*<! Means that the descriptors are composed by
194                          128 elements floating-point vector. */
195   } vpDescriptorType;
196 
197 public:
198   vpKeyPointSurf();
199 
200   virtual ~vpKeyPointSurf();
201 
202   unsigned int buildReference(const vpImage<unsigned char> &I);
203   unsigned int buildReference(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int height,
204                               unsigned int width);
205   unsigned int buildReference(const vpImage<unsigned char> &I, const vpRect &rectangle);
206   unsigned int matchPoint(const vpImage<unsigned char> &I);
207   unsigned int matchPoint(const vpImage<unsigned char> &I, const vpImagePoint &iP, unsigned int height,
208                           unsigned int width);
209   unsigned int matchPoint(const vpImage<unsigned char> &I, const vpRect &rectangle);
210   void display(const vpImage<unsigned char> &Iref, const vpImage<unsigned char> &Icurrent, unsigned int size = 3);
211   void display(const vpImage<unsigned char> &Icurrent, unsigned int size = 3, const vpColor &color = vpColor::green);
212   std::list<int *> *matchPoint(std::list<float *> descriptorList, std::list<int> laplacianList);
213   float *getDescriptorReferencePoint(int index);
214   int getLaplacianReferencePoint(int index);
215   void getDescriptorParamReferencePoint(int index, int &size, float &dir);
216   /*!
217 
218     Sets the value of the hessian threhold.  Note that during the
219     computation of the hessian for each potential points, only the
220     points which have a hessian value higher than the threshold are
221     keeped.  Fore more details about the threshold see the article
222     Herbert Bay, Tinne Tuytelaars and Luc Van Gool "SURF: Speeded Up
223     Robust Features", Proceedings of the 9th European Conference on
224     Computer Vision, Springer LNCS volume 3951, part 1, pp 404--417,
225     2006.
226 
227     \param hessian_threshold : Desired hessian threshold value.
228   */
setHessianThreshold(double hessian_threshold)229   void setHessianThreshold(double hessian_threshold)
230   {
231     this->hessianThreshold = hessian_threshold;
232     params = cvSURFParams(this->hessianThreshold, this->descriptorType);
233   };
234 
235   /*!
236 
237     Sets the type of descriptors to use.
238 
239     \param descriptor_type : Type of descriptor to use.
240   */
setDescriptorType(vpDescriptorType descriptor_type)241   void setDescriptorType(vpDescriptorType descriptor_type)
242   {
243     this->descriptorType = descriptor_type;
244     params = cvSURFParams(this->hessianThreshold, this->descriptorType);
245   };
246 
247   /*!
248     Gets the value of the hessian threhold.
249 
250     \return the hessian threshold value.
251   */
getHessianThreshold()252   double getHessianThreshold() { return hessianThreshold; }
253 
254   /*!
255     Gets the type of descriptor used.
256 
257     \return the type of descriptor used.
258   */
getDescriptorType()259   vpDescriptorType getDescriptorType() { return descriptorType; }
260 
261 private:
262   void init();
263 
264 private:
265   // OpenCV Parameters
266   CvMemStorage *storage;
267   CvSURFParams params;
268   CvMemStorage *storage_cur;
269 
270   CvSeq *image_keypoints;
271   CvSeq *image_descriptors;
272 
273   CvSeq *ref_keypoints;
274   CvSeq *ref_descriptors;
275 
276   /*!
277     only features with keypoint.hessian larger than that are extracted.
278     Good default value is ~300-500 (can depend on the average
279     local contrast and sharpness of the image).
280     User can further filter out some features based on their hessian values
281     and other characteristics.
282   */
283   double hessianThreshold;
284   vpDescriptorType descriptorType;
285 };
286 
287 #endif
288 
289 #endif
290