Added possibility of prefiltering into CascadeClassifier. Now OpenCV users can implement their own mask generators and insert them into CascadeClassifier.

pull/13383/head
Leonid Beynenson 13 years ago
parent 1e6479224a
commit 630288fdef
  1. 12
      modules/objdetect/include/opencv2/objdetect/objdetect.hpp
  2. 52
      modules/objdetect/src/cascadedetect.cpp

@ -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 )
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
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
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
{ {
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
} }
} }
Mat image;
CascadeClassifier* classifier; CascadeClassifier* classifier;
ConcurrentRectVector* rectangles; ConcurrentRectVector* rectangles;
Size processingRectSize; Size processingRectSize;
@ -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
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() );

Loading…
Cancel
Save