Smoothing Edges of a Binary Image

前端 未结 5 928
无人共我
无人共我 2020-12-23 22:32

How to smooth the edges of this binary image of blood vessels obtained after thresholding.

I tried a method somewhat similar to this method but did not qui

相关标签:
5条回答
  • 2020-12-23 23:09

    You can dilate then erode the areas http://docs.opencv.org/2.4/doc/tutorials/imgproc/erosion_dilatation/erosion_dilatation.html.

    import cv2
    import numpy as np
    blur=((3,3),1)
    erode_=(5,5)
    dilate_=(3, 3)
    cv2.imwrite('imgBool_erode_dilated_blured.png',cv2.dilate(cv2.erode(cv2.GaussianBlur(cv2.imread('so-br-in.png',0)/255, blur[0], blur[1]), np.ones(erode_)), np.ones(dilate_))*255)  
    

    EDIT whith a scale facor off 4 before the stuff

    0 讨论(0)
  • 2020-12-23 23:12

    Here is the result I obtained with your image:

    My method is mostly based on several cv::medianBlurapplied on a scaled-up image.

    Here is the code:

    cv::Mat vesselImage = cv::imread(filename); //the original image
    cv::threshold(vesselImage, vesselImage, 125, 255, THRESH_BINARY);
    cv::Mat blurredImage; //output of the algorithm
    cv::pyrUp(vesselImage, blurredImage);
    
    for (int i = 0; i < 15; i++)
        cv::medianBlur(blurredImage, blurredImage, 7);
    
    cv::pyrDown(blurredImage, blurredImage);
    cv::threshold(blurredImage, blurredImage, 200, 255, THRESH_BINARY);
    

    The jagged edges are due to the thresholding. If you are comfortable with an output image that is non-binary (i.e. with 256 shades of grAy), you can just remove it and you get this image:

    0 讨论(0)
  • 2020-12-23 23:14

    What you can do is increase the resolution of your image (e.g. double or triple it using resize). After that, erosion and dilation as described in the other answer above will lead to finer results.

    0 讨论(0)
  • 2020-12-23 23:19

    You most probably got a gray scale image of the blood vessels first and then thresholded. It still looks non-smooth because the original gray scale image had noise inside. Asking now for a smoothing of the edges will result in lower resolution. For example the dilution and erosion proposed in another answer might fuse neighboring vessels in the dilution step which then cannot be separated again in the erosion step.

    It might be preferable to remove the noise in the gray scale image first (aka do a smoothing there) and do the thresholding as the last step.

    Because you did not deliver the gray scale image I performed a mild smoothing (about one pixel width) here on the binary image and performed a thresholding again.

    I did a smoothing (with a Gaussian kernel of fixed size) and a thresholding (with a thresholding parameter). I suggest you do that on the grayscale image data and adjust the two parameters until you like the result.

    Matlab code in case it is of interest:

    % read
    img = imread('YyNQV.png');
    img = double(img(:, :, 1) ~= 255); % png is RGB -> binary
    
    % smooth
    kernel = fspecial('gaussian', 10, 1.5);
    kernel = kernel / sum(kernel(:)); % normalize to 1
    img_smooth = conv2(img, kernel, 'same');
    
    % binarize again
    threshold = 0.4; % experiment with values between 0 and 1
    img_smooth_threshold = img_smooth > threshold;
    
    % save (exchange black and white)
    imwrite(~img_smooth_threshold, 'YyNQV_smooth.png');
    
    0 讨论(0)
  • 2020-12-23 23:21

    i made some modifications on @dhanushka 's answer for another question and get these images.

    Sorry it is C++ code but maybe you will convert it to Python.

    You can change the parameters below to get different results.

    // contour smoothing parameters for gaussian filter
    int filterRadius = 10; // you can try to change this value
    int filterSize = 2 * filterRadius + 1;
    double sigma = 20; // you can try to change this value
    

    #include <opencv2/highgui.hpp>
    #include <opencv2/imgproc.hpp>
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    int main( int argc, const char** argv )
    {
        Mat im = imread(argv[1], 0);
    
        Mat cont = ~im;
        Mat original = Mat::zeros(im.rows, im.cols, CV_8UC3);
        Mat smoothed = Mat(im.rows, im.cols, CV_8UC3, Scalar(255,255,255));
    
        // 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 contours and store all contour points
        findContours(cont, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, Point(0, 0));
        for(size_t j = 0; j < contours.size(); j++)
        {
            // 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);
    
            Scalar color;
    
            if(hierarchy[j][3] < 0 )
            {
                color = Scalar(0,0,0);
            }
            else
            {
                color = Scalar(255,255,255);
            }
            drawContours(smoothed, smoothContours, 0, color, -1);
        }
        imshow( "result", smoothed );
        waitKey(0);
    }
    
    0 讨论(0)
提交回复
热议问题