使用MatchShapes对带孔的连接组件进行Emgu对象检测

时间:2013-05-21 07:08:56

标签: c# opencv computer-vision detection emgucv

我一直致力于使用emgu进行形状匹配功能,用于检测给定对象模板的对象和用于查找对象模板的目标图像。目标图像可以包含模板的多个实例。

我建造的功能运作得相当好。我有一个问题。如果我的模板有多个孔,则该函数可能无法给出正确的答案。

以下是代码中最重要的部分:

private Image<Bgr, byte> DrawContours(Image<Gray, byte> image, Contour<Point> contours, Bgr color, int thickness, int maxLevel)
{
    Image<Bgr, Byte> resultImage = new Image<Bgr, byte>(image.Size);
    resultImage = image.Convert<Bgr, Byte>();
    CvInvoke.cvDrawContours(resultImage, contours, color.MCvScalar, color.MCvScalar, maxLevel, thickness, LINE_TYPE.CV_AA, new Point(0, 0));
    return resultImage;
}

private Contour<Point> GetEdgeContours(Image<Gray, byte> image, Image<Gray, byte> mask, int threshold)
{
    CvInvoke.cvThreshold(image, image, 255, 255, THRESH.CV_THRESH_BINARY | THRESH.CV_THRESH_OTSU);
    image = image.Dilate(3).Erode(3);
    Contour<Point> cont = image.FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_TC89_L1, RETR_TYPE.CV_RETR_CCOMP);
    return cont;
}

private Polygon MCvBox2D2Polygon(MCvBox2D box)
{
    System.Windows.Media.PointCollection polyPoints = new System.Windows.Media.PointCollection(); 
    foreach (var p in box.GetVertices())
        polyPoints.Add(new System.Windows.Point(p.X, p.Y));
    Polygon poly = new Polygon();
    poly.Points = polyPoints;
    return poly;
}

private bool ProcessShapeMatching(ref Image<Gray, Byte> templateImage ,  out Image<Gray, Byte> targetImage)
{
    positions = new List<Polygon>();
    Contour<Point> templateContours = GetEdgeContours(templateImage, null, 100);
    Contour<Point> targetContours = GetEdgeContours(targetImage, maskImage, 100);

    MCvBox2D box = templateContours.GetMinAreaRect();

    double precision = 0.0001;
    double distanceThreshold = 0.4;
    int nCCompLevels = 2; // connected components have 2 levels. 1 of the outer boundary en possibly 1 for the inner boundaries (holes)

    using (MemStorage storage = new MemStorage()) //allocate storage for contour approximation
    {
        //Find largest connected component countour in the template
        Contour<Point> templateContour = new Contour<Point>(storage);
        double largestArea = 0;
        for (Contour<Point> cont = templateContours; cont != null; cont = cont.HNext)
            if (cont.Area > largestArea)
                templateContour = cont;
        if (templateContour == null)
            throw new NullReferenceException("No contours found in the template image");

        // reduce the nr of vertices in the template polygons
        templateContour = templateContour.ApproxPoly(templateContour.Perimeter * precision, nCCompLevels, storage);

        // reduce the nr of  vertices in the target polygons
        if (templateContour.Area > targetImage.Height * targetImage.Width / 1000) //only consider contours plausible area
        {
            double distance = 0;
            for (Contour<Point> targetContour = targetContours; targetContour != null; targetContour = targetContour.HNext)
            {
                if (targetContour.Area < targetImage.Height * targetImage.Width / 1000) //only consider contours plausible area
                    continue;

                Contour<Point> approximatedTargetContour = targetContour.ApproxPoly(targetContour.Perimeter * precision, nCCompLevels, storage);
                distance += templateContour.MatchShapes(approximatedTargetContour, CONTOURS_MATCH_TYPE.CV_CONTOURS_MATCH_I3);

                ImageViewer.Show(DrawContours(targetImage, approximatedTargetContour, new Bgr(Color.Cyan), 2, 0), "contour");

                //This is the smelly part, it only works when the number of holes in the template is zero or one
                            // in the template and target shapes are the 
                if ((templateContour.VNext != null) && (targetContour.VNext != null))
                    distance += templateContour.MatchShapes(approximatedTargetContour, CONTOURS_MATCH_TYPE.CV_CONTOURS_MATCH_I3);
                if ((templateContour.VNext != null) && (targetContour.VNext == null))
                    continue; // no match
                if ((templateContour.VNext == null) && (targetContour.VNext != null))
                    continue; // no match
                //http://stackoverflow.com/questions/15555615/equivalent-of-hierarchy-in-emgu

                if (distance > distanceThreshold)
                    continue;

                // we have a match, let's add the position
                positions.Add(MCvBox2D2Polygon(targetContour.GetMinAreaRect()));

                // draw some annotation
                Image<Bgr, Byte> imageAnotated = DrawContours(targetImage, approximatedTargetContour, new Bgr(Color.Salmon), 2, nCCompLevels);
                MCvBox2D boxi = approximatedTargetContour.GetMinAreaRect();
                imageAnotated.Draw(boxi, new Bgr(Color.Turquoise), 2);
                ImageViewer.Show(imageAnotated, String.Format("current contour {0}", distance));
            }
        }
    }
    return false;
}

我希望得到一些关于如何比较我的形状内部的好建议,这意味着我连接组件中的漏洞。也许我有一些标准的方式可以忽略?

提前致谢!

0 个答案:

没有答案