|
|
|
@ -1060,9 +1060,7 @@ void HOGDescriptor::detectMultiScale( |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
vector<int> dummy; |
|
|
|
|
dummy.resize(foundLocations.size(), INT_MAX); |
|
|
|
|
groupRectangles(foundLocations, (int)finalThreshold, 0.2, &dummy, &foundWeights); |
|
|
|
|
groupRectangles(foundLocations, foundWeights, (int)finalThreshold, 0.2); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2636,4 +2634,82 @@ void HOGDescriptor::readALTModel(std::string modelfile) |
|
|
|
|
fclose(modelfl); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void HOGDescriptor::groupRectangles(vector<cv::Rect>& rectList, vector<double>& weights, int groupThreshold, double eps) const |
|
|
|
|
{ |
|
|
|
|
if( groupThreshold <= 0 || rectList.empty() ) |
|
|
|
|
{ |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CV_Assert(rectList.size() == weights.size()); |
|
|
|
|
|
|
|
|
|
vector<int> labels; |
|
|
|
|
int nclasses = partition(rectList, labels, SimilarRects(eps)); |
|
|
|
|
|
|
|
|
|
vector<cv::Rect_<double>> rrects(nclasses); |
|
|
|
|
vector<int> numInClass(nclasses, 0); |
|
|
|
|
vector<double> foundWeights(nclasses, DBL_MIN); |
|
|
|
|
vector<double> totalFactorsPerClass(nclasses, 1); |
|
|
|
|
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]); |
|
|
|
|
numInClass[cls]++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
for( i = 0; i < nclasses; i++ ) |
|
|
|
|
{ |
|
|
|
|
// find the average of all ROI in the cluster
|
|
|
|
|
cv::Rect_<double> r = rrects[i]; |
|
|
|
|
float s = 1.f/numInClass[i]; |
|
|
|
|
rrects[i] = cv::Rect_<double>(cv::saturate_cast<double>(r.x*s), |
|
|
|
|
cv::saturate_cast<double>(r.y*s), |
|
|
|
|
cv::saturate_cast<double>(r.width*s), |
|
|
|
|
cv::saturate_cast<double>(r.height*s)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
rectList.clear(); |
|
|
|
|
weights.clear(); |
|
|
|
|
|
|
|
|
|
for( i = 0; i < nclasses; i++ ) |
|
|
|
|
{ |
|
|
|
|
cv::Rect r1 = rrects[i]; |
|
|
|
|
int n1 = numInClass[i]; |
|
|
|
|
double w1 = foundWeights[i]; |
|
|
|
|
if( n1 <= groupThreshold ) |
|
|
|
|
continue; |
|
|
|
|
// filter out small rectangles inside large rectangles
|
|
|
|
|
for( j = 0; j < nclasses; j++ ) |
|
|
|
|
{ |
|
|
|
|
int n2 = numInClass[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( 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); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|