HOGDescriptor::detectMultiScale() fails to return the combined weight of the group (Bug #3021)
Description
The following method accepts a vector<double>
parameter to return the weights (i.e. distances from the hyperplane) associated with each detection, however the method by default uses groupRectangle(vector<Rect>&, int, double)
function, which only groups ROIs and thus leaves the number of final vector<Rect>
and vector<double>
inconsistent
void HOGDescriptor::detectMultiScale( const Mat& img, vector<Rect>& foundLocations, vector<double>& foundWeights, double hitThreshold, Size winStride, Size padding, double scale0, double finalThreshold, bool useMeanshiftGrouping) const
Other variations of groupRectangle()
do not have the ability to correctly group SVM distances, so a new groupRectangle()
overload seems necessary. One solution would be to introduce the following overloaded function in cascadedetect.cpp:
void HOGDetector::groupROIs(vector<cv::Rect>& rectList, vector<double>& weights, int groupThreshold, double eps) const { if( groupThreshold <= 0 || rectList.empty() ) { return; } vector<int> labels; int nclasses = partition(rectList, labels, SimilarRects(eps)); vector<cv::Rect> rrects(nclasses); vector<int> rweights(nclasses, 0); vector<double> foundWeights(nclasses, DBL_MIN); int i, j, nlabels = (int)labels.size(); for( i = 0; i < nlabels; i++ ) { int cls = labels[i]; rrects[cls].x += rectList[i].x; rrects[cls].y += rectList[i].y; rrects[cls].width += rectList[i].width; rrects[cls].height += rectList[i].height; foundWeights[cls] = max(foundWeights[cls], weights[i]); rweights[cls]++; } for( i = 0; i < nclasses; i++ ) { cv::Rect r = rrects[i]; float s = 1.f/rweights[i]; rrects[i] = cv::Rect(cv::saturate_cast<int>(r.x*s), cv::saturate_cast<int>(r.y*s), cv::saturate_cast<int>(r.width*s), cv::saturate_cast<int>(r.height*s)); } rectList.clear(); weights.clear(); for( i = 0; i < nclasses; i++ ) { cv::Rect r1 = rrects[i]; int n1 = rweights[i]; double w1 = foundWeights[i]; if( n1 <= groupThreshold ) continue; // filter out small face rectangles inside large rectangles for( j = 0; j < nclasses; j++ ) { int n2 = rweights[j]; if( j == i || n2 <= groupThreshold ) continue; cv::Rect r2 = rrects[j]; int dx = cv::saturate_cast<int>( r2.width * eps ); int dy = cv::saturate_cast<int>( r2.height * eps ); if( /*i != j &&*/ // redundant, see previous if r1.x >= r2.x - dx && r1.y >= r2.y - dy && r1.x + r1.width <= r2.x + r2.width + dx && r1.y + r1.height <= r2.y + r2.height + dy && (n2 > std::max(3, n1) || n1 < 3) ) break; } if( j == nclasses ) { rectList.push_back(r1); weights.push_back(w1); } } }
And add the correct declaration to objdetect.hpp. Then change line 1063 of hog.cpp from:
groupRectangles(foundLocations, (int)finalThreshold, 0.2);
to:
groupRectangles(foundLocations, foundWeights, (int)finalThreshold, 0.2);
Associated revisions
Merge pull request #3021 from ElenaGvozdeva:ocl_flip
History
Updated by Bahram Dahi almost 12 years ago
In the solution code, the following line:
void HOGDetector::groupROIs(vector<cv::Rect>& rectList, vector<double>& weights, int groupThreshold, double eps) const
should be replaced by:
void groupRectangles(vector<cv::Rect>& rectList, vector<double>& weights, int groupThreshold, double eps) const
Updated by Alexander Shishkov almost 12 years ago
Marina, could you please review pullrequest with solution https://github.com/Itseez/opencv/pull/891?
- Assignee set to Marina Kolpakova
Updated by Kirill Kornyakov over 11 years ago
- Pull request set to https://github.com/Itseez/opencv/pull/891
Updated by Kirill Kornyakov over 11 years ago
- HW Platform set to Any
- Operating System set to Any
- Target version changed from 2.4.6 to Next Hackathon
Updated by Bahram Dahi over 11 years ago
- % Done changed from 0 to 100
- Status changed from Open to Done
- Target version changed from Next Hackathon to 2.4.7