diff --git a/src/histogram_equalization.jl b/src/histogram_equalization.jl index 5ade5ab3..d4441d6f 100644 --- a/src/histogram_equalization.jl +++ b/src/histogram_equalization.jl @@ -4,6 +4,10 @@ function to_uint8(arr::AbstractMatrix{T}) where {T<:AbstractFloat} return img end +function to_uint8(arr::AbstractMatrix{T}) where {T<:Integer} + img = clamp.(arr, 0, 255) + return img +end function anisotropic_diffusion_3D(I) rgbchannels = get_rgb_channels(I) @@ -13,10 +17,11 @@ function anisotropic_diffusion_3D(I) end return rgbchannels - end -function anisotropic_diffusion_2D(I::AbstractMatrix{T}; gradient_threshold::Union{T,Nothing}=nothing, niter::Int=1) where {T} +function anisotropic_diffusion_2D( + I::AbstractMatrix{T}; gradient_threshold::Union{T,Nothing}=nothing, niter::Int=1 +) where {T} if eltype(I) <: Int I = Gray.(I ./ 255) end @@ -34,11 +39,13 @@ function anisotropic_diffusion_2D(I::AbstractMatrix{T}; gradient_threshold::Unio for _ in 1:niter # These are zero-indexed offset arrays - diff_img_north = padded_img[0:end-1, 1:end-1] .- padded_img[1:end, 1:end-1] - diff_img_east = padded_img[1:end-1, 1:end] .- padded_img[1:end-1, 0:end-1] - diff_img_nw = padded_img[0:end-2, 0:end-2] .- I - diff_img_ne = padded_img[0:end-2, 2:end] .- I - diff_img_sw = padded_img[2:end, 0:end-2] .- I + diff_img_north = + padded_img[0:(end - 1), 1:(end - 1)] .- padded_img[1:end, 1:(end - 1)] + diff_img_east = + padded_img[1:(end - 1), 1:end] .- padded_img[1:(end - 1), 0:(end - 1)] + diff_img_nw = padded_img[0:(end - 2), 0:(end - 2)] .- I + diff_img_ne = padded_img[0:(end - 2), 2:end] .- I + diff_img_sw = padded_img[2:end, 0:(end - 2)] .- I diff_img_se = padded_img[2:end, 2:end] .- I # Exponential conduction coefficients @@ -49,7 +56,6 @@ function anisotropic_diffusion_2D(I::AbstractMatrix{T}; gradient_threshold::Unio conduct_coeff_sw = exp.(-(abs.(diff_img_sw) ./ gradient_threshold) .^ 2) conduct_coeff_se = exp.(-(abs.(diff_img_se) ./ gradient_threshold) .^ 2) - # Flux calculations flux_north = conduct_coeff_north .* diff_img_north flux_east = conduct_coeff_east .* diff_img_east @@ -59,28 +65,24 @@ function anisotropic_diffusion_2D(I::AbstractMatrix{T}; gradient_threshold::Unio flux_se = conduct_coeff_se .* diff_img_se # Back to regular 1-indexed arrays - flux_north_diff = flux_north[1:end-1, :] .- flux_north[2:end, :] - flux_east_diff = flux_east[:, 2:end] .- flux_east[:, 1:end-1] + flux_north_diff = flux_north[1:(end - 1), :] .- flux_north[2:end, :] + flux_east_diff = flux_east[:, 2:end] .- flux_east[:, 1:(end - 1)] # Discrete PDE solution sum_ = (1 / (dd^2)) .* (flux_nw .+ flux_ne .+ flux_sw .+ flux_se) I = I .+ diffusion_rate .* (flux_north_diff .- flux_north_diff .+ sum_) - end return I end - function imshow(img) if typeof(img) <: BitMatrix return Gray.(img) end - Gray.(img ./ 255) + return Gray.(img ./ 255) end - - function adapthisteq(img::Matrix{T}, nbins=256, clip=0.01) where {T} # Step 1: Normalize the image to [0, 1] based on its own min and max image_min, image_max = minimum(img), maximum(img) @@ -88,13 +90,15 @@ function adapthisteq(img::Matrix{T}, nbins=256, clip=0.01) where {T} # Step 2: Apply adaptive histogram equalization. equalize_adapthist handles the tiling to 1/8 of the image size (equivalent to 8x8 blocks in MATLAB) equalized_image = sk_exposure.equalize_adapthist( - normalized_image, + normalized_image; clip_limit=clip, # Equivalent to MATLAB's 'ClipLimit' - nbins=nbins # Number of histogram bins. 255 is used to match the default in MATLAB script + nbins=nbins, # Number of histogram bins. 255 is used to match the default in MATLAB script ) # Step 3: Rescale the image back to the original range [image_min, image_max] - final_image = sk_exposure.rescale_intensity(equalized_image, in_range="image", out_range=(image_min, image_max)) + final_image = sk_exposure.rescale_intensity( + equalized_image; in_range="image", out_range=(image_min, image_max) + ) # Convert back to the original data type if necessary final_image = to_uint8(final_image) @@ -120,10 +124,9 @@ function get_rgb_channels(img) greenc = green.(img) * 255 bluec = blue.(img) * 255 - return cat(redc, greenc, bluec, dims=3) + return cat(redc, greenc, bluec; dims=3) end - function _process_image_tiles( true_color_image, clouds_red, @@ -156,7 +159,6 @@ function _process_image_tiles( return rgbchannels end - """ conditional_histeq( true_color_image, @@ -192,7 +194,7 @@ function conditional_histeq( white_threshold::AbstractFloat=25.5, white_fraction_threshold::AbstractFloat=0.4, ) - tiles = get_tiles(true_color_image, rblocks=rblocks, cblocks=cblocks) + tiles = get_tiles(true_color_image; rblocks=rblocks, cblocks=cblocks) rgbchannels_equalized = _process_image_tiles( true_color_image, clouds_red, @@ -203,7 +205,6 @@ function conditional_histeq( ) return rgbchannels_equalized - end """ @@ -227,7 +228,6 @@ function conditional_histeq( white_threshold::AbstractFloat=25.5, white_fraction_threshold::AbstractFloat=0.4, ) - side_length = IceFloeTracker.get_optimal_tile_size(side_length, size(true_color_image)) tiles = IceFloeTracker.get_tiles(true_color_image, side_length) @@ -242,16 +242,16 @@ function conditional_histeq( ) return rgbchannels_equalized - end -function _get_false_color_cloudmasked(; false_color_image, +function _get_false_color_cloudmasked(; + false_color_image, prelim_threshold=110.0, band_7_threshold=200.0, band_2_threshold=190.0, ) mask_cloud_ice, clouds_view = IceFloeTracker._get_masks( - false_color_image, + false_color_image; prelim_threshold=prelim_threshold, band_7_threshold=band_7_threshold, band_2_threshold=band_2_threshold,