diff --git a/dilation.jl b/dilation.jl deleted file mode 100644 index 5a89494..0000000 --- a/dilation.jl +++ /dev/null @@ -1,56 +0,0 @@ -using KernelAbstractions -""" -# Description: -The kernel performs binary dilation on a 5D tensor of shape -[batch_size, channels, depth, height, width] using a given -structuring element. Each voxel is checked against its neighborhood -as defined by the structuring element. - -""" -@kernel function dilate_kernel(output, input, struct_element) - I = @index(Global, Cartesian) - b, c, k, i, j = Tuple(I) - offset_h = div(size(struct_element)[1], 2) - offset_w = div(size(struct_element)[2], 2) - offset_d = div(size(struct_element)[3], 2) - - if b <= size(input)[1] && c <= size(input)[2] && k <= size(input)[3] && - i <= size(input)[4] && j <= size(input)[5] - - result = false - - for m in 1:size(struct_element)[1] - for n in 1:size(struct_element)[2] - for p in 1:size(struct_element)[3] - # actual coordinates in the 3D input image within the current batch and channel slice - # that the structuring element is currently influencing - ni = i + m - offset_h - 1 - nj = j + n - offset_w - 1 - nk = k + p - offset_d - 1 - - if 1 <= nk <= size(input)[3] && 1 <= ni <= size(input)[4] && - 1 <= nj <= size(input)[5] - - if input[b, c, nk, ni, nj] == 1 && struct_element[m, n, p] == 1 - result = true - break - end - end - end - if result; break; end - end - if result; break; end - end - - @inbounds output[b, c, k, i, j] = result ? 1 : 0 - end -end - -function dilate!(output, input, struct_element) - - backend = get_backend(input) - kernel! = dilate_kernel!(backend) - kernel!(output, input, struct_element, ndrange=size(output)) - - return output -end diff --git a/src/Batching_channeling/batching_channeling.jl b/src/Batching_channeling/batching_channeling.jl new file mode 100644 index 0000000..4b20547 --- /dev/null +++ b/src/Batching_channeling/batching_channeling.jl @@ -0,0 +1,22 @@ +using ITKIOWrapper + +function batching_channeling!(tensor5D, input_images, number_of_batches, number_of_channels) + expected_length = number_of_batches * number_of_channels + if length(input_images) != expected_length + error("Input image count mismatch: expected $(expected_length), got $(length(input_images)).") + end + + reshaped_input_images = reshape(input_images, (number_of_batches, number_of_channels)) + + for batch in 1:number_of_batches + for channel in 1:number_of_channels + image = reshaped_input_images[batch, channel] + metadata = load_spatial_metadata(image) + voxel_data = load_voxel_data(image, metadata) + arr = voxel_data.dat + arr_perm = permutedims(arr, (3, 1, 2)) # (depth, height, width) + tensor5D[batch, channel, :, :, :] .= arr_perm + end + end + return tensor5D +end \ No newline at end of file diff --git a/src/Morphology_operations/dilation.jl b/src/Morphology_operations/dilation.jl index 5a89494..375e7e2 100644 --- a/src/Morphology_operations/dilation.jl +++ b/src/Morphology_operations/dilation.jl @@ -3,7 +3,7 @@ using KernelAbstractions # Description: The kernel performs binary dilation on a 5D tensor of shape [batch_size, channels, depth, height, width] using a given -structuring element. Each voxel is checked against its neighborhood +structuring element of shape [depth, height, width]. Each voxel is checked against its neighborhood as defined by the structuring element. """ @@ -24,9 +24,9 @@ as defined by the structuring element. for p in 1:size(struct_element)[3] # actual coordinates in the 3D input image within the current batch and channel slice # that the structuring element is currently influencing - ni = i + m - offset_h - 1 - nj = j + n - offset_w - 1 - nk = k + p - offset_d - 1 + nk = k + m - offset_d -1 + ni = i + n - offset_h - 1 + nj = j + p - offset_w - 1 if 1 <= nk <= size(input)[3] && 1 <= ni <= size(input)[4] && 1 <= nj <= size(input)[5] diff --git a/src/Morphology_operations/erosion.jl b/src/Morphology_operations/erosion.jl new file mode 100644 index 0000000..112cf25 --- /dev/null +++ b/src/Morphology_operations/erosion.jl @@ -0,0 +1,50 @@ +using KernelAbstractions + +@kernel function erode_kernel!(output, input, struct_element) + I = @index(Global, Cartesian) + b, c, k, i, j = Tuple(I) + + offset_d = div(size(struct_element)[1], 2) + offset_h = div(size(struct_element)[2], 2) + offset_w = div(size(struct_element)[3], 2) + + if b <= size(input)[1] && c <= size(input)[2] && k <= size(input)[3] && + i <= size(input)[4] && j <= size(input)[5] + + result = true + + for m in 1:size(struct_element)[1] + for n in 1:size(struct_element)[2] + for p in 1:size(struct_element)[3] + nk = k + m - offset_d - 1 + ni = i + n - offset_h - 1 + nj = j + p - offset_w + + if 1 <= nk <= size(input)[3] && 1 <= ni <= size(input)[4] && + nj <= size(input)[5] + if struct_element[m, n, p] == 1 && input[b, c, nk, ni, nj] == 0 + result = false + break + end + else + # Treat out-of-bounds as 0 (zero-padding erosion) + if struct_element[m, n, p] == 1 + result = false + break + end + end + end + if !result; break; end + end + if !result; break; end + end + @inbounds output[b, c, k, i, j] = result ? 1 : 0 + end +end + +function erode!(output, input, struct_element) + backend = get_backend(input) + kernel! = erode_kernel!(backend) + kernel!(output, input, struct_element, ndrange=size(output)) + return output +end \ No newline at end of file