#include "precomp.hpp"
#include <cstdio>
+#include <iostream>
#include "cascadedetect.hpp"
#include "opencv2/objdetect/objdetect_c.h"
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,
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 &&
!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