allow minObjectSize==maxObjectSize for single scale detection capability
This commit is contained in:
@@ -255,7 +255,7 @@ public:
|
||||
@param flags Parameter with the same meaning for an old cascade as in the function
|
||||
cvHaarDetectObjects. It is not used for a new cascade.
|
||||
@param minSize Minimum possible object size. Objects smaller than that are ignored.
|
||||
@param maxSize Maximum possible object size. Objects larger than that are ignored.
|
||||
@param maxSize Maximum possible object size. Objects larger than that are ignored. If `maxSize == minSize` model is evaluated on single scale.
|
||||
|
||||
The function is parallelized with the TBB library.
|
||||
|
||||
@@ -283,7 +283,7 @@ public:
|
||||
@param flags Parameter with the same meaning for an old cascade as in the function
|
||||
cvHaarDetectObjects. It is not used for a new cascade.
|
||||
@param minSize Minimum possible object size. Objects smaller than that are ignored.
|
||||
@param maxSize Maximum possible object size. Objects larger than that are ignored.
|
||||
@param maxSize Maximum possible object size. Objects larger than that are ignored. If `maxSize == minSize` model is evaluated on single scale.
|
||||
*/
|
||||
CV_WRAP_AS(detectMultiScale2) void detectMultiScale( InputArray image,
|
||||
CV_OUT std::vector<Rect>& objects,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Mat grayImage;
|
||||
_InputArray gray;
|
||||
|
||||
std::vector<float> scales;
|
||||
scales.reserve(1024);
|
||||
if (_image.channels() > 1)
|
||||
cvtColor(_image, grayImage, COLOR_BGR2GRAY);
|
||||
else if (_image.isMat())
|
||||
grayImage = _image.getMat();
|
||||
else
|
||||
_image.copyTo(grayImage);
|
||||
gray = grayImage;
|
||||
|
||||
for( double factor = 1; ; factor *= scaleFactor )
|
||||
{
|
||||
Size originalWindowSize = getOriginalWindowSize();
|
||||
|
||||
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( scales.size() == 0 || !featureEvaluator->setImage(gray, scales) )
|
||||
if( !featureEvaluator->setImage(gray, scales) )
|
||||
return;
|
||||
|
||||
#ifdef HAVE_OPENCL
|
||||
|
||||
Reference in New Issue
Block a user