LoginSignup
1
1

More than 3 years have passed since last update.

形状比較 (Huモーメント)

Posted at
private (Mat, Point[][], HierarchyIndex[]) FindContours(string filepath)
{
    var src = new Mat(filepath, ImreadModes.Grayscale);

    Cv2.Threshold(src, src, thresh: 87, maxval: 255, ThresholdTypes.BinaryInv);

    Cv2.FindContours(src, out Point[][] contours, out HierarchyIndex[] hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

    Mat edge = new Mat();
    Cv2.Canny(src, edge, threshold1: 96, threshold2: 96);

    return (edge, contours, hierarchy);
}

private void btnRun_Click(object sender, EventArgs e)
{
    Point[][] contours1;
    HierarchyIndex[] hierarchy1;

    Mat pattern;
    (pattern, contours1, hierarchy1) = FindContours(@".\pattern_nut.png");

    Cv2.ImShow("pattern", pattern);

    Point[][] contours2;
    HierarchyIndex[] hierarchy2;

    Mat data;
    (data, contours2, hierarchy2) = FindContours(@".\data.png");

    var output = new Mat();
    Cv2.CvtColor(data, output, ColorConversionCodes.GRAY2BGR);

    Cv2.ImShow("data", data);

    // ノイズ除去
    for (int i = 0; i < contours2.GetLength(0); ++i)
    {
        var area = Cv2.ContourArea(contours2[i].ToArray());

        if (area < 100)
        {
            var rect = Cv2.BoundingRect(contours2[i]);
            rect.Inflate(width: 1, height: 1);
            output.Rectangle(rect, Scalar.Black, thickness: -1);
        }
    }

    for (int i = 0; i < contours2.GetLength(0); ++i)
    {
        var area = Cv2.ContourArea(contours2[i].ToArray());

        if (area < 100)
        {
            continue;
        }

        var rect = Cv2.BoundingRect(contours2[i]);
        output.Rectangle(rect, Scalar.GreenYellow);

        var moments = Cv2.Moments(contours2[i]);
        Point centroid = new Point();
        centroid.X = (int)(moments.M10 / moments.M00);
        centroid.Y = (int)(moments.M01 / moments.M00);
        output.Circle(centroid, radius: 3, Scalar.Yellow, thickness: -1);

        double ratio = Cv2.MatchShapes(data[rect], pattern, ShapeMatchModes.I1);
        output.PutText(ratio.ToString("F3"), rect.TopLeft, HersheyFonts.HersheySimplex, fontScale: 0.8, (ratio < 0.005) ? Scalar.White : Scalar.Red);

        Cv2.MinEnclosingCircle(contours2[i], out Point2f center, out float fadius);
        var diff = center - centroid;
        double distance = Math.Sqrt(diff.X * diff.X + diff.Y * diff.Y);
        output.PutText(distance.ToString("F1"), centroid + new Point(10, 0), HersheyFonts.HersheySimplex, fontScale: 0.8, Scalar.Yellow, thickness: 2);
    }

    Cv2.ImShow("output", output);
}

7394c6479293d836cc457ac5306cbcd0[1].png
343e5c0d1c2180e2f6beef37b26fbad9[3].png
cf732495f3cc1aa373a4d6be2497e53b[1].png
2fe1da1f2dffeed36b29452765cfb8f9[1].png
bb030c5cb11803102cfed1fc84143d7a[1].png

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1