Reverted back to the previous method where a public method groupRectangles was added to HOGDescriptor to take care of ROI and weight grouping
This commit is contained in:
parent
8c25f9f28a
commit
dcad6ce65a
@ -192,12 +192,12 @@ typedef struct CvLSVMFilterObject{
|
|||||||
|
|
||||||
// data type: STRUCT CvLatentSvmDetector
|
// data type: STRUCT CvLatentSvmDetector
|
||||||
// structure contains internal representation of trained Latent SVM detector
|
// structure contains internal representation of trained Latent SVM detector
|
||||||
// num_filters - total number of filters (root plus part) in model
|
// num_filters - total number of filters (root plus part) in model
|
||||||
// num_components - number of components in model
|
// num_components - number of components in model
|
||||||
// num_part_filters - array containing number of part filters for each component
|
// num_part_filters - array containing number of part filters for each component
|
||||||
// filters - root and part filters for all model components
|
// filters - root and part filters for all model components
|
||||||
// b - biases for all model components
|
// b - biases for all model components
|
||||||
// score_threshold - confidence level threshold
|
// score_threshold - confidence level threshold
|
||||||
typedef struct CvLatentSvmDetector
|
typedef struct CvLatentSvmDetector
|
||||||
{
|
{
|
||||||
int num_filters;
|
int num_filters;
|
||||||
@ -211,8 +211,8 @@ CvLatentSvmDetector;
|
|||||||
|
|
||||||
// data type: STRUCT CvObjectDetection
|
// data type: STRUCT CvObjectDetection
|
||||||
// structure contains the bounding box and confidence level for detected object
|
// structure contains the bounding box and confidence level for detected object
|
||||||
// rect - bounding box for a detected object
|
// rect - bounding box for a detected object
|
||||||
// score - confidence level
|
// score - confidence level
|
||||||
typedef struct CvObjectDetection
|
typedef struct CvObjectDetection
|
||||||
{
|
{
|
||||||
CvRect rect;
|
CvRect rect;
|
||||||
@ -228,7 +228,7 @@ typedef struct CvObjectDetection
|
|||||||
// API
|
// API
|
||||||
// CvLatentSvmDetector* cvLoadLatentSvmDetector(const char* filename);
|
// CvLatentSvmDetector* cvLoadLatentSvmDetector(const char* filename);
|
||||||
// INPUT
|
// INPUT
|
||||||
// filename - path to the file containing the parameters of
|
// filename - path to the file containing the parameters of
|
||||||
- trained Latent SVM detector
|
- trained Latent SVM detector
|
||||||
// OUTPUT
|
// OUTPUT
|
||||||
// trained Latent SVM detector in internal representation
|
// trained Latent SVM detector in internal representation
|
||||||
@ -241,7 +241,7 @@ CVAPI(CvLatentSvmDetector*) cvLoadLatentSvmDetector(const char* filename);
|
|||||||
// API
|
// API
|
||||||
// void cvReleaseLatentSvmDetector(CvLatentSvmDetector** detector);
|
// void cvReleaseLatentSvmDetector(CvLatentSvmDetector** detector);
|
||||||
// INPUT
|
// INPUT
|
||||||
// detector - CvLatentSvmDetector structure to be released
|
// detector - CvLatentSvmDetector structure to be released
|
||||||
// OUTPUT
|
// OUTPUT
|
||||||
*/
|
*/
|
||||||
CVAPI(void) cvReleaseLatentSvmDetector(CvLatentSvmDetector** detector);
|
CVAPI(void) cvReleaseLatentSvmDetector(CvLatentSvmDetector** detector);
|
||||||
@ -252,16 +252,16 @@ CVAPI(void) cvReleaseLatentSvmDetector(CvLatentSvmDetector** detector);
|
|||||||
//
|
//
|
||||||
// API
|
// API
|
||||||
// CvSeq* cvLatentSvmDetectObjects(const IplImage* image,
|
// CvSeq* cvLatentSvmDetectObjects(const IplImage* image,
|
||||||
// CvLatentSvmDetector* detector,
|
// CvLatentSvmDetector* detector,
|
||||||
// CvMemStorage* storage,
|
// CvMemStorage* storage,
|
||||||
// float overlap_threshold = 0.5f,
|
// float overlap_threshold = 0.5f,
|
||||||
// int numThreads = -1);
|
// int numThreads = -1);
|
||||||
// INPUT
|
// INPUT
|
||||||
// image - image to detect objects in
|
// image - image to detect objects in
|
||||||
// detector - Latent SVM detector in internal representation
|
// detector - Latent SVM detector in internal representation
|
||||||
// storage - memory storage to store the resultant sequence
|
// storage - memory storage to store the resultant sequence
|
||||||
// of the object candidate rectangles
|
// of the object candidate rectangles
|
||||||
// overlap_threshold - threshold for the non-maximum suppression algorithm
|
// overlap_threshold - threshold for the non-maximum suppression algorithm
|
||||||
= 0.5f [here will be the reference to original paper]
|
= 0.5f [here will be the reference to original paper]
|
||||||
// OUTPUT
|
// OUTPUT
|
||||||
// sequence of detected objects (bounding boxes and confidence levels stored in CvObjectDetection structures)
|
// sequence of detected objects (bounding boxes and confidence levels stored in CvObjectDetection structures)
|
||||||
@ -327,6 +327,23 @@ private:
|
|||||||
vector<string> classNames;
|
vector<string> classNames;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// class for grouping object candidates, detected by Cascade Classifier, HOG etc.
|
||||||
|
// instance of the class is to be passed to cv::partition (see cxoperations.hpp)
|
||||||
|
class CV_EXPORTS SimilarRects
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SimilarRects(double _eps) : eps(_eps) {}
|
||||||
|
inline bool operator()(const Rect& r1, const Rect& r2) const
|
||||||
|
{
|
||||||
|
double delta = eps*(std::min(r1.width, r2.width) + std::min(r1.height, r2.height))*0.5;
|
||||||
|
return std::abs(r1.x - r2.x) <= delta &&
|
||||||
|
std::abs(r1.y - r2.y) <= delta &&
|
||||||
|
std::abs(r1.x + r1.width - r2.x - r2.width) <= delta &&
|
||||||
|
std::abs(r1.y + r1.height - r2.y - r2.height) <= delta;
|
||||||
|
}
|
||||||
|
double eps;
|
||||||
|
};
|
||||||
|
|
||||||
CV_EXPORTS void groupRectangles(CV_OUT CV_IN_OUT vector<Rect>& rectList, int groupThreshold, double eps=0.2);
|
CV_EXPORTS void groupRectangles(CV_OUT CV_IN_OUT vector<Rect>& rectList, int groupThreshold, double eps=0.2);
|
||||||
CV_EXPORTS_W void groupRectangles(CV_OUT CV_IN_OUT vector<Rect>& rectList, CV_OUT vector<int>& weights, int groupThreshold, double eps=0.2);
|
CV_EXPORTS_W void groupRectangles(CV_OUT CV_IN_OUT vector<Rect>& rectList, CV_OUT vector<int>& weights, int groupThreshold, double eps=0.2);
|
||||||
CV_EXPORTS void groupRectangles( vector<Rect>& rectList, int groupThreshold, double eps, vector<int>* weights, vector<double>* levelWeights );
|
CV_EXPORTS void groupRectangles( vector<Rect>& rectList, int groupThreshold, double eps, vector<int>* weights, vector<double>* levelWeights );
|
||||||
@ -611,6 +628,7 @@ public:
|
|||||||
|
|
||||||
// read/parse Dalal's alt model file
|
// read/parse Dalal's alt model file
|
||||||
void readALTModel(std::string modelfile);
|
void readALTModel(std::string modelfile);
|
||||||
|
void groupRectangles(vector<cv::Rect>& rectList, vector<double>& weights, int groupThreshold, double eps) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,24 +114,6 @@ struct Logger
|
|||||||
namespace cv
|
namespace cv
|
||||||
{
|
{
|
||||||
|
|
||||||
// class for grouping object candidates, detected by Cascade Classifier, HOG etc.
|
|
||||||
// instance of the class is to be passed to cv::partition (see cxoperations.hpp)
|
|
||||||
class CV_EXPORTS SimilarRects
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SimilarRects(double _eps) : eps(_eps) {}
|
|
||||||
inline bool operator()(const Rect& r1, const Rect& r2) const
|
|
||||||
{
|
|
||||||
double delta = eps*(std::min(r1.width, r2.width) + std::min(r1.height, r2.height))*0.5;
|
|
||||||
return std::abs(r1.x - r2.x) <= delta &&
|
|
||||||
std::abs(r1.y - r2.y) <= delta &&
|
|
||||||
std::abs(r1.x + r1.width - r2.x - r2.width) <= delta &&
|
|
||||||
std::abs(r1.y + r1.height - r2.y - r2.height) <= delta;
|
|
||||||
}
|
|
||||||
double eps;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void groupRectangles(vector<Rect>& rectList, int groupThreshold, double eps, vector<int>* weights, vector<double>* levelWeights)
|
void groupRectangles(vector<Rect>& rectList, int groupThreshold, double eps, vector<int>* weights, vector<double>* levelWeights)
|
||||||
{
|
{
|
||||||
if( groupThreshold <= 0 || rectList.empty() )
|
if( groupThreshold <= 0 || rectList.empty() )
|
||||||
|
@ -1060,9 +1060,7 @@ void HOGDescriptor::detectMultiScale(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
vector<int> dummy;
|
groupRectangles(foundLocations, foundWeights, (int)finalThreshold, 0.2);
|
||||||
dummy.resize(foundLocations.size(), INT_MAX);
|
|
||||||
groupRectangles(foundLocations, (int)finalThreshold, 0.2, &dummy, &foundWeights);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2636,4 +2634,82 @@ void HOGDescriptor::readALTModel(std::string modelfile)
|
|||||||
fclose(modelfl);
|
fclose(modelfl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HOGDescriptor::groupRectangles(vector<cv::Rect>& rectList, vector<double>& weights, int groupThreshold, double eps) const
|
||||||
|
{
|
||||||
|
if( groupThreshold <= 0 || rectList.empty() )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CV_Assert(rectList.size() == weights.size());
|
||||||
|
|
||||||
|
vector<int> labels;
|
||||||
|
int nclasses = partition(rectList, labels, SimilarRects(eps));
|
||||||
|
|
||||||
|
vector<cv::Rect_<double>> rrects(nclasses);
|
||||||
|
vector<int> numInClass(nclasses, 0);
|
||||||
|
vector<double> foundWeights(nclasses, DBL_MIN);
|
||||||
|
vector<double> totalFactorsPerClass(nclasses, 1);
|
||||||
|
int i, j, nlabels = (int)labels.size();
|
||||||
|
|
||||||
|
for( i = 0; i < nlabels; i++ )
|
||||||
|
{
|
||||||
|
int cls = labels[i];
|
||||||
|
rrects[cls].x += rectList[i].x;
|
||||||
|
rrects[cls].y += rectList[i].y;
|
||||||
|
rrects[cls].width += rectList[i].width;
|
||||||
|
rrects[cls].height += rectList[i].height;
|
||||||
|
foundWeights[cls] = max(foundWeights[cls], weights[i]);
|
||||||
|
numInClass[cls]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < nclasses; i++ )
|
||||||
|
{
|
||||||
|
// find the average of all ROI in the cluster
|
||||||
|
cv::Rect_<double> r = rrects[i];
|
||||||
|
float s = 1.f/numInClass[i];
|
||||||
|
rrects[i] = cv::Rect_<double>(cv::saturate_cast<double>(r.x*s),
|
||||||
|
cv::saturate_cast<double>(r.y*s),
|
||||||
|
cv::saturate_cast<double>(r.width*s),
|
||||||
|
cv::saturate_cast<double>(r.height*s));
|
||||||
|
}
|
||||||
|
|
||||||
|
rectList.clear();
|
||||||
|
weights.clear();
|
||||||
|
|
||||||
|
for( i = 0; i < nclasses; i++ )
|
||||||
|
{
|
||||||
|
cv::Rect r1 = rrects[i];
|
||||||
|
int n1 = numInClass[i];
|
||||||
|
double w1 = foundWeights[i];
|
||||||
|
if( n1 <= groupThreshold )
|
||||||
|
continue;
|
||||||
|
// filter out small rectangles inside large rectangles
|
||||||
|
for( j = 0; j < nclasses; j++ )
|
||||||
|
{
|
||||||
|
int n2 = numInClass[j];
|
||||||
|
|
||||||
|
if( j == i || n2 <= groupThreshold )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cv::Rect r2 = rrects[j];
|
||||||
|
|
||||||
|
int dx = cv::saturate_cast<int>( r2.width * eps );
|
||||||
|
int dy = cv::saturate_cast<int>( r2.height * eps );
|
||||||
|
|
||||||
|
if( r1.x >= r2.x - dx &&
|
||||||
|
r1.y >= r2.y - dy &&
|
||||||
|
r1.x + r1.width <= r2.x + r2.width + dx &&
|
||||||
|
r1.y + r1.height <= r2.y + r2.height + dy &&
|
||||||
|
(n2 > std::max(3, n1) || n1 < 3) )
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( j == nclasses )
|
||||||
|
{
|
||||||
|
rectList.push_back(r1);
|
||||||
|
weights.push_back(w1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user