Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/IceFloeTracker.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ end

Module for morphological operations with structuring element functionality adapted from ImageMorphology v0.4.3.

This module is temporary until v0.5 of ImageMorphology is relaeased.
This module is temporary until v0.5 of ImageMorphology is released.

Main functionality is `dilate(img, se)` for landmask computations.

Expand Down Expand Up @@ -136,5 +136,6 @@ module MorphSE
include("morphSE/closing.jl")
include("morphSE/bothat.jl")
include("morphSE/mreconstruct.jl")
include("morphSE/fill_holes.jl")
end
end
57 changes: 57 additions & 0 deletions src/morphSE/fill_holes.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# From https://github.com/JuliaImages/ImageMorphology.jl/pull/119

"""
fill_holes(img; [dims])
fill_holes(img; se)
Fill the holes in image 'img'. Could be binary or grascale
The `dims` keyword is used to specify the dimension to process by constructing the box shape
structuring element [`strel_box(img; dims)`](@ref strel_box). For generic structuring
element, the half-size is expected to be either `0` or `1` along each dimension.
The output has the same type as input image
"""

function fill_holes(img; dims=coords_spatial(img))
return fill_holes(img, strel_box(img, dims))
end

function fill_holes(img, se)
return fill_holes!(similar(img), img, se)
end

function fill_holes!(out, img; dims=coords_spatial(img))
return fill_holes!(out, img, strel_box(img, dims))
end

function fill_holes!(out, img, se)
return _fill_holes!(out, img, se)
end

function _fill_holes!(out, img, se)
N = ndims(img)

axes(out) == axes(img) || throw(DimensionMismatch("images should have the same axes"))

se_size = strel_size(se)
if length(se_size) != N
msg = "the input structuring element is not for $N dimensional array, instead it is for $(length(se_size)) dimensional array"
throw(DimensionMismatch(msg))
end
if !all(x -> in(x, (1, 3)), strel_size(se))
msg = "structuring element with half-size larger than 1 is invalid"
throw(DimensionMismatch(msg))
end

tmp = similar(img)

# fill marker image with max
fill!(tmp, typemax(eltype(img)))
# fill borders with 0
dimensions = size(tmp)
outerrange = CartesianIndices(map(i -> 1:i, dimensions))
innerrange = CartesianIndices(map(i -> (1 + 1):(i - 1), dimensions))
for i in EdgeIterator(outerrange, innerrange)
tmp[i] = 0
end

return mreconstruct!(erode, out, tmp, img, se)
end
4 changes: 2 additions & 2 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ testnames = [n[6:(end - 3)] for n in alltests]

## Put the filenames to test below

to_test = #alltests # uncomment this line to run all tests or add individual files below
to_test = alltests # uncomment this line to run all tests or add individual files below
[
# "test-create-landmask.jl",
# "test-create-cloudmask.jl",
Expand All @@ -30,7 +30,7 @@ to_test = #alltests # uncomment this line to run all tests or add individual fil
# "test-segmentation-b.jl",
# "test-segmentation-c.jl",
# "test-segmentation-d-e.jl",
"test-segmentation-f.jl",
# "test-segmentation-f.jl",
# "test-bwtraceboundary.jl",
# "test-resample-boundary.jl",
# "test-regionprops.jl",
Expand Down
12 changes: 11 additions & 1 deletion test/test-morphSE.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,31 @@
se = IceFloeTracker.MorphSE.strel_box((n, n))
@test IceFloeTracker.MorphSE.dilate(a, se) == ones(Int, n, n)

# Bothat, opening, erode using output from Matlab
# Bothat, opening, erode, filling holes, reconstruction using output from Matlab
A = zeros(Bool, 41, 41)
A[(21 - 10):(21 + 10), (21 - 10):(21 + 10)] .= 1
I = falses(8, 8)
I[1:8, 3:6] .= 1
I[[CartesianIndex(4, 4), CartesianIndex(5, 5)]] .= 0
I
se = centered(IceFloeTracker.se_disk4())

#read in expected files from MATLAB
path = joinpath(test_data_dir, "morphSE")
erode_withse_exp = readdlm(joinpath(path, "erode_withse1_exp.csv"), ',', Bool)
bothat_withse_exp = readdlm(joinpath(path, "bothat_withse1_exp.csv"), ',', Bool)
open_withse_exp = readdlm(joinpath(path, "open_withse1_exp.csv"), ',', Bool)
reconstruct_exp = readdlm(joinpath(path, "reconstruct_exp.csv"), ',', Int64)
matrix_A = readdlm(joinpath(path, "mat_a.csv"), ',', Int64)
matrix_B = readdlm(joinpath(path, "mat_b.csv"), ',', Int64)
filled_holes_exp = readdlm(joinpath(path, "filled_holes.csv"), ',', Int64)

#run tests
@test open_withse_exp == IceFloeTracker.MorphSE.opening(A, se)
@test erode_withse_exp == IceFloeTracker.MorphSE.erode(A, se)
@test bothat_withse_exp == IceFloeTracker.MorphSE.bothat(A, se)
@test reconstruct_exp == IceFloeTracker.MorphSE.mreconstruct(
IceFloeTracker.MorphSE.dilate, matrix_B, matrix_A
)
@test filled_holes_exp == IceFloeTracker.MorphSE.fill_holes(I)
end
8 changes: 4 additions & 4 deletions test/test-segmentation-f.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@

## Load inputs for comparison
segmentation_B_not_ice_mask = float64.(load("$(test_data_dir)/matlab_not_ice_mask.png"))
segmentation_C_ice_mask = load(segmented_c_test_file) .>= 0.5
segmentation_C_ice_mask = load(segmented_c_test_file) .> 0
cloudmask = convert(BitMatrix, load(cloudmask_test_file))
landmask = convert(BitMatrix, load(current_landmask_file))
watershed_intersect = load(watershed_test_file) .>= 0.5
watershed_intersect = load(watershed_test_file) .> 0
ice_labels =
Int64.(
vec(DelimitedFiles.readdlm("$(test_data_dir)/ice_labels_floe_region.csv", ','))
)
matlab_isolated_floes =
float64.(load("$(test_data_dir)/matlab_isolated_floes.png")) .>= 0.5
float64.(load("$(test_data_dir)/matlab_isolated_floes.png")) .> 0

## Run function with Matlab inputs

Expand All @@ -34,6 +34,6 @@

@test typeof(isolated_floes) == typeof(matlab_isolated_floes)
@test test_similarity(
isolated_floes, matlab_isolated_floes[ice_floe_test_region...], 0.033
isolated_floes, matlab_isolated_floes[ice_floe_test_region...], 0.035
)
end
8 changes: 8 additions & 0 deletions test/test_inputs/morphSE/filled_holes.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
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