diff --git a/modules/objdetect/src/cascadedetect.cpp b/modules/objdetect/src/cascadedetect.cpp index 1edf49d564..8d4ef6957c 100644 --- a/modules/objdetect/src/cascadedetect.cpp +++ b/modules/objdetect/src/cascadedetect.cpp @@ -943,10 +943,11 @@ void CascadeClassifier::setFaceDetectionMaskGenerator() #endif } -struct CascadeClassifierInvoker +class CascadeClassifierInvoker : public ParallelLoopBody { +public: CascadeClassifierInvoker( CascadeClassifier& _cc, Size _sz1, int _stripSize, int _yStep, double _factor, - ConcurrentRectVector& _vec, vector& _levels, vector& _weights, bool outputLevels, const Mat& _mask) + vector& _vec, vector& _levels, vector& _weights, bool outputLevels, const Mat& _mask, Mutex* _mtx) { classifier = &_cc; processingRectSize = _sz1; @@ -954,19 +955,20 @@ struct CascadeClassifierInvoker yStep = _yStep; scalingFactor = _factor; rectangles = &_vec; - rejectLevels = outputLevels ? &_levels : 0; - levelWeights = outputLevels ? &_weights : 0; - mask=_mask; + rejectLevels = outputLevels ? &_levels : 0; + levelWeights = outputLevels ? &_weights : 0; + mask = _mask; + mtx = _mtx; } - void operator()(const BlockedRange& range) const + void operator()(const Range& range) const { Ptr evaluator = classifier->featureEvaluator->clone(); Size winSize(cvRound(classifier->data.origWinSize.width * scalingFactor), cvRound(classifier->data.origWinSize.height * scalingFactor)); - int y1 = range.begin() * stripSize; - int y2 = min(range.end() * stripSize, processingRectSize.height); + int y1 = range.start * stripSize; + int y2 = min(range.end * stripSize, processingRectSize.height); for( int y = y1; y < y2; y += yStep ) { for( int x = 0; x < processingRectSize.width; x += yStep ) @@ -988,14 +990,20 @@ struct CascadeClassifierInvoker result = -(int)classifier->data.stages.size(); if( classifier->data.stages.size() + result < 4 ) { + mtx->lock(); rectangles->push_back(Rect(cvRound(x*scalingFactor), cvRound(y*scalingFactor), winSize.width, winSize.height)); + mtx->unlock(); rejectLevels->push_back(-result); levelWeights->push_back(gypWeight); } } else if( result > 0 ) + { + mtx->lock(); rectangles->push_back(Rect(cvRound(x*scalingFactor), cvRound(y*scalingFactor), winSize.width, winSize.height)); + mtx->unlock(); + } if( result == 0 ) x += yStep; } @@ -1003,13 +1011,14 @@ struct CascadeClassifierInvoker } CascadeClassifier* classifier; - ConcurrentRectVector* rectangles; + vector* rectangles; Size processingRectSize; int stripSize, yStep; double scalingFactor; vector *rejectLevels; vector *levelWeights; Mat mask; + Mutex* mtx; }; struct getRect { Rect operator ()(const CvAvgComp& e) const { return e.rect; } }; @@ -1031,22 +1040,23 @@ bool CascadeClassifier::detectSingleScale( const Mat& image, int stripCount, Siz currentMask=maskGenerator->generateMask(image); } - ConcurrentRectVector concurrentCandidates; + vector candidatesVector; vector rejectLevels; vector levelWeights; + Mutex mtx; if( outputRejectLevels ) { - parallel_for(BlockedRange(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor, - concurrentCandidates, rejectLevels, levelWeights, true, currentMask)); + parallel_for_(Range(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor, + candidatesVector, rejectLevels, levelWeights, true, currentMask, &mtx)); levels.insert( levels.end(), rejectLevels.begin(), rejectLevels.end() ); weights.insert( weights.end(), levelWeights.begin(), levelWeights.end() ); } else { - parallel_for(BlockedRange(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor, - concurrentCandidates, rejectLevels, levelWeights, false, currentMask)); + parallel_for_(Range(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor, + candidatesVector, rejectLevels, levelWeights, false, currentMask, &mtx)); } - candidates.insert( candidates.end(), concurrentCandidates.begin(), concurrentCandidates.end() ); + candidates.insert( candidates.end(), candidatesVector.begin(), candidatesVector.end() ); #if defined (LOG_CASCADE_STATISTIC) logger.write(); diff --git a/modules/objdetect/src/hog.cpp b/modules/objdetect/src/hog.cpp index 21bda2411c..b39f21c0b5 100644 --- a/modules/objdetect/src/hog.cpp +++ b/modules/objdetect/src/hog.cpp @@ -939,12 +939,13 @@ void HOGDescriptor::detect(const Mat& img, vector& hits, double hitThresh detect(img, hits, weightsV, hitThreshold, winStride, padding, locations); } -struct HOGInvoker +class HOGInvoker : public ParallelLoopBody { +public: HOGInvoker( const HOGDescriptor* _hog, const Mat& _img, double _hitThreshold, Size _winStride, Size _padding, - const double* _levelScale, ConcurrentRectVector* _vec, - ConcurrentDoubleVector* _weights=0, ConcurrentDoubleVector* _scales=0 ) + const double* _levelScale, std::vector * _vec, Mutex* _mtx, + std::vector* _weights=0, std::vector* _scales=0 ) { hog = _hog; img = _img; @@ -955,11 +956,12 @@ struct HOGInvoker vec = _vec; weights = _weights; scales = _scales; + mtx = _mtx; } - void operator()( const BlockedRange& range ) const + void operator()( const Range& range ) const { - int i, i1 = range.begin(), i2 = range.end(); + int i, i1 = range.start, i2 = range.end; double minScale = i1 > 0 ? levelScale[i1] : i2 > 1 ? levelScale[i1+1] : std::max(img.cols, img.rows); Size maxSz(cvCeil(img.cols/minScale), cvCeil(img.rows/minScale)); Mat smallerImgBuf(maxSz, img.type()); @@ -977,23 +979,29 @@ struct HOGInvoker resize(img, smallerImg, sz); hog->detect(smallerImg, locations, hitsWeights, hitThreshold, winStride, padding); Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale)); + + mtx->lock(); for( size_t j = 0; j < locations.size(); j++ ) { vec->push_back(Rect(cvRound(locations[j].x*scale), cvRound(locations[j].y*scale), scaledWinSize.width, scaledWinSize.height)); - if (scales) { + if (scales) + { scales->push_back(scale); } } - + mtx->unlock(); + if (weights && (!hitsWeights.empty())) { + mtx->lock(); for (size_t j = 0; j < locations.size(); j++) { weights->push_back(hitsWeights[j]); } - } + mtx->unlock(); + } } } @@ -1003,9 +1011,10 @@ struct HOGInvoker Size winStride; Size padding; const double* levelScale; - ConcurrentRectVector* vec; - ConcurrentDoubleVector* weights; - ConcurrentDoubleVector* scales; + std::vector* vec; + std::vector* weights; + std::vector* scales; + Mutex* mtx; }; @@ -1030,13 +1039,14 @@ void HOGDescriptor::detectMultiScale( levels = std::max(levels, 1); levelScale.resize(levels); - ConcurrentRectVector allCandidates; - ConcurrentDoubleVector tempScales; - ConcurrentDoubleVector tempWeights; - vector foundScales; - - parallel_for(BlockedRange(0, (int)levelScale.size()), - HOGInvoker(this, img, hitThreshold, winStride, padding, &levelScale[0], &allCandidates, &tempWeights, &tempScales)); + std::vector allCandidates; + std::vector tempScales; + std::vector tempWeights; + std::vector foundScales; + Mutex mtx; + + parallel_for_(Range(0, (int)levelScale.size()), + HOGInvoker(this, img, hitThreshold, winStride, padding, &levelScale[0], &allCandidates, &mtx, &tempWeights, &tempScales)); std::copy(tempScales.begin(), tempScales.end(), back_inserter(foundScales)); foundLocations.clear(); @@ -2382,12 +2392,13 @@ vector HOGDescriptor::getDaimlerPeopleDetector() return vector(detector, detector + sizeof(detector)/sizeof(detector[0])); } -struct HOGConfInvoker +class HOGConfInvoker : public ParallelLoopBody { +public: HOGConfInvoker( const HOGDescriptor* _hog, const Mat& _img, double _hitThreshold, Size _padding, std::vector* locs, - ConcurrentRectVector* _vec ) + std::vector* _vec, Mutex* _mtx ) { hog = _hog; img = _img; @@ -2395,11 +2406,12 @@ struct HOGConfInvoker padding = _padding; locations = locs; vec = _vec; + mtx = _mtx; } - void operator()( const BlockedRange& range ) const + void operator()( const Range& range ) const { - int i, i1 = range.begin(), i2 = range.end(); + int i, i1 = range.start, i2 = range.end; Size maxSz(cvCeil(img.cols/(*locations)[0].scale), cvCeil(img.rows/(*locations)[0].scale)); Mat smallerImgBuf(maxSz, img.type()); @@ -2419,10 +2431,14 @@ struct HOGConfInvoker hog->detectROI(smallerImg, (*locations)[i].locations, dets, (*locations)[i].confidences, hitThreshold, Size(), padding); Size scaledWinSize = Size(cvRound(hog->winSize.width*scale), cvRound(hog->winSize.height*scale)); + mtx->lock(); for( size_t j = 0; j < dets.size(); j++ ) + { vec->push_back(Rect(cvRound(dets[j].x*scale), cvRound(dets[j].y*scale), scaledWinSize.width, scaledWinSize.height)); + } + mtx->unlock(); } } @@ -2431,7 +2447,8 @@ struct HOGConfInvoker double hitThreshold; std::vector* locations; Size padding; - ConcurrentRectVector* vec; + std::vector* vec; + Mutex* mtx; }; void HOGDescriptor::detectROI(const cv::Mat& img, const vector &locations, @@ -2516,10 +2533,11 @@ void HOGDescriptor::detectMultiScaleROI(const cv::Mat& img, double hitThreshold, int groupThreshold) const { - ConcurrentRectVector allCandidates; + std::vector allCandidates; + Mutex mtx; - parallel_for(BlockedRange(0, (int)locations.size()), - HOGConfInvoker(this, img, hitThreshold, Size(8, 8), &locations, &allCandidates)); + parallel_for_(Range(0, (int)locations.size()), + HOGConfInvoker(this, img, hitThreshold, Size(8, 8), &locations, &allCandidates, &mtx)); foundLocations.resize(allCandidates.size()); std::copy(allCandidates.begin(), allCandidates.end(), foundLocations.begin());