opencv/modules/objdetect/src/matching.cpp
2013-02-01 18:09:58 -05:00

1798 lines
60 KiB
C++

#include "precomp.hpp"
#include "_lsvm_matching.h"
#include <stdio.h>
#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;
}
static 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(tmpPartsDisplacement);
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;
}
#ifdef HAVE_TBB
/*
// 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
*/
static 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;
int 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;
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;
}
// 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;
}
/*
// 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
static 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;
}