1818import torch
1919
2020from aind_exaspim_image_compression .machine_learning .unet3d import UNet
21- from aind_exaspim_image_compression .utils import img_util
2221
2322
2423def predict (
2524 img ,
2625 model ,
27- denoised = None ,
2826 batch_size = 32 ,
2927 normalization_percentiles = (0.5 , 99.9 ),
3028 patch_size = 64 ,
@@ -64,59 +62,49 @@ def predict(
6462 """
6563 # Preprocess image
6664 mn , mx = np .percentile (img , normalization_percentiles )
67- img = (img - mn ) / (mx - mn + 1e-5 )
65+ img = (img - mn ) / (mx - mn + 1e-8 )
6866 img = np .clip (img , 0 , 5 )
6967 while len (img .shape ) < 5 :
7068 img = img [np .newaxis , ...]
7169
7270 # Initializations
7371 patch_starts_generator = generate_patch_starts (img , patch_size , overlap )
7472 n_starts = count_patches (img , patch_size , overlap )
75- if denoised is None :
76- denoised = np .zeros_like (img )
73+ pbar = tqdm (total = n_starts , desc = "Denoise" ) if verbose else None
7774
7875 # Main
79- pbar = tqdm (total = n_starts , desc = "Denoise" ) if verbose else None
80- for i in range (0 , n_starts , batch_size ):
76+ accum_pred = np .zeros (img .shape [2 :])
77+ accum_wgt = np .zeros (img .shape [2 :])
78+ for _ in range (0 , n_starts , batch_size ):
8179 # Extract batch and run model
8280 starts = list (itertools .islice (patch_starts_generator , batch_size ))
8381 patches = _predict_batch (img , model , starts , patch_size , trim = trim )
8482
85- # Store result
83+ # Add batch predictions to result
8684 for patch , start in zip (patches , starts ):
87- start = [max (s + trim , 0 ) for s in start ]
88- end = [start [i ] + patch .shape [i ] for i in range (3 )]
89- end = [min (e , s ) for e , s in zip (end , img .shape [2 :])]
90- denoised [
91- 0 , 0 , start [0 ]:end [0 ], start [1 ]:end [1 ], start [2 ]:end [2 ]
92- ] = patch [: end [0 ] - start [0 ], : end [1 ] - start [1 ], : end [2 ] - start [2 ]]
85+ # Compute start and end coordinates
86+ s = [max (si + trim , 0 ) for si in start ]
87+ e = [
88+ min (si + pi , di )
89+ for si , pi , di in zip (s , patch .shape , img .shape [2 :])
90+ ]
91+
92+ # Create slices
93+ pred_slices = tuple (slice (si , ei ) for si , ei in zip (s , e ))
94+ patch_slices = tuple (slice (0 , ei - si ) for si , ei in zip (s , e ))
95+
96+ # Add patch prediction to result
97+ accum_pred [pred_slices ] += patch [patch_slices ]
98+ accum_wgt [pred_slices ] += 1
99+
93100 pbar .update (len (starts )) if verbose else None
94101
95- # Postprocess image
102+ # Postprocess prediction
103+ denoised = accum_pred [:, ...] / (accum_wgt + 1e-8 )
96104 denoised = np .clip (denoised * (mx - mn ) + mn , 0 , 2 ** 16 - 1 )
97105 return denoised .astype (np .uint16 )
98106
99107
100- def predict_largescale (
101- img ,
102- model ,
103- output_path ,
104- compressor ,
105- batch_size = 32 ,
106- normalization_percentiles = (0.5 , 99.9 ),
107- patch_size = 64 ,
108- overlap = 12 ,
109- output_chunks = (1 , 1 , 64 , 128 , 128 ),
110- trim = 5 ,
111- verbose = True
112- ):
113- # Initializations
114- denoised = img_util .init_ome_zarr (
115- img , output_path , compressor = compressor , chunks = output_chunks
116- )
117- predict (img , model , denoised = denoised )
118-
119-
120108def predict_patch (patch , model , normalization_percentiles = (0.5 , 99.9 )):
121109 """
122110 Denoises a single 3D patch using the provided model.
@@ -133,15 +121,15 @@ def predict_patch(patch, model, normalization_percentiles=(0.5, 99.9)):
133121
134122 Returns
135123 -------
136- numpy.ndarray
124+ pred : numpy.ndarray
137125 Denoised 3D patch with the same shape as input patch.
138126 """
139127 # Preprocess image
140128 mn , mx = np .percentile (patch , normalization_percentiles )
141- patch = (patch - mn ) / (mx - mn + 1e-5 )
129+ patch = (patch - mn ) / (mx - mn + 1e-8 )
142130 patch = np .clip (patch , 0 , 5 )
143- while len (img .shape ) < 5 :
144- img = img [np .newaxis , ...]
131+ while len (patch .shape ) < 5 :
132+ patch = patch [np .newaxis , ...]
145133
146134 # Run model
147135 patch = to_tensor (patch )
@@ -269,7 +257,7 @@ def load_model(path, device="cuda"):
269257
270258 Returns
271259 -------
272- torch.nn.Module
260+ model : torch.nn.Module
273261 UNet model loaded with weights and set to evaluation mode.
274262 """
275263 model = UNet ()
0 commit comments