2 #include "opencv2/objdetect/objdetect_c.h"
3 #include "_lsvm_matching.h"
7 #define max(a,b) (((a) > (b)) ? (a) : (b))
11 #define min(a,b) (((a) < (b)) ? (a) : (b))
15 // Function for convolution computation
21 // f - the convolution
25 int convolution(const CvLSVMFilterObject *Fi, const CvLSVMFeatureMap *map, float *f)
27 int n1, m1, n2, m2, p, /*size,*/ diff1, diff2;
28 int i1, i2, j1, j2, k;
29 float tmp_f1, tmp_f2, tmp_f3, tmp_f4;
41 //size = diff1 * diff2;
42 for (j1 = diff2 - 1; j1 >= 0; j1--)
45 for (i1 = diff1 - 1; i1 >= 0; i1--)
51 for (i2 = 0; i2 < n2; i2++)
53 for (j2 = 0; j2 < m2; j2++)
55 pMap = map->map + (i1 + i2) * m1 * p + (j1 + j2) * p;//sm2
56 pH = Fi->H + (i2 * m2 + j2) * p;//sm2
57 for (k = 0; k < p/4; k++)
60 tmp_f1 += pMap[4*k]*pH[4*k];//sm2
61 tmp_f2 += pMap[4*k+1]*pH[4*k+1];
62 tmp_f3 += pMap[4*k+2]*pH[4*k+2];
63 tmp_f4 += pMap[4*k+3]*pH[4*k+3];
68 tmp_f1 += pH[p-1]*pMap[p-1];
74 tmp_f1 += pH[p-2]*pMap[p-2] + pH[p-1]*pMap[p-1];
80 tmp_f1 += pH[p-3]*pMap[p-3] + pH[p-2]*pMap[p-2] + pH[p-1]*pMap[p-1];
87 f[i1 * diff2 + j1] = tmp_f1 + tmp_f2 + tmp_f3 + tmp_f4;//sm1
94 // Computation multiplication of FFT images
97 // int fftImagesMulti(float *fftImage1, float *fftImage2, int numRows, int numColls,
100 // fftImage1 - first fft image
101 // fftImage2 - second fft image
102 // (numRows, numColls) - image dimesions
104 // multi - multiplication
108 int fftImagesMulti(float *fftImage1, float *fftImage2, int numRows, int numColls,
112 size = numRows * numColls;
113 for (i = 0; i < size; i++)
116 multi[index] = fftImage1[index] * fftImage2[index] -
117 fftImage1[index + 1] * fftImage2[index + 1];
118 multi[index + 1] = fftImage1[index] * fftImage2[index + 1] +
119 fftImage1[index + 1] * fftImage2[index];
121 return LATENT_SVM_OK;
125 // Turnover filter matrix for the single feature
128 // int rot2PI(float *filter, int dimX, int dimY, float *rot2PIFilter,
131 // filter - filter weight matrix
132 // (dimX, dimY) - dimension of filter matrix
133 // p - number of features
134 // shift - number of feature (or channel)
136 // rot2PIFilter - rotated matrix
140 int rot2PI(float *filter, int dimX, int dimY, float *rot2PIFilter,
145 for (i = 0; i < size; i++)
147 rot2PIFilter[i] = filter[(size - i - 1) * p + shift];
149 return LATENT_SVM_OK;
153 // Addition nullable bars to the dimension of feature map (single feature)
156 // int addNullableBars(float *rot2PIFilter, int dimX, int dimY,
157 float *newFilter, int newDimX, int newDimY);
159 // rot2PIFilter - filter matrix for the single feature that was rotated
160 // (dimX, dimY) - dimension rot2PIFilter
161 // (newDimX, newDimY)- dimension of feature map for the single feature
163 // newFilter - filter matrix with nullable bars
167 int addNullableBars(float *rot2PIFilter, int dimX, int dimY,
168 float *newFilter, int newDimX, int newDimY)
171 size = newDimX * newDimY;
172 for (i = 0; i < size; i++)
174 newFilter[2 * i] = 0.0;
175 newFilter[2 * i + 1] = 0.0;
177 for (i = 0; i < dimY; i++)
179 for (j = 0; j < dimX; j++)
181 newFilter[2 * (i * newDimX + j)] = rot2PIFilter[i * dimX + j];
184 return LATENT_SVM_OK;
188 // Computation FFT image for filter object
191 // int getFFTImageFilterObject(const CvLSVMFilterObject *filter,
192 int mapDimX, int mapDimY,
195 // filter - filter object
196 // (mapDimX, mapDimY)- dimension of feature map
202 int getFFTImageFilterObject(const CvLSVMFilterObject *filter,
203 int mapDimX, int mapDimY,
204 CvLSVMFftImage **image)
206 int i, mapSize, filterSize, res;
207 float *newFilter, *rot2PIFilter;
209 filterSize = filter->sizeX * filter->sizeY;
210 mapSize = mapDimX * mapDimY;
212 res = allocFFTImage(image, filter->numFeatures, mapDimX, mapDimY);
213 if (res != LATENT_SVM_OK)
216 newFilter = (float *)malloc(sizeof(float) * (2 * mapSize));
217 rot2PIFilter = (float *)malloc(sizeof(float) * filterSize);
218 for (i = 0; i < filter->numFeatures; i++)
220 rot2PI(filter->H, filter->sizeX, filter->sizeY, rot2PIFilter, filter->numFeatures, i);
221 addNullableBars(rot2PIFilter, filter->sizeX, filter->sizeY,
222 newFilter, mapDimX, mapDimY);
223 fft2d(newFilter, (*image)->channels[i], mapDimY, mapDimX);
227 return LATENT_SVM_OK;
231 // Computation FFT image for feature map
234 // int getFFTImageFeatureMap(const featureMap *map, fftImage **image);
240 int getFFTImageFeatureMap(const CvLSVMFeatureMap *map, CvLSVMFftImage **image)
244 allocFFTImage(image, map->numFeatures, map->sizeX, map->sizeY);
245 size = map->sizeX * map->sizeY;
246 buf = (float *)malloc(sizeof(float) * (2 * size));
247 for (i = 0; i < map->numFeatures; i++)
249 for (j = 0; j < size; j++)
251 buf[2 * j] = map->map[j * map->numFeatures + i];
252 buf[2 * j + 1] = 0.0;
254 fft2d(buf, (*image)->channels[i], map->sizeY, map->sizeX);
257 return LATENT_SVM_OK;
261 // Function for convolution computation using FFT
264 // int convFFTConv2d(const fftImage *featMapImage, const fftImage *filterImage,
265 int filterDimX, int filterDimY, float **conv);
267 // featMapImage - feature map image
268 // filterImage - filter image
269 // (filterDimX,filterDimY) - filter dimension
271 // conv - the convolution
275 int convFFTConv2d(const CvLSVMFftImage *featMapImage, const CvLSVMFftImage *filterImage,
276 int filterDimX, int filterDimY, float **conv)
278 int i, j, size, diffX, diffY, index;
279 float *imagesMult, *imagesMultRes, *fconv;
280 size = 2 * featMapImage->dimX * featMapImage->dimY;
281 imagesMult = (float *)malloc(sizeof(float) * size);
282 imagesMultRes = (float *)malloc(sizeof(float) * size);
283 fftImagesMulti(featMapImage->channels[0], filterImage->channels[0],
284 featMapImage->dimY, featMapImage->dimX, imagesMultRes);
285 for (i = 1; (i < (int)featMapImage->numFeatures) && (i < (int)filterImage->numFeatures); i++)
287 fftImagesMulti(featMapImage->channels[i],filterImage->channels[i],
288 featMapImage->dimY, featMapImage->dimX, imagesMult);
289 for (j = 0; j < size; j++)
291 imagesMultRes[j] += imagesMult[j];
294 fconv = (float *)malloc(sizeof(float) * size);
295 fftInverse2d(imagesMultRes, fconv, featMapImage->dimY, featMapImage->dimX);
296 diffX = featMapImage->dimX - filterDimX + 1;
297 diffY = featMapImage->dimY - filterDimY + 1;
298 *conv = (float *)malloc(sizeof(float) * (diffX * diffY));
299 for (i = 0; i < diffY; i++)
301 for (j = 0; j < diffX; j++)
303 index = (i + filterDimY - 1) * featMapImage->dimX +
304 (j + filterDimX - 1);
305 (*conv)[i * diffX + j] = fconv[2 * index];
311 return LATENT_SVM_OK;
315 // Computation objective function D according the original paper
318 // int filterDispositionLevel(const CvLSVMFilterObject *Fi, const featurePyramid *H,
319 int level, float **scoreFi,
320 int **pointsX, int **pointsY);
322 // Fi - filter object (weights and coefficients of penalty
323 function that are used in this routine)
324 // H - feature pyramid
325 // level - level number
327 // scoreFi - values of distance transform on the level at all positions
328 // (pointsX, pointsY)- positions that correspond to the maximum value
329 of distance transform at all grid nodes
333 int filterDispositionLevel(const CvLSVMFilterObject *Fi, const CvLSVMFeatureMap *pyramid,
335 int **pointsX, int **pointsY)
337 int n1, m1, n2, m2, /*p,*/ size, diff1, diff2;
346 //p = pyramid->numFeatures;
351 // Processing the situation when part filter goes
352 // beyond the boundaries of the block set
353 if (n1 < n2 || m1 < m2)
355 return FILTER_OUT_OF_BOUNDARIES;
356 } /* if (n1 < n2 || m1 < m2) */
358 // Computation number of positions for the filter
361 size = diff1 * diff2;
363 // Allocation memory for additional array (must be free in this function)
364 f = (float *)malloc(sizeof(float) * size);
365 // Allocation memory for arrays for saving decisions
366 (*scoreFi) = (float *)malloc(sizeof(float) * size);
367 (*pointsX) = (int *)malloc(sizeof(int) * size);
368 (*pointsY) = (int *)malloc(sizeof(int) * size);
370 // Consruction values of the array f
371 // (a dot product vectors of feature map and weights of the filter)
372 res = convolution(Fi, pyramid, f);
373 if (res != LATENT_SVM_OK)
382 // TODO: necessary to change
383 for (i1 = 0; i1 < diff1; i1++)
385 for (j1 = 0; j1 < diff2; j1++)
387 f[i1 * diff2 + j1] *= (-1);
391 // Decision of the general distance transform task
392 DistanceTransformTwoDimensionalProblem(f, diff1, diff2, Fi->fineFunction,
393 (*scoreFi), (*pointsX), (*pointsY));
395 // Release allocated memory
397 return LATENT_SVM_OK;
401 // Computation objective function D according the original paper using FFT
404 // int filterDispositionLevelFFT(const CvLSVMFilterObject *Fi, const fftImage *featMapImage,
406 int **pointsX, int **pointsY);
408 // Fi - filter object (weights and coefficients of penalty
409 function that are used in this routine)
410 // featMapImage - FFT image of feature map
412 // scoreFi - values of distance transform on the level at all positions
413 // (pointsX, pointsY)- positions that correspond to the maximum value
414 of distance transform at all grid nodes
418 int filterDispositionLevelFFT(const CvLSVMFilterObject *Fi, const CvLSVMFftImage *featMapImage,
420 int **pointsX, int **pointsY)
422 int n1, m1, n2, m2, /*p,*/ size, diff1, diff2;
426 CvLSVMFftImage *filterImage;
428 n1 = featMapImage->dimY;
429 m1 = featMapImage->dimX;
432 //p = featMapImage->numFeatures;
437 // Processing the situation when part filter goes
438 // beyond the boundaries of the block set
439 if (n1 < n2 || m1 < m2)
441 return FILTER_OUT_OF_BOUNDARIES;
442 } /* if (n1 < n2 || m1 < m2) */
444 // Computation number of positions for the filter
447 size = diff1 * diff2;
449 // Allocation memory for arrays for saving decisions
450 (*scoreFi) = (float *)malloc(sizeof(float) * size);
451 (*pointsX) = (int *)malloc(sizeof(int) * size);
452 (*pointsY) = (int *)malloc(sizeof(int) * size);
454 // create filter image
455 getFFTImageFilterObject(Fi, featMapImage->dimX, featMapImage->dimY, &filterImage);
457 // Consruction values of the array f
458 // (a dot product vectors of feature map and weights of the filter)
459 res = convFFTConv2d(featMapImage, filterImage, Fi->sizeX, Fi->sizeY, &f);
460 if (res != LATENT_SVM_OK)
469 // TODO: necessary to change
470 for (i1 = 0; i1 < diff1; i1++)
472 for (j1 = 0; j1 < diff2; j1++)
474 f[i1 * diff2 + j1] *= (-1);
478 // Decision of the general distance transform task
479 DistanceTransformTwoDimensionalProblem(f, diff1, diff2, Fi->fineFunction,
480 (*scoreFi), (*pointsX), (*pointsY));
482 // Release allocated memory
484 freeFFTImage(&filterImage);
485 return LATENT_SVM_OK;
489 // Computation border size for feature map
492 // int computeBorderSize(int maxXBorder, int maxYBorder, int *bx, int *by);
494 // maxXBorder - the largest root filter size (X-direction)
495 // maxYBorder - the largest root filter size (Y-direction)
497 // bx - border size (X-direction)
498 // by - border size (Y-direction)
502 int computeBorderSize(int maxXBorder, int maxYBorder, int *bx, int *by)
504 *bx = (int)ceilf(((float) maxXBorder) / 2.0f + 1.0f);
505 *by = (int)ceilf(((float) maxYBorder) / 2.0f + 1.0f);
506 return LATENT_SVM_OK;
510 // Addition nullable border to the feature map
513 // int addNullableBorder(featureMap *map, int bx, int by);
516 // bx - border size (X-direction)
517 // by - border size (Y-direction)
522 int addNullableBorder(CvLSVMFeatureMap *map, int bx, int by)
524 int sizeX, sizeY, i, j, k;
526 sizeX = map->sizeX + 2 * bx;
527 sizeY = map->sizeY + 2 * by;
528 // fix for Windows Phone 8 ARM compiler
529 size_t size = sizeof(float) * sizeX * sizeY * map->numFeatures;
530 new_map = (float *)malloc(size);
531 for (i = 0; i < sizeX * sizeY * map->numFeatures; i++)
535 for (i = by; i < map->sizeY + by; i++)
537 for (j = bx; j < map->sizeX + bx; j++)
539 for (k = 0; k < map->numFeatures; k++)
541 new_map[(i * sizeX + j) * map->numFeatures + k] =
542 map->map[((i - by) * map->sizeX + j - bx) * map->numFeatures + k];
550 return LATENT_SVM_OK;
553 static CvLSVMFeatureMap* featureMapBorderPartFilter(CvLSVMFeatureMap *map,
554 int maxXBorder, int maxYBorder)
557 int sizeX, sizeY, i, j, k;
558 CvLSVMFeatureMap *new_map;
560 computeBorderSize(maxXBorder, maxYBorder, &bx, &by);
561 sizeX = map->sizeX + 2 * bx;
562 sizeY = map->sizeY + 2 * by;
563 allocFeatureMapObject(&new_map, sizeX, sizeY, map->numFeatures);
564 for (i = 0; i < sizeX * sizeY * map->numFeatures; i++)
566 new_map->map[i] = 0.0f;
568 for (i = by; i < map->sizeY + by; i++)
570 for (j = bx; j < map->sizeX + bx; j++)
572 for (k = 0; k < map->numFeatures; k++)
574 new_map->map[(i * sizeX + j) * map->numFeatures + k] =
575 map->map[((i - by) * map->sizeX + j - bx) * map->numFeatures + k];
583 // Computation the maximum of the score function at the level
586 // int maxFunctionalScoreFixedLevel(const CvLSVMFilterObject **all_F, int n,
587 const featurePyramid *H,
589 int maxXBorder, int maxYBorder,
590 float *score, CvPoint **points, int *kPoints,
591 CvPoint ***partsDisplacement);
593 // all_F - the set of filters (the first element is root filter,
594 the other - part filters)
595 // n - the number of part filters
596 // H - feature pyramid
597 // level - feature pyramid level for computation maximum score
598 // b - linear term of the score function
599 // maxXBorder - the largest root filter size (X-direction)
600 // maxYBorder - the largest root filter size (Y-direction)
602 // score - the maximum of the score function at the level
603 // points - the set of root filter positions (in the block space)
604 // levels - the set of levels
605 // kPoints - number of root filter positions
606 // partsDisplacement - displacement of part filters (in the block space)
610 int maxFunctionalScoreFixedLevel(const CvLSVMFilterObject **all_F, int n,
611 const CvLSVMFeaturePyramid *H,
613 int maxXBorder, int maxYBorder,
614 float *score, CvPoint **points,
615 int *kPoints, CvPoint ***partsDisplacement)
617 int i, j, k, dimX, dimY, nF0, mF0/*, p*/;
618 int diff1, diff2, index, last, partsLevel;
619 CvLSVMFilterDisposition **disposition;
622 float sumScorePartDisposition, maxScore;
624 CvLSVMFeatureMap *map;
626 CvLSVMFftImage *rootFilterImage, *mapImage;
634 char buf[40] = "..\\Data\\score\\score", buf1[10] = ".csv";
635 tmp = (char *)malloc(sizeof(char) * 80);
636 itoa(level, tmp, 10);
640 // Feature map matrix dimension on the level
641 dimX = H->pyramid[level]->sizeX;
642 dimY = H->pyramid[level]->sizeY;
644 // Number of features
645 //p = H->pyramid[level]->numFeatures;
647 // Getting dimension of root filter
648 nF0 = all_F[0]->sizeY;
649 mF0 = all_F[0]->sizeX;
650 // Processing the situation when root filter goes
651 // beyond the boundaries of the block set
652 if (nF0 > dimY || mF0 > dimX)
654 return LATENT_SVM_FAILED_SUPERPOSITION;
657 diff1 = dimY - nF0 + 1;
658 diff2 = dimX - mF0 + 1;
660 // Allocation memory for saving values of function D
661 // on the level for each part filter
662 disposition = (CvLSVMFilterDisposition **)malloc(sizeof(CvLSVMFilterDisposition *) * n);
663 for (i = 0; i < n; i++)
665 disposition[i] = (CvLSVMFilterDisposition *)malloc(sizeof(CvLSVMFilterDisposition));
668 // Allocation memory for values of score function for each block on the level
669 scores = (float *)malloc(sizeof(float) * (diff1 * diff2));
671 // A dot product vectors of feature map and weights of root filter
673 getFFTImageFeatureMap(H->pyramid[level], &mapImage);
674 getFFTImageFilterObject(all_F[0], H->pyramid[level]->sizeX, H->pyramid[level]->sizeY, &rootFilterImage);
675 res = convFFTConv2d(mapImage, rootFilterImage, all_F[0]->sizeX, all_F[0]->sizeY, &f);
676 freeFFTImage(&mapImage);
677 freeFFTImage(&rootFilterImage);
679 // Allocation memory for saving a dot product vectors of feature map and
680 // weights of root filter
681 f = (float *)malloc(sizeof(float) * (diff1 * diff2));
682 // A dot product vectors of feature map and weights of root filter
683 res = convolution(all_F[0], H->pyramid[level], f);
685 if (res != LATENT_SVM_OK)
689 for (i = 0; i < n; i++)
691 free(disposition[i]);
697 // Computation values of function D for each part filter
698 // on the level (level - LAMBDA)
699 partsLevel = level - LAMBDA;
700 // For feature map at the level 'partsLevel' add nullable border
701 map = featureMapBorderPartFilter(H->pyramid[partsLevel],
702 maxXBorder, maxYBorder);
704 // Computation the maximum of score function
705 sumScorePartDisposition = 0.0;
707 getFFTImageFeatureMap(map, &mapImage);
708 for (k = 1; k <= n; k++)
710 filterDispositionLevelFFT(all_F[k], mapImage,
711 &(disposition[k - 1]->score),
712 &(disposition[k - 1]->x),
713 &(disposition[k - 1]->y));
715 freeFFTImage(&mapImage);
717 for (k = 1; k <= n; k++)
719 filterDispositionLevel(all_F[k], map,
720 &(disposition[k - 1]->score),
721 &(disposition[k - 1]->x),
722 &(disposition[k - 1]->y));
725 scores[0] = f[0] - sumScorePartDisposition + b;
726 maxScore = scores[0];
728 for (i = 0; i < diff1; i++)
730 for (j = 0; j < diff2; j++)
732 sumScorePartDisposition = 0.0;
733 for (k = 1; k <= n; k++)
735 // This condition takes on a value true
736 // when filter goes beyond the boundaries of block set
737 if ((2 * i + all_F[k]->V.y <
738 map->sizeY - all_F[k]->sizeY + 1) &&
739 (2 * j + all_F[k]->V.x <
740 map->sizeX - all_F[k]->sizeX + 1))
742 index = (2 * i + all_F[k]->V.y) *
743 (map->sizeX - all_F[k]->sizeX + 1) +
744 (2 * j + all_F[k]->V.x);
745 sumScorePartDisposition += disposition[k - 1]->score[index];
748 scores[i * diff2 + j] = f[i * diff2 + j] - sumScorePartDisposition + b;
749 if (maxScore < scores[i * diff2 + j])
751 maxScore = scores[i * diff2 + j];
754 else if ((scores[i * diff2 + j] - maxScore) *
755 (scores[i * diff2 + j] - maxScore) <= EPS)
758 } /* if (maxScore < scores[i * diff2 + j]) */
762 // Allocation memory for saving positions of root filter and part filters
763 (*points) = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints));
764 (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (*kPoints));
765 for (i = 0; i < (*kPoints); i++)
767 (*partsDisplacement)[i] = (CvPoint *)malloc(sizeof(CvPoint) * n);
772 file = fopen(buf, "w+");
774 // Construction of the set of positions for root filter
775 // that correspond the maximum of score function on the level
778 for (i = 0; i < diff1; i++)
780 for (j = 0; j < diff2; j++)
782 if ((scores[i * diff2 + j] - maxScore) *
783 (scores[i * diff2 + j] - maxScore) <= EPS)
785 (*points)[last].y = i;
786 (*points)[last].x = j;
787 for (k = 1; k <= n; k++)
789 if ((2 * i + all_F[k]->V.y <
790 map->sizeY - all_F[k]->sizeY + 1) &&
791 (2 * j + all_F[k]->V.x <
792 map->sizeX - all_F[k]->sizeX + 1))
794 index = (2 * i + all_F[k]->V.y) *
795 (map->sizeX - all_F[k]->sizeX + 1) +
796 (2 * j + all_F[k]->V.x);
797 (*partsDisplacement)[last][k - 1].x =
798 disposition[k - 1]->x[index];
799 (*partsDisplacement)[last][k - 1].y =
800 disposition[k - 1]->y[index];
804 } /* if ((scores[i * diff2 + j] - maxScore) *
805 (scores[i * diff2 + j] - maxScore) <= EPS) */
806 //fprintf(file, "%lf;", scores[i * diff2 + j]);
808 //fprintf(file, "\n");
813 // Release allocated memory
814 for (i = 0; i < n ; i++)
816 free(disposition[i]->score);
817 free(disposition[i]->x);
818 free(disposition[i]->y);
819 free(disposition[i]);
824 freeFeatureMapObject(&map);
825 return LATENT_SVM_OK;
829 // Computation score function at the level that exceed threshold
832 // int thresholdFunctionalScoreFixedLevel(const CvLSVMFilterObject **all_F, int n,
833 const featurePyramid *H,
835 int maxXBorder, int maxYBorder,
836 float scoreThreshold,
837 float **score, CvPoint **points, int *kPoints,
838 CvPoint ***partsDisplacement);
840 // all_F - the set of filters (the first element is root filter,
841 the other - part filters)
842 // n - the number of part filters
843 // H - feature pyramid
844 // level - feature pyramid level for computation maximum score
845 // b - linear term of the score function
846 // maxXBorder - the largest root filter size (X-direction)
847 // maxYBorder - the largest root filter size (Y-direction)
848 // scoreThreshold - score threshold
850 // score - score function at the level that exceed threshold
851 // points - the set of root filter positions (in the block space)
852 // levels - the set of levels
853 // kPoints - number of root filter positions
854 // partsDisplacement - displacement of part filters (in the block space)
858 int thresholdFunctionalScoreFixedLevel(const CvLSVMFilterObject **all_F, int n,
859 const CvLSVMFeaturePyramid *H,
861 int maxXBorder, int maxYBorder,
862 float scoreThreshold,
863 float **score, CvPoint **points, int *kPoints,
864 CvPoint ***partsDisplacement)
866 int i, j, k, dimX, dimY, nF0, mF0/*, p*/;
867 int diff1, diff2, index, last, partsLevel;
868 CvLSVMFilterDisposition **disposition;
871 float sumScorePartDisposition;
873 CvLSVMFeatureMap *map;
875 CvLSVMFftImage *rootFilterImage, *mapImage;
882 char buf[40] = "..\\Data\\score\\score", buf1[10] = ".csv";
883 tmp = (char *)malloc(sizeof(char) * 80);
884 itoa(level, tmp, 10);
888 // Feature map matrix dimension on the level
889 dimX = H->pyramid[level]->sizeX;
890 dimY = H->pyramid[level]->sizeY;
892 // Number of features
893 //p = H->pyramid[level]->numFeatures;
895 // Getting dimension of root filter
896 nF0 = all_F[0]->sizeY;
897 mF0 = all_F[0]->sizeX;
898 // Processing the situation when root filter goes
899 // beyond the boundaries of the block set
900 if (nF0 > dimY || mF0 > dimX)
902 return LATENT_SVM_FAILED_SUPERPOSITION;
905 diff1 = dimY - nF0 + 1;
906 diff2 = dimX - mF0 + 1;
908 // Allocation memory for saving values of function D
909 // on the level for each part filter
910 disposition = (CvLSVMFilterDisposition **)malloc(sizeof(CvLSVMFilterDisposition *) * n);
911 for (i = 0; i < n; i++)
913 disposition[i] = (CvLSVMFilterDisposition *)malloc(sizeof(CvLSVMFilterDisposition));
916 // Allocation memory for values of score function for each block on the level
917 scores = (float *)malloc(sizeof(float) * (diff1 * diff2));
918 // A dot product vectors of feature map and weights of root filter
920 getFFTImageFeatureMap(H->pyramid[level], &mapImage);
921 getFFTImageFilterObject(all_F[0], H->pyramid[level]->sizeX, H->pyramid[level]->sizeY, &rootFilterImage);
922 res = convFFTConv2d(mapImage, rootFilterImage, all_F[0]->sizeX, all_F[0]->sizeY, &f);
923 freeFFTImage(&mapImage);
924 freeFFTImage(&rootFilterImage);
926 // Allocation memory for saving a dot product vectors of feature map and
927 // weights of root filter
928 f = (float *)malloc(sizeof(float) * (diff1 * diff2));
929 res = convolution(all_F[0], H->pyramid[level], f);
931 if (res != LATENT_SVM_OK)
935 for (i = 0; i < n; i++)
937 free(disposition[i]);
943 // Computation values of function D for each part filter
944 // on the level (level - LAMBDA)
945 partsLevel = level - LAMBDA;
946 // For feature map at the level 'partsLevel' add nullable border
947 map = featureMapBorderPartFilter(H->pyramid[partsLevel],
948 maxXBorder, maxYBorder);
950 // Computation the maximum of score function
951 sumScorePartDisposition = 0.0;
953 getFFTImageFeatureMap(map, &mapImage);
954 for (k = 1; k <= n; k++)
956 filterDispositionLevelFFT(all_F[k], mapImage,
957 &(disposition[k - 1]->score),
958 &(disposition[k - 1]->x),
959 &(disposition[k - 1]->y));
961 freeFFTImage(&mapImage);
963 for (k = 1; k <= n; k++)
965 filterDispositionLevel(all_F[k], map,
966 &(disposition[k - 1]->score),
967 &(disposition[k - 1]->x),
968 &(disposition[k - 1]->y));
972 for (i = 0; i < diff1; i++)
974 for (j = 0; j < diff2; j++)
976 sumScorePartDisposition = 0.0;
977 for (k = 1; k <= n; k++)
979 // This condition takes on a value true
980 // when filter goes beyond the boundaries of block set
981 if ((2 * i + all_F[k]->V.y <
982 map->sizeY - all_F[k]->sizeY + 1) &&
983 (2 * j + all_F[k]->V.x <
984 map->sizeX - all_F[k]->sizeX + 1))
986 index = (2 * i + all_F[k]->V.y) *
987 (map->sizeX - all_F[k]->sizeX + 1) +
988 (2 * j + all_F[k]->V.x);
989 sumScorePartDisposition += disposition[k - 1]->score[index];
992 scores[i * diff2 + j] = f[i * diff2 + j] - sumScorePartDisposition + b;
993 if (scores[i * diff2 + j] > scoreThreshold)
1000 // Allocation memory for saving positions of root filter and part filters
1001 (*points) = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints));
1002 (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (*kPoints));
1003 for (i = 0; i < (*kPoints); i++)
1005 (*partsDisplacement)[i] = (CvPoint *)malloc(sizeof(CvPoint) * n);
1010 file = fopen(buf, "w+");
1012 // Construction of the set of positions for root filter
1013 // that correspond score function on the level that exceed threshold
1014 (*score) = (float *)malloc(sizeof(float) * (*kPoints));
1016 for (i = 0; i < diff1; i++)
1018 for (j = 0; j < diff2; j++)
1020 if (scores[i * diff2 + j] > scoreThreshold)
1022 (*score)[last] = scores[i * diff2 + j];
1023 (*points)[last].y = i;
1024 (*points)[last].x = j;
1025 for (k = 1; k <= n; k++)
1027 if ((2 * i + all_F[k]->V.y <
1028 map->sizeY - all_F[k]->sizeY + 1) &&
1029 (2 * j + all_F[k]->V.x <
1030 map->sizeX - all_F[k]->sizeX + 1))
1032 index = (2 * i + all_F[k]->V.y) *
1033 (map->sizeX - all_F[k]->sizeX + 1) +
1034 (2 * j + all_F[k]->V.x);
1035 (*partsDisplacement)[last][k - 1].x =
1036 disposition[k - 1]->x[index];
1037 (*partsDisplacement)[last][k - 1].y =
1038 disposition[k - 1]->y[index];
1043 //fprintf(file, "%lf;", scores[i * diff2 + j]);
1045 //fprintf(file, "\n");
1050 // Release allocated memory
1051 for (i = 0; i < n ; i++)
1053 free(disposition[i]->score);
1054 free(disposition[i]->x);
1055 free(disposition[i]->y);
1056 free(disposition[i]);
1061 freeFeatureMapObject(&map);
1062 return LATENT_SVM_OK;
1066 // Computation the maximum of the score function
1069 // int maxFunctionalScore(const CvLSVMFilterObject **all_F, int n,
1070 const featurePyramid *H, float b,
1071 int maxXBorder, int maxYBorder,
1073 CvPoint **points, int **levels, int *kPoints,
1074 CvPoint ***partsDisplacement);
1076 // all_F - the set of filters (the first element is root filter,
1077 the other - part filters)
1078 // n - the number of part filters
1079 // H - feature pyramid
1080 // b - linear term of the score function
1081 // maxXBorder - the largest root filter size (X-direction)
1082 // maxYBorder - the largest root filter size (Y-direction)
1084 // score - the maximum of the score function
1085 // points - the set of root filter positions (in the block space)
1086 // levels - the set of levels
1087 // kPoints - number of root filter positions
1088 // partsDisplacement - displacement of part filters (in the block space)
1092 int maxFunctionalScore(const CvLSVMFilterObject **all_F, int n,
1093 const CvLSVMFeaturePyramid *H, float b,
1094 int maxXBorder, int maxYBorder,
1096 CvPoint **points, int **levels, int *kPoints,
1097 CvPoint ***partsDisplacement)
1099 int l, i, j, k, s, f, level, numLevels;
1101 CvPoint ***tmpPoints;
1102 CvPoint ****tmpPartsDisplacement;
1111 // Computation the number of levels for seaching object,
1112 // first lambda-levels are used for computation values
1113 // of score function for each position of root filter
1114 numLevels = H->numLevels - LAMBDA;
1116 // Allocation memory for maximum value of score function for each level
1117 tmpScore = (float *)malloc(sizeof(float) * numLevels);
1118 // Allocation memory for the set of points that corresponds
1119 // to the maximum of score function
1120 tmpPoints = (CvPoint ***)malloc(sizeof(CvPoint **) * numLevels);
1121 for (i = 0; i < numLevels; i++)
1123 tmpPoints[i] = (CvPoint **)malloc(sizeof(CvPoint *));
1125 // Allocation memory for memory for saving parts displacement on each level
1126 tmpPartsDisplacement = (CvPoint ****)malloc(sizeof(CvPoint ***) * numLevels);
1127 for (i = 0; i < numLevels; i++)
1129 tmpPartsDisplacement[i] = (CvPoint ***)malloc(sizeof(CvPoint **));
1131 // Number of points that corresponds to the maximum
1132 // of score function on each level
1133 tmpKPoints = (int *)malloc(sizeof(int) * numLevels);
1134 for (i = 0; i < numLevels; i++)
1139 // Set current value of the maximum of score function
1140 res = maxFunctionalScoreFixedLevel(all_F, n, H, LAMBDA, b,
1141 maxXBorder, maxYBorder,
1145 tmpPartsDisplacement[0]);
1146 maxScore = tmpScore[0];
1147 (*kPoints) = tmpKPoints[0];
1149 // Computation maxima of score function on each level
1150 // and getting the maximum on all levels
1152 file = fopen("maxScore.csv", "w+");
1153 fprintf(file, "%i;%lf;\n", H->lambda, tmpScore[0]);
1155 for (l = LAMBDA + 1; l < H->numLevels; l++)
1158 res = maxFunctionalScoreFixedLevel(all_F, n, H, l, b,
1159 maxXBorder, maxYBorder,
1163 tmpPartsDisplacement[k]);
1164 //fprintf(file, "%i;%lf;\n", l, tmpScore[k]);
1165 if (res != LATENT_SVM_OK)
1169 if (maxScore < tmpScore[k])
1171 maxScore = tmpScore[k];
1172 (*kPoints) = tmpKPoints[k];
1174 else if ((maxScore - tmpScore[k]) * (maxScore - tmpScore[k]) <= EPS)
1176 (*kPoints) += tmpKPoints[k];
1177 } /* if (maxScore < tmpScore[k]) else if (...)*/
1181 // Allocation memory for levels
1182 (*levels) = (int *)malloc(sizeof(int) * (*kPoints));
1183 // Allocation memory for the set of points
1184 (*points) = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints));
1185 // Allocation memory for parts displacement
1186 (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (*kPoints));
1188 // Filling the set of points, levels and parts displacement
1191 for (i = 0; i < numLevels; i++)
1193 if ((tmpScore[i] - maxScore) * (tmpScore[i] - maxScore) <= EPS)
1195 // Computation the number of level
1198 // Addition a set of points
1200 for (j = s; j < f; j++)
1202 (*levels)[j] = level;
1203 (*points)[j] = (*tmpPoints[i])[j - s];
1204 (*partsDisplacement)[j] = (*(tmpPartsDisplacement[i]))[j - s];
1207 } /* if ((tmpScore[i] - maxScore) * (tmpScore[i] - maxScore) <= EPS) */
1209 (*score) = maxScore;
1211 // Release allocated memory
1212 for (i = 0; i < numLevels; i++)
1215 free(tmpPartsDisplacement[i]);
1218 free(tmpPartsDisplacement);
1222 return LATENT_SVM_OK;
1226 // Computation score function that exceed threshold
1229 // int thresholdFunctionalScore(const CvLSVMFilterObject **all_F, int n,
1230 const featurePyramid *H,
1232 int maxXBorder, int maxYBorder,
1233 float scoreThreshold,
1235 CvPoint **points, int **levels, int *kPoints,
1236 CvPoint ***partsDisplacement);
1238 // all_F - the set of filters (the first element is root filter,
1239 the other - part filters)
1240 // n - the number of part filters
1241 // H - feature pyramid
1242 // b - linear term of the score function
1243 // maxXBorder - the largest root filter size (X-direction)
1244 // maxYBorder - the largest root filter size (Y-direction)
1245 // scoreThreshold - score threshold
1247 // score - score function values that exceed threshold
1248 // points - the set of root filter positions (in the block space)
1249 // levels - the set of levels
1250 // kPoints - number of root filter positions
1251 // partsDisplacement - displacement of part filters (in the block space)
1255 int thresholdFunctionalScore(const CvLSVMFilterObject **all_F, int n,
1256 const CvLSVMFeaturePyramid *H,
1258 int maxXBorder, int maxYBorder,
1259 float scoreThreshold,
1261 CvPoint **points, int **levels, int *kPoints,
1262 CvPoint ***partsDisplacement)
1264 int l, i, j, k, s, f, level, numLevels;
1266 CvPoint ***tmpPoints;
1267 CvPoint ****tmpPartsDisplacement;
1275 // Computation the number of levels for seaching object,
1276 // first lambda-levels are used for computation values
1277 // of score function for each position of root filter
1278 numLevels = H->numLevels - LAMBDA;
1280 // Allocation memory for values of score function for each level
1281 // that exceed threshold
1282 tmpScore = (float **)malloc(sizeof(float*) * numLevels);
1283 // Allocation memory for the set of points that corresponds
1284 // to the maximum of score function
1285 tmpPoints = (CvPoint ***)malloc(sizeof(CvPoint **) * numLevels);
1286 for (i = 0; i < numLevels; i++)
1288 tmpPoints[i] = (CvPoint **)malloc(sizeof(CvPoint *));
1290 // Allocation memory for memory for saving parts displacement on each level
1291 tmpPartsDisplacement = (CvPoint ****)malloc(sizeof(CvPoint ***) * numLevels);
1292 for (i = 0; i < numLevels; i++)
1294 tmpPartsDisplacement[i] = (CvPoint ***)malloc(sizeof(CvPoint **));
1296 // Number of points that corresponds to the maximum
1297 // of score function on each level
1298 tmpKPoints = (int *)malloc(sizeof(int) * numLevels);
1299 for (i = 0; i < numLevels; i++)
1304 // Computation maxima of score function on each level
1305 // and getting the maximum on all levels
1307 file = fopen("maxScore.csv", "w+");
1308 fprintf(file, "%i;%lf;\n", H->lambda, tmpScore[0]);
1311 for (l = LAMBDA; l < H->numLevels; l++)
1314 //printf("Score at the level %i\n", l);
1315 res = thresholdFunctionalScoreFixedLevel(all_F, n, H, l, b,
1316 maxXBorder, maxYBorder, scoreThreshold,
1320 tmpPartsDisplacement[k]);
1321 //fprintf(file, "%i;%lf;\n", l, tmpScore[k]);
1322 if (res != LATENT_SVM_OK)
1326 (*kPoints) += tmpKPoints[k];
1330 // Allocation memory for levels
1331 (*levels) = (int *)malloc(sizeof(int) * (*kPoints));
1332 // Allocation memory for the set of points
1333 (*points) = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints));
1334 // Allocation memory for parts displacement
1335 (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (*kPoints));
1336 // Allocation memory for score function values
1337 (*score) = (float *)malloc(sizeof(float) * (*kPoints));
1339 // Filling the set of points, levels and parts displacement
1342 for (i = 0; i < numLevels; i++)
1344 // Computation the number of level
1347 // Addition a set of points
1349 for (j = s; j < f; j++)
1351 (*levels)[j] = level;
1352 (*points)[j] = (*tmpPoints[i])[j - s];
1353 (*score)[j] = tmpScore[i][j - s];
1354 (*partsDisplacement)[j] = (*(tmpPartsDisplacement[i]))[j - s];
1359 // Release allocated memory
1360 for (i = 0; i < numLevels; i++)
1363 free(tmpPartsDisplacement[i]);
1368 free(tmpPartsDisplacement);
1370 return LATENT_SVM_OK;
1375 // Creating schedule of pyramid levels processing
1378 // int createSchedule(const featurePyramid *H, const filterObject **all_F,
1379 const int n, const int bx, const int by,
1380 const int threadsNum, int *kLevels,
1381 int **processingLevels)
1383 // H - feature pyramid
1384 // all_F - the set of filters (the first element is root filter,
1385 the other - part filters)
1386 // n - the number of part filters
1387 // bx - size of nullable border (X direction)
1388 // by - size of nullable border (Y direction)
1389 // threadsNum - number of threads that will be created in TBB version
1391 // kLevels - array that contains number of levels processed
1393 // processingLevels - array that contains lists of levels processed
1398 static int createSchedule(const CvLSVMFeaturePyramid *H, const CvLSVMFilterObject **all_F,
1399 const int n, const int bx, const int by,
1400 const int threadsNum, int *kLevels, int **processingLevels)
1402 int rootFilterDim, sumPartFiltersDim, i, numLevels, dbx, dby;
1403 int j, minValue, argMin, lambda, maxValue, k;
1404 int *dotProd, *weights, *disp;
1405 if (H == NULL || all_F == NULL)
1407 return LATENT_SVM_TBB_SCHEDULE_CREATION_FAILED;
1409 // Number of feature vectors in root filter
1410 rootFilterDim = all_F[0]->sizeX * all_F[0]->sizeY;
1411 // Number of feature vectors in all part filters
1412 sumPartFiltersDim = 0;
1413 for (i = 1; i <= n; i++)
1415 sumPartFiltersDim += all_F[i]->sizeX * all_F[i]->sizeY;
1417 // Number of levels which are used for computation of score function
1418 numLevels = H->numLevels - LAMBDA;
1419 // Allocation memory for saving number of dot products that will be
1420 // computed for each level of feature pyramid
1421 dotProd = (int *)malloc(sizeof(int) * numLevels);
1422 // Size of nullable border that's used in computing convolution
1423 // of feature map with part filter
1427 for (i = 0; i < numLevels; i++)
1429 dotProd[i] = H->pyramid[i + lambda]->sizeX *
1430 H->pyramid[i + lambda]->sizeY * rootFilterDim +
1431 (H->pyramid[i]->sizeX + dbx) *
1432 (H->pyramid[i]->sizeY + dby) * sumPartFiltersDim;
1434 // Allocation memory for saving dot product number performed by each thread
1435 weights = (int *)malloc(sizeof(int) * threadsNum);
1436 // Allocation memory for saving dispertion
1437 disp = (int *)malloc(sizeof(int) * threadsNum);
1438 // At the first step we think of first threadsNum levels will be processed
1439 // by different threads
1440 for (i = 0; i < threadsNum; i++)
1443 weights[i] = dotProd[i];
1446 // Computation number of levels that will be processed by each thread
1447 for (i = threadsNum; i < numLevels; i++)
1449 // Search number of thread that will process level number i
1450 for (j = 0; j < threadsNum; j++)
1452 weights[j] += dotProd[i];
1453 minValue = weights[0];
1454 maxValue = weights[0];
1455 for (k = 1; k < threadsNum; k++)
1457 minValue = min(minValue, weights[k]);
1458 maxValue = max(maxValue, weights[k]);
1460 disp[j] = maxValue - minValue;
1461 weights[j] -= dotProd[i];
1465 for (j = 1; j < threadsNum; j++)
1467 if (disp[j] < minValue)
1473 // Addition new level
1475 weights[argMin] += dotProd[i];
1477 for (i = 0; i < threadsNum; i++)
1479 // Allocation memory for saving list of levels for each level
1480 processingLevels[i] = (int *)malloc(sizeof(int) * kLevels[i]);
1481 // At the first step we think of first threadsNum levels will be processed
1482 // by different threads
1483 processingLevels[i][0] = lambda + i;
1485 weights[i] = dotProd[i];
1487 // Creating list of levels
1488 for (i = threadsNum; i < numLevels; i++)
1490 for (j = 0; j < threadsNum; j++)
1492 weights[j] += dotProd[i];
1493 minValue = weights[0];
1494 maxValue = weights[0];
1495 for (k = 1; k < threadsNum; k++)
1497 minValue = min(minValue, weights[k]);
1498 maxValue = max(maxValue, weights[k]);
1500 disp[j] = maxValue - minValue;
1501 weights[j] -= dotProd[i];
1505 for (j = 1; j < threadsNum; j++)
1507 if (disp[j] < minValue)
1513 processingLevels[argMin][kLevels[argMin]] = lambda + i;
1515 weights[argMin] += dotProd[i];
1517 // Release allocated memory
1521 return LATENT_SVM_OK;
1525 // int tbbThresholdFunctionalScore(const CvLSVMFilterObject **all_F, int n,
1526 const CvLSVMFeaturePyramid *H,
1528 const int maxXBorder, const int maxYBorder,
1529 const float scoreThreshold,
1530 const int threadsNum,
1532 CvPoint **points, int **levels, int *kPoints,
1533 CvPoint ***partsDisplacement);
1535 // all_F - the set of filters (the first element is root filter,
1536 the other - part filters)
1537 // n - the number of part filters
1538 // H - feature pyramid
1539 // b - linear term of the score function
1540 // maxXBorder - the largest root filter size (X-direction)
1541 // maxYBorder - the largest root filter size (Y-direction)
1542 // scoreThreshold - score threshold
1543 // threadsNum - number of threads that will be created using TBB version
1545 // score - score function values that exceed threshold
1546 // points - the set of root filter positions (in the block space)
1547 // levels - the set of levels
1548 // kPoints - number of root filter positions
1549 // partsDisplacement - displacement of part filters (in the block space)
1553 int tbbThresholdFunctionalScore(const CvLSVMFilterObject **all_F, int n,
1554 const CvLSVMFeaturePyramid *H,
1556 const int maxXBorder, const int maxYBorder,
1557 const float scoreThreshold,
1558 const int threadsNum,
1560 CvPoint **points, int **levels, int *kPoints,
1561 CvPoint ***partsDisplacement)
1563 int i, j, s, f, level, numLevels;
1565 CvPoint ***tmpPoints;
1566 CvPoint ****tmpPartsDisplacement;
1570 int *kLevels, **procLevels;
1573 // Computation the number of levels for seaching object,
1574 // first lambda-levels are used for computation values
1575 // of score function for each position of root filter
1576 numLevels = H->numLevels - LAMBDA;
1577 kLevels = (int *)malloc(sizeof(int) * threadsNum);
1578 procLevels = (int **)malloc(sizeof(int*) * threadsNum);
1579 computeBorderSize(maxXBorder, maxYBorder, &bx, &by);
1580 res = createSchedule(H, all_F, n, bx, by, threadsNum, kLevels, procLevels);
1581 if (res != LATENT_SVM_OK)
1583 for (i = 0; i < threadsNum; i++)
1585 if (procLevels[i] != NULL)
1587 free(procLevels[i]);
1595 // Allocation memory for values of score function for each level
1596 // that exceed threshold
1597 tmpScore = (float **)malloc(sizeof(float*) * numLevels);
1598 // Allocation memory for the set of points that corresponds
1599 // to the maximum of score function
1600 tmpPoints = (CvPoint ***)malloc(sizeof(CvPoint **) * numLevels);
1601 for (i = 0; i < numLevels; i++)
1603 tmpPoints[i] = (CvPoint **)malloc(sizeof(CvPoint *));
1605 // Allocation memory for memory for saving parts displacement on each level
1606 tmpPartsDisplacement = (CvPoint ****)malloc(sizeof(CvPoint ***) * numLevels);
1607 for (i = 0; i < numLevels; i++)
1609 tmpPartsDisplacement[i] = (CvPoint ***)malloc(sizeof(CvPoint **));
1611 // Number of points that corresponds to the maximum
1612 // of score function on each level
1613 tmpKPoints = (int *)malloc(sizeof(int) * numLevels);
1614 for (i = 0; i < numLevels; i++)
1619 // Computation maxima of score function on each level
1620 // and getting the maximum on all levels using TBB tasks
1621 tbbTasksThresholdFunctionalScore(all_F, n, H, b, maxXBorder, maxYBorder,
1622 scoreThreshold, kLevels, procLevels,
1623 threadsNum, tmpScore, tmpPoints,
1624 tmpKPoints, tmpPartsDisplacement);
1626 for (i = 0; i < numLevels; i++)
1628 (*kPoints) += tmpKPoints[i];
1631 // Allocation memory for levels
1632 (*levels) = (int *)malloc(sizeof(int) * (*kPoints));
1633 // Allocation memory for the set of points
1634 (*points) = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints));
1635 // Allocation memory for parts displacement
1636 (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (*kPoints));
1637 // Allocation memory for score function values
1638 (*score) = (float *)malloc(sizeof(float) * (*kPoints));
1640 // Filling the set of points, levels and parts displacement
1643 for (i = 0; i < numLevels; i++)
1645 // Computation the number of level
1646 level = i + LAMBDA;//H->lambda;
1648 // Addition a set of points
1650 for (j = s; j < f; j++)
1652 (*levels)[j] = level;
1653 (*points)[j] = (*tmpPoints[i])[j - s];
1654 (*score)[j] = tmpScore[i][j - s];
1655 (*partsDisplacement)[j] = (*(tmpPartsDisplacement[i]))[j - s];
1660 // Release allocated memory
1661 for (i = 0; i < numLevels; i++)
1664 free(tmpPartsDisplacement[i]);
1666 for (i = 0; i < threadsNum; i++)
1668 free(procLevels[i]);
1675 free(tmpPartsDisplacement);
1677 return LATENT_SVM_OK;
1681 static void sort(int n, const float* x, int* indices)
1684 for (i = 0; i < n; i++)
1685 for (j = i + 1; j < n; j++)
1687 if (x[indices[j]] > x[indices[i]])
1689 //float x_tmp = x[i];
1690 int index_tmp = indices[i];
1692 indices[i] = indices[j];
1694 indices[j] = index_tmp;
1700 // Perform non-maximum suppression algorithm (described in original paper)
1701 // to remove "similar" bounding boxes
1704 // int nonMaximumSuppression(int numBoxes, const CvPoint *points,
1705 const CvPoint *oppositePoints, const float *score,
1706 float overlapThreshold,
1707 int *numBoxesOut, CvPoint **pointsOut,
1708 CvPoint **oppositePointsOut, float **scoreOut);
1710 // numBoxes - number of bounding boxes
1711 // points - array of left top corner coordinates
1712 // oppositePoints - array of right bottom corner coordinates
1713 // score - array of detection scores
1714 // overlapThreshold - threshold: bounding box is removed if overlap part
1715 is greater than passed value
1717 // numBoxesOut - the number of bounding boxes algorithm returns
1718 // pointsOut - array of left top corner coordinates
1719 // oppositePointsOut - array of right bottom corner coordinates
1720 // scoreOut - array of detection scores
1724 int nonMaximumSuppression(int numBoxes, const CvPoint *points,
1725 const CvPoint *oppositePoints, const float *score,
1726 float overlapThreshold,
1727 int *numBoxesOut, CvPoint **pointsOut,
1728 CvPoint **oppositePointsOut, float **scoreOut)
1731 float* box_area = (float*)malloc(numBoxes * sizeof(float));
1732 int* indices = (int*)malloc(numBoxes * sizeof(int));
1733 int* is_suppressed = (int*)malloc(numBoxes * sizeof(int));
1735 for (i = 0; i < numBoxes; i++)
1738 is_suppressed[i] = 0;
1739 box_area[i] = (float)( (oppositePoints[i].x - points[i].x + 1) *
1740 (oppositePoints[i].y - points[i].y + 1));
1743 sort(numBoxes, score, indices);
1744 for (i = 0; i < numBoxes; i++)
1746 if (!is_suppressed[indices[i]])
1748 for (j = i + 1; j < numBoxes; j++)
1750 if (!is_suppressed[indices[j]])
1752 int x1max = max(points[indices[i]].x, points[indices[j]].x);
1753 int x2min = min(oppositePoints[indices[i]].x, oppositePoints[indices[j]].x);
1754 int y1max = max(points[indices[i]].y, points[indices[j]].y);
1755 int y2min = min(oppositePoints[indices[i]].y, oppositePoints[indices[j]].y);
1756 int overlapWidth = x2min - x1max + 1;
1757 int overlapHeight = y2min - y1max + 1;
1758 if (overlapWidth > 0 && overlapHeight > 0)
1760 float overlapPart = (overlapWidth * overlapHeight) / box_area[indices[j]];
1761 if (overlapPart > overlapThreshold)
1763 is_suppressed[indices[j]] = 1;
1772 for (i = 0; i < numBoxes; i++)
1774 if (!is_suppressed[i]) (*numBoxesOut)++;
1777 *pointsOut = (CvPoint *)malloc((*numBoxesOut) * sizeof(CvPoint));
1778 *oppositePointsOut = (CvPoint *)malloc((*numBoxesOut) * sizeof(CvPoint));
1779 *scoreOut = (float *)malloc((*numBoxesOut) * sizeof(float));
1781 for (i = 0; i < numBoxes; i++)
1783 if (!is_suppressed[indices[i]])
1785 (*pointsOut)[index].x = points[indices[i]].x;
1786 (*pointsOut)[index].y = points[indices[i]].y;
1787 (*oppositePointsOut)[index].x = oppositePoints[indices[i]].x;
1788 (*oppositePointsOut)[index].y = oppositePoints[indices[i]].y;
1789 (*scoreOut)[index] = score[indices[i]];
1797 free(is_suppressed);
1799 return LATENT_SVM_OK;