Merge pull request #1263 from abidrahmank:pyCLAHE_24
[profile/ivi/opencv.git] / modules / legacy / doc / feature_detection_and_description.rst
1 Feature Detection and Description
2 =================================
3
4 .. highlight:: cpp
5
6 RandomizedTree
7 --------------
8 .. ocv:class:: RandomizedTree
9
10 Class containing a base structure for ``RTreeClassifier``. ::
11
12     class CV_EXPORTS RandomizedTree
13     {
14     public:
15             friend class RTreeClassifier;
16
17             RandomizedTree();
18             ~RandomizedTree();
19
20             void train(std::vector<BaseKeypoint> const& base_set,
21                      RNG &rng, int depth, int views,
22                      size_t reduced_num_dim, int num_quant_bits);
23             void train(std::vector<BaseKeypoint> const& base_set,
24                      RNG &rng, PatchGenerator &make_patch, int depth,
25                      int views, size_t reduced_num_dim, int num_quant_bits);
26
27             // next two functions are EXPERIMENTAL
28             //(do not use unless you know exactly what you do)
29             static void quantizeVector(float *vec, int dim, int N, float bnds[2],
30                      int clamp_mode=0);
31             static void quantizeVector(float *src, int dim, int N, float bnds[2],
32                      uchar *dst);
33
34             // patch_data must be a 32x32 array (no row padding)
35             float* getPosterior(uchar* patch_data);
36             const float* getPosterior(uchar* patch_data) const;
37             uchar* getPosterior2(uchar* patch_data);
38
39             void read(const char* file_name, int num_quant_bits);
40             void read(std::istream &is, int num_quant_bits);
41             void write(const char* file_name) const;
42             void write(std::ostream &os) const;
43
44             int classes() { return classes_; }
45             int depth() { return depth_; }
46
47             void discardFloatPosteriors() { freePosteriors(1); }
48
49             inline void applyQuantization(int num_quant_bits)
50                      { makePosteriors2(num_quant_bits); }
51
52     private:
53             int classes_;
54             int depth_;
55             int num_leaves_;
56             std::vector<RTreeNode> nodes_;
57             float **posteriors_;        // 16-byte aligned posteriors
58             uchar **posteriors2_;     // 16-byte aligned posteriors
59             std::vector<int> leaf_counts_;
60
61             void createNodes(int num_nodes, RNG &rng);
62             void allocPosteriorsAligned(int num_leaves, int num_classes);
63             void freePosteriors(int which);
64                      // which: 1=posteriors_, 2=posteriors2_, 3=both
65             void init(int classes, int depth, RNG &rng);
66             void addExample(int class_id, uchar* patch_data);
67             void finalize(size_t reduced_num_dim, int num_quant_bits);
68             int getIndex(uchar* patch_data) const;
69             inline float* getPosteriorByIndex(int index);
70             inline uchar* getPosteriorByIndex2(int index);
71             inline const float* getPosteriorByIndex(int index) const;
72             void convertPosteriorsToChar();
73             void makePosteriors2(int num_quant_bits);
74             void compressLeaves(size_t reduced_num_dim);
75             void estimateQuantPercForPosteriors(float perc[2]);
76     };
77
78 .. note::
79
80    * : PYTHON : An example using Randomized Tree training for letter recognition can be found at opencv_source_code/samples/python2/letter_recog.py
81
82 RandomizedTree::train
83 -------------------------
84 Trains a randomized tree using an input set of keypoints.
85
86 .. ocv:function:: void RandomizedTree::train( vector<BaseKeypoint> const& base_set, RNG & rng, int depth, int views, size_t reduced_num_dim, int num_quant_bits )
87
88 .. ocv:function:: void RandomizedTree::train( vector<BaseKeypoint> const& base_set, RNG & rng, PatchGenerator & make_patch, int depth, int views, size_t reduced_num_dim, int num_quant_bits )
89
90     :param base_set: Vector of the ``BaseKeypoint`` type. It contains image keypoints used for training.
91
92     :param rng: Random-number generator used for training.
93
94     :param make_patch: Patch generator used for training.
95
96     :param depth: Maximum tree depth.
97
98     :param views: Number of random views of each keypoint neighborhood to generate.
99
100     :param reduced_num_dim: Number of dimensions used in the compressed signature.
101
102     :param num_quant_bits: Number of bits used for quantization.
103
104 .. note::
105
106    * : An example on training a Random Tree Classifier for letter recognition can be found at opencv_source_code\samples\cpp\letter_recog.cpp
107
108 RandomizedTree::read
109 ------------------------
110 Reads a pre-saved randomized tree from a file or stream.
111
112 .. ocv:function:: RandomizedTree::read(const char* file_name, int num_quant_bits)
113
114 .. ocv:function:: RandomizedTree::read(std::istream &is, int num_quant_bits)
115
116     :param file_name: Name of the file that contains randomized tree data.
117
118     :param is: Input stream associated with the file that contains randomized tree data.
119
120     :param num_quant_bits: Number of bits used for quantization.
121
122
123
124 RandomizedTree::write
125 -------------------------
126 Writes the current randomized tree to a file or stream.
127
128 .. ocv:function:: void RandomizedTree::write(const char* file_name) const
129
130 .. ocv:function:: void RandomizedTree::write(std::ostream &os) const
131
132     :param file_name: Name of the file where randomized tree data is stored.
133
134     :param os: Output stream associated with the file where randomized tree data is stored.
135
136
137
138 RandomizedTree::applyQuantization
139 -------------------------------------
140 .. ocv:function:: void RandomizedTree::applyQuantization(int num_quant_bits)
141
142     Applies quantization to the current randomized tree.
143
144     :param num_quant_bits: Number of bits used for quantization.
145
146
147 RTreeNode
148 ---------
149 .. ocv:struct:: RTreeNode
150
151 Class containing a base structure for ``RandomizedTree``. ::
152
153     struct RTreeNode
154     {
155             short offset1, offset2;
156
157             RTreeNode() {}
158
159             RTreeNode(uchar x1, uchar y1, uchar x2, uchar y2)
160                     : offset1(y1*PATCH_SIZE + x1),
161                     offset2(y2*PATCH_SIZE + x2)
162             {}
163
164             //! Left child on 0, right child on 1
165             inline bool operator() (uchar* patch_data) const
166             {
167                     return patch_data[offset1] > patch_data[offset2];
168             }
169     };
170
171
172
173 RTreeClassifier
174 ---------------
175 .. ocv:class:: RTreeClassifier
176
177 Class containing ``RTreeClassifier``. It represents the Calonder descriptor originally introduced by Michael Calonder. ::
178
179     class CV_EXPORTS RTreeClassifier
180     {
181     public:
182             static const int DEFAULT_TREES = 48;
183             static const size_t DEFAULT_NUM_QUANT_BITS = 4;
184
185             RTreeClassifier();
186
187             void train(std::vector<BaseKeypoint> const& base_set,
188                     RNG &rng,
189                     int num_trees = RTreeClassifier::DEFAULT_TREES,
190                     int depth = DEFAULT_DEPTH,
191                     int views = DEFAULT_VIEWS,
192                     size_t reduced_num_dim = DEFAULT_REDUCED_NUM_DIM,
193                     int num_quant_bits = DEFAULT_NUM_QUANT_BITS,
194                              bool print_status = true);
195             void train(std::vector<BaseKeypoint> const& base_set,
196                     RNG &rng,
197                     PatchGenerator &make_patch,
198                     int num_trees = RTreeClassifier::DEFAULT_TREES,
199                     int depth = DEFAULT_DEPTH,
200                     int views = DEFAULT_VIEWS,
201                     size_t reduced_num_dim = DEFAULT_REDUCED_NUM_DIM,
202                     int num_quant_bits = DEFAULT_NUM_QUANT_BITS,
203                      bool print_status = true);
204
205             // sig must point to a memory block of at least
206             //classes()*sizeof(float|uchar) bytes
207             void getSignature(IplImage *patch, uchar *sig);
208             void getSignature(IplImage *patch, float *sig);
209             void getSparseSignature(IplImage *patch, float *sig,
210                      float thresh);
211
212             static int countNonZeroElements(float *vec, int n, double tol=1e-10);
213             static inline void safeSignatureAlloc(uchar **sig, int num_sig=1,
214                             int sig_len=176);
215             static inline uchar* safeSignatureAlloc(int num_sig=1,
216                              int sig_len=176);
217
218             inline int classes() { return classes_; }
219             inline int original_num_classes()
220                      { return original_num_classes_; }
221
222             void setQuantization(int num_quant_bits);
223             void discardFloatPosteriors();
224
225             void read(const char* file_name);
226             void read(std::istream &is);
227             void write(const char* file_name) const;
228             void write(std::ostream &os) const;
229
230             std::vector<RandomizedTree> trees_;
231
232     private:
233             int classes_;
234             int num_quant_bits_;
235             uchar **posteriors_;
236             ushort *ptemp_;
237             int original_num_classes_;
238             bool keep_floats_;
239     };
240
241
242
243 RTreeClassifier::train
244 --------------------------
245 Trains a randomized tree classifier using an input set of keypoints.
246
247 .. ocv:function:: void RTreeClassifier::train( vector<BaseKeypoint> const& base_set, RNG & rng, int num_trees=RTreeClassifier::DEFAULT_TREES, int depth=RandomizedTree::DEFAULT_DEPTH, int views=RandomizedTree::DEFAULT_VIEWS, size_t reduced_num_dim=RandomizedTree::DEFAULT_REDUCED_NUM_DIM, int num_quant_bits=DEFAULT_NUM_QUANT_BITS )
248
249 .. ocv:function:: void RTreeClassifier::train( vector<BaseKeypoint> const& base_set, RNG & rng, PatchGenerator & make_patch, int num_trees=RTreeClassifier::DEFAULT_TREES, int depth=RandomizedTree::DEFAULT_DEPTH, int views=RandomizedTree::DEFAULT_VIEWS, size_t reduced_num_dim=RandomizedTree::DEFAULT_REDUCED_NUM_DIM, int num_quant_bits=DEFAULT_NUM_QUANT_BITS )
250
251     :param base_set: Vector of the ``BaseKeypoint``  type. It contains image keypoints used for training.
252
253     :param rng: Random-number generator used for training.
254
255     :param make_patch: Patch generator used for training.
256
257     :param num_trees: Number of randomized trees used in ``RTreeClassificator`` .
258
259     :param depth: Maximum tree depth.
260
261     :param views: Number of random views of each keypoint neighborhood to generate.
262
263     :param reduced_num_dim: Number of dimensions used in the compressed signature.
264
265     :param num_quant_bits: Number of bits used for quantization.
266
267
268 RTreeClassifier::getSignature
269 ---------------------------------
270 Returns a signature for an image patch.
271
272 .. ocv:function:: void RTreeClassifier::getSignature(IplImage *patch, uchar *sig)
273
274 .. ocv:function:: void RTreeClassifier::getSignature(IplImage *patch, float *sig)
275
276     :param patch: Image patch to calculate the signature for.
277     :param sig: Output signature (array dimension is ``reduced_num_dim)`` .
278
279
280
281 RTreeClassifier::getSparseSignature
282 ---------------------------------------
283 Returns a sparse signature for an image patch
284
285 .. ocv:function:: void RTreeClassifier::getSparseSignature(IplImage *patch, float *sig, float thresh)
286
287     :param patch: Image patch to calculate the signature for.
288
289     :param sig: Output signature (array dimension is ``reduced_num_dim)`` .
290
291     :param thresh: Threshold used for compressing the signature.
292
293     Returns a signature for an image patch similarly to ``getSignature``  but uses a threshold for removing all signature elements below the threshold so that the signature is compressed.
294
295
296 RTreeClassifier::countNonZeroElements
297 -----------------------------------------
298 Returns the number of non-zero elements in an input array.
299
300 .. ocv:function:: static int RTreeClassifier::countNonZeroElements(float *vec, int n, double tol=1e-10)
301
302     :param vec: Input vector containing float elements.
303
304     :param n: Input vector size.
305
306     :param tol: Threshold used for counting elements. All elements less than ``tol``  are considered as zero elements.
307
308
309
310 RTreeClassifier::read
311 -------------------------
312 Reads a pre-saved ``RTreeClassifier`` from a file or stream.
313
314 .. ocv:function:: void RTreeClassifier::read(const char* file_name)
315
316 .. ocv:function:: void RTreeClassifier::read( std::istream & is )
317
318     :param file_name: Name of the file that contains randomized tree data.
319
320     :param is: Input stream associated with the file that contains randomized tree data.
321
322
323
324 RTreeClassifier::write
325 --------------------------
326 Writes the current ``RTreeClassifier`` to a file or stream.
327
328 .. ocv:function:: void RTreeClassifier::write(const char* file_name) const
329
330 .. ocv:function:: void RTreeClassifier::write(std::ostream &os) const
331
332     :param file_name: Name of the file where randomized tree data is stored.
333
334     :param os: Output stream associated with the file where randomized tree data is stored.
335
336
337
338 RTreeClassifier::setQuantization
339 ------------------------------------
340 Applies quantization to the current randomized tree.
341
342 .. ocv:function:: void RTreeClassifier::setQuantization(int num_quant_bits)
343
344     :param num_quant_bits: Number of bits used for quantization.
345
346 The example below demonstrates the usage of ``RTreeClassifier`` for matching the features. The features are extracted from the test and train images with SURF. Output is
347 :math:`best\_corr` and
348 :math:`best\_corr\_idx` arrays that keep the best probabilities and corresponding features indices for every train feature. ::
349
350     CvMemStorage* storage = cvCreateMemStorage(0);
351     CvSeq *objectKeypoints = 0, *objectDescriptors = 0;
352     CvSeq *imageKeypoints = 0, *imageDescriptors = 0;
353     CvSURFParams params = cvSURFParams(500, 1);
354     cvExtractSURF( test_image, 0, &imageKeypoints, &imageDescriptors,
355                      storage, params );
356     cvExtractSURF( train_image, 0, &objectKeypoints, &objectDescriptors,
357                      storage, params );
358
359     RTreeClassifier detector;
360     int patch_width = PATCH_SIZE;
361     iint patch_height = PATCH_SIZE;
362     vector<BaseKeypoint> base_set;
363     int i=0;
364     CvSURFPoint* point;
365     for (i=0;i<(n_points > 0 ? n_points : objectKeypoints->total);i++)
366     {
367             point=(CvSURFPoint*)cvGetSeqElem(objectKeypoints,i);
368             base_set.push_back(
369                     BaseKeypoint(point->pt.x,point->pt.y,train_image));
370     }
371
372             //Detector training
373      RNG rng( cvGetTickCount() );
374     PatchGenerator gen(0,255,2,false,0.7,1.3,-CV_PI/3,CV_PI/3,
375                             -CV_PI/3,CV_PI/3);
376
377     printf("RTree Classifier training...n");
378     detector.train(base_set,rng,gen,24,DEFAULT_DEPTH,2000,
379             (int)base_set.size(), detector.DEFAULT_NUM_QUANT_BITS);
380     printf("Donen");
381
382     float* signature = new float[detector.original_num_classes()];
383     float* best_corr;
384     int* best_corr_idx;
385     if (imageKeypoints->total > 0)
386     {
387             best_corr = new float[imageKeypoints->total];
388             best_corr_idx = new int[imageKeypoints->total];
389     }
390
391     for(i=0; i < imageKeypoints->total; i++)
392     {
393             point=(CvSURFPoint*)cvGetSeqElem(imageKeypoints,i);
394             int part_idx = -1;
395             float prob = 0.0f;
396
397             CvRect roi = cvRect((int)(point->pt.x) - patch_width/2,
398                     (int)(point->pt.y) - patch_height/2,
399                      patch_width, patch_height);
400             cvSetImageROI(test_image, roi);
401             roi = cvGetImageROI(test_image);
402             if(roi.width != patch_width || roi.height != patch_height)
403             {
404                     best_corr_idx[i] = part_idx;
405                     best_corr[i] = prob;
406             }
407             else
408             {
409                     cvSetImageROI(test_image, roi);
410                     IplImage* roi_image =
411                              cvCreateImage(cvSize(roi.width, roi.height),
412                              test_image->depth, test_image->nChannels);
413                     cvCopy(test_image,roi_image);
414
415                     detector.getSignature(roi_image, signature);
416                     for (int j = 0; j< detector.original_num_classes();j++)
417                     {
418                             if (prob < signature[j])
419                             {
420                                     part_idx = j;
421                                     prob = signature[j];
422                             }
423                     }
424
425                     best_corr_idx[i] = part_idx;
426                     best_corr[i] = prob;
427
428                     if (roi_image)
429                             cvReleaseImage(&roi_image);
430             }
431             cvResetImageROI(test_image);
432     }
433
434 ..