Possible bug in cv::moments (Bug #1719)


Added by Will Lucas almost 13 years ago. Updated almost 13 years ago.


Status:Cancelled Start date:2012-03-27
Priority:Normal Due date:
Assignee:Vadim Pisarevsky % Done:

0%

Category:imgproc, video
Target version:2.4.0 Estimated time:3.00 hours
Affected version: Operating System:
Difficulty: HW Platform:
Pull request:

Description

I was trying to get the centroid of a series of points recently, and I noticed that this particular sequence of points returned an m00 of 0.0. The code below shows the issue I've run into:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    vector<Point> points;
    points.push_back(Point(50, 56));
    points.push_back(Point(53, 53));
    points.push_back(Point(46, 54));
    points.push_back(Point(49, 51));

    Moments m = moments(points, false);

    cout << "m.m00 = " << m.m00 << endl;
    cout << "m.m01 = " << m.m01 << endl;
    cout << "m.m01 = " << m.m10 << endl;

    return 0;
}

Is this supposed to return all zeros with this call? Thanks!


Associated revisions

Revision e88ff683
Added by Vadim Pisarevsky almost 13 years ago

added test for ticket #1719 and added a note about contour self-intersections to the docs

Revision 68c916aa
Added by Andrey Pavlenko over 11 years ago

Merge pull request #1719 from ilya-lavrenov:ocl_gaussianBlur

History

Updated by Stefan Balke almost 13 years ago

Got the same problem.

From my mail to Will:

Hi Will,

I got the same problem,
try out five Points and it will work.
I suppose that due to calculating the moments via green's law,
you need a minimum amount of points.

Do you have a deeper understanding of calculating it?

In the end I will kick contours smaller than 4 pixels out of my vector.

Best regards
Stefan

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    vector<Point> points;
    points.push_back(Point(50, 56));
    points.push_back(Point(53, 53));
    points.push_back(Point(46, 54));
    points.push_back(Point(49, 51));
    points.push_back(Point(49, 53));

    Moments m = moments(points, false);

    cout << "m.m00 = " << m.m00 << endl;
    cout << "m.m01 = " << m.m01 << endl;
    cout << "m.m01 = " << m.m10 << endl;

    return 0;
}

Does anyone know how openCV does the discrete calculation of Green's law?
Looked up the source code but didn't get the answer....

Thanks
Stefan

Updated by Vadim Pisarevsky almost 13 years ago

the contour contains self-intersections, thus the result is correct (i.e. it complies the Green formula). To handle butterfly contours correctly, you need to add a stub vertex at the intersection of the lines and change the ordering of vertices so that the contour will just touch itself, but not intersect, i.e. you should be able to draw the whole shape in either clockwise or counter-clockwise direction and not change the direction.

I added the note about it into the reference manual in SVN trunk.

  • Status changed from Open to Cancelled
  • Assignee set to Vadim Pisarevsky

Updated by Will Lucas almost 13 years ago

Thanks for the information about Green's formula! I learned something new! I switched to just averaging the contour locations, which worked for my specific problem.

Updated by Stefan Balke almost 13 years ago

To find these intersections one could use a sweep line algorithm:
http://www.cs.uu.nl/geobook/pseudo.pdf
cf. pp. 3-4

Also available in: Atom PDF