Update to 2.0.0 tree from current Fremantle build
[opencv] / include / opencv / cvaux.hpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////\r
2 //\r
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.\r
4 //\r
5 //  By downloading, copying, installing or using the software you agree to this license.\r
6 //  If you do not agree to this license, do not download, install,\r
7 //  copy or use the software.\r
8 //\r
9 //\r
10 //                        Intel License Agreement\r
11 //                For Open Source Computer Vision Library\r
12 //\r
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.\r
14 // Third party copyrights are property of their respective owners.\r
15 //\r
16 // Redistribution and use in source and binary forms, with or without modification,\r
17 // are permitted provided that the following conditions are met:\r
18 //\r
19 //   * Redistribution's of source code must retain the above copyright notice,\r
20 //     this list of conditions and the following disclaimer.\r
21 //\r
22 //   * Redistribution's in binary form must reproduce the above copyright notice,\r
23 //     this list of conditions and the following disclaimer in the documentation\r
24 //     and/or other materials provided with the distribution.\r
25 //\r
26 //   * The name of Intel Corporation may not be used to endorse or promote products\r
27 //     derived from this software without specific prior written permission.\r
28 //\r
29 // This software is provided by the copyright holders and contributors "as is" and\r
30 // any express or implied warranties, including, but not limited to, the implied\r
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.\r
32 // In no event shall the Intel Corporation or contributors be liable for any direct,\r
33 // indirect, incidental, special, exemplary, or consequential damages\r
34 // (including, but not limited to, procurement of substitute goods or services;\r
35 // loss of use, data, or profits; or business interruption) however caused\r
36 // and on any theory of liability, whether in contract, strict liability,\r
37 // or tort (including negligence or otherwise) arising in any way out of\r
38 // the use of this software, even if advised of the possibility of such damage.\r
39 //\r
40 //M*/\r
41 \r
42 #ifndef __CVAUX_HPP__\r
43 #define __CVAUX_HPP__\r
44 \r
45 #ifdef __cplusplus\r
46 \r
47 #include <iosfwd>\r
48 \r
49 /****************************************************************************************\\r
50 *                                       CamShiftTracker                                  *\r
51 \****************************************************************************************/\r
52 \r
53 class CV_EXPORTS CvCamShiftTracker\r
54 {\r
55 public:\r
56 \r
57     CvCamShiftTracker();\r
58     virtual ~CvCamShiftTracker();\r
59 \r
60     /**** Characteristics of the object that are calculated by track_object method *****/\r
61     float   get_orientation() const // orientation of the object in degrees\r
62     { return m_box.angle; }\r
63     float   get_length() const // the larger linear size of the object\r
64     { return m_box.size.height; }\r
65     float   get_width() const // the smaller linear size of the object\r
66     { return m_box.size.width; }\r
67     CvPoint2D32f get_center() const // center of the object\r
68     { return m_box.center; }\r
69     CvRect get_window() const // bounding rectangle for the object\r
70     { return m_comp.rect; }\r
71 \r
72     /*********************** Tracking parameters ************************/\r
73     int     get_threshold() const // thresholding value that applied to back project\r
74     { return m_threshold; }\r
75 \r
76     int     get_hist_dims( int* dims = 0 ) const // returns number of histogram dimensions and sets\r
77     { return m_hist ? cvGetDims( m_hist->bins, dims ) : 0; }\r
78 \r
79     int     get_min_ch_val( int channel ) const // get the minimum allowed value of the specified channel\r
80     { return m_min_ch_val[channel]; }\r
81 \r
82     int     get_max_ch_val( int channel ) const // get the maximum allowed value of the specified channel\r
83     { return m_max_ch_val[channel]; }\r
84 \r
85     // set initial object rectangle (must be called before initial calculation of the histogram)\r
86     bool    set_window( CvRect window)\r
87     { m_comp.rect = window; return true; }\r
88 \r
89     bool    set_threshold( int threshold ) // threshold applied to the histogram bins\r
90     { m_threshold = threshold; return true; }\r
91 \r
92     bool    set_hist_bin_range( int dim, int min_val, int max_val );\r
93 \r
94     bool    set_hist_dims( int c_dims, int* dims );// set the histogram parameters\r
95 \r
96     bool    set_min_ch_val( int channel, int val ) // set the minimum allowed value of the specified channel\r
97     { m_min_ch_val[channel] = val; return true; }\r
98     bool    set_max_ch_val( int channel, int val ) // set the maximum allowed value of the specified channel\r
99     { m_max_ch_val[channel] = val; return true; }\r
100 \r
101     /************************ The processing methods *********************************/\r
102     // update object position\r
103     virtual bool  track_object( const IplImage* cur_frame );\r
104 \r
105     // update object histogram\r
106     virtual bool  update_histogram( const IplImage* cur_frame );\r
107 \r
108     // reset histogram\r
109     virtual void  reset_histogram();\r
110 \r
111     /************************ Retrieving internal data *******************************/\r
112     // get back project image\r
113     virtual IplImage* get_back_project()\r
114     { return m_back_project; }\r
115 \r
116     float query( int* bin ) const\r
117     { return m_hist ? (float)cvGetRealND(m_hist->bins, bin) : 0.f; }\r
118 \r
119 protected:\r
120 \r
121     // internal method for color conversion: fills m_color_planes group\r
122     virtual void color_transform( const IplImage* img );\r
123 \r
124     CvHistogram* m_hist;\r
125 \r
126     CvBox2D    m_box;\r
127     CvConnectedComp m_comp;\r
128 \r
129     float      m_hist_ranges_data[CV_MAX_DIM][2];\r
130     float*     m_hist_ranges[CV_MAX_DIM];\r
131 \r
132     int        m_min_ch_val[CV_MAX_DIM];\r
133     int        m_max_ch_val[CV_MAX_DIM];\r
134     int        m_threshold;\r
135 \r
136     IplImage*  m_color_planes[CV_MAX_DIM];\r
137     IplImage*  m_back_project;\r
138     IplImage*  m_temp;\r
139     IplImage*  m_mask;\r
140 };\r
141 \r
142 /****************************************************************************************\\r
143 *                                   Adaptive Skin Detector                               *\r
144 \****************************************************************************************/\r
145 \r
146 class CV_EXPORTS CvAdaptiveSkinDetector\r
147 {\r
148 private:\r
149         enum {\r
150                 GSD_HUE_LT = 3,\r
151                 GSD_HUE_UT = 33,\r
152                 GSD_INTENSITY_LT = 15,\r
153                 GSD_INTENSITY_UT = 250\r
154         };\r
155 \r
156         class CV_EXPORTS Histogram\r
157         {\r
158         private:\r
159                 enum {\r
160                         HistogramSize = (GSD_HUE_UT - GSD_HUE_LT + 1)\r
161                 };\r
162 \r
163         protected:\r
164                 int findCoverageIndex(double surfaceToCover, int defaultValue = 0);\r
165 \r
166         public:\r
167                 CvHistogram *fHistogram;\r
168                 Histogram();\r
169                 virtual ~Histogram();\r
170 \r
171                 void findCurveThresholds(int &x1, int &x2, double percent = 0.05);\r
172                 void mergeWith(Histogram *source, double weight);\r
173         };\r
174 \r
175         int nStartCounter, nFrameCount, nSkinHueLowerBound, nSkinHueUpperBound, nMorphingMethod, nSamplingDivider;\r
176         double fHistogramMergeFactor, fHuePercentCovered;\r
177         Histogram histogramHueMotion, skinHueHistogram;\r
178         IplImage *imgHueFrame, *imgSaturationFrame, *imgLastGrayFrame, *imgMotionFrame, *imgFilteredFrame;\r
179         IplImage *imgShrinked, *imgTemp, *imgGrayFrame, *imgHSVFrame;\r
180 \r
181 protected:\r
182         void initData(IplImage *src, int widthDivider, int heightDivider);\r
183         void adaptiveFilter();\r
184 \r
185 public:\r
186 \r
187         enum {\r
188                 MORPHING_METHOD_NONE = 0,\r
189                 MORPHING_METHOD_ERODE = 1,\r
190                 MORPHING_METHOD_ERODE_ERODE     = 2,\r
191                 MORPHING_METHOD_ERODE_DILATE = 3\r
192         };\r
193 \r
194         CvAdaptiveSkinDetector(int samplingDivider = 1, int morphingMethod = MORPHING_METHOD_NONE);\r
195         virtual ~CvAdaptiveSkinDetector();\r
196 \r
197         virtual void process(IplImage *inputBGRImage, IplImage *outputHueMask);\r
198 };\r
199 \r
200 \r
201 /****************************************************************************************\\r
202 *                                  Fuzzy MeanShift Tracker                               *\r
203 \****************************************************************************************/\r
204 \r
205 class CV_EXPORTS CvFuzzyPoint {\r
206 public:\r
207         double x, y, value;\r
208 \r
209         CvFuzzyPoint(double _x, double _y);\r
210 };\r
211 \r
212 class CV_EXPORTS CvFuzzyCurve {\r
213 private:\r
214     std::vector<CvFuzzyPoint> points;\r
215         double value, centre;\r
216 \r
217         bool between(double x, double x1, double x2);\r
218 \r
219 public:\r
220         CvFuzzyCurve();\r
221         ~CvFuzzyCurve();\r
222 \r
223         void setCentre(double _centre);\r
224         double getCentre();\r
225         void clear();\r
226         void addPoint(double x, double y);\r
227         double calcValue(double param);\r
228         double getValue();\r
229         void setValue(double _value);\r
230 };\r
231 \r
232 class CV_EXPORTS CvFuzzyFunction {\r
233 public:\r
234     std::vector<CvFuzzyCurve> curves;\r
235 \r
236         CvFuzzyFunction();\r
237         ~CvFuzzyFunction();\r
238         void addCurve(CvFuzzyCurve *curve, double value = 0);\r
239         void resetValues();\r
240         double calcValue();\r
241         CvFuzzyCurve *newCurve();\r
242 };\r
243 \r
244 class CV_EXPORTS CvFuzzyRule {\r
245 private:\r
246         CvFuzzyCurve *fuzzyInput1, *fuzzyInput2;\r
247         CvFuzzyCurve *fuzzyOutput;\r
248 public:\r
249         CvFuzzyRule();\r
250         ~CvFuzzyRule();\r
251         void setRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1);\r
252         double calcValue(double param1, double param2);\r
253         CvFuzzyCurve *getOutputCurve();\r
254 };\r
255 \r
256 class CV_EXPORTS CvFuzzyController {\r
257 private:\r
258     std::vector<CvFuzzyRule*> rules;\r
259 public:\r
260         CvFuzzyController();\r
261         ~CvFuzzyController();\r
262         void addRule(CvFuzzyCurve *c1, CvFuzzyCurve *c2, CvFuzzyCurve *o1);\r
263         double calcOutput(double param1, double param2);\r
264 };\r
265 \r
266 class CV_EXPORTS CvFuzzyMeanShiftTracker\r
267 {\r
268 private:\r
269         class FuzzyResizer\r
270         {\r
271         private:\r
272                 CvFuzzyFunction iInput, iOutput;\r
273                 CvFuzzyController fuzzyController;\r
274         public:\r
275                 FuzzyResizer();\r
276                 int calcOutput(double edgeDensity, double density);\r
277         };\r
278 \r
279         class SearchWindow\r
280         {\r
281         public:\r
282                 FuzzyResizer *fuzzyResizer;\r
283                 int x, y;\r
284                 int width, height, maxWidth, maxHeight, ellipseHeight, ellipseWidth;\r
285                 int ldx, ldy, ldw, ldh, numShifts, numIters;\r
286                 int xGc, yGc;\r
287                 long m00, m01, m10, m11, m02, m20;\r
288                 double ellipseAngle;\r
289                 double density;\r
290                 unsigned int depthLow, depthHigh;\r
291                 int verticalEdgeLeft, verticalEdgeRight, horizontalEdgeTop, horizontalEdgeBottom;\r
292 \r
293                 SearchWindow();\r
294                 ~SearchWindow();\r
295                 void setSize(int _x, int _y, int _width, int _height);\r
296                 void initDepthValues(IplImage *maskImage, IplImage *depthMap);\r
297                 bool shift();\r
298                 void extractInfo(IplImage *maskImage, IplImage *depthMap, bool initDepth);\r
299                 void getResizeAttribsEdgeDensityLinear(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh);\r
300                 void getResizeAttribsInnerDensity(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh);\r
301                 void getResizeAttribsEdgeDensityFuzzy(int &resizeDx, int &resizeDy, int &resizeDw, int &resizeDh);\r
302                 bool meanShift(IplImage *maskImage, IplImage *depthMap, int maxIteration, bool initDepth);\r
303         };\r
304 \r
305 public:\r
306         enum TrackingState\r
307         {\r
308                 tsNone                  = 0,\r
309                 tsSearching     = 1,\r
310                 tsTracking              = 2,\r
311                 tsSetWindow     = 3,\r
312                 tsDisabled              = 10\r
313         };\r
314 \r
315         enum ResizeMethod {\r
316                 rmEdgeDensityLinear             = 0,\r
317                 rmEdgeDensityFuzzy              = 1,\r
318                 rmInnerDensity                  = 2\r
319         };\r
320 \r
321         enum {\r
322                 MinKernelMass                   = 1000\r
323         };\r
324 \r
325         SearchWindow kernel;\r
326         int searchMode;\r
327 \r
328 private:\r
329         enum\r
330         {\r
331                 MaxMeanShiftIteration   = 5,\r
332                 MaxSetSizeIteration     = 5\r
333         };\r
334 \r
335         void findOptimumSearchWindow(SearchWindow &searchWindow, IplImage *maskImage, IplImage *depthMap, int maxIteration, int resizeMethod, bool initDepth);\r
336 \r
337 public:\r
338         CvFuzzyMeanShiftTracker();\r
339         ~CvFuzzyMeanShiftTracker();\r
340 \r
341         void track(IplImage *maskImage, IplImage *depthMap, int resizeMethod, bool resetSearch, int minKernelMass = MinKernelMass);\r
342 };\r
343 \r
344 \r
345 namespace cv\r
346 {\r
347 \r
348 class CV_EXPORTS Octree\r
349 {\r
350 public:    \r
351     struct Node\r
352     {\r
353         Node() {}\r
354         int begin, end;\r
355         float x_min, x_max, y_min, y_max, z_min, z_max;         \r
356         int maxLevels;\r
357         bool isLeaf;\r
358         int children[8];\r
359     };\r
360 \r
361     Octree();\r
362     Octree( const vector<Point3f>& points, int maxLevels = 10, int minPoints = 20 );\r
363     virtual ~Octree();\r
364 \r
365     virtual void buildTree( const vector<Point3f>& points, int maxLevels = 10, int minPoints = 20 );\r
366     virtual void getPointsWithinSphere( const Point3f& center, float radius,\r
367                                         vector<Point3f>& points ) const;\r
368     const vector<Node>& getNodes() const { return nodes; }\r
369 private:\r
370     int minPoints;\r
371     vector<Point3f> points;\r
372     vector<Node> nodes;\r
373         \r
374         virtual void buildNext(size_t node_ind);\r
375 };\r
376 \r
377 \r
378 class CV_EXPORTS Mesh3D\r
379 {\r
380 public:\r
381     struct EmptyMeshException {};\r
382 \r
383     Mesh3D();\r
384     Mesh3D(const vector<Point3f>& vtx);\r
385     ~Mesh3D();\r
386 \r
387     void buildOctree();\r
388     void clearOctree();\r
389     float estimateResolution(float tryRatio = 0.1f);        \r
390     void computeNormals(float normalRadius, int minNeighbors = 20);\r
391     void computeNormals(const vector<int>& subset, float normalRadius, int minNeighbors = 20);\r
392     \r
393     void writeAsVrml(const String& file, const vector<Scalar>& colors = vector<Scalar>()) const;\r
394     \r
395     vector<Point3f> vtx;\r
396     vector<Point3f> normals;\r
397     float resolution;    \r
398     Octree octree;\r
399 \r
400     const static Point3f allzero;\r
401 };\r
402 \r
403 class CV_EXPORTS SpinImageModel\r
404 {\r
405 public:\r
406     \r
407     /* model parameters, leave unset for default or auto estimate */\r
408     float normalRadius;\r
409     int minNeighbors;\r
410 \r
411     float binSize;\r
412     int imageWidth;\r
413 \r
414     float lambda;                        \r
415     float gamma;\r
416 \r
417     float T_GeometriccConsistency;\r
418     float T_GroupingCorespondances;\r
419 \r
420     /* public interface */\r
421     SpinImageModel();\r
422     explicit SpinImageModel(const Mesh3D& mesh);\r
423     ~SpinImageModel();\r
424 \r
425     void setLogger(std::ostream* log);\r
426     void selectRandomSubset(float ratio);         \r
427     void setSubset(const vector<int>& subset);         \r
428     void compute();\r
429 \r
430     void match(const SpinImageModel& scene, vector< vector<Vec2i> >& result);    \r
431 \r
432     Mat packRandomScaledSpins(bool separateScale = false, size_t xCount = 10, size_t yCount = 10) const;\r
433     \r
434     size_t getSpinCount() const { return spinImages.rows; }\r
435     Mat getSpinImage(size_t index) const { return spinImages.row(index); }\r
436     const Point3f& getSpinVertex(size_t index) const { return mesh.vtx[subset[index]]; }\r
437     const Point3f& getSpinNormal(size_t index) const { return mesh.normals[subset[index]]; }\r
438 \r
439     const Mesh3D& getMesh() const { return mesh; }\r
440     Mesh3D& getMesh() { return mesh; }\r
441 \r
442     /* static utility functions */\r
443     static bool spinCorrelation(const Mat& spin1, const Mat& spin2, float lambda, float& result);\r
444 \r
445     static Point2f calcSpinMapCoo(const Point3f& point, const Point3f& vertex, const Point3f& normal);\r
446 \r
447     static float geometricConsistency(const Point3f& pointScene1, const Point3f& normalScene1,\r
448                                       const Point3f& pointModel1, const Point3f& normalModel1,   \r
449                                       const Point3f& pointScene2, const Point3f& normalScene2,                               \r
450                                       const Point3f& pointModel2, const Point3f& normalModel2);\r
451 \r
452     static float groupingCreteria(const Point3f& pointScene1, const Point3f& normalScene1,\r
453                                   const Point3f& pointModel1, const Point3f& normalModel1,\r
454                                   const Point3f& pointScene2, const Point3f& normalScene2,                               \r
455                                   const Point3f& pointModel2, const Point3f& normalModel2, \r
456                                   float gamma);\r
457 protected:       \r
458     void defaultParams();\r
459 \r
460     void matchSpinToModel(const Mat& spin, vector<int>& indeces, \r
461         vector<float>& corrCoeffs, bool useExtremeOutliers = true) const; \r
462 \r
463     void repackSpinImages(const vector<uchar>& mask, Mat& spinImages, bool reAlloc = true) const;\r
464              \r
465     vector<int> subset;\r
466     Mesh3D mesh;\r
467     Mat spinImages;\r
468     std::ostream* out;\r
469 };\r
470 \r
471 class CV_EXPORTS TickMeter\r
472 {\r
473 public:\r
474     TickMeter();\r
475     void start();    \r
476     void stop();\r
477 \r
478     int64 getTimeTicks() const;\r
479     double getTimeMicro() const;\r
480     double getTimeMilli() const;\r
481     double getTimeSec()   const;\r
482     int64 getCounter() const;\r
483 \r
484     void reset();\r
485 private:\r
486     int64 counter;\r
487     int64 sumTime;\r
488     int64 startTime;\r
489 };\r
490 \r
491 CV_EXPORTS std::ostream& operator<<(std::ostream& out, const TickMeter& tm);\r
492 \r
493 /****************************************************************************************\\r
494 *            HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector        *\r
495 \****************************************************************************************/\r
496 \r
497 struct CV_EXPORTS HOGDescriptor\r
498 {\r
499 public:\r
500     enum { L2Hys=0 };\r
501 \r
502     HOGDescriptor() : winSize(64,128), blockSize(16,16), blockStride(8,8),\r
503         cellSize(8,8), nbins(9), derivAperture(1), winSigma(-1),\r
504         histogramNormType(L2Hys), L2HysThreshold(0.2), gammaCorrection(true)\r
505     {}\r
506 \r
507     HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride,\r
508         Size _cellSize, int _nbins, int _derivAperture=1, double _winSigma=-1,\r
509         int _histogramNormType=L2Hys, double _L2HysThreshold=0.2, bool _gammaCorrection=false)\r
510         : winSize(_winSize), blockSize(_blockSize), blockStride(_blockStride), cellSize(_cellSize),\r
511         nbins(_nbins), derivAperture(_derivAperture), winSigma(_winSigma),\r
512         histogramNormType(_histogramNormType), L2HysThreshold(_L2HysThreshold),\r
513         gammaCorrection(_gammaCorrection)\r
514     {}\r
515 \r
516     HOGDescriptor(const String& filename)\r
517     {\r
518         load(filename);\r
519     }\r
520 \r
521     virtual ~HOGDescriptor() {}\r
522 \r
523     size_t getDescriptorSize() const;\r
524     bool checkDetectorSize() const;\r
525     double getWinSigma() const;\r
526 \r
527     virtual void setSVMDetector(const vector<float>& _svmdetector);\r
528 \r
529     virtual bool load(const String& filename, const String& objname=String());\r
530     virtual void save(const String& filename, const String& objname=String()) const;\r
531 \r
532     virtual void compute(const Mat& img,\r
533                          vector<float>& descriptors,\r
534                          Size winStride=Size(), Size padding=Size(),\r
535                          const vector<Point>& locations=vector<Point>()) const;\r
536     virtual void detect(const Mat& img, vector<Point>& foundLocations,\r
537                         double hitThreshold=0, Size winStride=Size(),\r
538                         Size padding=Size(),\r
539                         const vector<Point>& searchLocations=vector<Point>()) const;\r
540     virtual void detectMultiScale(const Mat& img, vector<Rect>& foundLocations,\r
541                                   double hitThreshold=0, Size winStride=Size(),\r
542                                   Size padding=Size(), double scale=1.05,\r
543                                   int groupThreshold=2) const;\r
544     virtual void computeGradient(const Mat& img, Mat& grad, Mat& angleOfs,\r
545                                  Size paddingTL=Size(), Size paddingBR=Size()) const;\r
546 \r
547     static vector<float> getDefaultPeopleDetector();\r
548 \r
549     Size winSize;\r
550     Size blockSize;\r
551     Size blockStride;\r
552     Size cellSize;\r
553     int nbins;\r
554     int derivAperture;\r
555     double winSigma;\r
556     int histogramNormType;\r
557     double L2HysThreshold;\r
558     bool gammaCorrection;\r
559     vector<float> svmDetector;\r
560 };\r
561 \r
562 \r
563 class CV_EXPORTS SelfSimDescriptor\r
564 {\r
565 public:\r
566     SelfSimDescriptor();\r
567     SelfSimDescriptor(int _ssize, int _lsize,\r
568         int _startDistanceBucket=DEFAULT_START_DISTANCE_BUCKET,\r
569         int _numberOfDistanceBuckets=DEFAULT_NUM_DISTANCE_BUCKETS,\r
570         int _nangles=DEFAULT_NUM_ANGLES);\r
571         SelfSimDescriptor(const SelfSimDescriptor& ss);\r
572         virtual ~SelfSimDescriptor();\r
573     SelfSimDescriptor& operator = (const SelfSimDescriptor& ss);\r
574 \r
575     size_t getDescriptorSize() const;\r
576     Size getGridSize( Size imgsize, Size winStride ) const;\r
577 \r
578     virtual void compute(const Mat& img, vector<float>& descriptors, Size winStride=Size(),\r
579                          const vector<Point>& locations=vector<Point>()) const;\r
580     virtual void computeLogPolarMapping(Mat& mappingMask) const;\r
581     virtual void SSD(const Mat& img, Point pt, Mat& ssd) const;\r
582 \r
583         int smallSize;\r
584         int largeSize;\r
585     int startDistanceBucket;\r
586     int numberOfDistanceBuckets;\r
587     int numberOfAngles;\r
588 \r
589     enum { DEFAULT_SMALL_SIZE = 5, DEFAULT_LARGE_SIZE = 41,\r
590         DEFAULT_NUM_ANGLES = 20, DEFAULT_START_DISTANCE_BUCKET = 3,\r
591         DEFAULT_NUM_DISTANCE_BUCKETS = 7 };\r
592 };\r
593 \r
594     \r
595 class CV_EXPORTS PatchGenerator\r
596 {\r
597 public:\r
598     PatchGenerator();\r
599     PatchGenerator(double _backgroundMin, double _backgroundMax,\r
600                    double _noiseRange, bool _randomBlur=true,\r
601                    double _lambdaMin=0.6, double _lambdaMax=1.5,\r
602                    double _thetaMin=-CV_PI, double _thetaMax=CV_PI,\r
603                    double _phiMin=-CV_PI, double _phiMax=CV_PI );\r
604     void operator()(const Mat& image, Point2f pt, Mat& patch, Size patchSize, RNG& rng) const;\r
605     void operator()(const Mat& image, const Mat& transform, Mat& patch,\r
606                     Size patchSize, RNG& rng) const;\r
607     void warpWholeImage(const Mat& image, Mat& _T, Mat& buf,\r
608                         Mat& warped, int border, RNG& rng) const;\r
609     void generateRandomTransform(Point2f srcCenter, Point2f dstCenter,\r
610                                  Mat& transform, RNG& rng, bool inverse=false) const;\r
611     double backgroundMin, backgroundMax;\r
612     double noiseRange;\r
613     bool randomBlur;\r
614     double lambdaMin, lambdaMax;\r
615     double thetaMin, thetaMax;\r
616     double phiMin, phiMax;\r
617 };\r
618 \r
619     \r
620 class CV_EXPORTS LDetector\r
621 {\r
622 public:    \r
623     LDetector();\r
624     LDetector(int _radius, int _threshold, int _nOctaves,\r
625               int _nViews, double _baseFeatureSize, double _clusteringDistance);\r
626     void operator()(const Mat& image, vector<KeyPoint>& keypoints, int maxCount=0, bool scaleCoords=true) const;\r
627     void operator()(const vector<Mat>& pyr, vector<KeyPoint>& keypoints, int maxCount=0, bool scaleCoords=true) const;\r
628     void getMostStable2D(const Mat& image, vector<KeyPoint>& keypoints,\r
629                          int maxCount, const PatchGenerator& patchGenerator) const;\r
630     void setVerbose(bool verbose);\r
631     \r
632     void read(const FileNode& node);\r
633     void write(FileStorage& fs, const String& name=String()) const;\r
634     \r
635     int radius;\r
636     int threshold;\r
637     int nOctaves;\r
638     int nViews;\r
639     bool verbose;\r
640     \r
641     double baseFeatureSize;\r
642     double clusteringDistance;\r
643 };\r
644 \r
645 typedef LDetector YAPE;\r
646 \r
647 class CV_EXPORTS FernClassifier\r
648 {\r
649 public:\r
650     FernClassifier();\r
651     FernClassifier(const FileNode& node);\r
652     FernClassifier(const vector<Point2f>& points,\r
653                    const vector<Ptr<Mat> >& refimgs,\r
654                    const vector<int>& labels=vector<int>(),\r
655                    int _nclasses=0, int _patchSize=PATCH_SIZE,\r
656                    int _signatureSize=DEFAULT_SIGNATURE_SIZE,\r
657                    int _nstructs=DEFAULT_STRUCTS,\r
658                    int _structSize=DEFAULT_STRUCT_SIZE,\r
659                    int _nviews=DEFAULT_VIEWS,\r
660                    int _compressionMethod=COMPRESSION_NONE,\r
661                    const PatchGenerator& patchGenerator=PatchGenerator());\r
662     virtual ~FernClassifier();\r
663     virtual void read(const FileNode& n);\r
664     virtual void write(FileStorage& fs, const String& name=String()) const;\r
665     virtual void trainFromSingleView(const Mat& image,\r
666                                      const vector<KeyPoint>& keypoints,\r
667                                      int _patchSize=PATCH_SIZE,\r
668                                      int _signatureSize=DEFAULT_SIGNATURE_SIZE,\r
669                                      int _nstructs=DEFAULT_STRUCTS,\r
670                                      int _structSize=DEFAULT_STRUCT_SIZE,\r
671                                      int _nviews=DEFAULT_VIEWS,\r
672                                      int _compressionMethod=COMPRESSION_NONE,\r
673                                      const PatchGenerator& patchGenerator=PatchGenerator());\r
674     virtual void train(const vector<Point2f>& points,\r
675                        const vector<Ptr<Mat> >& refimgs,\r
676                        const vector<int>& labels=vector<int>(),\r
677                        int _nclasses=0, int _patchSize=PATCH_SIZE,\r
678                        int _signatureSize=DEFAULT_SIGNATURE_SIZE,\r
679                        int _nstructs=DEFAULT_STRUCTS,\r
680                        int _structSize=DEFAULT_STRUCT_SIZE,\r
681                        int _nviews=DEFAULT_VIEWS,\r
682                        int _compressionMethod=COMPRESSION_NONE,\r
683                        const PatchGenerator& patchGenerator=PatchGenerator());\r
684     virtual int operator()(const Mat& img, Point2f kpt, vector<float>& signature) const;\r
685     virtual int operator()(const Mat& patch, vector<float>& signature) const;\r
686     virtual void clear();\r
687     void setVerbose(bool verbose);\r
688     \r
689     int getClassCount() const;\r
690     int getStructCount() const;\r
691     int getStructSize() const;\r
692     int getSignatureSize() const;\r
693     int getCompressionMethod() const;\r
694     Size getPatchSize() const;    \r
695     \r
696     struct Feature\r
697     {\r
698         uchar x1, y1, x2, y2;\r
699         Feature() : x1(0), y1(0), x2(0), y2(0) {}\r
700         Feature(int _x1, int _y1, int _x2, int _y2)\r
701         : x1((uchar)_x1), y1((uchar)_y1), x2((uchar)_x2), y2((uchar)_y2)\r
702         {}\r
703         template<typename _Tp> bool operator ()(const Mat_<_Tp>& patch) const\r
704         { return patch(y1,x1) > patch(y2, x2); }\r
705     };\r
706     \r
707     enum\r
708     {\r
709         PATCH_SIZE = 31,\r
710         DEFAULT_STRUCTS = 50,\r
711         DEFAULT_STRUCT_SIZE = 9,\r
712         DEFAULT_VIEWS = 5000,\r
713         DEFAULT_SIGNATURE_SIZE = 176,\r
714         COMPRESSION_NONE = 0,\r
715         COMPRESSION_RANDOM_PROJ = 1,\r
716         COMPRESSION_PCA = 2,\r
717         DEFAULT_COMPRESSION_METHOD = COMPRESSION_NONE\r
718     };\r
719     \r
720 protected:\r
721     virtual void prepare(int _nclasses, int _patchSize, int _signatureSize,\r
722                          int _nstructs, int _structSize,\r
723                          int _nviews, int _compressionMethod);\r
724     virtual void finalize(RNG& rng);\r
725     virtual int getLeaf(int fidx, const Mat& patch) const;\r
726     \r
727     bool verbose;\r
728     int nstructs;\r
729     int structSize;\r
730     int nclasses;\r
731     int signatureSize;\r
732     int compressionMethod;\r
733     int leavesPerStruct;\r
734     Size patchSize;\r
735     vector<Feature> features;\r
736     vector<int> classCounters;\r
737     vector<float> posteriors;\r
738 };\r
739 \r
740 class CV_EXPORTS PlanarObjectDetector\r
741 {\r
742 public:\r
743     PlanarObjectDetector();\r
744     PlanarObjectDetector(const FileNode& node);\r
745     PlanarObjectDetector(const vector<Mat>& pyr, int _npoints=300,\r
746                          int _patchSize=FernClassifier::PATCH_SIZE,\r
747                          int _nstructs=FernClassifier::DEFAULT_STRUCTS,\r
748                          int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE,\r
749                          int _nviews=FernClassifier::DEFAULT_VIEWS,\r
750                          const LDetector& detector=LDetector(),\r
751                          const PatchGenerator& patchGenerator=PatchGenerator()); \r
752     virtual ~PlanarObjectDetector();\r
753     virtual void train(const vector<Mat>& pyr, int _npoints=300,\r
754                        int _patchSize=FernClassifier::PATCH_SIZE,\r
755                        int _nstructs=FernClassifier::DEFAULT_STRUCTS,\r
756                        int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE,\r
757                        int _nviews=FernClassifier::DEFAULT_VIEWS,\r
758                        const LDetector& detector=LDetector(),\r
759                        const PatchGenerator& patchGenerator=PatchGenerator());\r
760     virtual void train(const vector<Mat>& pyr, const vector<KeyPoint>& keypoints,\r
761                        int _patchSize=FernClassifier::PATCH_SIZE,\r
762                        int _nstructs=FernClassifier::DEFAULT_STRUCTS,\r
763                        int _structSize=FernClassifier::DEFAULT_STRUCT_SIZE,\r
764                        int _nviews=FernClassifier::DEFAULT_VIEWS,\r
765                        const LDetector& detector=LDetector(),\r
766                        const PatchGenerator& patchGenerator=PatchGenerator());\r
767     Rect getModelROI() const;\r
768     vector<KeyPoint> getModelPoints() const;\r
769     const LDetector& getDetector() const;\r
770     const FernClassifier& getClassifier() const;\r
771     void setVerbose(bool verbose);\r
772     \r
773     void read(const FileNode& node);\r
774     void write(FileStorage& fs, const String& name=String()) const;\r
775     bool operator()(const Mat& image, Mat& H, vector<Point2f>& corners) const;\r
776     bool operator()(const vector<Mat>& pyr, const vector<KeyPoint>& keypoints,\r
777                     Mat& H, vector<Point2f>& corners, vector<int>* pairs=0) const;\r
778     \r
779 protected:\r
780     bool verbose;\r
781     Rect modelROI;\r
782     vector<KeyPoint> modelPoints;\r
783     LDetector ldetector;\r
784     FernClassifier fernClassifier;\r
785 };\r
786 \r
787 \r
788 ////////////////////////////////////////////////////////////////////////////////////////////////////    \r
789 //                                        One-Way Descriptor                                      //\r
790 ////////////////////////////////////////////////////////////////////////////////////////////////////    \r
791 \r
792 class AffinePose;\r
793     \r
794 // OneWayDescriptor: incapsulates a descriptor for a single point \r
795 class CV_EXPORTS OneWayDescriptor\r
796 {\r
797 public:\r
798     OneWayDescriptor();\r
799     ~OneWayDescriptor();\r
800     \r
801     // allocates memory for given descriptor parameters\r
802     void Allocate(int pose_count, Size size, int nChannels);\r
803     \r
804     // GenerateSamples: generates affine transformed patches with averaging them over small transformation variations.\r
805     // If external poses and transforms were specified, uses them instead of generating random ones\r
806     // - pose_count: the number of poses to be generated\r
807     // - frontal: the input patch (can be a roi in a larger image)\r
808     // - norm: if nonzero, normalizes the output patch so that the sum of pixel intensities is 1\r
809     void GenerateSamples(int pose_count, IplImage* frontal, int norm = 0);\r
810     \r
811     // GenerateSamplesFast: generates affine transformed patches with averaging them over small transformation variations.\r
812     // Uses precalculated transformed pca components.\r
813     // - frontal: the input patch (can be a roi in a larger image)\r
814     // - pca_hr_avg: pca average vector\r
815     // - pca_hr_eigenvectors: pca eigenvectors\r
816     // - pca_descriptors: an array of precomputed descriptors of pca components containing their affine transformations\r
817     //   pca_descriptors[0] corresponds to the average, pca_descriptors[1]-pca_descriptors[pca_dim] correspond to eigenvectors\r
818     void GenerateSamplesFast(IplImage* frontal, CvMat* pca_hr_avg, \r
819                              CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors);\r
820     \r
821     // sets the poses and corresponding transforms\r
822     void SetTransforms(AffinePose* poses, CvMat** transforms);\r
823     \r
824     // Initialize: builds a descriptor. \r
825     // - pose_count: the number of poses to build. If poses were set externally, uses them rather than generating random ones\r
826     // - frontal: input patch. Can be a roi in a larger image\r
827     // - feature_name: the feature name to be associated with the descriptor\r
828     // - norm: if 1, the affine transformed patches are normalized so that their sum is 1 \r
829     void Initialize(int pose_count, IplImage* frontal, const char* feature_name = 0, int norm = 0);\r
830     \r
831     // InitializeFast: builds a descriptor using precomputed descriptors of pca components\r
832     // - pose_count: the number of poses to build\r
833     // - frontal: input patch. Can be a roi in a larger image\r
834     // - feature_name: the feature name to be associated with the descriptor\r
835     // - pca_hr_avg: average vector for PCA\r
836     // - pca_hr_eigenvectors: PCA eigenvectors (one vector per row)\r
837     // - pca_descriptors: precomputed descriptors of PCA components, the first descriptor for the average vector\r
838     // followed by the descriptors for eigenvectors\r
839     void InitializeFast(int pose_count, IplImage* frontal, const char* feature_name, \r
840                         CvMat* pca_hr_avg, CvMat* pca_hr_eigenvectors, OneWayDescriptor* pca_descriptors);\r
841     \r
842     // ProjectPCASample: unwarps an image patch into a vector and projects it into PCA space\r
843     // - patch: input image patch\r
844     // - avg: PCA average vector\r
845     // - eigenvectors: PCA eigenvectors, one per row\r
846     // - pca_coeffs: output PCA coefficients\r
847     void ProjectPCASample(IplImage* patch, CvMat* avg, CvMat* eigenvectors, CvMat* pca_coeffs) const;\r
848     \r
849     // InitializePCACoeffs: projects all warped patches into PCA space\r
850     // - avg: PCA average vector\r
851     // - eigenvectors: PCA eigenvectors, one per row    \r
852     void InitializePCACoeffs(CvMat* avg, CvMat* eigenvectors);\r
853     \r
854     // EstimatePose: finds the closest match between an input patch and a set of patches with different poses\r
855     // - patch: input image patch\r
856     // - pose_idx: the output index of the closest pose\r
857     // - distance: the distance to the closest pose (L2 distance)\r
858     void EstimatePose(IplImage* patch, int& pose_idx, float& distance) const;\r
859     \r
860     // EstimatePosePCA: finds the closest match between an input patch and a set of patches with different poses. \r
861     // The distance between patches is computed in PCA space\r
862     // - patch: input image patch\r
863     // - pose_idx: the output index of the closest pose\r
864     // - distance: distance to the closest pose (L2 distance in PCA space)\r
865     // - avg: PCA average vector. If 0, matching without PCA is used\r
866     // - eigenvectors: PCA eigenvectors, one per row\r
867     void EstimatePosePCA(IplImage* patch, int& pose_idx, float& distance, CvMat* avg, CvMat* eigenvalues) const;\r
868     \r
869     // GetPatchSize: returns the size of each image patch after warping (2 times smaller than the input patch) \r
870     Size GetPatchSize() const\r
871     {\r
872         return m_patch_size;\r
873     }\r
874     \r
875     // GetInputPatchSize: returns the required size of the patch that the descriptor is built from \r
876     // (2 time larger than the patch after warping)\r
877     Size GetInputPatchSize() const\r
878     {\r
879         return cvSize(m_patch_size.width*2, m_patch_size.height*2);\r
880     }\r
881     \r
882     // GetPatch: returns a patch corresponding to specified pose index\r
883     // - index: pose index\r
884     // - return value: the patch corresponding to specified pose index\r
885     IplImage* GetPatch(int index);\r
886     \r
887     // GetPose: returns a pose corresponding to specified pose index\r
888     // - index: pose index\r
889     // - return value: the pose corresponding to specified pose index\r
890     AffinePose GetPose(int index) const;\r
891     \r
892     // Save: saves all patches with different poses to a specified path\r
893     void Save(const char* path);\r
894     \r
895     // ReadByName: reads a descriptor from a file storage\r
896     // - fs: file storage\r
897     // - parent: parent node\r
898     // - name: node name\r
899     // - return value: 1 if succeeded, 0 otherwise\r
900     int ReadByName(CvFileStorage* fs, CvFileNode* parent, const char* name);\r
901     \r
902     // Write: writes a descriptor into a file storage\r
903     // - fs: file storage\r
904     // - name: node name\r
905     void Write(CvFileStorage* fs, const char* name);\r
906     \r
907     // GetFeatureName: returns a name corresponding to a feature\r
908     const char* GetFeatureName() const;\r
909     \r
910     // GetCenter: returns the center of the feature\r
911     Point GetCenter() const;\r
912     \r
913     void SetPCADimHigh(int pca_dim_high) {m_pca_dim_high = pca_dim_high;};\r
914     void SetPCADimLow(int pca_dim_low) {m_pca_dim_low = pca_dim_low;};\r
915     \r
916 protected:\r
917     int m_pose_count; // the number of poses\r
918     Size m_patch_size; // size of each image\r
919     IplImage** m_samples; // an array of length m_pose_count containing the patch in different poses \r
920     CvMat** m_pca_coeffs; // an array of length m_pose_count containing pca decomposition of the patch in different poses\r
921     AffinePose* m_affine_poses; // an array of poses\r
922     CvMat** m_transforms; // an array of affine transforms corresponding to poses\r
923     \r
924     String m_feature_name; // the name of the feature associated with the descriptor\r
925     Point m_center; // the coordinates of the feature (the center of the input image ROI)\r
926     \r
927     int m_pca_dim_high; // the number of descriptor pca components to use for generating affine poses\r
928     int m_pca_dim_low; // the number of pca components to use for comparison\r
929 };\r
930 \r
931 CV_EXPORTS void findOneWayDescriptor(int desc_count, const OneWayDescriptor* descriptors,\r
932                                      IplImage* patch, int& desc_idx, int& pose_idx, float& distance, \r
933                                      CvMat* avg = 0, CvMat* eigenvalues = 0);\r
934 \r
935 CV_EXPORTS void findOneWayDescriptor(int desc_count, const OneWayDescriptor* descriptors, IplImage* patch, \r
936                                      float scale_min, float scale_max, float scale_step,\r
937                                      int& desc_idx, int& pose_idx, float& distance, float& scale, \r
938                                      CvMat* avg, CvMat* eigenvectors);\r
939     \r
940     \r
941 // OneWayDescriptorBase: encapsulates functionality for training/loading a set of one way descriptors\r
942 // and finding the nearest closest descriptor to an input feature\r
943 class CV_EXPORTS OneWayDescriptorBase\r
944 {\r
945 public:\r
946     \r
947     // creates an instance of OneWayDescriptor from a set of training files\r
948     // - patch_size: size of the input (large) patch\r
949     // - pose_count: the number of poses to generate for each descriptor\r
950     // - train_path: path to training files\r
951     // - pca_config: the name of the file that contains PCA for small patches (2 times smaller\r
952     // than patch_size each dimension\r
953     // - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size)\r
954     // - pca_desc_config: the name of the file that contains descriptors of PCA components\r
955     OneWayDescriptorBase(Size patch_size, int pose_count, const char* train_path = 0, const char* pca_config = 0, \r
956                          const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 2, \r
957                          int pca_dim_high = 100, int pca_dim_low = 100);\r
958     \r
959     ~OneWayDescriptorBase();\r
960     \r
961     // Allocate: allocates memory for a given number of descriptors\r
962     void Allocate(int train_feature_count);\r
963     \r
964     // AllocatePCADescriptors: allocates memory for pca descriptors\r
965     void AllocatePCADescriptors();\r
966     \r
967     // returns patch size\r
968     Size GetPatchSize() const {return m_patch_size;};\r
969     // returns the number of poses for each descriptor\r
970     int GetPoseCount() const {return m_pose_count;};\r
971     \r
972     // returns the number of pyramid levels\r
973     int GetPyrLevels() const {return m_pyr_levels;};\r
974     \r
975     // CreateDescriptorsFromImage: creates descriptors for each of the input features\r
976     // - src: input image\r
977     // - features: input features\r
978     // - pyr_levels: the number of pyramid levels\r
979     void CreateDescriptorsFromImage(IplImage* src, const vector<KeyPoint>& features);\r
980     \r
981     // CreatePCADescriptors: generates descriptors for PCA components, needed for fast generation of feature descriptors\r
982     void CreatePCADescriptors();\r
983     \r
984     // returns a feature descriptor by feature index\r
985     const OneWayDescriptor* GetDescriptor(int desc_idx) const;\r
986     \r
987     // FindDescriptor: finds the closest descriptor\r
988     // - patch: input image patch\r
989     // - desc_idx: output index of the closest descriptor to the input patch\r
990     // - pose_idx: output index of the closest pose of the closest descriptor to the input patch\r
991     // - distance: distance from the input patch to the closest feature pose\r
992     void FindDescriptor(IplImage* patch, int& desc_idx, int& pose_idx, float& distance) const;\r
993     \r
994     // FindDescriptor: finds the closest descriptor\r
995     // - src: input image \r
996     // - pt: center of the feature\r
997     // - desc_idx: output index of the closest descriptor to the input patch\r
998     // - pose_idx: output index of the closest pose of the closest descriptor to the input patch\r
999     // - distance: distance from the input patch to the closest feature pose\r
1000     void FindDescriptor(IplImage* src, Point2f pt, int& desc_idx, int& pose_idx, float& distance) const;\r
1001     \r
1002     // InitializePoses: generates random poses\r
1003     void InitializePoses();\r
1004     \r
1005     // InitializeTransformsFromPoses: generates 2x3 affine matrices from poses (initializes m_transforms)\r
1006     void InitializeTransformsFromPoses();\r
1007     \r
1008     // InitializePoseTransforms: subsequently calls InitializePoses and InitializeTransformsFromPoses\r
1009     void InitializePoseTransforms();\r
1010     \r
1011     // InitializeDescriptor: initializes a descriptor\r
1012     // - desc_idx: descriptor index\r
1013     // - train_image: image patch (ROI is supported)\r
1014     // - feature_label: feature textual label\r
1015     void InitializeDescriptor(int desc_idx, IplImage* train_image, const char* feature_label);\r
1016     \r
1017     // InitializeDescriptors: load features from an image and create descriptors for each of them \r
1018     void InitializeDescriptors(IplImage* train_image, const vector<KeyPoint>& features, \r
1019                                const char* feature_label = "", int desc_start_idx = 0);\r
1020     \r
1021     // LoadPCADescriptors: loads PCA descriptors from a file\r
1022     // - filename: input filename\r
1023     int LoadPCADescriptors(const char* filename);\r
1024     \r
1025     // SavePCADescriptors: saves PCA descriptors to a file\r
1026     // - filename: output filename\r
1027     void SavePCADescriptors(const char* filename);\r
1028     \r
1029     // SetPCAHigh: sets the high resolution pca matrices (copied to internal structures)\r
1030     void SetPCAHigh(CvMat* avg, CvMat* eigenvectors);\r
1031     \r
1032     // SetPCALow: sets the low resolution pca matrices (copied to internal structures)\r
1033     void SetPCALow(CvMat* avg, CvMat* eigenvectors);\r
1034     \r
1035     \r
1036 protected:\r
1037     Size m_patch_size; // patch size\r
1038     int m_pose_count; // the number of poses for each descriptor\r
1039     int m_train_feature_count; // the number of the training features\r
1040     OneWayDescriptor* m_descriptors; // array of train feature descriptors\r
1041     CvMat* m_pca_avg; // PCA average vector for small patches\r
1042     CvMat* m_pca_eigenvectors; // PCA eigenvectors for small patches\r
1043     CvMat* m_pca_hr_avg; // PCA average vector for large patches\r
1044     CvMat* m_pca_hr_eigenvectors; // PCA eigenvectors for large patches\r
1045     OneWayDescriptor* m_pca_descriptors; // an array of PCA descriptors\r
1046     \r
1047     AffinePose* m_poses; // array of poses\r
1048     CvMat** m_transforms; // array of affine transformations corresponding to poses\r
1049     \r
1050     int m_pca_dim_high;\r
1051     int m_pca_dim_low;\r
1052     \r
1053     int m_pyr_levels;\r
1054 };\r
1055 \r
1056 class CV_EXPORTS OneWayDescriptorObject : public OneWayDescriptorBase\r
1057 {\r
1058 public:\r
1059     // creates an instance of OneWayDescriptorObject from a set of training files\r
1060     // - patch_size: size of the input (large) patch\r
1061     // - pose_count: the number of poses to generate for each descriptor\r
1062     // - train_path: path to training files\r
1063     // - pca_config: the name of the file that contains PCA for small patches (2 times smaller\r
1064     // than patch_size each dimension\r
1065     // - pca_hr_config: the name of the file that contains PCA for large patches (of patch_size size)\r
1066     // - pca_desc_config: the name of the file that contains descriptors of PCA components\r
1067     OneWayDescriptorObject(Size patch_size, int pose_count, const char* train_path, const char* pca_config, \r
1068                            const char* pca_hr_config = 0, const char* pca_desc_config = 0, int pyr_levels = 2);\r
1069     \r
1070     ~OneWayDescriptorObject();\r
1071     \r
1072     // Allocate: allocates memory for a given number of features\r
1073     // - train_feature_count: the total number of features\r
1074     // - object_feature_count: the number of features extracted from the object \r
1075     void Allocate(int train_feature_count, int object_feature_count);\r
1076     \r
1077     \r
1078     void SetLabeledFeatures(const vector<KeyPoint>& features) {m_train_features = features;};\r
1079     vector<KeyPoint>& GetLabeledFeatures() {return m_train_features;};\r
1080     const vector<KeyPoint>& GetLabeledFeatures() const {return m_train_features;};\r
1081     \r
1082     // IsDescriptorObject: returns 1 if descriptor with specified index is positive, otherwise 0\r
1083     int IsDescriptorObject(int desc_idx) const;\r
1084     \r
1085     // MatchPointToPart: returns the part number of a feature if it matches one of the object parts, otherwise -1\r
1086     int MatchPointToPart(Point pt) const;\r
1087     \r
1088     // GetDescriptorPart: returns the part number of the feature corresponding to a specified descriptor  \r
1089     // - desc_idx: descriptor index\r
1090     int GetDescriptorPart(int desc_idx) const;\r
1091     \r
1092     // GetTrainFeatures: returns a set of training features\r
1093     const vector<KeyPoint>& GetTrainFeatures() const {return m_train_features;};\r
1094     vector<KeyPoint> _GetTrainFeatures() const;\r
1095     \r
1096     void InitializeObjectDescriptors(IplImage* train_image, const vector<KeyPoint>& features, \r
1097                                      const char* feature_label, int desc_start_idx = 0, float scale = 1.0f);\r
1098     \r
1099 protected:\r
1100     int* m_part_id; // contains part id for each of object descriptors\r
1101     vector<KeyPoint> m_train_features; // train features\r
1102     int m_object_feature_count; // the number of the positive features\r
1103 };\r
1104 \r
1105 \r
1106 // detect corners using FAST algorithm\r
1107 CV_EXPORTS void FAST( const Mat& image, vector<KeyPoint>& keypoints, int threshold, bool nonmax_supression=true );\r
1108 \r
1109 \r
1110 class CV_EXPORTS LevMarqSparse\r
1111 {\r
1112 public:\r
1113     LevMarqSparse();\r
1114     LevMarqSparse(int npoints, // number of points\r
1115             int ncameras, // number of cameras\r
1116             int nPointParams, // number of params per one point  (3 in case of 3D points)\r
1117             int nCameraParams, // number of parameters per one camera\r
1118             int nErrParams, // number of parameters in measurement vector\r
1119                             // for 1 point at one camera (2 in case of 2D projections)\r
1120             Mat& visibility, // visibility matrix. rows correspond to points, columns correspond to cameras\r
1121                              // 1 - point is visible for the camera, 0 - invisible\r
1122             Mat& P0, // starting vector of parameters, first cameras then points\r
1123             Mat& X, // measurements, in order of visibility. non visible cases are skipped \r
1124             TermCriteria criteria, // termination criteria\r
1125             \r
1126             // callback for estimation of Jacobian matrices\r
1127             void (CV_CDECL * fjac)(int i, int j, Mat& point_params,\r
1128                                    Mat& cam_params, Mat& A, Mat& B, void* data),\r
1129             // callback for estimation of backprojection errors\r
1130             void (CV_CDECL * func)(int i, int j, Mat& point_params,\r
1131                                    Mat& cam_params, Mat& estim, void* data),\r
1132             void* data // user-specific data passed to the callbacks\r
1133             );\r
1134     virtual ~LevMarqSparse();\r
1135     \r
1136     virtual void run( int npoints, // number of points\r
1137             int ncameras, // number of cameras\r
1138             int nPointParams, // number of params per one point  (3 in case of 3D points)\r
1139             int nCameraParams, // number of parameters per one camera\r
1140             int nErrParams, // number of parameters in measurement vector\r
1141                             // for 1 point at one camera (2 in case of 2D projections)\r
1142             Mat& visibility, // visibility matrix. rows correspond to points, columns correspond to cameras\r
1143                              // 1 - point is visible for the camera, 0 - invisible\r
1144             Mat& P0, // starting vector of parameters, first cameras then points\r
1145             Mat& X, // measurements, in order of visibility. non visible cases are skipped \r
1146             TermCriteria criteria, // termination criteria\r
1147             \r
1148             // callback for estimation of Jacobian matrices\r
1149             void (CV_CDECL * fjac)(int i, int j, Mat& point_params,\r
1150                                    Mat& cam_params, Mat& A, Mat& B, void* data),\r
1151             // callback for estimation of backprojection errors\r
1152             void (CV_CDECL * func)(int i, int j, Mat& point_params,\r
1153                                    Mat& cam_params, Mat& estim, void* data),\r
1154             void* data // user-specific data passed to the callbacks\r
1155             );\r
1156 \r
1157     virtual void clear();\r
1158     \r
1159     // useful function to do simple bundle adjastment tasks\r
1160     static void bundleAdjust(vector<Point3d>& points, //positions of points in global coordinate system (input and output)\r
1161                              const vector<vector<Point2d> >& imagePoints, //projections of 3d points for every camera \r
1162                              const vector<vector<int> >& visibility, //visibility of 3d points for every camera \r
1163                              vector<Mat>& cameraMatrix, //intrinsic matrices of all cameras (input and output)\r
1164                              vector<Mat>& R, //rotation matrices of all cameras (input and output)\r
1165                              vector<Mat>& T, //translation vector of all cameras (input and output)\r
1166                              vector<Mat>& distCoeffs, //distortion coefficients of all cameras (input and output)\r
1167                              const TermCriteria& criteria=\r
1168                              TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON));\r
1169     \r
1170 protected:\r
1171     virtual void optimize(); //main function that runs minimization\r
1172     \r
1173     //iteratively asks for measurement for visible camera-point pairs\r
1174     void ask_for_proj();                                        \r
1175     //iteratively asks for Jacobians for every camera_point pair\r
1176     void ask_for_projac();    \r
1177         \r
1178     CvMat* err; //error X-hX\r
1179     double prevErrNorm, errNorm;\r
1180     double lambda;\r
1181     CvTermCriteria criteria;\r
1182     int iters;\r
1183     \r
1184     CvMat** U; //size of array is equal to number of cameras\r
1185     CvMat** V; //size of array is equal to number of points\r
1186     CvMat** inv_V_star; //inverse of V*\r
1187 \r
1188     CvMat* A;\r
1189     CvMat* B;\r
1190     CvMat* W; \r
1191 \r
1192     CvMat* X; //measurement \r
1193     CvMat* hX; //current measurement extimation given new parameter vector \r
1194     \r
1195     CvMat* prevP; //current already accepted parameter. \r
1196     CvMat* P; // parameters used to evaluate function with new params\r
1197               // this parameters may be rejected \r
1198     \r
1199     CvMat* deltaP; //computed increase of parameters (result of normal system solution )\r
1200 \r
1201     CvMat** ea; // sum_i  AijT * e_ij , used as right part of normal equation\r
1202                 // length of array is j = number of cameras  \r
1203     CvMat** eb; // sum_j  BijT * e_ij , used as right part of normal equation\r
1204                 // length of array is i = number of points\r
1205 \r
1206     CvMat** Yj; //length of array is i = num_points\r
1207 \r
1208     CvMat* S; //big matrix of block Sjk  , each block has size num_cam_params x num_cam_params \r
1209 \r
1210     CvMat* JtJ_diag; //diagonal of JtJ,  used to backup diagonal elements before augmentation\r
1211 \r
1212     CvMat* Vis_index; // matrix which element is index of measurement for point i and camera j\r
1213                \r
1214     int num_cams;\r
1215     int num_points;\r
1216     int num_err_param;\r
1217     int num_cam_param;\r
1218     int num_point_param;\r
1219 \r
1220     //target function and jacobian pointers, which needs to be initialized \r
1221     void (*fjac)(int i, int j, Mat& point_params, Mat& cam_params, Mat& A, Mat& B, void* data);\r
1222     void (*func)(int i, int j, Mat& point_params, Mat& cam_params, Mat& estim, void* data );\r
1223 \r
1224     void* data;\r
1225 };\r
1226 \r
1227 \r
1228 }\r
1229 \r
1230 #endif /* __cplusplus */\r
1231 \r
1232 #endif /* __CVAUX_HPP__ */\r
1233 \r
1234 /* End of file. */\r