Commit 630288fd authored by Leonid Beynenson's avatar Leonid Beynenson

Added possibility of prefiltering into CascadeClassifier. Now OpenCV users can…

Added possibility of prefiltering into CascadeClassifier. Now OpenCV users can implement their own mask generators and insert them into CascadeClassifier. 
parent 1e647922
...@@ -468,6 +468,18 @@ protected: ...@@ -468,6 +468,18 @@ protected:
Data data; Data data;
Ptr<FeatureEvaluator> featureEvaluator; Ptr<FeatureEvaluator> featureEvaluator;
Ptr<CvHaarClassifierCascade> oldCascade; Ptr<CvHaarClassifierCascade> oldCascade;
public:
class MaskGenerator
{
public:
virtual cv::Mat generateMask(const cv::Mat& src)=0;
};
void setMaskGenerator(Ptr<MaskGenerator> maskGenerator);
Ptr<MaskGenerator> getMaskGenerator();
protected:
Ptr<MaskGenerator> maskGenerator;
Ptr<MaskGenerator> getDefaultMaskGenerator();
}; };
......
...@@ -787,10 +787,14 @@ Ptr<FeatureEvaluator> FeatureEvaluator::create( int featureType ) ...@@ -787,10 +787,14 @@ Ptr<FeatureEvaluator> FeatureEvaluator::create( int featureType )
CascadeClassifier::CascadeClassifier() CascadeClassifier::CascadeClassifier()
{ {
maskGenerator=getDefaultMaskGenerator();
} }
CascadeClassifier::CascadeClassifier(const string& filename) CascadeClassifier::CascadeClassifier(const string& filename)
{ load(filename); } {
load(filename);
maskGenerator=getDefaultMaskGenerator();
}
CascadeClassifier::~CascadeClassifier() CascadeClassifier::~CascadeClassifier()
{ {
...@@ -859,12 +863,29 @@ bool CascadeClassifier::setImage( Ptr<FeatureEvaluator>& featureEvaluator, const ...@@ -859,12 +863,29 @@ bool CascadeClassifier::setImage( Ptr<FeatureEvaluator>& featureEvaluator, const
return empty() ? false : featureEvaluator->setImage(image, data.origWinSize); return empty() ? false : featureEvaluator->setImage(image, data.origWinSize);
} }
void CascadeClassifier::setMaskGenerator(Ptr<MaskGenerator> _maskGenerator)
{
maskGenerator=_maskGenerator;
}
Ptr<CascadeClassifier::MaskGenerator> CascadeClassifier::getMaskGenerator()
{
return maskGenerator;
}
Ptr<CascadeClassifier::MaskGenerator> CascadeClassifier::getDefaultMaskGenerator()
{
#ifdef HAVE_TEGRA_OPTIMIZATION
return tegra::getCascadeClassifierMaskGenerator(*this);
#else
return Ptr<CascadeClassifier::MaskGenerator>();
#endif
}
struct CascadeClassifierInvoker struct CascadeClassifierInvoker
{ {
CascadeClassifierInvoker( const Mat& _image, CascadeClassifier& _cc, Size _sz1, int _stripSize, int _yStep, double _factor, CascadeClassifierInvoker( CascadeClassifier& _cc, Size _sz1, int _stripSize, int _yStep, double _factor,
ConcurrentRectVector& _vec, vector<int>& _levels, vector<double>& _weights, bool outputLevels = false ) ConcurrentRectVector& _vec, vector<int>& _levels, vector<double>& _weights, bool outputLevels, const Mat& _mask)
{ {
image=_image;
classifier = &_cc; classifier = &_cc;
processingRectSize = _sz1; processingRectSize = _sz1;
stripSize = _stripSize; stripSize = _stripSize;
...@@ -873,15 +894,13 @@ struct CascadeClassifierInvoker ...@@ -873,15 +894,13 @@ struct CascadeClassifierInvoker
rectangles = &_vec; rectangles = &_vec;
rejectLevels = outputLevels ? &_levels : 0; rejectLevels = outputLevels ? &_levels : 0;
levelWeights = outputLevels ? &_weights : 0; levelWeights = outputLevels ? &_weights : 0;
mask=_mask;
} }
void operator()(const BlockedRange& range) const void operator()(const BlockedRange& range) const
{ {
Ptr<FeatureEvaluator> evaluator = classifier->featureEvaluator->clone(); Ptr<FeatureEvaluator> evaluator = classifier->featureEvaluator->clone();
#ifdef HAVE_TEGRA_OPTIMIZATION
Mat currentMask=tegra::getCascadeClassifierMask(image, classifier->data.origWinSize);
#endif
Size winSize(cvRound(classifier->data.origWinSize.width * scalingFactor), cvRound(classifier->data.origWinSize.height * scalingFactor)); Size winSize(cvRound(classifier->data.origWinSize.width * scalingFactor), cvRound(classifier->data.origWinSize.height * scalingFactor));
int y1 = range.begin() * stripSize; int y1 = range.begin() * stripSize;
...@@ -890,11 +909,9 @@ struct CascadeClassifierInvoker ...@@ -890,11 +909,9 @@ struct CascadeClassifierInvoker
{ {
for( int x = 0; x < processingRectSize.width; x += yStep ) for( int x = 0; x < processingRectSize.width; x += yStep )
{ {
#ifdef HAVE_TEGRA_OPTIMIZATION if ( (!mask.empty()) && (mask.at<uchar>(Point(x,y))==0)) {
if ( (!currentMask.empty()) && (currentMask.at<uchar>(Point(x,y))==0)) {
continue; continue;
} }
#endif
double gypWeight; double gypWeight;
int result = classifier->runAt(evaluator, Point(x, y), gypWeight); int result = classifier->runAt(evaluator, Point(x, y), gypWeight);
...@@ -918,7 +935,6 @@ struct CascadeClassifierInvoker ...@@ -918,7 +935,6 @@ struct CascadeClassifierInvoker
} }
} }
Mat image;
CascadeClassifier* classifier; CascadeClassifier* classifier;
ConcurrentRectVector* rectangles; ConcurrentRectVector* rectangles;
Size processingRectSize; Size processingRectSize;
...@@ -926,6 +942,7 @@ struct CascadeClassifierInvoker ...@@ -926,6 +942,7 @@ struct CascadeClassifierInvoker
double scalingFactor; double scalingFactor;
vector<int> *rejectLevels; vector<int> *rejectLevels;
vector<double> *levelWeights; vector<double> *levelWeights;
Mat mask;
}; };
struct getRect { Rect operator ()(const CvAvgComp& e) const { return e.rect; } }; struct getRect { Rect operator ()(const CvAvgComp& e) const { return e.rect; } };
...@@ -937,20 +954,25 @@ bool CascadeClassifier::detectSingleScale( const Mat& image, int stripCount, Siz ...@@ -937,20 +954,25 @@ bool CascadeClassifier::detectSingleScale( const Mat& image, int stripCount, Siz
if( !featureEvaluator->setImage( image, data.origWinSize ) ) if( !featureEvaluator->setImage( image, data.origWinSize ) )
return false; return false;
Mat currentMask;
if (!maskGenerator.empty()) {
currentMask=maskGenerator->generateMask(image);
}
ConcurrentRectVector concurrentCandidates; ConcurrentRectVector concurrentCandidates;
vector<int> rejectLevels; vector<int> rejectLevels;
vector<double> levelWeights; vector<double> levelWeights;
if( outputRejectLevels ) if( outputRejectLevels )
{ {
parallel_for(BlockedRange(0, stripCount), CascadeClassifierInvoker( image, *this, processingRectSize, stripSize, yStep, factor, parallel_for(BlockedRange(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor,
concurrentCandidates, rejectLevels, levelWeights, true)); concurrentCandidates, rejectLevels, levelWeights, true, currentMask));
levels.insert( levels.end(), rejectLevels.begin(), rejectLevels.end() ); levels.insert( levels.end(), rejectLevels.begin(), rejectLevels.end() );
weights.insert( weights.end(), levelWeights.begin(), levelWeights.end() ); weights.insert( weights.end(), levelWeights.begin(), levelWeights.end() );
} }
else else
{ {
parallel_for(BlockedRange(0, stripCount), CascadeClassifierInvoker( image, *this, processingRectSize, stripSize, yStep, factor, parallel_for(BlockedRange(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor,
concurrentCandidates, rejectLevels, levelWeights, false)); concurrentCandidates, rejectLevels, levelWeights, false, currentMask));
} }
candidates.insert( candidates.end(), concurrentCandidates.begin(), concurrentCandidates.end() ); candidates.insert( candidates.end(), concurrentCandidates.begin(), concurrentCandidates.end() );
......
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