图像的形态学运算 [英] Morphological Operations On Image

查看:351
本文介绍了图像的形态学运算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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





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

解决方案

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






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

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



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





然后你可以在里面填充洪水(灰色):





这是完整代码(再次,它是C ++):

  #include< opencv2 / opencv.hpp> 
使用命名空间cv;

int main(int,char **)
{
//加载灰度图像
Mat1b thresholded = imread(path_to_image,IMREAD_GRAYSCALE);

//摆脱JPEG压缩工件
thresholded = thresholded> 100;

//需要所以findContours正确处理边界轮廓
Mat1b bin;
copyMakeBorder(thresholded,bin,1,1,1,1,BORDER_CONSTANT,0);

//应用形态学操作关闭
Mat1b关闭;
Mat kernel = getStructuringElement(MORPH_ELLIPSE,Size(3,3));
morphologyEx(bin,closed,MORPH_OPEN,kernel);

//查找轮廓
vector< vector< Point>>轮廓;
findContours(bin.clone(),contours,RETR_EXTERNAL,CHAIN_APPROX_NONE,Point(-1,-1)); // Point(-1,-1)占先前copyMakeBorder

//保持最大轮廓
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(已关闭,dbg,COLOR_GRAY2BGR);


//黑色初始化掩码
Mat1b掩码(thresholded.rows,thresholded.cols,uchar(0));

if(idx_largest> = 0)
{
drawContours(dbg,contours,idx_largest,Scalar(0,255,0),CV_FILLED);

//在面具上绘制填充的多边形
drawContours(mask,contours,idx_largest,Scalar(255),1);
}

//在轮廓内获得一个点
时刻m =时刻(轮廓[idx_largest]);
Point2f里面(m.m10 / m.m00,m.m01 / m.m00);

floodFill(mask,inside,Scalar(127));

Mat3b结果;
cvtColor(thresholded,result,COLOR_GRAY2BGR);
result.setTo(Scalar(0),mask!= 127);


imshow(已关闭,已结束);
imshow(Contour,dbg);
imshow(结果,结果);
waitKey();

返回0;
}


I am currently doing a project in which I am trying to identify humans based on hands vascular pattern in C# using Emgu CV. The gray-scale image of the hand was first processed using the Adaptive Threshold function. Now I want to create a mask of the image using the morphological operations. The purpose is to remove the noise from the image. This is the adaptive-thresholded image:

Kindly guide me which function should I use and how to use.

解决方案

The code here is in C++. It shouldn't be difficult to port to C#, since it's mostly OpenCV functions calls. You can use that as guideline. Sorry about that.


You can apply a open operation with a small kernel to remove most of the noise:

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

As you can see, some noise is still present, and you can't remove it with other morphological operations. You can simply consider the largest blob as the correct one (in green here):

Then you can floodfill the inside of the hand (in gray here):

And set to 0 all values in original image where the corresponding mask in not the same color of the inside of the image:

This is the full code (again, it's 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;
    }

这篇关于图像的形态学运算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆