Add OpenCV source code
[platform/upstream/opencv.git] / modules / objdetect / src / latentsvm.cpp
1 #include "precomp.hpp"
2 #include "_latentsvm.h"
3 #include "_lsvm_matching.h"
4
5 /*
6 // Transformation filter displacement from the block space
7 // to the space of pixels at the initial image
8 //
9 // API
10 // int convertPoints(int countLevel, CvPoint *points, int *levels,
11                   CvPoint **partsDisplacement, int kPoints, int n);
12 // INPUT
13 // countLevel        - the number of levels in the feature pyramid
14 // points            - the set of root filter positions (in the block space)
15 // levels            - the set of levels
16 // partsDisplacement - displacement of part filters (in the block space)
17 // kPoints           - number of root filter positions
18 // n                 - number of part filters
19 // initialImageLevel - level that contains features for initial image
20 // maxXBorder        - the largest root filter size (X-direction)
21 // maxYBorder        - the largest root filter size (Y-direction)
22 // OUTPUT
23 // points            - the set of root filter positions (in the space of pixels)
24 // partsDisplacement - displacement of part filters (in the space of pixels)
25 // RESULT
26 // Error status
27 */
28 int convertPoints(int /*countLevel*/, int lambda,
29                   int initialImageLevel,
30                   CvPoint *points, int *levels,
31                   CvPoint **partsDisplacement, int kPoints, int n,
32                   int maxXBorder,
33                   int maxYBorder)
34 {
35     int i, j, bx, by;
36     float step, scale;
37     step = powf( 2.0f, 1.0f / ((float)lambda) );
38
39     computeBorderSize(maxXBorder, maxYBorder, &bx, &by);
40
41     for (i = 0; i < kPoints; i++)
42     {
43         // scaling factor for root filter
44         scale = SIDE_LENGTH * powf(step, (float)(levels[i] - initialImageLevel));
45         points[i].x = (int)((points[i].x - bx + 1) * scale);
46         points[i].y = (int)((points[i].y - by + 1) * scale);
47
48         // scaling factor for part filters
49         scale = SIDE_LENGTH * powf(step, (float)(levels[i] - lambda - initialImageLevel));
50         for (j = 0; j < n; j++)
51         {
52             partsDisplacement[i][j].x = (int)((partsDisplacement[i][j].x -
53                                                2 * bx + 1) * scale);
54             partsDisplacement[i][j].y = (int)((partsDisplacement[i][j].y -
55                                                2 * by + 1) * scale);
56         }
57     }
58     return LATENT_SVM_OK;
59 }
60
61 /*
62 // Elimination boxes that are outside the image boudaries
63 //
64 // API
65 // int clippingBoxes(int width, int height,
66                      CvPoint *points, int kPoints);
67 // INPUT
68 // width             - image wediht
69 // height            - image heigth
70 // points            - a set of points (coordinates of top left or
71                        bottom right corners)
72 // kPoints           - points number
73 // OUTPUT
74 // points            - updated points (if coordinates less than zero then
75                        set zero coordinate, if coordinates more than image
76                        size then set coordinates equal image size)
77 // RESULT
78 // Error status
79 */
80 int clippingBoxes(int width, int height,
81                   CvPoint *points, int kPoints)
82 {
83     int i;
84     for (i = 0; i < kPoints; i++)
85     {
86         if (points[i].x > width - 1)
87         {
88             points[i].x = width - 1;
89         }
90         if (points[i].x < 0)
91         {
92             points[i].x = 0;
93         }
94         if (points[i].y > height - 1)
95         {
96             points[i].y = height - 1;
97         }
98         if (points[i].y < 0)
99         {
100             points[i].y = 0;
101         }
102     }
103     return LATENT_SVM_OK;
104 }
105
106 /*
107 // Creation feature pyramid with nullable border
108 //
109 // API
110 // featurePyramid* createFeaturePyramidWithBorder(const IplImage *image,
111                                                   int maxXBorder, int maxYBorder);
112
113 // INPUT
114 // image             - initial image
115 // maxXBorder        - the largest root filter size (X-direction)
116 // maxYBorder        - the largest root filter size (Y-direction)
117 // OUTPUT
118 // RESULT
119 // Feature pyramid with nullable border
120 */
121 CvLSVMFeaturePyramid* createFeaturePyramidWithBorder(IplImage *image,
122                                                int maxXBorder, int maxYBorder)
123 {
124     int opResult;
125     int bx, by;
126     int level;
127     CvLSVMFeaturePyramid *H;
128
129     // Obtaining feature pyramid
130     opResult = getFeaturePyramid(image, &H);
131
132     if (opResult != LATENT_SVM_OK)
133     {
134         freeFeaturePyramidObject(&H);
135         return NULL;
136     } /* if (opResult != LATENT_SVM_OK) */
137
138     // Addition nullable border for each feature map
139     // the size of the border for root filters
140     computeBorderSize(maxXBorder, maxYBorder, &bx, &by);
141     for (level = 0; level < H->numLevels; level++)
142     {
143         addNullableBorder(H->pyramid[level], bx, by);
144     }
145     return H;
146 }
147
148 /*
149 // Computation of the root filter displacement and values of score function
150 //
151 // API
152 // int searchObject(const featurePyramid *H, const filterObject **all_F, int n,
153                     float b,
154                     int maxXBorder,
155                      int maxYBorder,
156                      CvPoint **points, int **levels, int *kPoints, float *score,
157                      CvPoint ***partsDisplacement);
158 // INPUT
159 // image             - initial image for searhing object
160 // all_F             - the set of filters (the first element is root filter,
161                        other elements - part filters)
162 // n                 - the number of part filters
163 // b                 - linear term of the score function
164 // maxXBorder        - the largest root filter size (X-direction)
165 // maxYBorder        - the largest root filter size (Y-direction)
166 // OUTPUT
167 // points            - positions (x, y) of the upper-left corner
168                        of root filter frame
169 // levels            - levels that correspond to each position
170 // kPoints           - number of positions
171 // score             - value of the score function
172 // partsDisplacement - part filters displacement for each position
173                        of the root filter
174 // RESULT
175 // Error status
176 */
177 int searchObject(const CvLSVMFeaturePyramid *H, const CvLSVMFilterObject **all_F,
178                  int n, float b,
179                  int maxXBorder,
180                  int maxYBorder,
181                  CvPoint **points, int **levels, int *kPoints, float *score,
182                  CvPoint ***partsDisplacement)
183 {
184     int opResult;
185
186     // Matching
187     opResult = maxFunctionalScore(all_F, n, H, b, maxXBorder, maxYBorder,
188                                   score, points, levels,
189                                   kPoints, partsDisplacement);
190     if (opResult != LATENT_SVM_OK)
191     {
192         return LATENT_SVM_SEARCH_OBJECT_FAILED;
193     }
194
195     // Transformation filter displacement from the block space
196     // to the space of pixels at the initial image
197     // that settles at the level number LAMBDA
198     convertPoints(H->numLevels, LAMBDA, LAMBDA, (*points),
199                   (*levels), (*partsDisplacement), (*kPoints), n,
200                   maxXBorder, maxYBorder);
201
202     return LATENT_SVM_OK;
203 }
204
205 /*
206 // Computation right bottom corners coordinates of bounding boxes
207 //
208 // API
209 // int estimateBoxes(CvPoint *points, int *levels, int kPoints,
210                      int sizeX, int sizeY, CvPoint **oppositePoints);
211 // INPUT
212 // points            - left top corners coordinates of bounding boxes
213 // levels            - levels of feature pyramid where points were found
214 // (sizeX, sizeY)    - size of root filter
215 // OUTPUT
216 // oppositePoins     - right bottom corners coordinates of bounding boxes
217 // RESULT
218 // Error status
219 */
220 static int estimateBoxes(CvPoint *points, int *levels, int kPoints,
221                   int sizeX, int sizeY, CvPoint **oppositePoints)
222 {
223     int i;
224     float step;
225
226     step = powf( 2.0f, 1.0f / ((float)(LAMBDA)));
227
228     *oppositePoints = (CvPoint *)malloc(sizeof(CvPoint) * kPoints);
229     for (i = 0; i < kPoints; i++)
230     {
231         getOppositePoint(points[i], sizeX, sizeY, step, levels[i] - LAMBDA, &((*oppositePoints)[i]));
232     }
233     return LATENT_SVM_OK;
234 }
235
236 /*
237 // Computation of the root filter displacement and values of score function
238 //
239 // API
240 // int searchObjectThreshold(const featurePyramid *H,
241                              const filterObject **all_F, int n,
242                              float b,
243                              int maxXBorder, int maxYBorder,
244                              float scoreThreshold,
245                              CvPoint **points, int **levels, int *kPoints,
246                              float **score, CvPoint ***partsDisplacement);
247 // INPUT
248 // H                 - feature pyramid
249 // all_F             - the set of filters (the first element is root filter,
250                        other elements - part filters)
251 // n                 - the number of part filters
252 // b                 - linear term of the score function
253 // maxXBorder        - the largest root filter size (X-direction)
254 // maxYBorder        - the largest root filter size (Y-direction)
255 // scoreThreshold    - score threshold
256 // OUTPUT
257 // points            - positions (x, y) of the upper-left corner
258                        of root filter frame
259 // levels            - levels that correspond to each position
260 // kPoints           - number of positions
261 // score             - values of the score function
262 // partsDisplacement - part filters displacement for each position
263                        of the root filter
264 // RESULT
265 // Error status
266 */
267 int searchObjectThreshold(const CvLSVMFeaturePyramid *H,
268                           const CvLSVMFilterObject **all_F, int n,
269                           float b,
270                           int maxXBorder, int maxYBorder,
271                           float scoreThreshold,
272                           CvPoint **points, int **levels, int *kPoints,
273                           float **score, CvPoint ***partsDisplacement,
274                           int numThreads)
275 {
276     int opResult;
277
278
279     // Matching
280 #ifdef HAVE_TBB
281     if (numThreads <= 0)
282     {
283         opResult = LATENT_SVM_TBB_NUMTHREADS_NOT_CORRECT;
284         return opResult;
285     }
286     opResult = tbbThresholdFunctionalScore(all_F, n, H, b, maxXBorder, maxYBorder,
287                                            scoreThreshold, numThreads, score,
288                                            points, levels, kPoints,
289                                            partsDisplacement);
290 #else
291     opResult = thresholdFunctionalScore(all_F, n, H, b,
292                                         maxXBorder, maxYBorder,
293                                         scoreThreshold,
294                                         score, points, levels,
295                                         kPoints, partsDisplacement);
296
297   (void)numThreads;
298 #endif
299     if (opResult != LATENT_SVM_OK)
300     {
301         return LATENT_SVM_SEARCH_OBJECT_FAILED;
302     }
303
304     // Transformation filter displacement from the block space
305     // to the space of pixels at the initial image
306     // that settles at the level number LAMBDA
307     convertPoints(H->numLevels, LAMBDA, LAMBDA, (*points),
308                   (*levels), (*partsDisplacement), (*kPoints), n,
309                   maxXBorder, maxYBorder);
310
311     return LATENT_SVM_OK;
312 }
313
314 /*
315 // Compute opposite point for filter box
316 //
317 // API
318 // int getOppositePoint(CvPoint point,
319                         int sizeX, int sizeY,
320                         float step, int degree,
321                         CvPoint *oppositePoint);
322
323 // INPUT
324 // point             - coordinates of filter top left corner
325                        (in the space of pixels)
326 // (sizeX, sizeY)    - filter dimension in the block space
327 // step              - scaling factor
328 // degree            - degree of the scaling factor
329 // OUTPUT
330 // oppositePoint     - coordinates of filter bottom corner
331                        (in the space of pixels)
332 // RESULT
333 // Error status
334 */
335 int getOppositePoint(CvPoint point,
336                      int sizeX, int sizeY,
337                      float step, int degree,
338                      CvPoint *oppositePoint)
339 {
340     float scale;
341     scale = SIDE_LENGTH * powf(step, (float)degree);
342     oppositePoint->x = (int)(point.x + sizeX * scale);
343     oppositePoint->y = (int)(point.y + sizeY * scale);
344     return LATENT_SVM_OK;
345 }
346
347
348 /*
349 // Drawing root filter boxes
350 //
351 // API
352 // int showRootFilterBoxes(const IplImage *image,
353                            const filterObject *filter,
354                            CvPoint *points, int *levels, int kPoints,
355                            CvScalar color, int thickness,
356                            int line_type, int shift);
357 // INPUT
358 // image             - initial image
359 // filter            - root filter object
360 // points            - a set of points
361 // levels            - levels of feature pyramid
362 // kPoints           - number of points
363 // color             - line color for each box
364 // thickness         - line thickness
365 // line_type         - line type
366 // shift             - shift
367 // OUTPUT
368 // window contained initial image and filter boxes
369 // RESULT
370 // Error status
371 */
372 int showRootFilterBoxes(IplImage *image,
373                         const CvLSVMFilterObject *filter,
374                         CvPoint *points, int *levels, int kPoints,
375                         CvScalar color, int thickness,
376                         int line_type, int shift)
377 {
378     int i;
379     float step;
380     CvPoint oppositePoint;
381     step = powf( 2.0f, 1.0f / ((float)LAMBDA));
382
383     for (i = 0; i < kPoints; i++)
384     {
385         // Drawing rectangle for filter
386         getOppositePoint(points[i], filter->sizeX, filter->sizeY,
387                          step, levels[i] - LAMBDA, &oppositePoint);
388         cvRectangle(image, points[i], oppositePoint,
389                     color, thickness, line_type, shift);
390     }
391 #ifdef HAVE_OPENCV_HIGHGUI
392     cvShowImage("Initial image", image);
393 #endif
394     return LATENT_SVM_OK;
395 }
396
397 /*
398 // Drawing part filter boxes
399 //
400 // API
401 // int showPartFilterBoxes(const IplImage *image,
402                            const filterObject *filter,
403                            CvPoint *points, int *levels, int kPoints,
404                            CvScalar color, int thickness,
405                            int line_type, int shift);
406 // INPUT
407 // image             - initial image
408 // filters           - a set of part filters
409 // n                 - number of part filters
410 // partsDisplacement - a set of points
411 // levels            - levels of feature pyramid
412 // kPoints           - number of foot filter positions
413 // color             - line color for each box
414 // thickness         - line thickness
415 // line_type         - line type
416 // shift             - shift
417 // OUTPUT
418 // window contained initial image and filter boxes
419 // RESULT
420 // Error status
421 */
422 int showPartFilterBoxes(IplImage *image,
423                         const CvLSVMFilterObject **filters,
424                         int n, CvPoint **partsDisplacement,
425                         int *levels, int kPoints,
426                         CvScalar color, int thickness,
427                         int line_type, int shift)
428 {
429     int i, j;
430     float step;
431     CvPoint oppositePoint;
432
433     step = powf( 2.0f, 1.0f / ((float)LAMBDA));
434
435     for (i = 0; i < kPoints; i++)
436     {
437         for (j = 0; j < n; j++)
438         {
439             // Drawing rectangles for part filters
440             getOppositePoint(partsDisplacement[i][j],
441                              filters[j + 1]->sizeX, filters[j + 1]->sizeY,
442                              step, levels[i] - 2 * LAMBDA, &oppositePoint);
443             cvRectangle(image, partsDisplacement[i][j], oppositePoint,
444                         color, thickness, line_type, shift);
445         }
446     }
447 #ifdef HAVE_OPENCV_HIGHGUI
448     cvShowImage("Initial image", image);
449 #endif
450     return LATENT_SVM_OK;
451 }
452
453 /*
454 // Drawing boxes
455 //
456 // API
457 // int showBoxes(const IplImage *img,
458                  const CvPoint *points, const CvPoint *oppositePoints, int kPoints,
459                  CvScalar color, int thickness, int line_type, int shift);
460 // INPUT
461 // img               - initial image
462 // points            - top left corner coordinates
463 // oppositePoints    - right bottom corner coordinates
464 // kPoints           - points number
465 // color             - line color for each box
466 // thickness         - line thickness
467 // line_type         - line type
468 // shift             - shift
469 // OUTPUT
470 // RESULT
471 // Error status
472 */
473 int showBoxes(IplImage *img,
474               const CvPoint *points, const CvPoint *oppositePoints, int kPoints,
475               CvScalar color, int thickness, int line_type, int shift)
476 {
477     int i;
478     for (i = 0; i < kPoints; i++)
479     {
480         cvRectangle(img, points[i], oppositePoints[i],
481                     color, thickness, line_type, shift);
482     }
483 #ifdef HAVE_OPENCV_HIGHGUI
484     cvShowImage("Initial image", img);
485 #endif
486     return LATENT_SVM_OK;
487 }
488
489 /*
490 // Computation maximum filter size for each dimension
491 //
492 // API
493 // int getMaxFilterDims(const filterObject **filters, int kComponents,
494                         const int *kPartFilters,
495                         unsigned int *maxXBorder, unsigned int *maxYBorder);
496 // INPUT
497 // filters           - a set of filters (at first root filter, then part filters
498                        and etc. for all components)
499 // kComponents       - number of components
500 // kPartFilters      - number of part filters for each component
501 // OUTPUT
502 // maxXBorder        - maximum of filter size at the horizontal dimension
503 // maxYBorder        - maximum of filter size at the vertical dimension
504 // RESULT
505 // Error status
506 */
507 int getMaxFilterDims(const CvLSVMFilterObject **filters, int kComponents,
508                      const int *kPartFilters,
509                      unsigned int *maxXBorder, unsigned int *maxYBorder)
510 {
511     int i, componentIndex;
512     *maxXBorder = filters[0]->sizeX;
513     *maxYBorder = filters[0]->sizeY;
514     componentIndex = kPartFilters[0] + 1;
515     for (i = 1; i < kComponents; i++)
516     {
517         if ((unsigned)filters[componentIndex]->sizeX > *maxXBorder)
518         {
519             *maxXBorder = filters[componentIndex]->sizeX;
520         }
521         if ((unsigned)filters[componentIndex]->sizeY > *maxYBorder)
522         {
523             *maxYBorder = filters[componentIndex]->sizeY;
524         }
525         componentIndex += (kPartFilters[i] + 1);
526     }
527     return LATENT_SVM_OK;
528 }
529
530 /*
531 // Computation root filters displacement and values of score function
532 //
533 // API
534 // int searchObjectThresholdSomeComponents(const featurePyramid *H,
535                                            const filterObject **filters,
536                                            int kComponents, const int *kPartFilters,
537                                            const float *b, float scoreThreshold,
538                                            CvPoint **points, CvPoint **oppPoints,
539                                            float **score, int *kPoints);
540 // INPUT
541 // H                 - feature pyramid
542 // filters           - filters (root filter then it's part filters, etc.)
543 // kComponents       - root filters number
544 // kPartFilters      - array of part filters number for each component
545 // b                 - array of linear terms
546 // scoreThreshold    - score threshold
547 // OUTPUT
548 // points            - root filters displacement (top left corners)
549 // oppPoints         - root filters displacement (bottom right corners)
550 // score             - array of score values
551 // kPoints           - number of boxes
552 // RESULT
553 // Error status
554 */
555 int searchObjectThresholdSomeComponents(const CvLSVMFeaturePyramid *H,
556                                         const CvLSVMFilterObject **filters,
557                                         int kComponents, const int *kPartFilters,
558                                         const float *b, float scoreThreshold,
559                                         CvPoint **points, CvPoint **oppPoints,
560                                         float **score, int *kPoints,
561                                         int numThreads)
562 {
563     //int error = 0;
564     int i, j, s, f, componentIndex;
565     unsigned int maxXBorder, maxYBorder;
566     CvPoint **pointsArr, **oppPointsArr, ***partsDisplacementArr;
567     float **scoreArr;
568     int *kPointsArr, **levelsArr;
569
570     // Allocation memory
571     pointsArr = (CvPoint **)malloc(sizeof(CvPoint *) * kComponents);
572     oppPointsArr = (CvPoint **)malloc(sizeof(CvPoint *) * kComponents);
573     scoreArr = (float **)malloc(sizeof(float *) * kComponents);
574     kPointsArr = (int *)malloc(sizeof(int) * kComponents);
575     levelsArr = (int **)malloc(sizeof(int *) * kComponents);
576     partsDisplacementArr = (CvPoint ***)malloc(sizeof(CvPoint **) * kComponents);
577
578     // Getting maximum filter dimensions
579     /*error = */getMaxFilterDims(filters, kComponents, kPartFilters, &maxXBorder, &maxYBorder);
580     componentIndex = 0;
581     *kPoints = 0;
582     // For each component perform searching
583     for (i = 0; i < kComponents; i++)
584     {
585         int error = searchObjectThreshold(H, &(filters[componentIndex]), kPartFilters[i],
586             b[i], maxXBorder, maxYBorder, scoreThreshold,
587             &(pointsArr[i]), &(levelsArr[i]), &(kPointsArr[i]),
588             &(scoreArr[i]), &(partsDisplacementArr[i]), numThreads);
589         if (error != LATENT_SVM_OK)
590         {
591             // Release allocated memory
592             free(pointsArr);
593             free(oppPointsArr);
594             free(scoreArr);
595             free(kPointsArr);
596             free(levelsArr);
597             free(partsDisplacementArr);
598             return LATENT_SVM_SEARCH_OBJECT_FAILED;
599         }
600         estimateBoxes(pointsArr[i], levelsArr[i], kPointsArr[i],
601             filters[componentIndex]->sizeX, filters[componentIndex]->sizeY, &(oppPointsArr[i]));
602         componentIndex += (kPartFilters[i] + 1);
603         *kPoints += kPointsArr[i];
604     }
605
606     *points = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints));
607     *oppPoints = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints));
608     *score = (float *)malloc(sizeof(float) * (*kPoints));
609     s = 0;
610     for (i = 0; i < kComponents; i++)
611     {
612         f = s + kPointsArr[i];
613         for (j = s; j < f; j++)
614         {
615             (*points)[j].x = pointsArr[i][j - s].x;
616             (*points)[j].y = pointsArr[i][j - s].y;
617             (*oppPoints)[j].x = oppPointsArr[i][j - s].x;
618             (*oppPoints)[j].y = oppPointsArr[i][j - s].y;
619             (*score)[j] = scoreArr[i][j - s];
620         }
621         s = f;
622     }
623
624     // Release allocated memory
625     for (i = 0; i < kComponents; i++)
626     {
627         free(pointsArr[i]);
628         free(oppPointsArr[i]);
629         free(scoreArr[i]);
630         free(levelsArr[i]);
631         for (j = 0; j < kPointsArr[i]; j++)
632         {
633             free(partsDisplacementArr[i][j]);
634         }
635         free(partsDisplacementArr[i]);
636     }
637     free(pointsArr);
638     free(oppPointsArr);
639     free(scoreArr);
640     free(kPointsArr);
641     free(levelsArr);
642     free(partsDisplacementArr);
643     return LATENT_SVM_OK;
644 }