Home > Blockchain >  How to find coordinate of contour centroid in C#
How to find coordinate of contour centroid in C#

Time:11-10

I am doing image processing so that I am finding contours in the image. What I need is the centroid pixel number of the found contour in the image. To find the pixel number I am using the code given below. After finding the pixel number I want to show it in the text boxes as x and y coordinates. But the code is not working. Please help me. What is wrong?

                VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
                CvInvoke.FindContours(cannyImage, contours, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);
                    var cannyOut = cannyImage.ToImage<Bgr, byte>();
                    //CvInvoke.DrawContours(cannyOut, contours, 2, new MCvScalar(255, 0, 0),2);

                    VectorOfPoint approx = new VectorOfPoint();

                    Dictionary<int, double> shapes = new Dictionary<int, double>();

                    for (int i = 0; i < contours.Size; i  )
                    {
                        approx.Clear();
                        double perimeter = CvInvoke.ArcLength(contours[i], true);
                        CvInvoke.ApproxPolyDP(contours[i], approx, 0.04 * perimeter, true);
                        double area = CvInvoke.ContourArea(contours[i]);

                        if (approx.Size > 4)
                        {
                            shapes.Add(i, area);
                        }
                    }
                    if (shapes.Count > 0)
                    {
                        var sortedShapes = (from item in shapes
                                            orderby item.Value ascending
                                            select item).ToList();

                        for (int i = 0; i < sortedShapes.Count; i  )
                        {
                            
                            CvInvoke.DrawContours(cannyOut, contours, sortedShapes[i].Key, new MCvScalar(255, 0, 0), 2);
                            var moments = CvInvoke.Moments(contours[sortedShapes[i].Key]);
                            int x = (int)(moments.M10 / moments.M00);
                            int y = (int)(moments.M01 / moments.M00);

                            CvInvoke.PutText(cannyOut, (i   1).ToString(), new Point(x, y), Emgu.CV.CvEnum.FontFace.HersheyTriplex, 1.0,
                                new MCvScalar(255, 0, 0), 2);
                            //CvInvoke.PutText(cannyOut, sortedShapes[i].Value.ToString(), new Point(x, y - 30), Emgu.CV.CvEnum.FontFace.HersheyTriplex, 1.0,
                            //    new MCvScalar(255, 0, 0), 2);

                            textBox1.Text = x.ToString();
                            textBox2.Text = y.ToString();
                        }

                    }

CodePudding user response:

To find the centroid of a shape you need to split it into many triangles first.

Then for each triangle with vertices A, B, C you do the summation weighted by the area of the triangle just as so

static void Main(string[] args)
{
    var shape = new List<Triangle>();
    // fill shape with triangles

    float area = 0f;
    Vector2 centroid = Vector2.Zero;

    foreach (var triangle in shape)
    {
        float trig_area = triangle.Area;
        Vector2 trig_cen = triangle.Centroid;

        area  = trig_area;
        centroid  = trig_area * trig_cen;
    }
    centroid /= area;

}

For reference, a 2D triangle has the following properties

public readonly struct Triangle
{

    public Triangle(Vector2 a, Vector2 b, Vector2 c) : this()
    {
        A = a;
        B = b;
        C = c;
    }

    public Vector2 A { get; }
    public Vector2 B { get; }
    public Vector2 C { get; }

    public float Area { get => (Cross(A, B)   Cross(B, C)   Cross(C, A)) / 2; }
    public Vector2 Centroid { get => (A   B   C) / 3; }

    // helper function
    static float Cross(Vector2 a, Vector2 b) => a.X * b.Y - a.Y * b.X;
}
  • Related