如何在图像中找到相似的形状

时间:2019-07-27 15:57:14

标签: c# opencv emgucv template-matching

我需要从一个区域检测蠕虫的形状。

original image

我尝试使用许多功能从带阈值的固定图像中提取形状,但没有成功。 我注意到,我可以使用他的身体反射的光线看到蠕虫的形状,这种反射或多或少像一个C字母的小弧,具有许多方向和大小。 我检测到了这种反射,并用圆圈将其包围。

IMG1:如您所见,这是唯一具有弧形圆的区域

我试图创建一个模板库,以使用this article来识别所有'C'形式的相似性,并且效果很好,但是由于我的圈子组不够精确,轮廓analisys并不可靠。

然后我考虑将一个范围内的所有斜切圆合并以创建更易读的C形,但是我不知道该怎么做。

另一种选择是验证每个圆是否在一定范围内有另一个圆,验证是否存在3个或更多,并验证通过所有圆心的虚拟线的坐标是否会形成圆弧。情况下我可能有一个C。此外,我可以继续在找到的C圆周上向左和向右找到圆,以验证是否存在更多要整合为C形的圆。 我不确定最好的方法是什么,目前我很乐意验证是否有任何圆圈在附近,或者如何“融化”附近的圆圈以创建更整洁的身材。

我在EmguCv C#工作,但也接受phython的建议。 :)。 (请不要c++

我的英语致歉。

有关信息,这是绘制圆的功能。

// ************************************************************
private void BlobFind(Image<Bgr, byte> img)
{
    double dp = 0;
    double distMin = 0;
    double cannyThreshold = 0;
    double circleAccumulatorThreshold = 0;
    int circleRadiusMin = 0;
    int circleRadiusMax = 0;

    // pen for circles
    Pen penYellow = new Pen(new SolidBrush(Color.Yellow), 1);
    Pen penRed = new Pen(new SolidBrush(Color.Red), 3);
    Pen penGreen = new Pen(new SolidBrush(Color.Green), 3);
    Pen penWhite = new Pen(new SolidBrush(Color.White), 3);

    // *******************
    // circles coordinates list
    List<float> m_ListaCerchi = new List<float>();
    // *******************

    dp = (float)TbCannyAccumulator.Value / 10;
    distMin = TbCannyThresh.Value;

    cannyThreshold = tbWCCannyMin.Value;
    circleAccumulatorThreshold = tbWCCannyMax.Value;

    circleRadiusMin = TbCannyRadiusMin.Value;
    circleRadiusMax = TbCannyRadiusMax.Value;

    PictureBox pic = new PictureBox();

    //Convert the image to grayscale and filter out the noise
    UMat uimage = new UMat();    
    uimage = img.ToUMat();

    // gray conversion
    CvInvoke.CvtColor(uimage, uimage, ColorConversion.Bgr2Gray);

    // circle detection
    CircleF[] circles = CvInvoke.HoughCircles(uimage, HoughType.Gradient, dp, distMin, cannyThreshold, circleAccumulatorThreshold, circleRadiusMin, circleRadiusMax);

    if (circles.Length == 0) return;

    // circles draw
    Image<Bgr, Byte> circleImage = img.CopyBlank();

    Graphics g = pictureBox1.CreateGraphics();

    // circles coordinates
    m_CirclesList.Clear();

    int circlesCounter = 0;

    // found circles loop
    m_FlgEndAnalisis = false;

    foreach (CircleF circle in circles)
    {
        float trimRadius = float.Parse(nudtrimRadius.Value.ToString());

        // coordinate circle
        float radius = circle.Radius;
        radius += trimRadius;
        float x = circle.Center.X - radius;
        float y = circle.Center.Y - radius;
        float width = 2 * radius;
        float height = 2 * radius;

        bool FlgCompleteCircle = true;

        // verify if outbound circle
        if (circle.Center.X + radius > pictureBox1.Width ||
            circle.Center.X - radius < 0 ||
            circle.Center.Y + radius > pictureBox1.Height ||
            circle.Center.Y - radius < 0)
        {

            FlgCompleteCircle = false;
        }

        if (FlgCompleteCircle == false)    // outbound circle
        {
            x = circle.Center.X - radius;
            y = circle.Center.Y - radius;
            width = 2 * radius;
            height = 2 * radius;

            // draw outbound circle
            g.DrawEllipse(penRed, x, y, width, height);
        }

        // ***********************
        int X0 = (int)x;
        int Y0 = (int)y;
        int X1 = X0 + (int)radius * 2;
        int Y1 = Y0 + (int)radius * 2;

        // area to copy
        int wid = Math.Abs(X0 - X1);
        int hgt = Math.Abs(Y0 - Y1);

        if ((wid < 1) || (hgt < 1)) return;

        Bitmap area = new Bitmap(wid, hgt);

        using (Graphics gr = Graphics.FromImage(area))
        {
            Rectangle source_rectangle = new Rectangle(Math.Min(X0, X1), Math.Min(Y0, Y1), wid, hgt);
            Rectangle dest_rectangle = new Rectangle(0, 0, wid, hgt);

            gr.DrawImage(pictureBox1.Image, dest_rectangle, source_rectangle, GraphicsUnit.Pixel);
        }

        // OK
        Image<Gray, Byte> myImage = new Image<Gray, Byte>(area);

        Gray m_TargetColor;

        m_TargetColor = myImage.GetAverage();

        // *************************
        if (FlgCompleteCircle == true)
        {
            // if circle complete save coordinates
            circlesCounter++;

            float[] Circle_coord = { circlesCounter, x, y, radius };   // radius is always the same
            m_CirclesList.AddRange(Circle_coord);

            // draw circle number
            using (Font myFont = new Font("Arial", 12))
            {
                g.DrawString(circlesCounter.ToString(), myFont, Brushes.White, new Point((int)x + (int)radius - 10, (int)y + (int)radius - 20));
            }

            // draw main circle
            g.DrawEllipse(penWhite, x, y, width, height);
        }
    }

    m_FlgEndAnalisis = true;
}

0 个答案:

没有答案