|
|
|
@ -41,6 +41,7 @@ |
|
|
|
|
|
|
|
|
|
#include "precomp.hpp" |
|
|
|
|
#include <cstdio> |
|
|
|
|
#include <iostream> |
|
|
|
|
|
|
|
|
|
#include "cascadedetect.hpp" |
|
|
|
|
#include "opencv2/objdetect/objdetect_c.h" |
|
|
|
@ -1221,7 +1222,6 @@ static void detectMultiScaleOldFormat( const Mat& image, Ptr<CvHaarClassifierCas |
|
|
|
|
std::transform(vecAvgComp.begin(), vecAvgComp.end(), objects.begin(), getRect()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CascadeClassifierImpl::detectMultiScaleNoGrouping( InputArray _image, std::vector<Rect>& candidates, |
|
|
|
|
std::vector<int>& rejectLevels, std::vector<double>& levelWeights, |
|
|
|
|
double scaleFactor, Size minObjectSize, Size maxObjectSize, |
|
|
|
@ -1230,17 +1230,64 @@ void CascadeClassifierImpl::detectMultiScaleNoGrouping( InputArray _image, std:: |
|
|
|
|
CV_INSTRUMENT_REGION() |
|
|
|
|
|
|
|
|
|
Size imgsz = _image.size(); |
|
|
|
|
Size originalWindowSize = getOriginalWindowSize(); |
|
|
|
|
|
|
|
|
|
Mat grayImage; |
|
|
|
|
_InputArray gray; |
|
|
|
|
if( maxObjectSize.height == 0 || maxObjectSize.width == 0 ) |
|
|
|
|
maxObjectSize = imgsz; |
|
|
|
|
|
|
|
|
|
// If a too small image patch is entering the function, break early before any processing
|
|
|
|
|
if( (imgsz.height < originalWindowSize.height) || (imgsz.width < originalWindowSize.width) ) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
std::vector<float> all_scales, scales; |
|
|
|
|
all_scales.reserve(1024); |
|
|
|
|
scales.reserve(1024); |
|
|
|
|
|
|
|
|
|
// First calculate all possible scales for the given image and model, then remove undesired scales
|
|
|
|
|
// This allows us to cope with single scale detections (minSize == maxSize) that do not fall on precalculated scale
|
|
|
|
|
for( double factor = 1; ; factor *= scaleFactor ) |
|
|
|
|
{ |
|
|
|
|
Size windowSize( cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) ); |
|
|
|
|
if( windowSize.width > imgsz.width || windowSize.height > imgsz.height ) |
|
|
|
|
break; |
|
|
|
|
all_scales.push_back((float)factor); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// This will capture allowed scales and a minSize==maxSize scale, if it is in the precalculated scales
|
|
|
|
|
for( size_t index = 0; index < all_scales.size(); index++){ |
|
|
|
|
Size windowSize( cvRound(originalWindowSize.width*all_scales[index]), cvRound(originalWindowSize.height*all_scales[index]) ); |
|
|
|
|
if( windowSize.width > maxObjectSize.width || windowSize.height > maxObjectSize.height) |
|
|
|
|
break; |
|
|
|
|
if( windowSize.width < minObjectSize.width || windowSize.height < minObjectSize.height ) |
|
|
|
|
continue; |
|
|
|
|
scales.push_back(all_scales[index]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// If minSize and maxSize parameter are equal and scales is not filled yet, then the scale was not available in the precalculated scales
|
|
|
|
|
// In that case we want to return the most fitting scale (closest corresponding scale using L2 distance)
|
|
|
|
|
if( scales.empty() && !all_scales.empty() ){ |
|
|
|
|
std::vector<double> distances; |
|
|
|
|
// Calculate distances
|
|
|
|
|
for(size_t v = 0; v < all_scales.size(); v++){ |
|
|
|
|
Size windowSize( cvRound(originalWindowSize.width*all_scales[v]), cvRound(originalWindowSize.height*all_scales[v]) ); |
|
|
|
|
double d = (minObjectSize.width - windowSize.width) * (minObjectSize.width - windowSize.width) |
|
|
|
|
+ (minObjectSize.height - windowSize.height) * (minObjectSize.height - windowSize.height); |
|
|
|
|
distances.push_back(d); |
|
|
|
|
} |
|
|
|
|
// Take the index of lowest value
|
|
|
|
|
// Use that index to push the correct scale parameter
|
|
|
|
|
size_t iMin=0; |
|
|
|
|
for(size_t i = 0; i < distances.size(); ++i){ |
|
|
|
|
if(distances[iMin] > distances[i]) |
|
|
|
|
iMin=i; |
|
|
|
|
} |
|
|
|
|
scales.push_back(all_scales[iMin]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
candidates.clear(); |
|
|
|
|
rejectLevels.clear(); |
|
|
|
|
levelWeights.clear(); |
|
|
|
|
|
|
|
|
|
if( maxObjectSize.height == 0 || maxObjectSize.width == 0 ) |
|
|
|
|
maxObjectSize = imgsz; |
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
|
bool use_ocl = tryOpenCL && ocl::useOpenCL() && |
|
|
|
|
featureEvaluator->getLocalSize().area() > 0 && |
|
|
|
@ -1251,44 +1298,18 @@ void CascadeClassifierImpl::detectMultiScaleNoGrouping( InputArray _image, std:: |
|
|
|
|
!outputRejectLevels; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
/*if( use_ocl )
|
|
|
|
|
{ |
|
|
|
|
if (_image.channels() > 1) |
|
|
|
|
cvtColor(_image, ugrayImage, COLOR_BGR2GRAY); |
|
|
|
|
else if (_image.isUMat()) |
|
|
|
|
ugrayImage = _image.getUMat(); |
|
|
|
|
else |
|
|
|
|
_image.copyTo(ugrayImage); |
|
|
|
|
gray = ugrayImage; |
|
|
|
|
} |
|
|
|
|
else*/ |
|
|
|
|
{ |
|
|
|
|
if (_image.channels() > 1) |
|
|
|
|
cvtColor(_image, grayImage, COLOR_BGR2GRAY); |
|
|
|
|
else if (_image.isMat()) |
|
|
|
|
grayImage = _image.getMat(); |
|
|
|
|
else |
|
|
|
|
_image.copyTo(grayImage); |
|
|
|
|
gray = grayImage; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
std::vector<float> scales; |
|
|
|
|
scales.reserve(1024); |
|
|
|
|
|
|
|
|
|
for( double factor = 1; ; factor *= scaleFactor ) |
|
|
|
|
{ |
|
|
|
|
Size originalWindowSize = getOriginalWindowSize(); |
|
|
|
|
Mat grayImage; |
|
|
|
|
_InputArray gray; |
|
|
|
|
|
|
|
|
|
Size windowSize( cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) ); |
|
|
|
|
if( windowSize.width > maxObjectSize.width || windowSize.height > maxObjectSize.height || |
|
|
|
|
windowSize.width > imgsz.width || windowSize.height > imgsz.height ) |
|
|
|
|
break; |
|
|
|
|
if( windowSize.width < minObjectSize.width || windowSize.height < minObjectSize.height ) |
|
|
|
|
continue; |
|
|
|
|
scales.push_back((float)factor); |
|
|
|
|
} |
|
|
|
|
if (_image.channels() > 1) |
|
|
|
|
cvtColor(_image, grayImage, COLOR_BGR2GRAY); |
|
|
|
|
else if (_image.isMat()) |
|
|
|
|
grayImage = _image.getMat(); |
|
|
|
|
else |
|
|
|
|
_image.copyTo(grayImage); |
|
|
|
|
gray = grayImage; |
|
|
|
|
|
|
|
|
|
if( scales.size() == 0 || !featureEvaluator->setImage(gray, scales) ) |
|
|
|
|
if( !featureEvaluator->setImage(gray, scales) ) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
#ifdef HAVE_OPENCL |
|
|
|
|