-
Notifications
You must be signed in to change notification settings - Fork 22
Open
Description
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.
- Find black pixels on the boundary of the image
- Invert the image so that holes and background are black,
false. - Use
label_componentsto label the holes and background regions. - Identify components that contain the black pixels on the boundary image identified in Step 1.
- 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 0This 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 0Metadata
Metadata
Assignees
Labels
No labels