图像形态学操作

Morphological Operations On Image

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

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

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


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

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

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

然后你可以填充手的内部(此处为灰色):

并将原始图像中的所有值设置为 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;
    }