Non connecting morphological filter

前端 未结 2 456
故里飘歌
故里飘歌 2021-02-11 00:10

After some simple preprocessing I am receiving boolean mask of segmented images.

I want to \"enhance\" borders of the mask and make them more smooth. For that

2条回答
  •  野趣味
    野趣味 (楼主)
    2021-02-11 00:37

    Without applying a morphological filter first, you can try to detect the external contours of the image. Now you can draw these external contours as filled contours and then apply your morphological filter. This works because now you don't have any holes to fill. This is fairly simple.

    Another approach:

    • find external contours
    • take the x, y of coordinates of the contour points. you can consider these as 1-D signals and apply a smoothing filter to these signals

    In the code below, I've applied the second approach to a sample image.

    Input image

    External contours without any smoothing

    After applying a Gaussian filter to x and y 1-D signals

    C++ code

    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 > contours;
    vector 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 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 xFilt, yFilt;
        GaussianBlur(x, xFilt, Size(filterSize, filterSize), sigma, sigma);
        GaussianBlur(y, yFilt, Size(filterSize, filterSize), sigma, sigma);
        // build smoothed contour
        vector > smoothContours;
        vector 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;
    }
    

提交回复
热议问题