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  * Class that implements the Fern classifier and the YAPE detector thanks
33  * to the OpenCV library.
34  *
35  * Authors:
36  * Romain Tallonneau
37  *
38  *****************************************************************************/
39 
40 #ifndef vpFernClassifier_H
41 #define vpFernClassifier_H
42 
43 #include <visp3/core/vpConfig.h>
44 
45 #include <string>
46 
47 #if (VISP_HAVE_OPENCV_VERSION >= 0x020000) &&                                                                          \
48     (VISP_HAVE_OPENCV_VERSION < 0x030000)  // Require opencv >= 2.0.0 and < 3.0.0
49 #if (VISP_HAVE_OPENCV_VERSION >= 0x020101) // Require opencv >= 2.1.1
50 #include <opencv2/features2d/features2d.hpp>
51 #include <opencv2/imgproc/imgproc.hpp>
52 #include <opencv2/legacy/legacy.hpp>
53 #elif (VISP_HAVE_OPENCV_VERSION >= 0x020000) // Require opencv >= 2.0.0
54 #include <cv.h>
55 #include <cvaux.hpp>
56 #endif
57 
58 #include <visp3/vision/vpBasicKeyPoint.h>
59 
60 /*!
61   \class vpFernClassifier
62   \ingroup group_vision_keypoints
63 
64   \brief Class that implements the Fern classifier and the YAPE detector
65   thanks to the OpenCV library.
66 
67   \deprecated This class is deprecated with OpenCV 3.0.0 or more recent.
68 
69   This class provides a way to detect and match point using the YAPE and
70   a Fern Classifiers, thanks to the OpenCV library (version >= 2.0)
71 
72   This class provides a tool to match points between a model and the current
73   image. The points of interests belonging to the model and the points
74   detected in the current image are given in pixels thanks to the vpImagePoint
75   class.
76 
77   For more details about the Ferns Classifier and the point detector,
78   see \cite Ozuysal10 and \cite Lepetit04c.
79 
80   To use this class, you first have to detect points in the model and train
81   the associated Fern classifier. Then, for each new grabbed image, You can
82   detect points and try to match them with the model.
83 
84   As training can requires up to several minutes, it is possible to save (in a
85   file) and load the classifier.
86 
87   The following small example shows how to use the class.
88 
89   \code
90 #include <visp3/core/vpImage.h>
91 #include <visp3/vision/vpFernClassifier.h>
92 
93 #if VISP_HAVE_OPENCV_VERSION >= 0x020000 // Fern classifier only available
94 since OpenCV-2.0.0 int main()
95 {
96   vpImage<unsigned char> Ireference;
97   vpImage<unsigned char> Icurrent;
98   vpFernClassifier fern;
99 
100   //First grab the reference image Ireference
101 
102   //Build the reference points.
103   fern.buildReference(Ireference);
104 
105   //Then grab another image which represents the current image Icurrent
106 
107   //Match points between the reference points and the points detected in the current image.
108   fern.matchPoint(Icurrent);
109 
110   //Display the matched points
111   fern.display(Ireference, Icurrent);
112 
113   return (0);
114 }
115 #else
116 int main() {}
117 #endif
118   \endcode
119 
120   It is also possible to create the reference thanks to only a part of the
121   reference image (not the whole image) and find points to match in only a
122   part of the current image. The small following example shows how to do this.
123 
124   \code
125 #include <visp3/core/vpDisplay.h>
126 #include <visp3/core/vpImage.h>
127 #include <visp3/vision/vpFernClassifier.h>
128 
129 #if VISP_HAVE_OPENCV_VERSION >= 0x020000 // Fern classifier only available
130 since OpenCV-2.0.0 int main()
131 {
132   vpImage<unsigned char> Ireference;
133   vpImage<unsigned char> Icurrent;
134   vpFernClassifier fern;
135 
136   //First grab the reference image Ireference
137 
138   //Select a part of the image by clicking on two points which define a rectangle
139   vpImagePoint corners[2];
140   for (int i=0 ; i < 2 ; i++)  {
141     vpDisplay::getClick(Ireference, corners[i]);
142   }
143 
144   //Build the reference points.
145   int nbrRef;
146   unsigned int height, width;
147   height = (unsigned int)(corners[1].get_i() - corners[0].get_i());
148   width = (unsigned int)(corners[1].get_j() - corners[0].get_j());
149   nbrRef = fern.buildReference(Ireference, corners[0], height, width);
150 
151   // Then grab another image which represents the current image Icurrent
152 
153   //Select a part of the image by clincking on two points which define a rectangle
154   for (int i=0 ; i < 2 ; i++) {
155     vpDisplay::getClick(Icurrent, corners[i]);
156   }
157 
158   // Match points between the reference points and the points detected in the current image.
159   int nbrMatched;
160   height = (unsigned int)(corners[1].get_i() - corners[0].get_i());
161   width = (unsigned int)(corners[1].get_j() - corners[0].get_j());
162   nbrMatched = fern.matchPoint(Icurrent, corners[0], height, width);
163 
164   // Display the matched points
165   fern.display(Ireference, Icurrent);
166 
167   return(0);
168 }
169 #else
170 int main() {}
171 #endif
172   \endcode
173 */
174 class VISP_EXPORT vpFernClassifier : public vpBasicKeyPoint
175 {
176 protected:
177   //! The points of interest detector.
178   cv::LDetector ldetector;
179 
180   //! The Fern classifier.
181   cv::FernClassifier fernClassifier;
182 
183   //! The patch generator (OpenCV format).
184   cv::PatchGenerator gen;
185 
186   //! Flag to indicate whether the classifier has been trained or not.
187   bool hasLearn;
188 
189   /* parameters for the key-points detector and the classifier */
190   //! Threshold to accept or reject points (usually around 20)
191   int threshold;
192   //! Number of view to generate for the training
193   int nbView;
194   //! Minimal distance between two points
195   int dist;
196   //! Number of classifier
197   int nbClassfier;
198   //! Size of the classifier
199   int ClassifierSize;
200   //! Number of octave for the multi scale
201   int nbOctave;
202   //! Size of the patch
203   int patchSize;
204   //! Radius for the detector
205   int radius;
206   //! Maximal number of points
207   int nbPoints;
208 
209   /* parameters for the filter */
210   //! Flag to specify whether the reference image have to be blurred or not in
211   //! order to improve the recognition rate
212   bool blurImage;
213   //! Radius of the kernel used to blur the image
214   int radiusBlur;
215   //! Sigma of the kernel used to blur the image
216   int sigmaBlur;
217 
218   //! Number of minimum point below which the homography is not estimated
219   //! (must be at least four)
220   unsigned int nbMinPoint;
221 
222 //! The current image in the OpenCV format.
223 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
224   cv::Mat curImg;
225 #else
226   IplImage *curImg;
227 #endif
228 
229   //! keypoints detected in the reference image.
230   std::vector<cv::KeyPoint> objKeypoints;
231   //! the ROI in the reference image.
232   cv::Rect modelROI_Ref;
233   //! the ROI for the reference image.
234   cv::Rect modelROI;
235   //! the vector containing the points in the model.
236   std::vector<cv::KeyPoint> modelPoints;
237   //! the vector containing the points in the current image.
238   std::vector<cv::KeyPoint> imgKeypoints;
239   //! vector in the OpenCV format to be used by the detector.
240   std::vector<cv::Point2f> refPt, curPt;
241 
242 public:
243   vpFernClassifier();
244   vpFernClassifier(const std::string &_dataFile, const std::string &_objectName);
245   virtual ~vpFernClassifier();
246 
247   /* build reference */
248   virtual unsigned int buildReference(const vpImage<unsigned char> &I);
249   virtual unsigned int buildReference(const vpImage<unsigned char> &_I, const vpImagePoint &_iP,
250                                       unsigned int _height, unsigned int _width);
251   virtual unsigned int buildReference(const vpImage<unsigned char> &I, const vpRect &rectangle);
252 
253   /* matching */
254   virtual unsigned int matchPoint(const vpImage<unsigned char> &I);
255   virtual unsigned int matchPoint(const vpImage<unsigned char> &_I, const vpImagePoint &_iP, unsigned int _height,
256                                   unsigned int _width);
257   virtual unsigned int matchPoint(const vpImage<unsigned char> &I, const vpRect &rectangle);
258 
259   /* display */
260   virtual void display(const vpImage<unsigned char> &Iref, const vpImage<unsigned char> &Icurrent,
261                        unsigned int size = 3);
262   virtual void display(const vpImage<unsigned char> &Icurrent, unsigned int size = 3,
263                        const vpColor &color = vpColor::green);
264 
265   /* io methods */
266   void load(const std::string &_dataFile, const std::string & /*_objectName*/);
267   void record(const std::string &_objectName, const std::string &_dataFile);
268 
269   /* accessors */
270   /*!
271     The image is blurred before being processed. This solution can lead to a
272     better recognition rate.
273 
274     \param _blur : the new option for the blur
275   */
setBlurSetting(const bool _blur)276   inline void setBlurSetting(const bool _blur) { blurImage = _blur; }
277   inline void setBlurSettings(const bool _blur, int _sigma, int _size);
278 
279   /*!
280     Return the blur option.
281     The Blur option is used to activate a filter used to blur the input image.
282     The blurring can improve the robustness of the detection.
283 
284     \return the value of the blur option.
285   */
getBlurSetting()286   inline bool getBlurSetting() { return blurImage; }
287 
288   /*!
289     Return the blur sigma (for the filter) option.
290 
291     \return The value of the sigma for the blur filter.
292   */
getBlurSigma()293   inline int getBlurSigma() { return this->sigmaBlur; }
294 
295   /*!
296     return the blur size (for the filter) option
297 
298     \return the value of the radius for the blur filter
299   */
getBlurSize()300   inline int getBlurSize() { return this->radiusBlur; }
301 
302   /*!
303     Return a reference on the vector of reference points in the OpenCV format
304 
305     \return the list of reference points
306   */
getRefPt()307   const std::vector<cv::Point2f> &getRefPt() const { return refPt; }
308 
309   /*!
310     Return a reference on the vector of current points in the OpenCV format
311 
312     \return the list of current points
313   */
getCurPt()314   const std::vector<cv::Point2f> &getCurPt() const { return curPt; }
315 
316   /*!
317     Return the region of interest in the OpenCV format
318   */
getModelROI()319   cv::Rect getModelROI() const { return modelROI; }
320 
321 protected:
322   void setImage(const vpImage<unsigned char> &I);
323   void train();
324   virtual void init();
325 };
326 
327 #endif /* opencv ver > 2.0.0 */
328 
329 #endif
330