【问题标题】:Morphological Operations On Image图像的形态学运算
【发布时间】:2016-02-17 15:31:07
【问题描述】:

我目前正在做一个项目,我正在尝试使用 Emgu CV 根据 C# 中的手部血管模式识别人类。 首先使用自适应阈值函数处理手部的灰度图像。 现在我想使用形态学操作创建图像的蒙版。 目的是去除图像中的噪声。 这是自适应阈值图像:

请指导我应该使用哪个功能以及如何使用。

【问题讨论】:

    标签: c# opencv image-processing emgucv image-morphology


    【解决方案1】:

    这里的代码是 C++。移植到 C# 应该不难,因为它主要是 OpenCV 函数调用。您可以将其用作指导方针。对此感到抱歉。


    您可以使用小内核应用 open 操作来消除大部分噪音:

    Mat1b opened;
    Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
    morphologyEx(thresholded, opened, MORPH_OPEN, kernel);
    

    如您所见,一些噪声仍然存在,您无法通过其他形态学操作将其移除。您可以简单地将最大的 blob 视为正确的 blob(此处为绿色):

    然后你可以填充手的内侧(这里是灰色的):

    并将原始图像中对应蒙版与图像内部颜色不同的所​​有值设置为0:

    这是完整的代码(还是 C++):

            #include <opencv2/opencv.hpp>
        using namespace cv;
    
        int main(int, char**)
        {
            // Load grayscale image
            Mat1b thresholded = imread("path_to_image", IMREAD_GRAYSCALE);
    
            // Get rid of JPEG compression artifacts
            thresholded = thresholded > 100;
    
            // Needed so findContours handles borders contours correctly
            Mat1b bin;
            copyMakeBorder(thresholded, bin, 1,1,1,1, BORDER_CONSTANT, 0);
    
            // Apply morphological operation "close"
            Mat1b closed;
            Mat kernel = getStructuringElement(MORPH_ELLIPSE, Size(3, 3));
            morphologyEx(bin, closed, MORPH_OPEN, kernel);
    
            // Find contours
            vector<vector<Point>> contours;
            findContours(bin.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE, Point(-1,-1)); // Point(-1,-1) accounts for previous copyMakeBorder
    
            // Keep largest contour
            int size_largest = 0;
            int idx_largest = -1;
            for (int i = 0; i < contours.size(); ++i)
            {
                if (contours[i].size() > size_largest)
                {
                    size_largest = contours[i].size();
                    idx_largest = i;
                }
            }
    
            Mat3b dbg;
            cvtColor(closed, dbg, COLOR_GRAY2BGR);
    
    
            // Black initialized mask
            Mat1b mask(thresholded.rows, thresholded.cols, uchar(0));
    
            if (idx_largest >= 0)
            {
                drawContours(dbg, contours, idx_largest, Scalar(0, 255, 0), CV_FILLED);
    
                // Draw filled polygin on mask
                drawContours(mask, contours, idx_largest, Scalar(255), 1);
            }
    
            // Get a point inside the contour
            Moments m = moments(contours[idx_largest]);
            Point2f inside(m.m10 / m.m00, m.m01 / m.m00);
    
            floodFill(mask, inside, Scalar(127));
    
            Mat3b result;
            cvtColor(thresholded, result, COLOR_GRAY2BGR);
            result.setTo(Scalar(0), mask != 127);
    
    
            imshow("Closed", closed);
            imshow("Contour", dbg);
            imshow("Result", result);
            waitKey();
    
            return 0;
        }
    

    【讨论】:

    • 谢谢伙计。它有很大帮助。我面临的问题是,如果您看到原始图像,您会发现静脉位于细黑线中。用你的方法,手中的所有细节都消失了。我不想在去除手部区域之外的噪音时丢失这些细节。
    • 现在检查,让我知道
    • 好的。在多次尝试后,我会在一段时间内告诉你图像结果。
    • 我已经检查过了。有用。问题是有些函数不能在 C# 中使用。如何做到这一点
    • 很高兴它有效。对此没有任何想法。 C# 不是我的东西;D。 emgucv 不支持哪些功能?
    猜你喜欢
    • 2016-03-30
    • 2020-07-31
    • 2021-05-20
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 2020-01-30
    • 1970-01-01
    • 2012-03-27
    相关资源
    最近更新 更多