How can I use OpenCV to find the center of mass. [closed]

asked 2018-10-12 13:39:11 -0500

webatxcent gravatar image

updated 2018-10-12 14:10:03 -0500

I am working on an inspection process that requires me to precisely locate features in the field of view. Specifically I am finding features on a circuit board which could include finding tooling holes and solder pads. Our vision setup gives us a per-pixel size of ~100 microns.

At that resolution there is a great deal of material clutter as solder pads leak beyond their intended circumference, and tooling holes have microscopic burrs which can distort.

The question is about a tooling hole where a couple of burrs are causing my centroid calculation to result in a center point that does not correspond with the center of mass of the object. I have attached the raw image and a processed image that shows the detected contour, the calculated centroid and the circle based on the area of the contour centered at the centroid.

Looking at the output I would expect the circle to be shifted much further to the left as the omitted pieces of the contour look much larger than the extra pieces to right.

Raw Capture

raw capture

Processed Image

processed image

    static void Process( string filename ) {
        Mat raw;

        raw = Cv2.ImRead( filename, ImreadModes.GrayScale );

        Mat threshold = new Mat();
        Cv2.Threshold( raw, threshold, 190, 255, ThresholdTypes.Otsu );

        Point[][] contours;
        HierarchyIndex[] hierarchyIndexes;

        Cv2.FindContours( threshold, out contours, out hierarchyIndexes, RetrievalModes.List, ContourApproximationModes.ApproxSimple );

        Mat rawColor = new Mat();
        Cv2.CvtColor( raw, rawColor, ColorConversionCodes.GRAY2RGB );

        if ( contours.Length != 0 ) {
            var contourIndex = 0;
            while ( contourIndex >= 0 ) {

                var area = Cv2.ContourArea( contours[ contourIndex ] );

                Debug.Print( $"{contourIndex} points: {contours[ contourIndex ].Length}, area: {area}" );

                //only look for features that have a given area
                if ( area < 1100000 && area > 400000.0 ) {
                //if ( area < 1100000 && area > 60000.0 ) {
                    Cv2.DrawContours( rawColor, contours, contourIndex, new Scalar( 255, 0, 0 ), 10, LineTypes.Link8, hierarchyIndexes, int.MaxValue );
                    Point centroid = Centroid( contours[ contourIndex ] );
                    Cv2.Circle( rawColor, centroid, 20, new Scalar( 0, 0, 255 ), 3 );

                    var radius = Math.Sqrt( area / Math.PI );
                    Cv2.Circle( rawColor, centroid, (int)radius, new Scalar( 0, 0, 255 ), thickness: 3 );

                }
                contourIndex = hierarchyIndexes[ contourIndex ].Next;
            }
        }
    }

    static Point Centroid ( Point[] knots ) {
        Point center = new Point();

        int sumofx = 0, sumofy = 0;

        for ( int i = 0; i < knots.Length; i++ ) {
            sumofx = sumofx + knots[ i ].X;
            sumofy = sumofy + knots[ i ].Y;
        }
        center.X = sumofx / knots.Length;
        center.Y = sumofy / knots.Length;

        return center;

    }
edit retag flag offensive reopen merge delete

Closed for the following reason question is not relevant or outdated by sturkmen
close date 2020-10-06 11:46:16.694829

Comments

please add the code, you're trying with

berak gravatar imageberak ( 2018-10-12 13:41:02 -0500 )edit
1

OP updated with code.

webatxcent gravatar imagewebatxcent ( 2018-10-12 14:21:52 -0500 )edit
1

Take a look at the moments function. m10/m00 is x, and m01/m00 is y, unless they're backwards. You should test that before you believe me.

Tetragramm gravatar imageTetragramm ( 2018-10-12 20:49:53 -0500 )edit

"unless they're backwards" -- you're also using an unsupported 3rdparty wrapper, and we have no idea, what they're doing !

berak gravatar imageberak ( 2018-10-13 02:23:52 -0500 )edit

Is that not Java? That looks like the normal OpenCV Java to me.

Tetragramm gravatar imageTetragramm ( 2018-10-13 21:38:14 -0500 )edit

@Tetragramm, no. opencv's java bindings do not have a Cv2 prefix

i rather guess: some (unsupported) c# binding

@webatxcent , -- do you realize, what kind of trouble you're in ?

berak gravatar imageberak ( 2018-10-13 22:01:54 -0500 )edit