【问题标题】:Non connecting morphological filter非连接形态滤波器
【发布时间】:2016-04-04 07:11:28
【问题描述】:

经过一些简单的预处理后,我收到了分段图像的布尔掩码。

我想“增强”蒙版的边框并使其更平滑。为此,我使用带有相当大的圆形内核的 OPEN 形态滤波器,它工作得很好,直到分段对象之间的距离足够。但在很多样本中,物体粘在一起。是否存在一些或多或少简单的方法来平滑此类图像而不改变其形态?

【问题讨论】:

    标签: opencv image-processing computer-vision image-morphology


    【解决方案1】:

    在不先应用形态滤波器的情况下,您可以尝试检测图像的外部轮廓。现在您可以将这些外部轮廓绘制为填充轮廓,然后应用您的形态过滤器。这是有效的,因为现在您没有任何要填充的孔。这很简单。

    另一种方法:

    • 寻找外部轮廓
    • 取轮廓点坐标的x、y。您可以将这些信号视为一维信号,并对这些信号应用平滑滤波器

    在下面的代码中,我将第二种方法应用于示例图像。

    输入图像

    没有任何平滑的外部轮廓

    对 x 和 y 一维信号应用高斯滤波器后

    C++ 代码

    Mat im = imread("4.png", 0);
    
    Mat cont = im.clone();
    Mat original = Mat::zeros(im.rows, im.cols, CV_8UC3);
    Mat smoothed = Mat::zeros(im.rows, im.cols, CV_8UC3);
    
    // contour smoothing parameters for gaussian filter
    int filterRadius = 5;
    int filterSize = 2 * filterRadius + 1;
    double sigma = 10;      
    
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    // find external contours and store all contour points
    findContours(cont, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point(0, 0));
    for(size_t j = 0; j < contours.size(); j++)
    {
        // draw the initial contour shape
        drawContours(original, contours, j, Scalar(0, 255, 0), 1);
        // extract x and y coordinates of points. we'll consider these as 1-D signals
        // add circular padding to 1-D signals
        size_t len = contours[j].size() + 2 * filterRadius;
        size_t idx = (contours[j].size() - filterRadius);
        vector<float> x, y;
        for (size_t i = 0; i < len; i++)
        {
            x.push_back(contours[j][(idx + i) % contours[j].size()].x);
            y.push_back(contours[j][(idx + i) % contours[j].size()].y);
        }
        // filter 1-D signals
        vector<float> xFilt, yFilt;
        GaussianBlur(x, xFilt, Size(filterSize, filterSize), sigma, sigma);
        GaussianBlur(y, yFilt, Size(filterSize, filterSize), sigma, sigma);
        // build smoothed contour
        vector<vector<Point> > smoothContours;
        vector<Point> smooth;
        for (size_t i = filterRadius; i < contours[j].size() + filterRadius; i++)
        {
            smooth.push_back(Point(xFilt[i], yFilt[i]));
        }
        smoothContours.push_back(smooth);
    
        drawContours(smoothed, smoothContours, 0, Scalar(255, 0, 0), 1);
    
        cout << "debug contour " << j << " : " << contours[j].size() << ", " << smooth.size() << endl;
    }
    

    【讨论】:

      【解决方案2】:

      不是 100% 确定您要达到的目标,但这可能是一个探索的途径...potrace 工具获取图像并将它们转换为涉及平滑的矢量化图像。它更喜欢PGM 格式的输入文件,所以我使用 ImageMagick 来准备它们。无论如何,这里是一个命令示例和结果,看看你的想法:

      convert disks.png pgm:- | potrace - -s -o out.svg
      

      我已将生成的 SVG 文件转换为 PNG,因此我可以将其上传到 SO。

      【讨论】:

        猜你喜欢
        • 2014-07-14
        • 1970-01-01
        • 2017-01-18
        • 1970-01-01
        • 1970-01-01
        • 2011-07-05
        • 2014-04-29
        • 2018-01-02
        • 2016-09-10
        相关资源
        最近更新 更多