如何使用EmguCV提取识别的内外轮廓?

问题描述 投票:0回答:1

我正在做一个使用图像处理处理脑损伤的项目。为了提高其准确性,我只需要从头骨中提取大脑物质。

使用 EmguCV 我能够识别内部和外部轮廓(蓝色和深蓝色)。有没有办法将这些识别的轮廓提取到另一幅图像中?

Image<Gray, byte> grayImage = new Image<Gray, byte>(bitmap);
Image<Bgr, byte> color = new Image<Bgr, byte>(bitmap);

grayImage = grayImage.ThresholdBinary(new Gray(220), new Gray(255));

using (MemStorage storage = new MemStorage())
{
    for (Contour<Point> contours = grayImage.FindContours(
        Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_TREE, storage); contours != null; contours = contours.HNext)
    {
        Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.015, storage);
        if (currentContour.BoundingRectangle.Width > 20)
        {
            CvInvoke.cvDrawContours(color, contours, new MCvScalar(100), new MCvScalar(255), -1, 2, Emgu.CV.CvEnum.LINE_TYPE.EIGHT_CONNECTED, new Point(0, 0));
        }
    }
}

EmguCV 2.2.2

预期输出:

c# image-processing contour emgucv medical
1个回答
0
投票

实现这一目标的一个好方法是使用掩码,如这个 C++ 示例中所示。我以这张图片为例:

它是根据 CC-NC-SA 许可证获得许可的,请参阅源网站。 首先使用

CvInvoke.FindContours
提取头骨的内部轮廓:

然后根据内部轮廓使用

CvInvoke.FillPoly
创建蒙版:

最后你可以将原始图像复制到蒙版图像中,你将只得到头骨的内部。

完整代码可在此处获取。请注意,我使用 EmguCV 4.8.1,因此需要进行一些更改。

using System.Drawing;
using System.IO;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;

namespace emgutest
{
    class Program
    {
        private static string testFile = "test.jpg";

        static void Main(string[] args)
        {
            Bitmap testImage;

            using (var stream = new FileStream(testFile, FileMode.Open))
            {
                testImage = (Bitmap)Image.FromStream(stream);
            }

            var color = testImage.ToImage<Bgr, byte>();
            var grayImage = color.Convert<Gray, byte>();

            grayImage = grayImage.ThresholdBinary(new Gray(220), new Gray(255));

            // Extract contour
            VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
            Mat hierarchy = new Mat();

            CvInvoke.FindContours(grayImage, contours, hierarchy, RetrType.Tree, ChainApproxMethod.ChainApproxSimple);

            // Draw contour on original image
            var color_contour = color.Copy();
            CvInvoke.DrawContours(color_contour, contours, 1, new MCvScalar(255, 0, 0), 2);  // Inner contour (-1 for all, 0 for outer)

            color_contour.Save("output_contour.jpg");

            // Create mask
            Mat output_image = color.Mat;
            VectorOfVectorOfPoint inner_contours = new VectorOfVectorOfPoint(contours[1]);  // Select inner contour only

            Mat blackedOut = new Mat(color.Size, DepthType.Cv8U, 3);
            blackedOut.SetTo(new MCvScalar(0, 0, 0));  // Full black image

            Mat mask = new Mat(grayImage.Size, DepthType.Cv8U, 1);
            CvInvoke.FillPoly(mask, inner_contours, new MCvScalar(255), LineType.AntiAlias);
            CvInvoke.DrawContours(mask, contours, -1, new MCvScalar(0), 2, LineType.Filled);

            // Copy image to mask
            output_image.CopyTo(blackedOut, mask);

            blackedOut.Save("output.jpg");

        }
    }
}

© www.soinside.com 2019 - 2024. All rights reserved.