Skip to content

Commit 22661a6

Browse files
authored
Merge pull request #168 from BrainLesion/166-feature-adjustment-for-ct-image-defacing
Updated defacer to either use minimum or custom value
2 parents 6878ce1 + 1f9cf2d commit 22661a6

File tree

2 files changed

+43
-23
lines changed

2 files changed

+43
-23
lines changed

brainles_preprocessing/defacing/defacer.py

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,41 @@
11
from abc import ABC, abstractmethod
22
from pathlib import Path
3-
from typing import Union
4-
3+
from typing import Union, Optional
4+
import numpy as np
55
from auxiliary.io import read_image, write_image
66

77

88
class Defacer(ABC):
9-
"""
10-
Base class for defacing medical images using brain masks.
11-
12-
Subclasses should implement the `deface` method to generate a defaced image
13-
based on the provided input image and mask.
14-
"""
15-
16-
@abstractmethod
17-
def deface(
9+
def __init__(
1810
self,
19-
input_image_path: Union[str, Path],
20-
mask_image_path: Union[str, Path],
21-
) -> None:
11+
masking_value: Optional[Union[int, float]] = None,
12+
):
2213
"""
23-
Generate a defacing mask provided an input image.
14+
Base class for defacing medical images using brain masks.
2415
25-
Args:
26-
input_image_path (str or Path): Path to the input image (NIfTI format).
27-
mask_image_path (str or Path): Path to the output mask image (NIfTI format).
16+
Subclasses should implement the `deface` method to generate a defaced image
17+
based on the provided input image and mask.
2818
"""
29-
pass
19+
# Here, masking value functions as a global value across all images and modalities
20+
# If no value is passed, the minimum of a given input image is chosen
21+
# TODO: Consider extending this to modality-specific masking values in the future, this should
22+
# probably be implemented as a property of the the specific modality
23+
self.masking_value = masking_value
24+
25+
@abstractmethod
26+
def deface(
27+
self,
28+
input_image_path: Union[str, Path],
29+
mask_image_path: Union[str, Path],
30+
) -> None:
31+
"""
32+
Generate a defacing mask provided an input image.
33+
34+
Args:
35+
input_image_path (str or Path): Path to the input image (NIfTI format).
36+
mask_image_path (str or Path): Path to the output mask image (NIfTI format).
37+
"""
38+
pass
3039

3140
def apply_mask(
3241
self,
@@ -63,8 +72,17 @@ def apply_mask(
6372
if input_data.shape != mask_data.shape:
6473
raise ValueError("Input image and mask must have the same dimensions.")
6574

66-
# Apply mask (element-wise multiplication)
67-
masked_data = input_data * mask_data
75+
# check whether a global masking value was passed, otherwise choose minimum
76+
if self.masking_value is None:
77+
current_masking_value = np.min(input_data)
78+
else:
79+
current_masking_value = (
80+
np.array(self.masking_value).astype(input_data.dtype).item()
81+
)
82+
# Apply mask (element-wise either input or masking value)
83+
masked_data = np.where(
84+
mask_data.astype(bool), input_data, current_masking_value
85+
)
6886

6987
# Save the defaced image
7088
write_image(

brainles_preprocessing/defacing/quickshear/quickshear.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from pathlib import Path
2-
from typing import Union
2+
from typing import Union, Optional
33

44
import nibabel as nib
55
from auxiliary.io import read_image, write_image
@@ -35,15 +35,17 @@ def __init__(
3535
buffer: float = 10.0,
3636
force_atlas_registration: bool = True,
3737
atlas_image_path: Union[str, Path, Atlas] = Atlas.SRI24,
38+
masking_value: Optional[Union[int, float]] = None,
3839
):
3940
"""Initialize Quickshear defacer
4041
4142
Args:
4243
buffer (float, optional): buffer parameter from quickshear algorithm. Defaults to 10.0.
4344
force_atlas_registration (bool, optional): If True, forces atlas registration of the BET mask before defacing to potentially boost quickshear performance. Defaults to True.
4445
atlas_image_path (Union[str, Path, Atlas], optional): Path to the atlas image or an Atlas enum value that will be used for the optional atlas registrations. Defaults to Atlas.SRI24.
46+
masking_value (Optional[Union[int, float]], optional): global value to be inserted in the masked areas. Default is None which leads to the minimum of each respective image.
4547
"""
46-
super().__init__()
48+
super().__init__(masking_value=masking_value)
4749
self.buffer = buffer
4850
self.force_atlas_registration = force_atlas_registration
4951
self.atlas_image_path = atlas_image_path

0 commit comments

Comments
 (0)