Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Function to fill interior holes #116

Open
mkitti opened this issue Dec 18, 2022 · 3 comments
Open

Function to fill interior holes #116

mkitti opened this issue Dec 18, 2022 · 3 comments

Comments

@mkitti
Copy link
Member

mkitti commented Dec 18, 2022

I would like to add a function that fills interior holes in binary images.

This is roughly equivalent to MATLAB's imfill with the 'holes' option specified.

This may also be similar to https://docs.scipy.org/doc/scipy/reference/generated/scipy.ndimage.binary_fill_holes.html

This is distinct from the current imfill here which uses a flood fill algorithm.

The algorithm to fill interior, black, holes is as follows.

  1. Find black pixels on the boundary of the image
  2. Invert the image so that holes and background are black, false.
  3. Use label_components to label the holes and background regions.
  4. Identify components that contain the black pixels on the boundary image identified in Step 1.
  5. The resulting image fills all the components containing black pixels on the boundary with black. All other pixels are white.

Here's a quick implementation.

julia> function imfill_interior_holes(I)
           boundary_pixels = filter(ci->(any(ci.I .∈ indices[1].I) || any(ci.I .∈ indices[end].I)) && !I[ci], indices)
           labels = label_components(.!I)
           background_labels = unique(labels[boundary_pixels])
           return labels .∉ Ref(background_labels)
       end
imfill_interior_holes (generic function with 1 method)

julia> I = falses(8,8); I[1:8,3:6] .= 1; I[[CartesianIndex(4,4), CartesianIndex(5,5)]] .= 0; I
8×8 BitMatrix:
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  0  1  1  0  0
 0  0  1  1  0  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0

julia> imfill_interior_holes(I)
8×8 BitMatrix:
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0

This a breakdown of the steps.

julia> I = falses(8,8); I[1:8,3:6] .= 1; I[[CartesianIndex(4,4), CartesianIndex(5,5)]] .= 0; I
8×8 BitMatrix:
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  0  1  1  0  0
 0  0  1  1  0  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0

julia> boundary_pixels = filter(ci->(any(ci.I .∈ indices[1].I) || any(ci.I .∈ indices[end].I)) && !I[ci], indices);

julia> labels = label_components(.!I)
8×8 Matrix{Int64}:
 1  1  0  0  0  0  4  4
 1  1  0  0  0  0  4  4
 1  1  0  0  0  0  4  4
 1  1  0  2  0  0  4  4
 1  1  0  0  3  0  4  4
 1  1  0  0  0  0  4  4
 1  1  0  0  0  0  4  4
 1  1  0  0  0  0  4  4

julia> background_labels = unique(labels[boundary_pixels])
2-element Vector{Int64}:
 1
 4

julia> labels .∉ Ref(background_labels)
8×8 BitMatrix:
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
 0  0  1  1  1  1  0  0
@ThomasRetornaz
Copy link
Collaborator

Hello o/ the generic and simplest way to achieve that is to use morphologycal reconstruction (mreconstruct in julia ops)
see img https://www.researchgate.net/figure/Fill-holes-transformation-Morphological-reconstruction-by-erosion-of-f-from-f-marker_fig2_259134752

@mkitti
Copy link
Member Author

mkitti commented Jan 2, 2023

Hello o/ the generic and simplest way to achieve that is to use morphologycal reconstruction (mreconstruct in julia ops) see img https://www.researchgate.net/figure/Fill-holes-transformation-Morphological-reconstruction-by-erosion-of-f-from-f-marker_fig2_259134752

That is one approach to the gray scale case.

@ThomasRetornaz
Copy link
Collaborator

The implem is generic see #119
May we could add a specific implem for binary case and/or specialize mreconstruct for binary case

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants