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

opencv - 非连接形态过滤器-LMLPHP

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

opencv - 非连接形态过滤器-LMLPHP

最佳答案

无需先应用形态过滤器,您可以尝试检测图像的外部轮廓。现在您可以将这些外部轮廓绘制为填充轮廓,然后应用您的形态过滤器。这是有效的,因为现在你没有任何洞可以填补。这相当简单。

另一种方法:

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

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

    输入图像

    opencv - 非连接形态过滤器-LMLPHP

    没有任何平滑的外部轮廓

    opencv - 非连接形态过滤器-LMLPHP

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

    opencv - 非连接形态过滤器-LMLPHP

    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;
    }
    

    关于opencv - 非连接形态过滤器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34527349/

    10-10 13:24