mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
644 lines
22 KiB
644 lines
22 KiB
#include "precomp.hpp" |
|
#include "_latentsvm.h" |
|
#include "_lsvm_matching.h" |
|
|
|
/* |
|
// Transformation filter displacement from the block space |
|
// to the space of pixels at the initial image |
|
// |
|
// API |
|
// int convertPoints(int countLevel, CvPoint *points, int *levels, |
|
CvPoint **partsDisplacement, int kPoints, int n); |
|
// INPUT |
|
// countLevel - the number of levels in the feature pyramid |
|
// points - the set of root filter positions (in the block space) |
|
// levels - the set of levels |
|
// partsDisplacement - displacement of part filters (in the block space) |
|
// kPoints - number of root filter positions |
|
// n - number of part filters |
|
// initialImageLevel - level that contains features for initial image |
|
// maxXBorder - the largest root filter size (X-direction) |
|
// maxYBorder - the largest root filter size (Y-direction) |
|
// OUTPUT |
|
// points - the set of root filter positions (in the space of pixels) |
|
// partsDisplacement - displacement of part filters (in the space of pixels) |
|
// RESULT |
|
// Error status |
|
*/ |
|
int convertPoints(int /*countLevel*/, int lambda, |
|
int initialImageLevel, |
|
CvPoint *points, int *levels, |
|
CvPoint **partsDisplacement, int kPoints, int n, |
|
int maxXBorder, |
|
int maxYBorder) |
|
{ |
|
int i, j, bx, by; |
|
float step, scale; |
|
step = powf( 2.0f, 1.0f / ((float)lambda) ); |
|
|
|
computeBorderSize(maxXBorder, maxYBorder, &bx, &by); |
|
|
|
for (i = 0; i < kPoints; i++) |
|
{ |
|
// scaling factor for root filter |
|
scale = SIDE_LENGTH * powf(step, (float)(levels[i] - initialImageLevel)); |
|
points[i].x = (int)((points[i].x - bx + 1) * scale); |
|
points[i].y = (int)((points[i].y - by + 1) * scale); |
|
|
|
// scaling factor for part filters |
|
scale = SIDE_LENGTH * powf(step, (float)(levels[i] - lambda - initialImageLevel)); |
|
for (j = 0; j < n; j++) |
|
{ |
|
partsDisplacement[i][j].x = (int)((partsDisplacement[i][j].x - |
|
2 * bx + 1) * scale); |
|
partsDisplacement[i][j].y = (int)((partsDisplacement[i][j].y - |
|
2 * by + 1) * scale); |
|
} |
|
} |
|
return LATENT_SVM_OK; |
|
} |
|
|
|
/* |
|
// Elimination boxes that are outside the image boudaries |
|
// |
|
// API |
|
// int clippingBoxes(int width, int height, |
|
CvPoint *points, int kPoints); |
|
// INPUT |
|
// width - image wediht |
|
// height - image heigth |
|
// points - a set of points (coordinates of top left or |
|
bottom right corners) |
|
// kPoints - points number |
|
// OUTPUT |
|
// points - updated points (if coordinates less than zero then |
|
set zero coordinate, if coordinates more than image |
|
size then set coordinates equal image size) |
|
// RESULT |
|
// Error status |
|
*/ |
|
int clippingBoxes(int width, int height, |
|
CvPoint *points, int kPoints) |
|
{ |
|
int i; |
|
for (i = 0; i < kPoints; i++) |
|
{ |
|
if (points[i].x > width - 1) |
|
{ |
|
points[i].x = width - 1; |
|
} |
|
if (points[i].x < 0) |
|
{ |
|
points[i].x = 0; |
|
} |
|
if (points[i].y > height - 1) |
|
{ |
|
points[i].y = height - 1; |
|
} |
|
if (points[i].y < 0) |
|
{ |
|
points[i].y = 0; |
|
} |
|
} |
|
return LATENT_SVM_OK; |
|
} |
|
|
|
/* |
|
// Creation feature pyramid with nullable border |
|
// |
|
// API |
|
// featurePyramid* createFeaturePyramidWithBorder(const IplImage *image, |
|
int maxXBorder, int maxYBorder); |
|
|
|
// INPUT |
|
// image - initial image |
|
// maxXBorder - the largest root filter size (X-direction) |
|
// maxYBorder - the largest root filter size (Y-direction) |
|
// OUTPUT |
|
// RESULT |
|
// Feature pyramid with nullable border |
|
*/ |
|
CvLSVMFeaturePyramid* createFeaturePyramidWithBorder(IplImage *image, |
|
int maxXBorder, int maxYBorder) |
|
{ |
|
int opResult; |
|
int bx, by; |
|
int level; |
|
CvLSVMFeaturePyramid *H; |
|
|
|
// Obtaining feature pyramid |
|
opResult = getFeaturePyramid(image, &H); |
|
|
|
if (opResult != LATENT_SVM_OK) |
|
{ |
|
freeFeaturePyramidObject(&H); |
|
return NULL; |
|
} /* if (opResult != LATENT_SVM_OK) */ |
|
|
|
// Addition nullable border for each feature map |
|
// the size of the border for root filters |
|
computeBorderSize(maxXBorder, maxYBorder, &bx, &by); |
|
for (level = 0; level < H->numLevels; level++) |
|
{ |
|
addNullableBorder(H->pyramid[level], bx, by); |
|
} |
|
return H; |
|
} |
|
|
|
/* |
|
// Computation of the root filter displacement and values of score function |
|
// |
|
// API |
|
// int searchObject(const featurePyramid *H, const filterObject **all_F, int n, |
|
float b, |
|
int maxXBorder, |
|
int maxYBorder, |
|
CvPoint **points, int **levels, int *kPoints, float *score, |
|
CvPoint ***partsDisplacement); |
|
// INPUT |
|
// image - initial image for searhing object |
|
// all_F - the set of filters (the first element is root filter, |
|
other elements - part filters) |
|
// n - the number of part filters |
|
// b - linear term of the score function |
|
// maxXBorder - the largest root filter size (X-direction) |
|
// maxYBorder - the largest root filter size (Y-direction) |
|
// OUTPUT |
|
// points - positions (x, y) of the upper-left corner |
|
of root filter frame |
|
// levels - levels that correspond to each position |
|
// kPoints - number of positions |
|
// score - value of the score function |
|
// partsDisplacement - part filters displacement for each position |
|
of the root filter |
|
// RESULT |
|
// Error status |
|
*/ |
|
int searchObject(const CvLSVMFeaturePyramid *H, const CvLSVMFilterObject **all_F, |
|
int n, float b, |
|
int maxXBorder, |
|
int maxYBorder, |
|
CvPoint **points, int **levels, int *kPoints, float *score, |
|
CvPoint ***partsDisplacement) |
|
{ |
|
int opResult; |
|
|
|
// Matching |
|
opResult = maxFunctionalScore(all_F, n, H, b, maxXBorder, maxYBorder, |
|
score, points, levels, |
|
kPoints, partsDisplacement); |
|
if (opResult != LATENT_SVM_OK) |
|
{ |
|
return LATENT_SVM_SEARCH_OBJECT_FAILED; |
|
} |
|
|
|
// Transformation filter displacement from the block space |
|
// to the space of pixels at the initial image |
|
// that settles at the level number LAMBDA |
|
convertPoints(H->numLevels, LAMBDA, LAMBDA, (*points), |
|
(*levels), (*partsDisplacement), (*kPoints), n, |
|
maxXBorder, maxYBorder); |
|
|
|
return LATENT_SVM_OK; |
|
} |
|
|
|
/* |
|
// Computation right bottom corners coordinates of bounding boxes |
|
// |
|
// API |
|
// int estimateBoxes(CvPoint *points, int *levels, int kPoints, |
|
int sizeX, int sizeY, CvPoint **oppositePoints); |
|
// INPUT |
|
// points - left top corners coordinates of bounding boxes |
|
// levels - levels of feature pyramid where points were found |
|
// (sizeX, sizeY) - size of root filter |
|
// OUTPUT |
|
// oppositePoins - right bottom corners coordinates of bounding boxes |
|
// RESULT |
|
// Error status |
|
*/ |
|
static int estimateBoxes(CvPoint *points, int *levels, int kPoints, |
|
int sizeX, int sizeY, CvPoint **oppositePoints) |
|
{ |
|
int i; |
|
float step; |
|
|
|
step = powf( 2.0f, 1.0f / ((float)(LAMBDA))); |
|
|
|
*oppositePoints = (CvPoint *)malloc(sizeof(CvPoint) * kPoints); |
|
for (i = 0; i < kPoints; i++) |
|
{ |
|
getOppositePoint(points[i], sizeX, sizeY, step, levels[i] - LAMBDA, &((*oppositePoints)[i])); |
|
} |
|
return LATENT_SVM_OK; |
|
} |
|
|
|
/* |
|
// Computation of the root filter displacement and values of score function |
|
// |
|
// API |
|
// int searchObjectThreshold(const featurePyramid *H, |
|
const filterObject **all_F, int n, |
|
float b, |
|
int maxXBorder, int maxYBorder, |
|
float scoreThreshold, |
|
CvPoint **points, int **levels, int *kPoints, |
|
float **score, CvPoint ***partsDisplacement); |
|
// INPUT |
|
// H - feature pyramid |
|
// all_F - the set of filters (the first element is root filter, |
|
other elements - part filters) |
|
// n - the number of part filters |
|
// 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 |
|
// points - positions (x, y) of the upper-left corner |
|
of root filter frame |
|
// levels - levels that correspond to each position |
|
// kPoints - number of positions |
|
// score - values of the score function |
|
// partsDisplacement - part filters displacement for each position |
|
of the root filter |
|
// RESULT |
|
// Error status |
|
*/ |
|
int searchObjectThreshold(const CvLSVMFeaturePyramid *H, |
|
const CvLSVMFilterObject **all_F, int n, |
|
float b, |
|
int maxXBorder, int maxYBorder, |
|
float scoreThreshold, |
|
CvPoint **points, int **levels, int *kPoints, |
|
float **score, CvPoint ***partsDisplacement, |
|
int numThreads) |
|
{ |
|
int opResult; |
|
|
|
|
|
// Matching |
|
#ifdef HAVE_TBB |
|
if (numThreads <= 0) |
|
{ |
|
opResult = LATENT_SVM_TBB_NUMTHREADS_NOT_CORRECT; |
|
return opResult; |
|
} |
|
opResult = tbbThresholdFunctionalScore(all_F, n, H, b, maxXBorder, maxYBorder, |
|
scoreThreshold, numThreads, score, |
|
points, levels, kPoints, |
|
partsDisplacement); |
|
#else |
|
opResult = thresholdFunctionalScore(all_F, n, H, b, |
|
maxXBorder, maxYBorder, |
|
scoreThreshold, |
|
score, points, levels, |
|
kPoints, partsDisplacement); |
|
|
|
(void)numThreads; |
|
#endif |
|
if (opResult != LATENT_SVM_OK) |
|
{ |
|
return LATENT_SVM_SEARCH_OBJECT_FAILED; |
|
} |
|
|
|
// Transformation filter displacement from the block space |
|
// to the space of pixels at the initial image |
|
// that settles at the level number LAMBDA |
|
convertPoints(H->numLevels, LAMBDA, LAMBDA, (*points), |
|
(*levels), (*partsDisplacement), (*kPoints), n, |
|
maxXBorder, maxYBorder); |
|
|
|
return LATENT_SVM_OK; |
|
} |
|
|
|
/* |
|
// Compute opposite point for filter box |
|
// |
|
// API |
|
// int getOppositePoint(CvPoint point, |
|
int sizeX, int sizeY, |
|
float step, int degree, |
|
CvPoint *oppositePoint); |
|
|
|
// INPUT |
|
// point - coordinates of filter top left corner |
|
(in the space of pixels) |
|
// (sizeX, sizeY) - filter dimension in the block space |
|
// step - scaling factor |
|
// degree - degree of the scaling factor |
|
// OUTPUT |
|
// oppositePoint - coordinates of filter bottom corner |
|
(in the space of pixels) |
|
// RESULT |
|
// Error status |
|
*/ |
|
int getOppositePoint(CvPoint point, |
|
int sizeX, int sizeY, |
|
float step, int degree, |
|
CvPoint *oppositePoint) |
|
{ |
|
float scale; |
|
scale = SIDE_LENGTH * powf(step, (float)degree); |
|
oppositePoint->x = (int)(point.x + sizeX * scale); |
|
oppositePoint->y = (int)(point.y + sizeY * scale); |
|
return LATENT_SVM_OK; |
|
} |
|
|
|
|
|
/* |
|
// Drawing root filter boxes |
|
// |
|
// API |
|
// int showRootFilterBoxes(const IplImage *image, |
|
const filterObject *filter, |
|
CvPoint *points, int *levels, int kPoints, |
|
CvScalar color, int thickness, |
|
int line_type, int shift); |
|
// INPUT |
|
// image - initial image |
|
// filter - root filter object |
|
// points - a set of points |
|
// levels - levels of feature pyramid |
|
// kPoints - number of points |
|
// color - line color for each box |
|
// thickness - line thickness |
|
// line_type - line type |
|
// shift - shift |
|
// OUTPUT |
|
// window contained initial image and filter boxes |
|
// RESULT |
|
// Error status |
|
*/ |
|
int showRootFilterBoxes(IplImage *image, |
|
const CvLSVMFilterObject *filter, |
|
CvPoint *points, int *levels, int kPoints, |
|
CvScalar color, int thickness, |
|
int line_type, int shift) |
|
{ |
|
int i; |
|
float step; |
|
CvPoint oppositePoint; |
|
step = powf( 2.0f, 1.0f / ((float)LAMBDA)); |
|
|
|
for (i = 0; i < kPoints; i++) |
|
{ |
|
// Drawing rectangle for filter |
|
getOppositePoint(points[i], filter->sizeX, filter->sizeY, |
|
step, levels[i] - LAMBDA, &oppositePoint); |
|
cvRectangle(image, points[i], oppositePoint, |
|
color, thickness, line_type, shift); |
|
} |
|
#ifdef HAVE_OPENCV_HIGHGUI |
|
cv::imshow("Initial image", cv::cvarrToMat(image)); |
|
#endif |
|
return LATENT_SVM_OK; |
|
} |
|
|
|
/* |
|
// Drawing part filter boxes |
|
// |
|
// API |
|
// int showPartFilterBoxes(const IplImage *image, |
|
const filterObject *filter, |
|
CvPoint *points, int *levels, int kPoints, |
|
CvScalar color, int thickness, |
|
int line_type, int shift); |
|
// INPUT |
|
// image - initial image |
|
// filters - a set of part filters |
|
// n - number of part filters |
|
// partsDisplacement - a set of points |
|
// levels - levels of feature pyramid |
|
// kPoints - number of foot filter positions |
|
// color - line color for each box |
|
// thickness - line thickness |
|
// line_type - line type |
|
// shift - shift |
|
// OUTPUT |
|
// window contained initial image and filter boxes |
|
// RESULT |
|
// Error status |
|
*/ |
|
int showPartFilterBoxes(IplImage *image, |
|
const CvLSVMFilterObject **filters, |
|
int n, CvPoint **partsDisplacement, |
|
int *levels, int kPoints, |
|
CvScalar color, int thickness, |
|
int line_type, int shift) |
|
{ |
|
int i, j; |
|
float step; |
|
CvPoint oppositePoint; |
|
|
|
step = powf( 2.0f, 1.0f / ((float)LAMBDA)); |
|
|
|
for (i = 0; i < kPoints; i++) |
|
{ |
|
for (j = 0; j < n; j++) |
|
{ |
|
// Drawing rectangles for part filters |
|
getOppositePoint(partsDisplacement[i][j], |
|
filters[j + 1]->sizeX, filters[j + 1]->sizeY, |
|
step, levels[i] - 2 * LAMBDA, &oppositePoint); |
|
cvRectangle(image, partsDisplacement[i][j], oppositePoint, |
|
color, thickness, line_type, shift); |
|
} |
|
} |
|
#ifdef HAVE_OPENCV_HIGHGUI |
|
cv::imshow("Initial image", cv::cvarrToMat(image)); |
|
#endif |
|
return LATENT_SVM_OK; |
|
} |
|
|
|
/* |
|
// Drawing boxes |
|
// |
|
// API |
|
// int showBoxes(const IplImage *img, |
|
const CvPoint *points, const CvPoint *oppositePoints, int kPoints, |
|
CvScalar color, int thickness, int line_type, int shift); |
|
// INPUT |
|
// img - initial image |
|
// points - top left corner coordinates |
|
// oppositePoints - right bottom corner coordinates |
|
// kPoints - points number |
|
// color - line color for each box |
|
// thickness - line thickness |
|
// line_type - line type |
|
// shift - shift |
|
// OUTPUT |
|
// RESULT |
|
// Error status |
|
*/ |
|
int showBoxes(IplImage *img, |
|
const CvPoint *points, const CvPoint *oppositePoints, int kPoints, |
|
CvScalar color, int thickness, int line_type, int shift) |
|
{ |
|
int i; |
|
for (i = 0; i < kPoints; i++) |
|
{ |
|
cvRectangle(img, points[i], oppositePoints[i], |
|
color, thickness, line_type, shift); |
|
} |
|
#ifdef HAVE_OPENCV_HIGHGUI |
|
cv::imshow("Initial image", cv::cvarrToMat(img)); |
|
#endif |
|
return LATENT_SVM_OK; |
|
} |
|
|
|
/* |
|
// Computation maximum filter size for each dimension |
|
// |
|
// API |
|
// int getMaxFilterDims(const filterObject **filters, int kComponents, |
|
const int *kPartFilters, |
|
unsigned int *maxXBorder, unsigned int *maxYBorder); |
|
// INPUT |
|
// filters - a set of filters (at first root filter, then part filters |
|
and etc. for all components) |
|
// kComponents - number of components |
|
// kPartFilters - number of part filters for each component |
|
// OUTPUT |
|
// maxXBorder - maximum of filter size at the horizontal dimension |
|
// maxYBorder - maximum of filter size at the vertical dimension |
|
// RESULT |
|
// Error status |
|
*/ |
|
int getMaxFilterDims(const CvLSVMFilterObject **filters, int kComponents, |
|
const int *kPartFilters, |
|
unsigned int *maxXBorder, unsigned int *maxYBorder) |
|
{ |
|
int i, componentIndex; |
|
*maxXBorder = filters[0]->sizeX; |
|
*maxYBorder = filters[0]->sizeY; |
|
componentIndex = kPartFilters[0] + 1; |
|
for (i = 1; i < kComponents; i++) |
|
{ |
|
if ((unsigned)filters[componentIndex]->sizeX > *maxXBorder) |
|
{ |
|
*maxXBorder = filters[componentIndex]->sizeX; |
|
} |
|
if ((unsigned)filters[componentIndex]->sizeY > *maxYBorder) |
|
{ |
|
*maxYBorder = filters[componentIndex]->sizeY; |
|
} |
|
componentIndex += (kPartFilters[i] + 1); |
|
} |
|
return LATENT_SVM_OK; |
|
} |
|
|
|
/* |
|
// Computation root filters displacement and values of score function |
|
// |
|
// API |
|
// int searchObjectThresholdSomeComponents(const featurePyramid *H, |
|
const filterObject **filters, |
|
int kComponents, const int *kPartFilters, |
|
const float *b, float scoreThreshold, |
|
CvPoint **points, CvPoint **oppPoints, |
|
float **score, int *kPoints); |
|
// INPUT |
|
// H - feature pyramid |
|
// filters - filters (root filter then it's part filters, etc.) |
|
// kComponents - root filters number |
|
// kPartFilters - array of part filters number for each component |
|
// b - array of linear terms |
|
// scoreThreshold - score threshold |
|
// OUTPUT |
|
// points - root filters displacement (top left corners) |
|
// oppPoints - root filters displacement (bottom right corners) |
|
// score - array of score values |
|
// kPoints - number of boxes |
|
// RESULT |
|
// Error status |
|
*/ |
|
int searchObjectThresholdSomeComponents(const CvLSVMFeaturePyramid *H, |
|
const CvLSVMFilterObject **filters, |
|
int kComponents, const int *kPartFilters, |
|
const float *b, float scoreThreshold, |
|
CvPoint **points, CvPoint **oppPoints, |
|
float **score, int *kPoints, |
|
int numThreads) |
|
{ |
|
//int error = 0; |
|
int i, j, s, f, componentIndex; |
|
unsigned int maxXBorder, maxYBorder; |
|
CvPoint **pointsArr, **oppPointsArr, ***partsDisplacementArr; |
|
float **scoreArr; |
|
int *kPointsArr, **levelsArr; |
|
|
|
// Allocation memory |
|
pointsArr = (CvPoint **)malloc(sizeof(CvPoint *) * kComponents); |
|
oppPointsArr = (CvPoint **)malloc(sizeof(CvPoint *) * kComponents); |
|
scoreArr = (float **)malloc(sizeof(float *) * kComponents); |
|
kPointsArr = (int *)malloc(sizeof(int) * kComponents); |
|
levelsArr = (int **)malloc(sizeof(int *) * kComponents); |
|
partsDisplacementArr = (CvPoint ***)malloc(sizeof(CvPoint **) * kComponents); |
|
|
|
// Getting maximum filter dimensions |
|
/*error = */getMaxFilterDims(filters, kComponents, kPartFilters, &maxXBorder, &maxYBorder); |
|
componentIndex = 0; |
|
*kPoints = 0; |
|
// For each component perform searching |
|
for (i = 0; i < kComponents; i++) |
|
{ |
|
int error = searchObjectThreshold(H, &(filters[componentIndex]), kPartFilters[i], |
|
b[i], maxXBorder, maxYBorder, scoreThreshold, |
|
&(pointsArr[i]), &(levelsArr[i]), &(kPointsArr[i]), |
|
&(scoreArr[i]), &(partsDisplacementArr[i]), numThreads); |
|
if (error != LATENT_SVM_OK) |
|
{ |
|
// Release allocated memory |
|
free(pointsArr); |
|
free(oppPointsArr); |
|
free(scoreArr); |
|
free(kPointsArr); |
|
free(levelsArr); |
|
free(partsDisplacementArr); |
|
return LATENT_SVM_SEARCH_OBJECT_FAILED; |
|
} |
|
estimateBoxes(pointsArr[i], levelsArr[i], kPointsArr[i], |
|
filters[componentIndex]->sizeX, filters[componentIndex]->sizeY, &(oppPointsArr[i])); |
|
componentIndex += (kPartFilters[i] + 1); |
|
*kPoints += kPointsArr[i]; |
|
} |
|
|
|
*points = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints)); |
|
*oppPoints = (CvPoint *)malloc(sizeof(CvPoint) * (*kPoints)); |
|
*score = (float *)malloc(sizeof(float) * (*kPoints)); |
|
s = 0; |
|
for (i = 0; i < kComponents; i++) |
|
{ |
|
f = s + kPointsArr[i]; |
|
for (j = s; j < f; j++) |
|
{ |
|
(*points)[j].x = pointsArr[i][j - s].x; |
|
(*points)[j].y = pointsArr[i][j - s].y; |
|
(*oppPoints)[j].x = oppPointsArr[i][j - s].x; |
|
(*oppPoints)[j].y = oppPointsArr[i][j - s].y; |
|
(*score)[j] = scoreArr[i][j - s]; |
|
} |
|
s = f; |
|
} |
|
|
|
// Release allocated memory |
|
for (i = 0; i < kComponents; i++) |
|
{ |
|
free(pointsArr[i]); |
|
free(oppPointsArr[i]); |
|
free(scoreArr[i]); |
|
free(levelsArr[i]); |
|
for (j = 0; j < kPointsArr[i]; j++) |
|
{ |
|
free(partsDisplacementArr[i][j]); |
|
} |
|
free(partsDisplacementArr[i]); |
|
} |
|
free(pointsArr); |
|
free(oppPointsArr); |
|
free(scoreArr); |
|
free(kPointsArr); |
|
free(levelsArr); |
|
free(partsDisplacementArr); |
|
return LATENT_SVM_OK; |
|
}
|
|
|