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();
double maxScale;
int scales;
- int rejfactor;
+ int rejCriteria;
};
CV_EXPORTS bool initModule_objdetect(void);
{
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)
{
};
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;}
return fields->fill(fn);
}
+namespace {
+typedef cv::SCascade::Detection Detection;
+typedef std::vector<Detection> 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<NMS> createNMS(int type)
+{
+ CV_Assert(type == cv::SCascade::DOLLAR);
+ return cv::Ptr<NMS>(new DollarNMS);
+}
+
+}
+
void cv::SCascade::detectNoRoi(const cv::Mat& image, std::vector<Detection>& objects) const
{
Fields& fld = *fields;
}
}
}
+
+ if (rejCriteria != NO_REJECT)
+ createNMS(rejCriteria)->apply(objects);
}
void cv::SCascade::detect(cv::InputArray _image, cv::InputArray _rois, std::vector<Detection>& objects) const
}
}
}
+
+ if (rejCriteria != NO_REJECT)
+ createNMS(rejCriteria)->apply(objects);
}
void cv::SCascade::detect(InputArray _image, InputArray _rois, OutputArray _rects, OutputArray _confs) const