HOGDescriptor::detectMultiScale() fails to return the combined weight of the group (Bug #3021)


Added by Bahram Dahi almost 12 years ago. Updated over 11 years ago.


Status:Done Start date:2013-05-13
Priority:Normal Due date:
Assignee:Marina Kolpakova % Done:

100%

Category:objdetect
Target version:2.4.7
Affected version:branch 'master' (2.4.9) Operating System:Any
Difficulty: HW Platform:Any
Pull request:https://github.com/Itseez/opencv/pull/891

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

Revision 17a6b8cd
Added by Alexander Alekhin over 10 years ago

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

Also available in: Atom PDF