|
a |
|
b/utils/preprocess.py |
|
|
1 |
import os |
|
|
2 |
import SimpleITK as sitk |
|
|
3 |
import numpy as np |
|
|
4 |
from skimage import exposure |
|
|
5 |
|
|
|
6 |
def anisotropic_diffusion_denoise_3d(input_volume, conductance_parameter, time_step, number_of_iterations): |
|
|
7 |
''' |
|
|
8 |
Denoise the input volume using anisotropic diffusion. |
|
|
9 |
|
|
|
10 |
Args: |
|
|
11 |
input_volume ('SimpleITK Image'): Input volume. |
|
|
12 |
conductance_parameter ('float'): Conductance parameter. |
|
|
13 |
time_step ('float'): Time step. |
|
|
14 |
number_of_iterations ('int'): Number of iterations. |
|
|
15 |
|
|
|
16 |
Returns: |
|
|
17 |
output_volume ('SimpleITK Image'): Denoised volume. |
|
|
18 |
|
|
|
19 |
''' |
|
|
20 |
# Convert the input volume to float |
|
|
21 |
input_volume_float = sitk.Cast(input_volume, sitk.sitkFloat32) |
|
|
22 |
|
|
|
23 |
anisotropic_diffusion = sitk.GradientAnisotropicDiffusionImageFilter() |
|
|
24 |
anisotropic_diffusion.SetConductanceParameter(conductance_parameter) |
|
|
25 |
anisotropic_diffusion.SetTimeStep(time_step) |
|
|
26 |
anisotropic_diffusion.SetNumberOfIterations(number_of_iterations) |
|
|
27 |
|
|
|
28 |
output_volume_float = anisotropic_diffusion.Execute(input_volume_float) |
|
|
29 |
output_volume = sitk.Cast(output_volume_float, sitk.sitkInt16) |
|
|
30 |
|
|
|
31 |
return output_volume |
|
|
32 |
|
|
|
33 |
def bilateral_filter_3d(input_volume, domain_sigma, range_sigma): |
|
|
34 |
''' |
|
|
35 |
Apply bilateral filter to the input volume. |
|
|
36 |
|
|
|
37 |
Args: |
|
|
38 |
input_volume ('SimpleITK Image'): Input volume. |
|
|
39 |
domain_sigma ('float'): Domain sigma. |
|
|
40 |
range_sigma ('float'): Range sigma. |
|
|
41 |
|
|
|
42 |
Returns: |
|
|
43 |
output_volume ('SimpleITK Image'): Filtered volume. |
|
|
44 |
''' |
|
|
45 |
filtered_slices = [] |
|
|
46 |
|
|
|
47 |
for z in range(input_volume.GetDepth()): |
|
|
48 |
# Get 2D slice |
|
|
49 |
input_slice = sitk.Extract(input_volume, (input_volume.GetWidth(), input_volume.GetHeight(), 1), (0, 0, z)) |
|
|
50 |
|
|
|
51 |
# Apply bilateral filter to the 2D slice |
|
|
52 |
bilateral_filter = sitk.BilateralImageFilter() |
|
|
53 |
bilateral_filter.SetDomainSigma(domain_sigma) |
|
|
54 |
bilateral_filter.SetRangeSigma(range_sigma) |
|
|
55 |
output_slice = bilateral_filter.Execute(input_slice) |
|
|
56 |
|
|
|
57 |
# Append the filtered slice to the list |
|
|
58 |
filtered_slices.append(sitk.GetArrayFromImage(output_slice)[0]) # [0] to get the slice from the 3D volume |
|
|
59 |
|
|
|
60 |
# Convert the list of slices to a NumPy array |
|
|
61 |
filtered_slices_array = np.array(filtered_slices) |
|
|
62 |
output_volume = sitk.GetImageFromArray(filtered_slices_array) |
|
|
63 |
|
|
|
64 |
# Copy the information from the input volume to the output volume |
|
|
65 |
output_volume.CopyInformation(input_volume) |
|
|
66 |
|
|
|
67 |
return output_volume |
|
|
68 |
|
|
|
69 |
|
|
|
70 |
def clahe_3d(input_volume, clip_limit=0.1): |
|
|
71 |
""" |
|
|
72 |
Apply Contrast Limited Adaptive Histogram Equalization (CLAHE) to a 3D image. |
|
|
73 |
|
|
|
74 |
Args: |
|
|
75 |
input_volume (SimpleITK Image): The input image. |
|
|
76 |
|
|
|
77 |
Returns: |
|
|
78 |
SimpleITK Image: The output image after applying CLAHE. |
|
|
79 |
""" |
|
|
80 |
# Get the minimum and maximum intensity values of the input image |
|
|
81 |
min_max_filter = sitk.MinimumMaximumImageFilter() |
|
|
82 |
min_max_filter.Execute(input_volume) |
|
|
83 |
|
|
|
84 |
original_min = min_max_filter.GetMinimum() |
|
|
85 |
original_max = min_max_filter.GetMaximum() |
|
|
86 |
|
|
|
87 |
# Get the dimensions of the 3D volume |
|
|
88 |
size_x, size_y, size_z = input_volume.GetSize() |
|
|
89 |
|
|
|
90 |
# Determine kernel sizes in each dim relative to image shape |
|
|
91 |
kernel_size = (size_x // 5, size_y // 5, size_z // 2) |
|
|
92 |
|
|
|
93 |
# get the image from the input volume |
|
|
94 |
input_volume_image = sitk.GetArrayFromImage(input_volume) |
|
|
95 |
|
|
|
96 |
# Normalize intensity values to the range [0, 1] |
|
|
97 |
# input_volume_normalized = sitk.RescaleIntensity(input_volume_image, outputMinimum=0, outputMaximum=1) |
|
|
98 |
input_volume_normalized = exposure.rescale_intensity(input_volume_image, in_range='image', out_range=(0, 1)) |
|
|
99 |
|
|
|
100 |
# Apply CLAHE to the normalized image |
|
|
101 |
input_volume_enhanced = exposure.equalize_adapthist(input_volume_normalized, kernel_size=kernel_size, clip_limit=clip_limit) |
|
|
102 |
|
|
|
103 |
# Rescale intensity values to the original range |
|
|
104 |
input_volume_rescaled = exposure.rescale_intensity(input_volume_enhanced, in_range='image', out_range=(original_min, original_max)) |
|
|
105 |
|
|
|
106 |
# Convert the NumPy array to a SimpleITK image |
|
|
107 |
output_result = sitk.GetImageFromArray(input_volume_rescaled) |
|
|
108 |
output_result.CopyInformation(input_volume) |
|
|
109 |
|
|
|
110 |
return output_result |