Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I smooth the segmented blob?

I am getting some flickers (sharp lines) along with the segmented blob. How can I reduce them to make the boundary smoother? For more clarity, I have attached the image with input and expected output.

Note that, it is a binary image and I have no raw image (gray). The input is binary.

I have tried Gaussian blur but the method makes my shape smaller.

mask = ndimage.filters.gaussian_filter(mask, 0.5, order=0, output=None, mode='reflect', cval=0.0, truncate=5.0)

example input and expected output, as described above

like image 599
Moon Lee Avatar asked Dec 23 '22 02:12

Moon Lee


2 Answers

If your image defects are thin enough, you can try morphology operations: erosion, then dilation to restore overall form (with the same kernel size). This operation sequence is equivalent to morphologyEx opening

enter image description here

Note that edge of blob will smoother, but sometimes unwanted peculiarities might arise (in general it's impossible to enhance arbitrary picture without some distortions)

like image 60
MBo Avatar answered Dec 25 '22 16:12

MBo


To expand on MBo's answer:

The opening should be applied with a disk structuring element (kernel) to prevent directional bias.

The size of the disk dictates how much of the artifacts are removed. Below is the example image from the OP (left) and 5 opening results, with diameters of 7, 9, 11, 13 and 15 pixels. It seems to me that either 13 or 15 pixels are best for this case, though at 15 pixels there might be more detail being removed as well. Filtering noise is always a compromise between removing noise and preserving detail. The more noise is removed, the more detail is removed as well.

example image from OP with possible outputs

SciPy ndimage has an opening, to apply it with a disk structuring element do as follows:

diameter = 15
radius = diameter // 2
x = np.arange(-radius, radius+1)
x, y = np.meshgrid(x, x)
r = x**2 + y**2
se = r < radius**2
ndimage.binary_opening(img, se)

In this code, we first create a 1D array x that indicates the distance from the middle. np.meshgrid takes this array and creates two 2D arrays (images) containing the x and y coordinates with the origin in the middle of the image. The next line computes r, the squared distance to the origin. Finally we can obtain the structuring element se as all pixels within radius of the origin.

It is possible that OpenCV has an easier way of applying an opening with a disk. I'm suggesting SciPy ndimage because that is what is used in OP.

like image 36
Cris Luengo Avatar answered Dec 25 '22 16:12

Cris Luengo