void GroupRects(std::vector<cv::Rect> &rectList, std::vector<int> &labels, std::set<int> &validLabelValues, int groupThreshold, float eps) { if( groupThreshold <= 0 || rectList.empty() ) return; // cluster the rectangle when four points are close labels.clear(); validLabelValues.clear(); int nclasses = partition(rectList, labels, SimilarRects(eps)); std::vector<cv::Rect> rrects(nclasses); std::vector<int> rweights(nclasses, 0); std::vector<int> rejectLevels(nclasses, 0); // what's this for? std::vector<double> rejectWeights(nclasses, DBL_MIN); // and this int i, j, nlabels = (int)labels.size(); for( i = 0; i < nlabels; i++ ) { // sum all the retangles 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; // counter the number of retangles in one class 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(); for( i = 0; i < nclasses; i++ ) { cv::Rect r1 = rrects[i]; int n1 = rweights[i]; double w1 = rejectWeights[i]; if( n1 < groupThreshold ) continue; // filter out small 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 && 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 ) break; } if( j == nclasses ) { rectList.push_back(r1); validLabelValues.insert(i); } } }
void groupRectangles(std::vector<MyRect>& rectList, int groupThreshold, float eps) { if( groupThreshold <= 0 || rectList.empty() ) return; std::vector<int> labels; int nclasses = partition(rectList, labels, eps); std::vector<MyRect> rrects(nclasses); std::vector<int> rweights(nclasses); 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; rweights[cls]++; } for( i = 0; i < nclasses; i++ ) { MyRect r = rrects[i]; float s = 1.f/rweights[i]; rrects[i].x = myRound(r.x*s); rrects[i].y = myRound(r.y*s); rrects[i].width = myRound(r.width*s); rrects[i].height = myRound(r.height*s); } rectList.clear(); for( i = 0; i < nclasses; i++ ) { MyRect r1 = rrects[i]; int n1 = rweights[i]; if( n1 <= groupThreshold ) continue; /* filter out small face rectangles inside large rectangles */ for( j = 0; j < nclasses; j++ ) { int n2 = rweights[j]; /********************************* * if it is the same rectangle, * or the number of rectangles in class j is < group threshold, * do nothing ********************************/ if( j == i || n2 <= groupThreshold ) continue; MyRect r2 = rrects[j]; int dx = myRound( r2.width * eps ); int dy = myRound( r2.height * eps ); if( i != j && 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 > myMax(3, n1) || n1 < 3) ) break; } if( j == nclasses ) { rectList.push_back(r1); // insert back r1 } } }