Commit d03b89f1 authored by Valentina Kustikova's avatar Valentina Kustikova

Parallel version of Latent SVM.

parent 7539b7de
......@@ -127,6 +127,7 @@ CV_INLINE IppiSize ippiSize(int width, int height)
#include "tbb/tbb_stddef.h"
#if TBB_VERSION_MAJOR*100 + TBB_VERSION_MINOR >= 202
#include "tbb/tbb.h"
#include "tbb/task.h"
#undef min
#undef max
#else
......
......@@ -247,7 +247,8 @@ CVAPI(void) cvReleaseLatentSvmDetector(CvLatentSvmDetector** detector);
// CvSeq* cvLatentSvmDetectObjects(const IplImage* image,
// CvLatentSvmDetector* detector,
// CvMemStorage* storage,
// float overlap_threshold = 0.5f);
// float overlap_threshold = 0.5f,
// int numThreads = -1);
// INPUT
// image - image to detect objects in
// detector - Latent SVM detector in internal representation
......@@ -261,7 +262,8 @@ CVAPI(void) cvReleaseLatentSvmDetector(CvLatentSvmDetector** detector);
CVAPI(CvSeq*) cvLatentSvmDetectObjects(IplImage* image,
CvLatentSvmDetector* detector,
CvMemStorage* storage,
float overlap_threshold CV_DEFAULT(0.5f));
float overlap_threshold CV_DEFAULT(0.5f),
int numThreads CV_DEFAULT(-1));
#ifdef __cplusplus
}
......
......@@ -248,7 +248,8 @@ int searchObjectThreshold(const CvLSVMFeaturePyramid *H,
int maxXBorder, int maxYBorder,
float scoreThreshold,
CvPoint **points, int **levels, int *kPoints,
float **score, CvPoint ***partsDisplacement);
float **score, CvPoint ***partsDisplacement,
int numThreads CV_DEFAULT(-1));
/*
// Computation root filters displacement and values of score function
......@@ -283,7 +284,7 @@ int searchObjectThresholdSomeComponents(const CvLSVMFeaturePyramid *H,
int kComponents, const int *kPartFilters,
const float *b, float scoreThreshold,
CvPoint **points, CvPoint **oppPoints,
float **score, int *kPoints);
float **score, int *kPoints, int numThreads);
/*
// Compute opposite point for filter box
......
......@@ -10,8 +10,10 @@
#define LATENT_SVM_SEARCH_OBJECT_FAILED -5
#define LATENT_SVM_FAILED_SUPERPOSITION -6
#define FILTER_OUT_OF_BOUNDARIES -7
#define LATENT_SVM_TBB_SCHEDULE_CREATION_FAILED -8
#define LATENT_SVM_TBB_NUMTHREADS_NOT_CORRECT -9
#define FFT_OK 2
#define FFT_ERROR -8
#define LSVM_PARSER_FILE_NOT_FOUND -9
#define FFT_ERROR -10
#define LSVM_PARSER_FILE_NOT_FOUND -11
#endif
......@@ -11,6 +11,10 @@
#include "_lsvm_fft.h"
#include "_lsvm_routine.h"
#ifdef HAVE_TBB
#include "_lsvm_tbbversion.h"
#endif
//extern "C" {
/*
// Function for convolution computation
......@@ -352,6 +356,46 @@ int thresholdFunctionalScore(const CvLSVMFilterObject **all_F, int n,
CvPoint **points, int **levels, int *kPoints,
CvPoint ***partsDisplacement);
#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);
#endif
/*
// Perform non-maximum suppression algorithm (described in original paper)
......
#ifndef _LSVM_TBBVERSION_H
#define _LSVM_TBBVERSION_H
#include "_lsvm_matching.h"
#include "precomp.hpp"
/*
// Computation score function using TBB tasks
//
// API
// int tbbTasksThresholdFunctionalScore(const CvLSVMFilterObject **filters, const int n,
const CvLSVMFeaturePyramid *H, const float b,
const int maxXBorder, const int maxYBorder,
const float scoreThreshold,
int *kLevels, int **procLevels,
const int threadsNum,
float **score, CvPoint ***points,
int *kPoints,
CvPoint ****partsDisplacement);
// INPUT
// filters - 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
// kLevels - array that contains number of levels processed
by each thread
// procLevels - array that contains lists of levels processed
by each thread
// threadsNum - the number of created threads
// OUTPUT
// score - score function values that exceed threshold
// points - the set of root filter positions (in the block space)
// kPoints - number of root filter positions
// partsDisplacement - displacement of part filters (in the block space)
// RESULT
//
*/
int tbbTasksThresholdFunctionalScore(const CvLSVMFilterObject **filters, const int n,
const CvLSVMFeaturePyramid *H, const float b,
const int maxXBorder, const int maxYBorder,
const float scoreThreshold,
int *kLevels, int **procLevels,
const int threadsNum,
float **score, CvPoint ***points,
int *kPoints,
CvPoint ****partsDisplacement);
#endif
\ No newline at end of file
......@@ -271,17 +271,30 @@ int searchObjectThreshold(const CvLSVMFeaturePyramid *H,
int maxXBorder, int maxYBorder,
float scoreThreshold,
CvPoint **points, int **levels, int *kPoints,
float **score, CvPoint ***partsDisplacement)
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);
#endif
if (opResult != LATENT_SVM_OK)
{
return LATENT_SVM_SEARCH_OBJECT_FAILED;
......@@ -537,7 +550,8 @@ int searchObjectThresholdSomeComponents(const CvLSVMFeaturePyramid *H,
int kComponents, const int *kPartFilters,
const float *b, float scoreThreshold,
CvPoint **points, CvPoint **oppPoints,
float **score, int *kPoints)
float **score, int *kPoints,
int numThreads)
{
int error = 0;
int i, j, s, f, componentIndex;
......@@ -561,10 +575,17 @@ int searchObjectThresholdSomeComponents(const CvLSVMFeaturePyramid *H,
// For each component perform searching
for (i = 0; i < kComponents; i++)
{
#ifdef HAVE_TBB
searchObjectThreshold(H, &(filters[componentIndex]), kPartFilters[i],
b[i], maxXBorder, maxYBorder, scoreThreshold,
&(pointsArr[i]), &(levelsArr[i]), &(kPointsArr[i]),
&(scoreArr[i]), &(partsDisplacementArr[i]), numThreads);
#else
searchObjectThreshold(H, &(filters[componentIndex]), kPartFilters[i],
b[i], maxXBorder, maxYBorder, scoreThreshold,
&(pointsArr[i]), &(levelsArr[i]), &(kPointsArr[i]),
&(scoreArr[i]), &(partsDisplacementArr[i]));
#endif
estimateBoxes(pointsArr[i], levelsArr[i], kPointsArr[i],
filters[componentIndex]->sizeX, filters[componentIndex]->sizeY, &(oppPointsArr[i]));
componentIndex += (kPartFilters[i] + 1);
......
......@@ -69,7 +69,8 @@ void cvReleaseLatentSvmDetector(CvLatentSvmDetector** detector)
// CvSeq* cvLatentSvmDetectObjects(const IplImage* image,
// CvLatentSvmDetector* detector,
// CvMemStorage* storage,
// float overlap_threshold = 0.5f);
// float overlap_threshold = 0.5f,
int numThreads = -1);
// INPUT
// image - image to detect objects in
// detector - Latent SVM detector in internal representation
......@@ -82,7 +83,7 @@ void cvReleaseLatentSvmDetector(CvLatentSvmDetector** detector)
CvSeq* cvLatentSvmDetectObjects(IplImage* image,
CvLatentSvmDetector* detector,
CvMemStorage* storage,
float overlap_threshold)
float overlap_threshold, int numThreads)
{
CvLSVMFeaturePyramid *H = 0;
CvPoint *points = 0, *oppPoints = 0;
......@@ -103,7 +104,7 @@ CvSeq* cvLatentSvmDetectObjects(IplImage* image,
// Search object
searchObjectThresholdSomeComponents(H, (const CvLSVMFilterObject**)(detector->filters), detector->num_components,
detector->num_part_filters, detector->b, detector->score_threshold,
&points, &oppPoints, &score, &kPoints);
&points, &oppPoints, &score, &kPoints, numThreads);
// Clipping boxes
clippingBoxes(image->width, image->height, points, kPoints);
clippingBoxes(image->width, image->height, oppPoints, kPoints);
......
#include "_lsvm_tbbversion.h"
#ifdef HAVE_TBB
/*
// Task class
*/
class ScoreComputation : public tbb::task
{
private:
const CvLSVMFilterObject **filters;
const int n;
const CvLSVMFeaturePyramid *H;
const float b;
const int maxXBorder;
const int maxYBorder;
const float scoreThreshold;
const int kLevels;
const int *procLevels;
public:
float **score;
CvPoint ***points;
CvPoint ****partsDisplacement;
int *kPoints;
public:
ScoreComputation(const CvLSVMFilterObject **_filters, int _n,
const CvLSVMFeaturePyramid *_H,
float _b, int _maxXBorder, int _maxYBorder,
float _scoreThreshold, int _kLevels, const int *_procLevels,
float **_score, CvPoint ***_points, int *_kPoints,
CvPoint ****_partsDisplacement) :
n(_n), b(_b), maxXBorder(_maxXBorder),
maxYBorder(_maxYBorder), scoreThreshold(_scoreThreshold),
kLevels(_kLevels), score(_score), points(_points), kPoints(_kPoints),
partsDisplacement(_partsDisplacement)
{
filters = _filters;
H = _H;
procLevels = _procLevels;
};
task* execute()
{
int i, level, partsLevel, res;
for (i = 0; i < kLevels; i++)
{
level = procLevels[i];
partsLevel = level - H->lambda;
res = thresholdFunctionalScoreFixedLevel(
filters, n, H, level, b,
maxXBorder, maxYBorder, scoreThreshold, &(score[partsLevel]),
points[partsLevel], &(kPoints[partsLevel]),
partsDisplacement[partsLevel]);
if (res != LATENT_SVM_OK)
{
continue;
}
}
return NULL;
}
};
/*
// Computation score function using TBB tasks
//
// API
// int tbbTasksThresholdFunctionalScore(const CvLSVMFilterObject **filters, const int n,
const CvLSVMFeatureMap *H, const float b,
const int maxXBorder, const int maxYBorder,
const float scoreThreshold,
int *kLevels, int **procLevels,
const int threadsNum,
float **score, CvPoint ***points,
int *kPoints,
CvPoint ****partsDisplacement);
// INPUT
// filters - 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
// kLevels - array that contains number of levels processed
by each thread
// procLevels - array that contains lists of levels processed
by each thread
// threadsNum - the number of created threads
// OUTPUT
// score - score function values that exceed threshold
// points - the set of root filter positions (in the block space)
// kPoints - number of root filter positions
// partsDisplacement - displacement of part filters (in the block space)
// RESULT
//
*/
int tbbTasksThresholdFunctionalScore(const CvLSVMFilterObject **filters, const int n,
const CvLSVMFeaturePyramid *H, const float b,
const int maxXBorder, const int maxYBorder,
const float scoreThreshold,
int *kLevels, int **procLevels,
const int threadsNum,
float **score, CvPoint ***points,
int *kPoints,
CvPoint ****partsDisplacement)
{
tbb::task_list tasks;
int i;
for (i = 0; i < threadsNum; i++)
{
ScoreComputation& sc =
*new(tbb::task::allocate_root()) ScoreComputation(filters, n, H, b,
maxXBorder, maxYBorder, scoreThreshold, kLevels[i], procLevels[i],
score, points, kPoints, partsDisplacement);
tasks.push_back(sc);
}
tbb::task::spawn_root_and_wait(tasks);
return LATENT_SVM_OK;
};
#endif
\ No newline at end of file
This diff is collapsed.
......@@ -2,6 +2,13 @@
#include "opencv2/highgui/highgui.hpp"
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include <cvconfig.h>
#endif
#ifdef HAVE_TBB
#include "tbb/task_scheduler_init.h"
#endif
using namespace cv;
void help()
......@@ -9,26 +16,43 @@ void help()
printf( "This program demonstrated the use of the latentSVM detector.\n"
"It reads in a trained object model and then uses that to detect the object in an image\n"
"Call:\n"
"./latentsvmdetect [<image_filename> <model_filename]\n"
"./latentsvmdetect [<image_filename> <model_filename> [<threads_number>]]\n"
" The defaults for image_filename and model_filename are cat.jpg and cat.xml respectively\n"
" Press any key to quit.\n");
}
const char* model_filename = "cat.xml";
const char* image_filename = "cat.jpg";
int tbbNumThreads = -1;
void detect_and_draw_objects( IplImage* image, CvLatentSvmDetector* detector)
void detect_and_draw_objects( IplImage* image, CvLatentSvmDetector* detector, int numThreads = -1)
{
CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* detections = 0;
int i = 0;
int64 start = 0, finish = 0;
#ifdef HAVE_TBB
tbb::task_scheduler_init init(tbb::task_scheduler_init::deferred);
if (numThreads > 0)
{
init.initialize(numThreads);
printf("Number of threads %i\n", numThreads);
}
else
{
printf("Number of threads is not correct for TBB version");
return;
}
#endif
start = cvGetTickCount();
detections = cvLatentSvmDetectObjects(image, detector, storage);
detections = cvLatentSvmDetectObjects(image, detector, storage, 0.5f, numThreads);
finish = cvGetTickCount();
printf("detection time = %.3f\n", (float)(finish - start) / (float)(cvGetTickFrequency() * 1000000.0));
#ifdef HAVE_TBB
init.terminate();
#endif
for( i = 0; i < detections->total; i++ )
{
CvObjectDetection detection = *(CvObjectDetection*)cvGetSeqElem( detections, i );
......@@ -48,6 +72,10 @@ int main(int argc, char* argv[])
{
image_filename = argv[1];
model_filename = argv[2];
if (argc > 3)
{
tbbNumThreads = atoi(argv[3]);
}
}
IplImage* image = cvLoadImage(image_filename);
if (!image)
......@@ -64,7 +92,7 @@ int main(int argc, char* argv[])
cvReleaseImage( &image );
return -1;
}
detect_and_draw_objects( image, detector );
detect_and_draw_objects( image, detector, tbbNumThreads );
cvNamedWindow( "test", 0 );
cvShowImage( "test", image );
cvWaitKey(0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment