diff --git a/modules/objdetect/include/opencv2/objdetect/objdetect.hpp b/modules/objdetect/include/opencv2/objdetect/objdetect.hpp index a78bef56f..f0bb58e5f 100644 --- a/modules/objdetect/include/opencv2/objdetect/objdetect.hpp +++ b/modules/objdetect/include/opencv2/objdetect/objdetect.hpp @@ -534,12 +534,14 @@ public: int shrinkage; }; + enum { NO_REJECT = 1, DOLLAR = 2, /*PASCAL = 4,*/ DEFAULT = NO_REJECT}; + // An empty cascade will be created. // Param minScale is a minimum scale relative to the original size of the image on which cascade will be applyed. // Param minScale is a maximum scale relative to the original size of the image on which cascade will be applyed. // Param scales is a number of scales from minScale to maxScale. // Param rejfactor is used for NMS. - CV_WRAP SCascade(const double minScale = 0.4, const double maxScale = 5., const int scales = 55, const int rejfactor = 1); + CV_WRAP SCascade(const double minScale = 0.4, const double maxScale = 5., const int scales = 55, const int rejCriteria = 1); CV_WRAP virtual ~SCascade(); @@ -571,7 +573,7 @@ private: double maxScale; int scales; - int rejfactor; + int rejCriteria; }; CV_EXPORTS bool initModule_objdetect(void); diff --git a/modules/objdetect/src/objdetect_init.cpp b/modules/objdetect/src/objdetect_init.cpp index d53c9480d..77afeaa6e 100644 --- a/modules/objdetect/src/objdetect_init.cpp +++ b/modules/objdetect/src/objdetect_init.cpp @@ -46,10 +46,10 @@ namespace cv { CV_INIT_ALGORITHM(SCascade, "CascadeDetector.SCascade", - obj.info()->addParam(obj, "minScale", obj.minScale); - obj.info()->addParam(obj, "maxScale", obj.maxScale); - obj.info()->addParam(obj, "scales", obj.scales); - obj.info()->addParam(obj, "rejfactor", obj.rejfactor)); + obj.info()->addParam(obj, "minScale", obj.minScale); + obj.info()->addParam(obj, "maxScale", obj.maxScale); + obj.info()->addParam(obj, "scales", obj.scales); + obj.info()->addParam(obj, "rejCriteria", obj.rejCriteria)); bool initModule_objdetect(void) { diff --git a/modules/objdetect/src/softcascade.cpp b/modules/objdetect/src/softcascade.cpp index 0ee7c0fd4..384a989fe 100644 --- a/modules/objdetect/src/softcascade.cpp +++ b/modules/objdetect/src/softcascade.cpp @@ -422,7 +422,7 @@ struct cv::SCascade::Fields }; cv::SCascade::SCascade(const double mins, const double maxs, const int nsc, const int rej) -: fields(0), minScale(mins), maxScale(maxs), scales(nsc), rejfactor(rej) {} +: fields(0), minScale(mins), maxScale(maxs), scales(nsc), rejCriteria(rej) {} cv::SCascade::~SCascade() { delete fields;} @@ -439,6 +439,68 @@ bool cv::SCascade::load(const FileNode& fn) return fields->fill(fn); } +namespace { +typedef cv::SCascade::Detection Detection; +typedef std::vector dvector; + +struct NMS +{ + + virtual ~NMS(){} + virtual void apply(dvector& objects) const = 0; +}; + + +struct ConfidenceLess +{ + bool operator()(const Detection& a, const Detection& b) const + { + return a.confidence > b.confidence; + } +}; + +struct DollarNMS: public NMS +{ + virtual ~DollarNMS(){} + + static float overlap(const cv::Rect &a, const cv::Rect &b) + { + int w = std::min(a.x + a.width, b.x + b.width) - std::max(a.x, b.x); + int h = std::min(a.y + a.height, b.y + b.height) - std::max(a.y, b.y); + + return (w < 0 || h < 0)? 0.f : (float)(w * h); + } + + virtual void apply(dvector& objects) const + { + std::sort(objects.begin(), objects.end(), ConfidenceLess()); + + for (dvector::iterator dIt = objects.begin(); dIt != objects.end(); ++dIt) + { + const Detection &a = *dIt; + for (dvector::iterator next = dIt + 1; next != objects.end(); ) + { + const Detection &b = *next; + + const float ovl = overlap(a.bb, b.bb) / std::min(a.bb.area(), b.bb.area()); + + if (ovl > 0.65f) + next = objects.erase(next); + else + ++next; + } + } + } +}; + +cv::Ptr createNMS(int type) +{ + CV_Assert(type == cv::SCascade::DOLLAR); + return cv::Ptr(new DollarNMS); +} + +} + void cv::SCascade::detectNoRoi(const cv::Mat& image, std::vector& objects) const { Fields& fld = *fields; @@ -459,6 +521,9 @@ void cv::SCascade::detectNoRoi(const cv::Mat& image, std::vector& obj } } } + + if (rejCriteria != NO_REJECT) + createNMS(rejCriteria)->apply(objects); } void cv::SCascade::detect(cv::InputArray _image, cv::InputArray _rois, std::vector& objects) const @@ -506,6 +571,9 @@ void cv::SCascade::detect(cv::InputArray _image, cv::InputArray _rois, std::vect } } } + + if (rejCriteria != NO_REJECT) + createNMS(rejCriteria)->apply(objects); } void cv::SCascade::detect(InputArray _image, InputArray _rois, OutputArray _rects, OutputArray _confs) const