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

feature: save labeled segmentations rather than binary segmentations #193

Closed
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
69991da
add step to label segmented floes
hollandjg Nov 5, 2024
cc12dfc
simplify test script to move into directory and run simpler commands …
hollandjg Nov 5, 2024
17318bc
add fixed point numbers dependency
hollandjg Nov 6, 2024
caca865
add label to props collected on floes
hollandjg Nov 6, 2024
c9f6f46
load FixedPointNumbers
hollandjg Nov 6, 2024
617dac1
update loading labeled floes
hollandjg Nov 6, 2024
211991f
fix type of Img to default for the dataframe to get around a type err…
hollandjg Nov 6, 2024
1656f56
update example file to use new filename
hollandjg Nov 6, 2024
d815d87
Merge branch 'jghrefactor/A2f-add-single-file-versions-of-cli-hdf5fil…
hollandjg Nov 6, 2024
1597b4a
Update IFTPipeline.jl/src/tracker.jl
hollandjg Nov 6, 2024
3d5f053
Update IFTPipeline.jl/src/preprocess.jl
hollandjg Nov 6, 2024
8bf8a24
add beginnings of functions to save and load labeled segmented images
hollandjg Nov 9, 2024
4d06328
feat: handle saving and loading integer images
hollandjg Nov 11, 2024
9cc594b
remove commented out code
hollandjg Nov 11, 2024
8e24794
add docstrings
hollandjg Nov 11, 2024
d932c5e
use image saving/loading for preprocess, tracker, h5
hollandjg Nov 11, 2024
16d8fa6
recast imgs to Int so they match the type of the labels in the props
hollandjg Nov 11, 2024
5dd478f
add recast to Image type based on Gray subtype
hollandjg Nov 11, 2024
1296d75
add cast to integer type when loading from gray
hollandjg Nov 11, 2024
973a454
convert just the labels rather than the image – more memory efficient
hollandjg Nov 11, 2024
9dadb45
update docs
hollandjg Nov 11, 2024
ce505e8
update extractfeatures_single to use the load_labeled_img function
hollandjg Nov 11, 2024
89bc5fc
remove debug message which ruins the output
hollandjg Nov 11, 2024
9f18d78
remove excess debug messages
hollandjg Nov 11, 2024
1adcbf3
remove label from feature extraction in batch mode
hollandjg Nov 11, 2024
5496c84
add option to extractfeatures to work with bool images
hollandjg Nov 11, 2024
1f9af06
update paths for batch processing test
hollandjg Nov 11, 2024
4ae04f8
don't cd – that breaks the IFT call
hollandjg Nov 11, 2024
753d0fa
simplify test save load definitions
hollandjg Nov 26, 2024
739e294
fix broken function definition
hollandjg Nov 26, 2024
d6b6ca4
Update IFTPipeline.jl/src/feature-extraction.jl
hollandjg Nov 26, 2024
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
2 changes: 2 additions & 0 deletions IFTPipeline.jl/Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ ArgParse = "c7e460c6-2fb9-53a9-8c5b-16f535851c63"
CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b"
CSVFiles = "5d742f6a-9f54-50ce-8119-2520741973ca"
FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549"
FixedPointNumbers = "53c48c17-4a7d-5ca2-90c5-79b7896eea93"
Folds = "41a02a25-b8f0-4f67-bc48-60067656b558"
HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"
IceFloeTracker = "04643c7a-9ac6-48c5-822f-2704f9e70bd3"
ImageSegmentation = "80713f31-8817-5129-9cf8-209ff8fb23e1"
Images = "916415d5-f1e6-5110-898d-aaa5f9f070e0"
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
LoggingExtras = "e6f89c97-d47a-5376-807f-9c37f3926c36"
Expand Down
2 changes: 2 additions & 0 deletions IFTPipeline.jl/src/IFTPipeline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ using Pkg
using FileIO
using Images
using CSV
using ImageSegmentation
using FixedPointNumbers

include("cli.jl")
include("soit-parser.jl")
Expand Down
4 changes: 2 additions & 2 deletions IFTPipeline.jl/src/cli.jl
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ function mkcliextract!(settings)

"--features", "-f"
help = """Features to extract. Format: "feature1 feature2". For an extensive list of extractable features see https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops:~:text=The%20following%20properties%20can%20be%20accessed%20as%20attributes%20or%20keys"""
default = "centroid area major_axis_length minor_axis_length convex_area bbox orientation perimeter"
default = "label centroid area major_axis_length minor_axis_length convex_area bbox orientation perimeter"
end
return nothing
end
Expand Down Expand Up @@ -104,7 +104,7 @@ function mkcliextract_single!(settings)
help = """Features to extract. Format: "feature1 feature2". For an extensive list of extractable features see https://scikit-image.org/docs/stable/api/skimage.measure.html#skimage.measure.regionprops:~:text=The%20following%20properties%20can%20be%20accessed%20as%20attributes%20or%20keys"""
nargs = '+'
arg_type = String
default = ["centroid", "area", "major_axis_length", "minor_axis_length", "convex_area", "bbox", "orientation", "perimeter"]
default = ["label", "centroid", "area", "major_axis_length", "minor_axis_length", "convex_area", "bbox", "orientation", "perimeter"]
end
return nothing
end
Expand Down
13 changes: 7 additions & 6 deletions IFTPipeline.jl/src/feature-extraction.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,16 @@ julia> IFTPipeline.extractfeatures(bw_img; minarea=minarea, maxarea=maxarea, fea
```
"""
function extractfeatures(
bw::T;
labeled_floes::AbstractArray{<:Integer};
minarea::Int64=350,
maxarea::Int64=90000,
features::Union{Vector{Symbol},Vector{<:AbstractString}}
)::DataFrame where {T<:AbstractArray{Bool}}
)::DataFrame
# assert the first area threshold is less than the second
minarea >= maxarea &&
throw(ArgumentError("The minimum area must be less than the maximum area."))

props = regionprops_table(label_components(bw, trues(3, 3)); properties=features)
props = regionprops_table(labeled_floes; properties=features)
hollandjg marked this conversation as resolved.
Show resolved Hide resolved

# filter by area using the area thresholds
return props[minarea.<=props.area.<=maxarea, :]
Expand Down Expand Up @@ -94,11 +94,12 @@ end
function extractfeatures_single(;
input::String, output::String, minarea::Int64, maxarea::Int64, features::Array{String}
)
@info "Loading segmented floes as a binarized image from $input"
segmented_floes = BitMatrix(FileIO.load(input))
@info "Loading segmented floes from $input"
image = FileIO.load(input)
labeled_floes = Int64.(reinterpret.(real.(image)))
hollandjg marked this conversation as resolved.
Show resolved Hide resolved

@info "Extracting features from each floe: $features"
props = IFTPipeline.extractfeatures(segmented_floes; minarea=minarea, maxarea=maxarea, features=features)
props = IFTPipeline.extractfeatures(labeled_floes; minarea=minarea, maxarea=maxarea, features=features)

@info "Extracted properties:"
@info props
Expand Down
9 changes: 7 additions & 2 deletions IFTPipeline.jl/src/preprocess.jl
Original file line number Diff line number Diff line change
Expand Up @@ -287,10 +287,15 @@ function preprocess_single(; truecolor::T, falsecolor::T, landmask::T, landmask_

@info "Segmenting floes started"
segmented_floes = preprocess(rgb_truecolor_img, rgb_falsecolor_img, landmask)
@info "Segmenting floes complete"
@debug "Segmenting floes complete: $segmented_floes"

@info "Labeling floes"
labeled_floes = label_components(segmented_floes)
labeled_floes_cast = convert(Array{choose_dtype(maximum(labeled_floes))}, labeled_floes)
hollandjg marked this conversation as resolved.
Show resolved Hide resolved
@debug "Labeled floes: $labeled_floes"

@info "Writing segmented floes to $output"
FileIO.save(output, segmented_floes)
FileIO.save(output, labeled_floes_cast)
hollandjg marked this conversation as resolved.
Show resolved Hide resolved

return nothing
end
2 changes: 1 addition & 1 deletion IFTPipeline.jl/src/tracker.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ function track_single(;

# Load the files – can we drop the memory requirements by doing two at once?
@info "Loading $imgs"
imgs_ = [Integer.(rawview(channelview((FileIO.load(img))))) for img in imgs]
imgs_ = [Int64.(rawview(channelview((FileIO.load(img))))) for img in imgs]
hollandjg marked this conversation as resolved.
Show resolved Hide resolved

@info "Loading $props"
props_ = [DataFrame(CSV.File(prop)) for prop in props]
Expand Down
34 changes: 18 additions & 16 deletions test/test-IFTPipeline.jl-cli.sh
hollandjg marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# Refs:
# - https://stackoverflow.com/a/28085062/24937841 and
# - https://unix.stackexchange.com/a/31712
: "${IFT:=julia --project=../IFTPipeline.jl ../IFTPipeline.jl/src/cli.jl}"
: "${IFT:=julia --project=`pwd`/../IFTPipeline.jl `pwd`/../IFTPipeline.jl/src/cli.jl}"
echo "IFT=${IFT}"

# Data target
Expand All @@ -21,32 +21,34 @@ echo "DATA_TARGET=${DATA_TARGET}"
echo "DATA_SOURCE=${DATA_SOURCE}"

cp -r ${DATA_SOURCE}/* ${DATA_TARGET}/
SAMPLEIMG=${DATA_TARGET}/20220914.terra.truecolor.250m.tiff
cd ${DATA_TARGET}
echo "in ${DATA_TARGET}"

SAMPLEIMG=20220914.terra.truecolor.250m.tiff

# Set up debug messages
export JULIA_DEBUG="Main,IFTPipeline,IceFloeTracker"

# Run the processing (single files)
LANDMASK=${DATA_TARGET}/landmask.tiff
LANDMASK_NON_DILATED=${DATA_TARGET}/landmask.non-dilated.tiff
LANDMASK_DILATED=${DATA_TARGET}/landmask.dilated.tiff
LANDMASK=landmask.tiff
LANDMASK_NON_DILATED=landmask.non-dilated.tiff
LANDMASK_DILATED=landmask.dilated.tiff

${IFT} landmask_single -i ${LANDMASK} -o ${LANDMASK_NON_DILATED} -d ${LANDMASK_DILATED}

for satellite in "aqua" "terra"
do
TRUECOLOR=${DATA_TARGET}/20220914.${satellite}.truecolor.250m.tiff
FALSECOLOR=${DATA_TARGET}/20220914.${satellite}.falsecolor.250m.tiff
SEGMENTED=${DATA_TARGET}/20220914.${satellite}.segmented.250m.tiff
FLOEPROPERTIES=${DATA_TARGET}/20220914.${satellite}.segmented.250m.props.csv
HDF5FILE=${DATA_TARGET}/20220914.${satellite}.h5
${IFT} preprocess_single --truecolor ${TRUECOLOR} --falsecolor ${FALSECOLOR} --landmask ${LANDMASK_NON_DILATED} --landmask-dilated ${LANDMASK_DILATED} --output ${SEGMENTED}
${IFT} extractfeatures_single --input ${SEGMENTED} --output ${FLOEPROPERTIES}
${IFT} makeh5files_single --passtime "2022-09-14T12:00:00" --truecolor ${TRUECOLOR} --falsecolor ${FALSECOLOR} --labeled ${SEGMENTED} --props ${FLOEPROPERTIES} --output ${HDF5FILE}
TRUECOLOR=20220914.${satellite}.truecolor.250m.tiff
FALSECOLOR=20220914.${satellite}.falsecolor.250m.tiff
LABELED=20220914.${satellite}.labeled.250m.tiff
FLOEPROPERTIES=20220914.${satellite}.labeled.250m.props.csv
HDF5FILE=20220914.${satellite}.h5
${IFT} preprocess_single --truecolor ${TRUECOLOR} --falsecolor ${FALSECOLOR} --landmask ${LANDMASK_NON_DILATED} --landmask-dilated ${LANDMASK_DILATED} --output ${LABELED}
${IFT} extractfeatures_single --input ${LABELED} --output ${FLOEPROPERTIES}
${IFT} makeh5files_single --passtime "2022-09-14T12:00:00" --truecolor ${TRUECOLOR} --falsecolor ${FALSECOLOR} --labeled ${LABELED} --props ${FLOEPROPERTIES} --output ${HDF5FILE}
done

${IFT} track_single --imgs ${DATA_TARGET}/20220914.{aqua,terra}.segmented.250m.tiff --props ${DATA_TARGET}/20220914.{aqua,terra}.segmented.250m.props.csv --latlon ${TRUECOLOR} --passtimes "2022-09-14T12:00:00" "2022-09-15T12:00:00" --output ${DATA_TARGET}/paired-floes.csv


${IFT} track_single --imgs 20220914.{aqua,terra}.labeled.250m.tiff --props 20220914.{aqua,terra}.labeled.250m.props.csv --latlon ${TRUECOLOR} --passtimes "2022-09-14T12:00:00" "2022-09-15T12:00:00" --output paired-floes.csv

# Run the processing (batch)
${IFT} landmask ${DATA_TARGET} ${DATA_TARGET}
Expand Down
Loading