#include "precomp.hpp" #include "_lsvm_matching.h" #include #ifndef max #define max(a,b) (((a) > (b)) ? (a) : (b)) #endif #ifndef min #define min(a,b) (((a) < (b)) ? (a) : (b)) #endif /* // Function for convolution computation // // INPUT // Fi - filter object // map - feature map // OUTPUT // f - the convolution // RESULT // Error status */ int convolution(const CvLSVMFilterObject *Fi, const CvLSVMFeatureMap *map, float *f) { int n1, m1, n2, m2, p, size, diff1, diff2; int i1, i2, j1, j2, k; float tmp_f1, tmp_f2, tmp_f3, tmp_f4; float *pMap = NULL; float *pH = NULL; n1 = map->sizeY; m1 = map->sizeX; n2 = Fi->sizeY; m2 = Fi->sizeX; p = map->numFeatures; diff1 = n1 - n2 + 1; diff2 = m1 - m2 + 1; size = diff1 * diff2; for (j1 = diff2 - 1; j1 >= 0; j1--) { for (i1 = diff1 - 1; i1 >= 0; i1--) { tmp_f1 = 0.0f; tmp_f2 = 0.0f; tmp_f3 = 0.0f; tmp_f4 = 0.0f; for (i2 = 0; i2 < n2; i2++) { for (j2 = 0; j2 < m2; j2++) { pMap = map->map + (i1 + i2) * m1 * p + (j1 + j2) * p;//sm2 pH = Fi->H + (i2 * m2 + j2) * p;//sm2 for (k = 0; k < p/4; k++) { tmp_f1 += pMap[4*k]*pH[4*k];//sm2 tmp_f2 += pMap[4*k+1]*pH[4*k+1]; tmp_f3 += pMap[4*k+2]*pH[4*k+2]; tmp_f4 += pMap[4*k+3]*pH[4*k+3]; } if (p%4==1) { tmp_f1 += pH[p-1]*pMap[p-1]; } else { if (p%4==2) { tmp_f1 += pH[p-2]*pMap[p-2] + pH[p-1]*pMap[p-1]; } else { if (p%4==3) { tmp_f1 += pH[p-3]*pMap[p-3] + pH[p-2]*pMap[p-2] + pH[p-1]*pMap[p-1]; } } } } } f[i1 * diff2 + j1] = tmp_f1 + tmp_f2 + tmp_f3 + tmp_f4;//sm1 } } return LATENT_SVM_OK; } /* // Computation multiplication of FFT images // // API // int fftImagesMulti(float *fftImage1, float *fftImage2, int numRows, int numColls, float *multi); // INPUT // fftImage1 - first fft image // fftImage2 - second fft image // (numRows, numColls) - image dimesions // OUTPUT // multi - multiplication // RESULT // Error status */ int fftImagesMulti(float *fftImage1, float *fftImage2, int numRows, int numColls, float *multi) { int i, index, size; size = numRows * numColls; for (i = 0; i < size; i++) { index = 2 * i; multi[index] = fftImage1[index] * fftImage2[index] - fftImage1[index + 1] * fftImage2[index + 1]; multi[index + 1] = fftImage1[index] * fftImage2[index + 1] + fftImage1[index + 1] * fftImage2[index]; } return LATENT_SVM_OK; } /* // Turnover filter matrix for the single feature // // API // int rot2PI(float *filter, int dimX, int dimY, float *rot2PIFilter, int p, int shift); // INPUT // filter - filter weight matrix // (dimX, dimY) - dimension of filter matrix // p - number of features // shift - number of feature (or channel) // OUTPUT // rot2PIFilter - rotated matrix // RESULT // Error status */ int rot2PI(float *filter, int dimX, int dimY, float *rot2PIFilter, int p, int shift) { int i, size; size = dimX * dimY; for (i = 0; i < size; i++) { rot2PIFilter[i] = filter[(size - i - 1) * p + shift]; } return LATENT_SVM_OK; } /* // Addition nullable bars to the dimension of feature map (single feature) // // API // int addNullableBars(float *rot2PIFilter, int dimX, int dimY, float *newFilter, int newDimX, int newDimY); // INPUT // rot2PIFilter - filter matrix for the single feature that was rotated // (dimX, dimY) - dimension rot2PIFilter // (newDimX, newDimY)- dimension of feature map for the single feature // OUTPUT // newFilter - filter matrix with nullable bars // RESULT // Error status */ int addNullableBars(float *rot2PIFilter, int dimX, int dimY, float *newFilter, int newDimX, int newDimY) { int size, i, j; size = newDimX * newDimY; for (i = 0; i < size; i++) { newFilter[2 * i] = 0.0; newFilter[2 * i + 1] = 0.0; } for (i = 0; i < dimY; i++) { for (j = 0; j < dimX; j++) { newFilter[2 * (i * newDimX + j)] = rot2PIFilter[i * dimX + j]; } } return LATENT_SVM_OK; } /* // Computation FFT image for filter object // // API // int getFFTImageFilterObject(const CvLSVMFilterObject *filter, int mapDimX, int mapDimY, fftImage **image); // INPUT // filter - filter object // (mapDimX, mapDimY)- dimension of feature map // OUTPUT // image - fft image // RESULT // Error status */ int getFFTImageFilterObject(const CvLSVMFilterObject *filter, int mapDimX, int mapDimY, CvLSVMFftImage **image) { int i, mapSize, filterSize, res; float *newFilter, *rot2PIFilter; filterSize = filter->sizeX * filter->sizeY; mapSize = mapDimX * mapDimY; res = allocFFTImage(image, filter->numFeatures, mapDimX, mapDimY); if (res != LATENT_SVM_OK) return res; newFilter = (float *)malloc(sizeof(float) * (2 * mapSize)); rot2PIFilter = (float *)malloc(sizeof(float) * filterSize); for (i = 0; i < filter->numFeatures; i++) { rot2PI(filter->H, filter->sizeX, filter->sizeY, rot2PIFilter, filter->numFeatures, i); addNullableBars(rot2PIFilter, filter->sizeX, filter->sizeY, newFilter, mapDimX, mapDimY); fft2d(newFilter, (*image)->channels[i], mapDimY, mapDimX); } free(newFilter); free(rot2PIFilter); return LATENT_SVM_OK; } /* // Computation FFT image for feature map // // API // int getFFTImageFeatureMap(const featureMap *map, fftImage **image); // INPUT // OUTPUT // RESULT // Error status */ int getFFTImageFeatureMap(const CvLSVMFeatureMap *map, CvLSVMFftImage **image) { int i, j, size; float *buf; allocFFTImage(image, map->numFeatures, map->sizeX, map->sizeY); size = map->sizeX * map->sizeY; buf = (float *)malloc(sizeof(float) * (2 * size)); for (i = 0; i < map->numFeatures; i++) { for (j = 0; j < size; j++) { buf[2 * j] = map->map[j * map->numFeatures + i]; buf[2 * j + 1] = 0.0; } fft2d(buf, (*image)->channels[i], map->sizeY, map->sizeX); } free(buf); return LATENT_SVM_OK; } /* // Function for convolution computation using FFT // // API // int convFFTConv2d(const fftImage *featMapImage, const fftImage *filterImage, int filterDimX, int filterDimY, float **conv); // INPUT // featMapImage - feature map image // filterImage - filter image // (filterDimX,filterDimY) - filter dimension // OUTPUT // conv - the convolution // RESULT // Error status */ int convFFTConv2d(const CvLSVMFftImage *featMapImage, const CvLSVMFftImage *filterImage, int filterDimX, int filterDimY, float **conv) { int i, j, size, diffX, diffY, index; float *imagesMult, *imagesMultRes, *fconv; size = 2 * featMapImage->dimX * featMapImage->dimY; imagesMult = (float *)malloc(sizeof(float) * size); imagesMultRes = (float *)malloc(sizeof(float) * size); fftImagesMulti(featMapImage->channels[0], filterImage->channels[0], featMapImage->dimY, featMapImage->dimX, imagesMultRes); for (i = 1; (i < (int)featMapImage->numFeatures) && (i < (int)filterImage->numFeatures); i++) { fftImagesMulti(featMapImage->channels[i],filterImage->channels[i], featMapImage->dimY, featMapImage->dimX, imagesMult); for (j = 0; j < size; j++) { imagesMultRes[j] += imagesMult[j]; } } fconv = (float *)malloc(sizeof(float) * size); fftInverse2d(imagesMultRes, fconv, featMapImage->dimY, featMapImage->dimX); diffX = featMapImage->dimX - filterDimX + 1; diffY = featMapImage->dimY - filterDimY + 1; *conv = (float *)malloc(sizeof(float) * (diffX * diffY)); for (i = 0; i < diffY; i++) { for (j = 0; j < diffX; j++) { index = (i + filterDimY - 1) * featMapImage->dimX + (j + filterDimX - 1); (*conv)[i * diffX + j] = fconv[2 * index]; } } free(imagesMult); free(imagesMultRes); free(fconv); return LATENT_SVM_OK; } /* // Computation objective function D according the original paper // // API // int filterDispositionLevel(const CvLSVMFilterObject *Fi, const featurePyramid *H, int level, float **scoreFi, int **pointsX, int **pointsY); // INPUT // Fi - filter object (weights and coefficients of penalty function that are used in this routine) // H - feature pyramid // level - level number // OUTPUT // scoreFi - values of distance transform on the level at all positions // (pointsX, pointsY)- positions that correspond to the maximum value of distance transform at all grid nodes // RESULT // Error status */ int filterDispositionLevel(const CvLSVMFilterObject *Fi, const CvLSVMFeatureMap *pyramid, float **scoreFi, int **pointsX, int **pointsY) { int n1, m1, n2, m2, p, size, diff1, diff2; float *f; int i1, j1; int res; n1 = pyramid->sizeY; m1 = pyramid->sizeX; n2 = Fi->sizeY; m2 = Fi->sizeX; p = pyramid->numFeatures; (*scoreFi) = NULL; (*pointsX) = NULL; (*pointsY) = NULL; // Processing the situation when part filter goes // beyond the boundaries of the block set if (n1 < n2 || m1 < m2) { return FILTER_OUT_OF_BOUNDARIES; } /* if (n1 < n2 || m1 < m2) */ // Computation number of positions for the filter diff1 = n1 - n2 + 1; diff2 = m1 - m2 + 1; size = diff1 * diff2; // Allocation memory for additional array (must be free in this function) f = (float *)malloc(sizeof(float) * size); // Allocation memory for arrays for saving decisions (*scoreFi) = (float *)malloc(sizeof(float) * size); (*pointsX) = (int *)malloc(sizeof(int) * size); (*pointsY) = (int *)malloc(sizeof(int) * size); // Consruction values of the array f // (a dot product vectors of feature map and weights of the filter) res = convolution(Fi, pyramid, f); if (res != LATENT_SVM_OK) { free(f); free(*scoreFi); free(*pointsX); free(*pointsY); return res; } // TODO: necessary to change for (i1 = 0; i1 < diff1; i1++) { for (j1 = 0; j1 < diff2; j1++) { f[i1 * diff2 + j1] *= (-1); } } // Decision of the general distance transform task DistanceTransformTwoDimensionalProblem(f, diff1, diff2, Fi->fineFunction, (*scoreFi), (*pointsX), (*pointsY)); // Release allocated memory free(f); return LATENT_SVM_OK; } /* // Computation objective function D according the original paper using FFT // // API // int filterDispositionLevelFFT(const CvLSVMFilterObject *Fi, const fftImage *featMapImage, float **scoreFi, int **pointsX, int **pointsY); // INPUT // Fi - filter object (weights and coefficients of penalty function that are used in this routine) // featMapImage - FFT image of feature map // OUTPUT // scoreFi - values of distance transform on the level at all positions // (pointsX, pointsY)- positions that correspond to the maximum value of distance transform at all grid nodes // RESULT // Error status */ int filterDispositionLevelFFT(const CvLSVMFilterObject *Fi, const CvLSVMFftImage *featMapImage, float **scoreFi, int **pointsX, int **pointsY) { int n1, m1, n2, m2, p, size, diff1, diff2; float *f; int i1, j1; int res; CvLSVMFftImage *filterImage; n1 = featMapImage->dimY; m1 = featMapImage->dimX; n2 = Fi->sizeY; m2 = Fi->sizeX; p = featMapImage->numFeatures; (*scoreFi) = NULL; (*pointsX) = NULL; (*pointsY) = NULL; // Processing the situation when part filter goes // beyond the boundaries of the block set if (n1 < n2 || m1 < m2) { return FILTER_OUT_OF_BOUNDARIES; } /* if (n1 < n2 || m1 < m2) */ // Computation number of positions for the filter diff1 = n1 - n2 + 1; diff2 = m1 - m2 + 1; size = diff1 * diff2; // Allocation memory for arrays for saving decisions (*scoreFi) = (float *)malloc(sizeof(float) * size); (*pointsX) = (int *)malloc(sizeof(int) * size); (*pointsY) = (int *)malloc(sizeof(int) * size); // create filter image getFFTImageFilterObject(Fi, featMapImage->dimX, featMapImage->dimY, &filterImage); // Consruction values of the array f // (a dot product vectors of feature map and weights of the filter) res = convFFTConv2d(featMapImage, filterImage, Fi->sizeX, Fi->sizeY, &f); if (res != LATENT_SVM_OK) { free(f); free(*scoreFi); free(*pointsX); free(*pointsY); return res; } // TODO: necessary to change for (i1 = 0; i1 < diff1; i1++) { for (j1 = 0; j1 < diff2; j1++) { f[i1 * diff2 + j1] *= (-1); } } // Decision of the general distance transform task DistanceTransformTwoDimensionalProblem(f, diff1, diff2, Fi->fineFunction, (*scoreFi), (*pointsX), (*pointsY)); // Release allocated memory free(f); freeFFTImage(&filterImage); return LATENT_SVM_OK; } /* // Computation border size for feature map // // API // int computeBorderSize(int maxXBorder, int maxYBorder, int *bx, int *by); // INPUT // maxXBorder - the largest root filter size (X-direction) // maxYBorder - the largest root filter size (Y-direction) // OUTPUT // bx - border size (X-direction) // by - border size (Y-direction) // RESULT // Error status */ int computeBorderSize(int maxXBorder, int maxYBorder, int *bx, int *by) { *bx = (int)ceilf(((float) maxXBorder) / 2.0f + 1.0f); *by = (int)ceilf(((float) maxYBorder) / 2.0f + 1.0f); return LATENT_SVM_OK; } /* // Addition nullable border to the feature map // // API // int addNullableBorder(featureMap *map, int bx, int by); // INPUT // map - feature map // bx - border size (X-direction) // by - border size (Y-direction) // OUTPUT // RESULT // Error status */ int addNullableBorder(CvLSVMFeatureMap *map, int bx, int by) { int sizeX, sizeY, i, j, k; float *new_map; sizeX = map->sizeX + 2 * bx; sizeY = map->sizeY + 2 * by; new_map = (float *)malloc(sizeof(float) * sizeX * sizeY * map->numFeatures); for (i = 0; i < sizeX * sizeY * map->numFeatures; i++) { new_map[i] = 0.0; } for (i = by; i < map->sizeY + by; i++) { for (j = bx; j < map->sizeX + bx; j++) { for (k = 0; k < map->numFeatures; k++) { new_map[(i * sizeX + j) * map->numFeatures + k] = map->map[((i - by) * map->sizeX + j - bx) * map->numFeatures + k]; } } } map->sizeX = sizeX; map->sizeY = sizeY; free(map->map); map->map = new_map; return LATENT_SVM_OK; } CvLSVMFeatureMap* featureMapBorderPartFilter(CvLSVMFeatureMap *map, int maxXBorder, int maxYBorder) { int bx, by; int sizeX, sizeY, i, j, k; CvLSVMFeatureMap *new_map; computeBorderSize(maxXBorder, maxYBorder, &bx, &by); sizeX = map->sizeX + 2 * bx; sizeY = map->sizeY + 2 * by; allocFeatureMapObject(&new_map, sizeX, sizeY, map->numFeatures); for (i = 0; i < sizeX * sizeY * map->numFeatures; i++) { new_map->map[i] = 0.0f; } for (i = by; i < map->sizeY + by; i++) { for (j = bx; j < map->sizeX + bx; j++) { for (k = 0; k < map->numFeatures; k++) { new_map->map[(i * sizeX + j) * map->numFeatures + k] = map->map[((i - by) * map->sizeX + j - bx) * map->numFeatures + k]; } } } return new_map; } /* // Computation the maximum of the score function at the level // // API // int maxFunctionalScoreFixedLevel(const CvLSVMFilterObject **all_F, int n, const featurePyramid *H, int level, float b, int maxXBorder, int maxYBorder, float *score, CvPoint **points, int *kPoints, CvPoint ***partsDisplacement); // INPUT // all_F - the set of filters (the first element is root filter, the other - part filters) // n - the number of part filters // H - feature pyramid // level - feature pyramid level for computation maximum score // b - linear term of the score function // maxXBorder - the largest root filter size (X-direction) // maxYBorder - the largest root filter size (Y-direction) // OUTPUT // score - the maximum of the score function at the level // points - the set of root filter positions (in the block space) // levels - the set of levels // kPoints - number of root filter positions // partsDisplacement - displacement of part filters (in the block space) // RESULT // Error status */ int maxFunctionalScoreFixedLevel(const CvLSVMFilterObject **all_F, int n, const CvLSVMFeaturePyramid *H, int level, float b, int maxXBorder, int maxYBorder, float *score, CvPoint **points, int *kPoints, CvPoint ***partsDisplacement) { int i, j, k, dimX, dimY, nF0, mF0, p; int diff1, diff2, index, last, partsLevel; CvLSVMFilterDisposition **disposition; float *f; float *scores; float sumScorePartDisposition, maxScore; int res; CvLSVMFeatureMap *map; #ifdef FFT_CONV CvLSVMFftImage *rootFilterImage, *mapImage; #else #endif /* // DEBUG variables FILE *file; char *tmp; char buf[40] = "..\\Data\\score\\score", buf1[10] = ".csv"; tmp = (char *)malloc(sizeof(char) * 80); itoa(level, tmp, 10); strcat(tmp, buf1); //*/ // Feature map matrix dimension on the level dimX = H->pyramid[level]->sizeX; dimY = H->pyramid[level]->sizeY; // Number of features p = H->pyramid[level]->numFeatures; // Getting dimension of root filter nF0 = all_F[0]->sizeY; mF0 = all_F[0]->sizeX; // Processing the situation when root filter goes // beyond the boundaries of the block set if (nF0 > dimY || mF0 > dimX) { return LATENT_SVM_FAILED_SUPERPOSITION; } diff1 = dimY - nF0 + 1; diff2 = dimX - mF0 + 1; // Allocation memory for saving values of function D // on the level for each part filter disposition = (CvLSVMFilterDisposition **)malloc(sizeof(CvLSVMFilterDisposition *) * n); for (i = 0; i < n; i++) { disposition[i] = (CvLSVMFilterDisposition *)malloc(sizeof(CvLSVMFilterDisposition)); } // Allocation memory for values of score function for each block on the level scores = (float *)malloc(sizeof(float) * (diff1 * diff2)); // A dot product vectors of feature map and weights of root filter #ifdef FFT_CONV getFFTImageFeatureMap(H->pyramid[level], &mapImage); getFFTImageFilterObject(all_F[0], H->pyramid[level]->sizeX, H->pyramid[level]->sizeY, &rootFilterImage); res = convFFTConv2d(mapImage, rootFilterImage, all_F[0]->sizeX, all_F[0]->sizeY, &f); freeFFTImage(&mapImage); freeFFTImage(&rootFilterImage); #else // Allocation memory for saving a dot product vectors of feature map and // weights of root filter f = (float *)malloc(sizeof(float) * (diff1 * diff2)); // A dot product vectors of feature map and weights of root filter res = convolution(all_F[0], H->pyramid[level], f); #endif if (res != LATENT_SVM_OK) { free(f); free(scores); for (i = 0; i < n; i++) { free(disposition[i]); } free(disposition); return res; } // Computation values of function D for each part filter // on the level (level - LAMBDA) partsLevel = level - LAMBDA; // For feature map at the level 'partsLevel' add nullable border map = featureMapBorderPartFilter(H->pyramid[partsLevel], maxXBorder, maxYBorder); // Computation the maximum of score function sumScorePartDisposition = 0.0; #ifdef FFT_CONV getFFTImageFeatureMap(map, &mapImage); for (k = 1; k <= n; k++) { filterDispositionLevelFFT(all_F[k], mapImage, &(disposition[k - 1]->score), &(disposition[k - 1]->x), &(disposition[k - 1]->y)); } freeFFTImage(&mapImage); #else for (k = 1; k <= n; k++) { filterDispositionLevel(all_F[k], map, &(disposition[k - 1]->score), &(disposition[k - 1]->x), &(disposition[k - 1]->y)); } #endif scores[0] = f[0] - sumScorePartDisposition + b; maxScore = scores[0]; (*kPoints) = 0; for (i = 0; i < diff1; i++) { for (j = 0; j < diff2; j++) { sumScorePartDisposition = 0.0; for (k = 1; k <= n; k++) { // This condition takes on a value true // when filter goes beyond the boundaries of block set if ((2 * i + all_F[k]->V.y < map->sizeY - all_F[k]->sizeY + 1) && (2 * j + all_F[k]->V.x < map->sizeX - all_F[k]->sizeX + 1)) { index = (2 * i + all_F[k]->V.y) * (map->sizeX - all_F[k]->sizeX + 1) + (2 * j + all_F[k]->V.x); sumScorePartDisposition += disposition[k - 1]->score[index]; } } scores[i * diff2 + j] = f[i * diff2 + j] - sumScorePartDisposition + b; if (maxScore < scores[i * diff2 + j]) { maxScore = scores[i * diff2 + j]; (*kPoints) = 1; } else if ((scores[i * diff2 + j] - maxScore) * (scores[i * diff2 + j] - maxScore) <= EPS) { (*kPoints)++; } /* if (maxScore < scores[i * diff2 + j]) */ } } // Allocation memory for saving positions of root filter and part filters (*points) = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints)); (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (*kPoints)); for (i = 0; i < (*kPoints); i++) { (*partsDisplacement)[i] = (CvPoint *)malloc(sizeof(CvPoint) * n); } /*// DEBUG strcat(buf, tmp); file = fopen(buf, "w+"); //*/ // Construction of the set of positions for root filter // that correspond the maximum of score function on the level (*score) = maxScore; last = 0; for (i = 0; i < diff1; i++) { for (j = 0; j < diff2; j++) { if ((scores[i * diff2 + j] - maxScore) * (scores[i * diff2 + j] - maxScore) <= EPS) { (*points)[last].y = i; (*points)[last].x = j; for (k = 1; k <= n; k++) { if ((2 * i + all_F[k]->V.y < map->sizeY - all_F[k]->sizeY + 1) && (2 * j + all_F[k]->V.x < map->sizeX - all_F[k]->sizeX + 1)) { index = (2 * i + all_F[k]->V.y) * (map->sizeX - all_F[k]->sizeX + 1) + (2 * j + all_F[k]->V.x); (*partsDisplacement)[last][k - 1].x = disposition[k - 1]->x[index]; (*partsDisplacement)[last][k - 1].y = disposition[k - 1]->y[index]; } } last++; } /* if ((scores[i * diff2 + j] - maxScore) * (scores[i * diff2 + j] - maxScore) <= EPS) */ //fprintf(file, "%lf;", scores[i * diff2 + j]); } //fprintf(file, "\n"); } //fclose(file); //free(tmp); // Release allocated memory for (i = 0; i < n ; i++) { free(disposition[i]->score); free(disposition[i]->x); free(disposition[i]->y); free(disposition[i]); } free(disposition); free(f); free(scores); freeFeatureMapObject(&map); return LATENT_SVM_OK; } /* // Computation score function at the level that exceed threshold // // API // int thresholdFunctionalScoreFixedLevel(const CvLSVMFilterObject **all_F, int n, const featurePyramid *H, int level, float b, int maxXBorder, int maxYBorder, float scoreThreshold, float **score, CvPoint **points, int *kPoints, CvPoint ***partsDisplacement); // INPUT // all_F - the set of filters (the first element is root filter, the other - part filters) // n - the number of part filters // H - feature pyramid // level - feature pyramid level for computation maximum score // b - linear term of the score function // maxXBorder - the largest root filter size (X-direction) // maxYBorder - the largest root filter size (Y-direction) // scoreThreshold - score threshold // OUTPUT // score - score function at the level that exceed threshold // points - the set of root filter positions (in the block space) // levels - the set of levels // kPoints - number of root filter positions // partsDisplacement - displacement of part filters (in the block space) // RESULT // Error status */ int thresholdFunctionalScoreFixedLevel(const CvLSVMFilterObject **all_F, int n, const CvLSVMFeaturePyramid *H, int level, float b, int maxXBorder, int maxYBorder, float scoreThreshold, float **score, CvPoint **points, int *kPoints, CvPoint ***partsDisplacement) { int i, j, k, dimX, dimY, nF0, mF0, p; int diff1, diff2, index, last, partsLevel; CvLSVMFilterDisposition **disposition; float *f; float *scores; float sumScorePartDisposition; int res; CvLSVMFeatureMap *map; #ifdef FFT_CONV CvLSVMFftImage *rootFilterImage, *mapImage; #else #endif /* // DEBUG variables FILE *file; char *tmp; char buf[40] = "..\\Data\\score\\score", buf1[10] = ".csv"; tmp = (char *)malloc(sizeof(char) * 80); itoa(level, tmp, 10); strcat(tmp, buf1); //*/ // Feature map matrix dimension on the level dimX = H->pyramid[level]->sizeX; dimY = H->pyramid[level]->sizeY; // Number of features p = H->pyramid[level]->numFeatures; // Getting dimension of root filter nF0 = all_F[0]->sizeY; mF0 = all_F[0]->sizeX; // Processing the situation when root filter goes // beyond the boundaries of the block set if (nF0 > dimY || mF0 > dimX) { return LATENT_SVM_FAILED_SUPERPOSITION; } diff1 = dimY - nF0 + 1; diff2 = dimX - mF0 + 1; // Allocation memory for saving values of function D // on the level for each part filter disposition = (CvLSVMFilterDisposition **)malloc(sizeof(CvLSVMFilterDisposition *) * n); for (i = 0; i < n; i++) { disposition[i] = (CvLSVMFilterDisposition *)malloc(sizeof(CvLSVMFilterDisposition)); } // Allocation memory for values of score function for each block on the level scores = (float *)malloc(sizeof(float) * (diff1 * diff2)); // A dot product vectors of feature map and weights of root filter #ifdef FFT_CONV getFFTImageFeatureMap(H->pyramid[level], &mapImage); getFFTImageFilterObject(all_F[0], H->pyramid[level]->sizeX, H->pyramid[level]->sizeY, &rootFilterImage); res = convFFTConv2d(mapImage, rootFilterImage, all_F[0]->sizeX, all_F[0]->sizeY, &f); freeFFTImage(&mapImage); freeFFTImage(&rootFilterImage); #else // Allocation memory for saving a dot product vectors of feature map and // weights of root filter f = (float *)malloc(sizeof(float) * (diff1 * diff2)); res = convolution(all_F[0], H->pyramid[level], f); #endif if (res != LATENT_SVM_OK) { free(f); free(scores); for (i = 0; i < n; i++) { free(disposition[i]); } free(disposition); return res; } // Computation values of function D for each part filter // on the level (level - LAMBDA) partsLevel = level - LAMBDA; // For feature map at the level 'partsLevel' add nullable border map = featureMapBorderPartFilter(H->pyramid[partsLevel], maxXBorder, maxYBorder); // Computation the maximum of score function sumScorePartDisposition = 0.0; #ifdef FFT_CONV getFFTImageFeatureMap(map, &mapImage); for (k = 1; k <= n; k++) { filterDispositionLevelFFT(all_F[k], mapImage, &(disposition[k - 1]->score), &(disposition[k - 1]->x), &(disposition[k - 1]->y)); } freeFFTImage(&mapImage); #else for (k = 1; k <= n; k++) { filterDispositionLevel(all_F[k], map, &(disposition[k - 1]->score), &(disposition[k - 1]->x), &(disposition[k - 1]->y)); } #endif (*kPoints) = 0; for (i = 0; i < diff1; i++) { for (j = 0; j < diff2; j++) { sumScorePartDisposition = 0.0; for (k = 1; k <= n; k++) { // This condition takes on a value true // when filter goes beyond the boundaries of block set if ((2 * i + all_F[k]->V.y < map->sizeY - all_F[k]->sizeY + 1) && (2 * j + all_F[k]->V.x < map->sizeX - all_F[k]->sizeX + 1)) { index = (2 * i + all_F[k]->V.y) * (map->sizeX - all_F[k]->sizeX + 1) + (2 * j + all_F[k]->V.x); sumScorePartDisposition += disposition[k - 1]->score[index]; } } scores[i * diff2 + j] = f[i * diff2 + j] - sumScorePartDisposition + b; if (scores[i * diff2 + j] > scoreThreshold) { (*kPoints)++; } } } // Allocation memory for saving positions of root filter and part filters (*points) = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints)); (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (*kPoints)); for (i = 0; i < (*kPoints); i++) { (*partsDisplacement)[i] = (CvPoint *)malloc(sizeof(CvPoint) * n); } /*// DEBUG strcat(buf, tmp); file = fopen(buf, "w+"); //*/ // Construction of the set of positions for root filter // that correspond score function on the level that exceed threshold (*score) = (float *)malloc(sizeof(float) * (*kPoints)); last = 0; for (i = 0; i < diff1; i++) { for (j = 0; j < diff2; j++) { if (scores[i * diff2 + j] > scoreThreshold) { (*score)[last] = scores[i * diff2 + j]; (*points)[last].y = i; (*points)[last].x = j; for (k = 1; k <= n; k++) { if ((2 * i + all_F[k]->V.y < map->sizeY - all_F[k]->sizeY + 1) && (2 * j + all_F[k]->V.x < map->sizeX - all_F[k]->sizeX + 1)) { index = (2 * i + all_F[k]->V.y) * (map->sizeX - all_F[k]->sizeX + 1) + (2 * j + all_F[k]->V.x); (*partsDisplacement)[last][k - 1].x = disposition[k - 1]->x[index]; (*partsDisplacement)[last][k - 1].y = disposition[k - 1]->y[index]; } } last++; } //fprintf(file, "%lf;", scores[i * diff2 + j]); } //fprintf(file, "\n"); } //fclose(file); //free(tmp); // Release allocated memory for (i = 0; i < n ; i++) { free(disposition[i]->score); free(disposition[i]->x); free(disposition[i]->y); free(disposition[i]); } free(disposition); free(f); free(scores); freeFeatureMapObject(&map); return LATENT_SVM_OK; } /* // Computation the maximum of the score function // // API // int maxFunctionalScore(const CvLSVMFilterObject **all_F, int n, const featurePyramid *H, float b, int maxXBorder, int maxYBorder, float *score, CvPoint **points, int **levels, int *kPoints, CvPoint ***partsDisplacement); // INPUT // all_F - the set of filters (the first element is root filter, the other - part filters) // n - the number of part filters // H - feature pyramid // b - linear term of the score function // maxXBorder - the largest root filter size (X-direction) // maxYBorder - the largest root filter size (Y-direction) // OUTPUT // score - the maximum of the score function // points - the set of root filter positions (in the block space) // levels - the set of levels // kPoints - number of root filter positions // partsDisplacement - displacement of part filters (in the block space) // RESULT // Error status */ int maxFunctionalScore(const CvLSVMFilterObject **all_F, int n, const CvLSVMFeaturePyramid *H, float b, int maxXBorder, int maxYBorder, float *score, CvPoint **points, int **levels, int *kPoints, CvPoint ***partsDisplacement) { int l, i, j, k, s, f, level, numLevels; float *tmpScore; CvPoint ***tmpPoints; CvPoint ****tmpPartsDisplacement; int *tmpKPoints; float maxScore; int res; /* DEBUG FILE *file; //*/ // Computation the number of levels for seaching object, // first lambda-levels are used for computation values // of score function for each position of root filter numLevels = H->numLevels - LAMBDA; // Allocation memory for maximum value of score function for each level tmpScore = (float *)malloc(sizeof(float) * numLevels); // Allocation memory for the set of points that corresponds // to the maximum of score function tmpPoints = (CvPoint ***)malloc(sizeof(CvPoint **) * numLevels); for (i = 0; i < numLevels; i++) { tmpPoints[i] = (CvPoint **)malloc(sizeof(CvPoint *)); } // Allocation memory for memory for saving parts displacement on each level tmpPartsDisplacement = (CvPoint ****)malloc(sizeof(CvPoint ***) * numLevels); for (i = 0; i < numLevels; i++) { tmpPartsDisplacement[i] = (CvPoint ***)malloc(sizeof(CvPoint **)); } // Number of points that corresponds to the maximum // of score function on each level tmpKPoints = (int *)malloc(sizeof(int) * numLevels); for (i = 0; i < numLevels; i++) { tmpKPoints[i] = 0; } // Set current value of the maximum of score function res = maxFunctionalScoreFixedLevel(all_F, n, H, LAMBDA, b, maxXBorder, maxYBorder, &(tmpScore[0]), tmpPoints[0], &(tmpKPoints[0]), tmpPartsDisplacement[0]); maxScore = tmpScore[0]; (*kPoints) = tmpKPoints[0]; // Computation maxima of score function on each level // and getting the maximum on all levels /* DEBUG: maxScore file = fopen("maxScore.csv", "w+"); fprintf(file, "%i;%lf;\n", H->lambda, tmpScore[0]); //*/ for (l = LAMBDA + 1; l < H->numLevels; l++) { k = l - LAMBDA; res = maxFunctionalScoreFixedLevel(all_F, n, H, l, b, maxXBorder, maxYBorder, &(tmpScore[k]), tmpPoints[k], &(tmpKPoints[k]), tmpPartsDisplacement[k]); //fprintf(file, "%i;%lf;\n", l, tmpScore[k]); if (res != LATENT_SVM_OK) { continue; } if (maxScore < tmpScore[k]) { maxScore = tmpScore[k]; (*kPoints) = tmpKPoints[k]; } else if ((maxScore - tmpScore[k]) * (maxScore - tmpScore[k]) <= EPS) { (*kPoints) += tmpKPoints[k]; } /* if (maxScore < tmpScore[k]) else if (...)*/ } //fclose(file); // Allocation memory for levels (*levels) = (int *)malloc(sizeof(int) * (*kPoints)); // Allocation memory for the set of points (*points) = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints)); // Allocation memory for parts displacement (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (*kPoints)); // Filling the set of points, levels and parts displacement s = 0; f = 0; for (i = 0; i < numLevels; i++) { if ((tmpScore[i] - maxScore) * (tmpScore[i] - maxScore) <= EPS) { // Computation the number of level level = i + LAMBDA; // Addition a set of points f += tmpKPoints[i]; for (j = s; j < f; j++) { (*levels)[j] = level; (*points)[j] = (*tmpPoints[i])[j - s]; (*partsDisplacement)[j] = (*(tmpPartsDisplacement[i]))[j - s]; } s = f; } /* if ((tmpScore[i] - maxScore) * (tmpScore[i] - maxScore) <= EPS) */ } (*score) = maxScore; // Release allocated memory for (i = 0; i < numLevels; i++) { free(tmpPoints[i]); free(tmpPartsDisplacement[i]); } free(tmpPoints); free(tmpScore); free(tmpKPoints); return LATENT_SVM_OK; } /* // Computation score function that exceed threshold // // API // int thresholdFunctionalScore(const CvLSVMFilterObject **all_F, int n, const featurePyramid *H, float b, int maxXBorder, int maxYBorder, float scoreThreshold, float **score, CvPoint **points, int **levels, int *kPoints, CvPoint ***partsDisplacement); // INPUT // all_F - the set of filters (the first element is root filter, the other - part filters) // n - the number of part filters // H - feature pyramid // b - linear term of the score function // maxXBorder - the largest root filter size (X-direction) // maxYBorder - the largest root filter size (Y-direction) // scoreThreshold - score threshold // OUTPUT // score - score function values that exceed threshold // points - the set of root filter positions (in the block space) // levels - the set of levels // kPoints - number of root filter positions // partsDisplacement - displacement of part filters (in the block space) // RESULT // Error status */ int thresholdFunctionalScore(const CvLSVMFilterObject **all_F, int n, const CvLSVMFeaturePyramid *H, float b, int maxXBorder, int maxYBorder, float scoreThreshold, float **score, CvPoint **points, int **levels, int *kPoints, CvPoint ***partsDisplacement) { int l, i, j, k, s, f, level, numLevels; float **tmpScore; CvPoint ***tmpPoints; CvPoint ****tmpPartsDisplacement; int *tmpKPoints; int res; /* DEBUG FILE *file; //*/ // Computation the number of levels for seaching object, // first lambda-levels are used for computation values // of score function for each position of root filter numLevels = H->numLevels - LAMBDA; // Allocation memory for values of score function for each level // that exceed threshold tmpScore = (float **)malloc(sizeof(float*) * numLevels); // Allocation memory for the set of points that corresponds // to the maximum of score function tmpPoints = (CvPoint ***)malloc(sizeof(CvPoint **) * numLevels); for (i = 0; i < numLevels; i++) { tmpPoints[i] = (CvPoint **)malloc(sizeof(CvPoint *)); } // Allocation memory for memory for saving parts displacement on each level tmpPartsDisplacement = (CvPoint ****)malloc(sizeof(CvPoint ***) * numLevels); for (i = 0; i < numLevels; i++) { tmpPartsDisplacement[i] = (CvPoint ***)malloc(sizeof(CvPoint **)); } // Number of points that corresponds to the maximum // of score function on each level tmpKPoints = (int *)malloc(sizeof(int) * numLevels); for (i = 0; i < numLevels; i++) { tmpKPoints[i] = 0; } // Computation maxima of score function on each level // and getting the maximum on all levels /* DEBUG: maxScore file = fopen("maxScore.csv", "w+"); fprintf(file, "%i;%lf;\n", H->lambda, tmpScore[0]); //*/ (*kPoints) = 0; for (l = LAMBDA; l < H->numLevels; l++) { k = l - LAMBDA; //printf("Score at the level %i\n", l); res = thresholdFunctionalScoreFixedLevel(all_F, n, H, l, b, maxXBorder, maxYBorder, scoreThreshold, &(tmpScore[k]), tmpPoints[k], &(tmpKPoints[k]), tmpPartsDisplacement[k]); //fprintf(file, "%i;%lf;\n", l, tmpScore[k]); if (res != LATENT_SVM_OK) { continue; } (*kPoints) += tmpKPoints[k]; } //fclose(file); // Allocation memory for levels (*levels) = (int *)malloc(sizeof(int) * (*kPoints)); // Allocation memory for the set of points (*points) = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints)); // Allocation memory for parts displacement (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (*kPoints)); // Allocation memory for score function values (*score) = (float *)malloc(sizeof(float) * (*kPoints)); // Filling the set of points, levels and parts displacement s = 0; f = 0; for (i = 0; i < numLevels; i++) { // Computation the number of level level = i + LAMBDA; // Addition a set of points f += tmpKPoints[i]; for (j = s; j < f; j++) { (*levels)[j] = level; (*points)[j] = (*tmpPoints[i])[j - s]; (*score)[j] = tmpScore[i][j - s]; (*partsDisplacement)[j] = (*(tmpPartsDisplacement[i]))[j - s]; } s = f; } // Release allocated memory for (i = 0; i < numLevels; i++) { free(tmpPoints[i]); free(tmpPartsDisplacement[i]); } free(tmpPoints); free(tmpScore); free(tmpKPoints); free(tmpPartsDisplacement); return LATENT_SVM_OK; } /* // Creating schedule of pyramid levels processing // // API // int createSchedule(const featurePyramid *H, const filterObject **all_F, const int n, const int bx, const int by, const int threadsNum, int *kLevels, int **processingLevels) // INPUT // H - feature pyramid // all_F - the set of filters (the first element is root filter, the other - part filters) // n - the number of part filters // bx - size of nullable border (X direction) // by - size of nullable border (Y direction) // threadsNum - number of threads that will be created in TBB version // OUTPUT // kLevels - array that contains number of levels processed by each thread // processingLevels - array that contains lists of levels processed by each thread // RESULT // Error status */ int createSchedule(const CvLSVMFeaturePyramid *H, const CvLSVMFilterObject **all_F, const int n, const int bx, const int by, const int threadsNum, int *kLevels, int **processingLevels) { int rootFilterDim, sumPartFiltersDim, i, numLevels, dbx, dby, numDotProducts; int averNumDotProd, j, minValue, argMin, lambda, maxValue, k; int *dotProd, *weights, *disp; if (H == NULL || all_F == NULL) { return LATENT_SVM_TBB_SCHEDULE_CREATION_FAILED; } // Number of feature vectors in root filter rootFilterDim = all_F[0]->sizeX * all_F[0]->sizeY; // Number of feature vectors in all part filters sumPartFiltersDim = 0; for (i = 1; i <= n; i++) { sumPartFiltersDim += all_F[i]->sizeX * all_F[i]->sizeY; } // Number of levels which are used for computation of score function numLevels = H->numLevels - LAMBDA; // Allocation memory for saving number of dot products that will be // computed for each level of feature pyramid dotProd = (int *)malloc(sizeof(int) * numLevels); // Size of nullable border that's used in computing convolution // of feature map with part filter dbx = 2 * bx; dby = 2 * by; // Total number of dot products for all levels numDotProducts = 0; lambda = LAMBDA; for (i = 0; i < numLevels; i++) { dotProd[i] = H->pyramid[i + lambda]->sizeX * H->pyramid[i + lambda]->sizeY * rootFilterDim + (H->pyramid[i]->sizeX + dbx) * (H->pyramid[i]->sizeY + dby) * sumPartFiltersDim; numDotProducts += dotProd[i]; } // Average number of dot products that would be performed at the best averNumDotProd = numDotProducts / threadsNum; // Allocation memory for saving dot product number performed by each thread weights = (int *)malloc(sizeof(int) * threadsNum); // Allocation memory for saving dispertion disp = (int *)malloc(sizeof(int) * threadsNum); // At the first step we think of first threadsNum levels will be processed // by different threads for (i = 0; i < threadsNum; i++) { kLevels[i] = 1; weights[i] = dotProd[i]; disp[i] = 0; } // Computation number of levels that will be processed by each thread for (i = threadsNum; i < numLevels; i++) { // Search number of thread that will process level number i for (j = 0; j < threadsNum; j++) { weights[j] += dotProd[i]; minValue = weights[0]; maxValue = weights[0]; for (k = 1; k < threadsNum; k++) { minValue = min(minValue, weights[k]); maxValue = max(maxValue, weights[k]); } disp[j] = maxValue - minValue; weights[j] -= dotProd[i]; } minValue = disp[0]; argMin = 0; for (j = 1; j < threadsNum; j++) { if (disp[j] < minValue) { minValue = disp[j]; argMin = j; } } // Addition new level kLevels[argMin]++; weights[argMin] += dotProd[i]; } for (i = 0; i < threadsNum; i++) { // Allocation memory for saving list of levels for each level processingLevels[i] = (int *)malloc(sizeof(int) * kLevels[i]); // At the first step we think of first threadsNum levels will be processed // by different threads processingLevels[i][0] = lambda + i; kLevels[i] = 1; weights[i] = dotProd[i]; } // Creating list of levels for (i = threadsNum; i < numLevels; i++) { for (j = 0; j < threadsNum; j++) { weights[j] += dotProd[i]; minValue = weights[0]; maxValue = weights[0]; for (k = 1; k < threadsNum; k++) { minValue = min(minValue, weights[k]); maxValue = max(maxValue, weights[k]); } disp[j] = maxValue - minValue; weights[j] -= dotProd[i]; } minValue = disp[0]; argMin = 0; for (j = 1; j < threadsNum; j++) { if (disp[j] < minValue) { minValue = disp[j]; argMin = j; } } processingLevels[argMin][kLevels[argMin]] = lambda + i; kLevels[argMin]++; weights[argMin] += dotProd[i]; } // Release allocated memory free(weights); free(dotProd); free(disp); return LATENT_SVM_OK; } #ifdef HAVE_TBB /* // int tbbThresholdFunctionalScore(const CvLSVMFilterObject **all_F, int n, const CvLSVMFeaturePyramid *H, const float b, const int maxXBorder, const int maxYBorder, const float scoreThreshold, const int threadsNum, float **score, CvPoint **points, int **levels, int *kPoints, CvPoint ***partsDisplacement); // INPUT // all_F - the set of filters (the first element is root filter, the other - part filters) // n - the number of part filters // H - feature pyramid // b - linear term of the score function // maxXBorder - the largest root filter size (X-direction) // maxYBorder - the largest root filter size (Y-direction) // scoreThreshold - score threshold // threadsNum - number of threads that will be created using TBB version // OUTPUT // score - score function values that exceed threshold // points - the set of root filter positions (in the block space) // levels - the set of levels // kPoints - number of root filter positions // partsDisplacement - displacement of part filters (in the block space) // RESULT // Error status */ int tbbThresholdFunctionalScore(const CvLSVMFilterObject **all_F, int n, const CvLSVMFeaturePyramid *H, const float b, const int maxXBorder, const int maxYBorder, const float scoreThreshold, const int threadsNum, float **score, CvPoint **points, int **levels, int *kPoints, CvPoint ***partsDisplacement) { int i, j, s, f, level, numLevels; float **tmpScore; CvPoint ***tmpPoints; CvPoint ****tmpPartsDisplacement; int *tmpKPoints; int res; int *kLevels, **procLevels; int bx, by; // Computation the number of levels for seaching object, // first lambda-levels are used for computation values // of score function for each position of root filter numLevels = H->numLevels - LAMBDA; kLevels = (int *)malloc(sizeof(int) * threadsNum); procLevels = (int **)malloc(sizeof(int*) * threadsNum); computeBorderSize(maxXBorder, maxYBorder, &bx, &by); res = createSchedule(H, all_F, n, bx, by, threadsNum, kLevels, procLevels); if (res != LATENT_SVM_OK) { for (i = 0; i < threadsNum; i++) { if (procLevels[i] != NULL) { free(procLevels[i]); } } free(procLevels); free(kLevels); return res; } // Allocation memory for values of score function for each level // that exceed threshold tmpScore = (float **)malloc(sizeof(float*) * numLevels); // Allocation memory for the set of points that corresponds // to the maximum of score function tmpPoints = (CvPoint ***)malloc(sizeof(CvPoint **) * numLevels); for (i = 0; i < numLevels; i++) { tmpPoints[i] = (CvPoint **)malloc(sizeof(CvPoint *)); } // Allocation memory for memory for saving parts displacement on each level tmpPartsDisplacement = (CvPoint ****)malloc(sizeof(CvPoint ***) * numLevels); for (i = 0; i < numLevels; i++) { tmpPartsDisplacement[i] = (CvPoint ***)malloc(sizeof(CvPoint **)); } // Number of points that corresponds to the maximum // of score function on each level tmpKPoints = (int *)malloc(sizeof(int) * numLevels); for (i = 0; i < numLevels; i++) { tmpKPoints[i] = 0; } // Computation maxima of score function on each level // and getting the maximum on all levels using TBB tasks tbbTasksThresholdFunctionalScore(all_F, n, H, b, maxXBorder, maxYBorder, scoreThreshold, kLevels, procLevels, threadsNum, tmpScore, tmpPoints, tmpKPoints, tmpPartsDisplacement); (*kPoints) = 0; for (i = 0; i < numLevels; i++) { (*kPoints) += tmpKPoints[i]; } // Allocation memory for levels (*levels) = (int *)malloc(sizeof(int) * (*kPoints)); // Allocation memory for the set of points (*points) = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints)); // Allocation memory for parts displacement (*partsDisplacement) = (CvPoint **)malloc(sizeof(CvPoint *) * (*kPoints)); // Allocation memory for score function values (*score) = (float *)malloc(sizeof(float) * (*kPoints)); // Filling the set of points, levels and parts displacement s = 0; f = 0; for (i = 0; i < numLevels; i++) { // Computation the number of level level = i + LAMBDA;//H->lambda; // Addition a set of points f += tmpKPoints[i]; for (j = s; j < f; j++) { (*levels)[j] = level; (*points)[j] = (*tmpPoints[i])[j - s]; (*score)[j] = tmpScore[i][j - s]; (*partsDisplacement)[j] = (*(tmpPartsDisplacement[i]))[j - s]; } s = f; } // Release allocated memory for (i = 0; i < numLevels; i++) { free(tmpPoints[i]); free(tmpPartsDisplacement[i]); } for (i = 0; i < threadsNum; i++) { free(procLevels[i]); } free(procLevels); free(kLevels); free(tmpPoints); free(tmpScore); free(tmpKPoints); free(tmpPartsDisplacement); return LATENT_SVM_OK; } #endif void sort(int n, const float* x, int* indices) { int i, j; for (i = 0; i < n; i++) for (j = i + 1; j < n; j++) { if (x[indices[j]] > x[indices[i]]) { //float x_tmp = x[i]; int index_tmp = indices[i]; //x[i] = x[j]; indices[i] = indices[j]; //x[j] = x_tmp; indices[j] = index_tmp; } } } /* // Perform non-maximum suppression algorithm (described in original paper) // to remove "similar" bounding boxes // // API // int nonMaximumSuppression(int numBoxes, const CvPoint *points, const CvPoint *oppositePoints, const float *score, float overlapThreshold, int *numBoxesOut, CvPoint **pointsOut, CvPoint **oppositePointsOut, float **scoreOut); // INPUT // numBoxes - number of bounding boxes // points - array of left top corner coordinates // oppositePoints - array of right bottom corner coordinates // score - array of detection scores // overlapThreshold - threshold: bounding box is removed if overlap part is greater than passed value // OUTPUT // numBoxesOut - the number of bounding boxes algorithm returns // pointsOut - array of left top corner coordinates // oppositePointsOut - array of right bottom corner coordinates // scoreOut - array of detection scores // RESULT // Error status */ int nonMaximumSuppression(int numBoxes, const CvPoint *points, const CvPoint *oppositePoints, const float *score, float overlapThreshold, int *numBoxesOut, CvPoint **pointsOut, CvPoint **oppositePointsOut, float **scoreOut) { int i, j, index; float* box_area = (float*)malloc(numBoxes * sizeof(float)); int* indices = (int*)malloc(numBoxes * sizeof(int)); int* is_suppressed = (int*)malloc(numBoxes * sizeof(int)); for (i = 0; i < numBoxes; i++) { indices[i] = i; is_suppressed[i] = 0; box_area[i] = (float)( (oppositePoints[i].x - points[i].x + 1) * (oppositePoints[i].y - points[i].y + 1)); } sort(numBoxes, score, indices); for (i = 0; i < numBoxes; i++) { if (!is_suppressed[indices[i]]) { for (j = i + 1; j < numBoxes; j++) { if (!is_suppressed[indices[j]]) { int x1max = max(points[indices[i]].x, points[indices[j]].x); int x2min = min(oppositePoints[indices[i]].x, oppositePoints[indices[j]].x); int y1max = max(points[indices[i]].y, points[indices[j]].y); int y2min = min(oppositePoints[indices[i]].y, oppositePoints[indices[j]].y); int overlapWidth = x2min - x1max + 1; int overlapHeight = y2min - y1max + 1; if (overlapWidth > 0 && overlapHeight > 0) { float overlapPart = (overlapWidth * overlapHeight) / box_area[indices[j]]; if (overlapPart > overlapThreshold) { is_suppressed[indices[j]] = 1; } } } } } } *numBoxesOut = 0; for (i = 0; i < numBoxes; i++) { if (!is_suppressed[i]) (*numBoxesOut)++; } *pointsOut = (CvPoint *)malloc((*numBoxesOut) * sizeof(CvPoint)); *oppositePointsOut = (CvPoint *)malloc((*numBoxesOut) * sizeof(CvPoint)); *scoreOut = (float *)malloc((*numBoxesOut) * sizeof(float)); index = 0; for (i = 0; i < numBoxes; i++) { if (!is_suppressed[indices[i]]) { (*pointsOut)[index].x = points[indices[i]].x; (*pointsOut)[index].y = points[indices[i]].y; (*oppositePointsOut)[index].x = oppositePoints[indices[i]].x; (*oppositePointsOut)[index].y = oppositePoints[indices[i]].y; (*scoreOut)[index] = score[indices[i]]; index++; } } free(indices); free(box_area); free(is_suppressed); return LATENT_SVM_OK; }