Ask Your Question

Revision history [back]

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

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

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

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;

    }