|
import os, sys |
|
currentdir = os.path.dirname(os.path.realpath(__file__)) |
|
parentdir = os.path.dirname(currentdir) |
|
sys.path.append(parentdir) |
|
|
|
import h5py |
|
import nibabel as nib |
|
from nilearn.image import resample_img |
|
import re |
|
import numpy as np |
|
from scipy.ndimage import zoom |
|
from skimage.measure import regionprops |
|
from tqdm import tqdm |
|
from argparse import ArgumentParser |
|
from scipy.ndimage.morphology import binary_dilation, generate_binary_structure |
|
|
|
import pandas as pd |
|
|
|
from ddmr.utils import constants as C |
|
from ddmr.utils.misc import segmentation_cardinal_to_ohe, segmentation_ohe_to_cardinal |
|
|
|
SEGMENTATION_NR2LBL_LUT = {0: 'background', |
|
1: 'parenchyma', |
|
2: 'vessel'} |
|
SEGMENTATION_LBL2NR_LUT = {v: k for k, v in SEGMENTATION_NR2LBL_LUT.items()} |
|
|
|
IMG_DIRECTORY = '/mnt/EncryptedData1/Users/javier/ext_datasets/COMET_dataset/OSLO_COMET_CT/Volumes' |
|
SEG_DIRECTORY = '/mnt/EncryptedData1/Users/javier/ext_datasets/COMET_dataset/OSLO_COMET_CT/Segmentations' |
|
|
|
IMG_NAME_PATTERN = '(.*).nii.gz' |
|
SEG_NAME_PATTERN = '(.*).nii.gz' |
|
|
|
OUT_DIRECTORY = '/mnt/EncryptedData1/Users/javier/ext_datasets/COMET_dataset/OSLO_COMET_CT/Formatted_128x128x128/w_bboxes' |
|
|
|
|
|
if __name__ == '__main__': |
|
parser = ArgumentParser() |
|
parser.add_argument('--crop', action='store_true') |
|
parser.add_argument('--offset', type=int, default=C.MAX_AUG_DISP_ISOT + 10, help='Crop offset in mm') |
|
parser.add_argument('--dilate-segmentations', type=bool, default=False) |
|
args = parser.parse_args() |
|
|
|
img_list = [os.path.join(IMG_DIRECTORY, f) for f in os.listdir(IMG_DIRECTORY) if f.endswith('.nii.gz')] |
|
img_list.sort() |
|
|
|
seg_list = [os.path.join(SEG_DIRECTORY, f) for f in os.listdir(SEG_DIRECTORY) if f.endswith('.nii.gz')] |
|
seg_list.sort() |
|
|
|
zoom_file = pd.DataFrame(columns=['scale_i', 'scale_j', 'scale_k']) |
|
os.makedirs(OUT_DIRECTORY, exist_ok=True) |
|
binary_ball = generate_binary_structure(3, 1) |
|
for seg_file in tqdm(seg_list): |
|
img_name = re.match(SEG_NAME_PATTERN, os.path.split(seg_file)[-1])[1] |
|
img_file = os.path.join(IMG_DIRECTORY, img_name + '.nii.gz') |
|
|
|
img = resample_img(nib.load(img_file), np.eye(3)) |
|
seg = resample_img(nib.load(seg_file), np.eye(3), interpolation='nearest') |
|
|
|
img = np.asarray(img.dataobj) |
|
seg = np.asarray(seg.dataobj) |
|
|
|
segs_are_ohe = bool(len(seg.shape) > 3 and seg.shape[3] > 1) |
|
bbox = [0]*6 |
|
if args.crop: |
|
parenchyma = regionprops(seg[..., 0])[0] |
|
bbox = np.asarray(parenchyma.bbox) + [*[-args.offset]*3, *[args.offset]*3] |
|
|
|
bbox[:3] = np.maximum(bbox[:3], [0, 0, 0]) |
|
bbox[3:] = np.minimum(bbox[3:], img.shape) |
|
img = img[bbox[0]:bbox[3], bbox[1]:bbox[4], bbox[2]:bbox[5]] |
|
seg = seg[bbox[0]:bbox[3], bbox[1]:bbox[4], bbox[2]:bbox[5], ...] |
|
|
|
isot_shape = img.shape |
|
|
|
zoom_factors = (np.asarray([128]*3) / np.asarray(img.shape)).tolist() |
|
img_isotropic = np.copy(img) |
|
img = zoom(img, zoom_factors, order=3) |
|
if args.dilate_segmentations: |
|
seg = binary_dilation(seg, binary_ball, iterations=1) |
|
seg_isotropic = np.copy(seg) |
|
seg = zoom(seg, zoom_factors + [1]*(len(seg.shape) - len(img.shape)), order=0) |
|
zoom_file = zoom_file.append({'scale_i': zoom_factors[0], |
|
'scale_j': zoom_factors[1], |
|
'scale_k': zoom_factors[2]}, ignore_index=True) |
|
|
|
|
|
|
|
if segs_are_ohe: |
|
seg_expanded = seg.copy() |
|
seg = segmentation_ohe_to_cardinal(seg) |
|
else: |
|
seg_expanded = segmentation_cardinal_to_ohe(seg) |
|
|
|
h5_file = h5py.File(os.path.join(OUT_DIRECTORY, img_name + '.h5'), 'w') |
|
|
|
h5_file.create_dataset('image', data=img[..., np.newaxis], dtype=np.float32) |
|
h5_file.create_dataset('image_isotropic', data=img_isotropic[..., np.newaxis], dtype=np.float32) |
|
h5_file.create_dataset('segmentation_isotropic', data=seg_isotropic.astype(np.uint8), dtype=np.uint8) |
|
h5_file.create_dataset('segmentation', data=seg.astype(np.uint8), dtype=np.uint8) |
|
h5_file.create_dataset('segmentation_expanded', data=seg_expanded.astype(np.uint8), dtype=np.uint8) |
|
h5_file.create_dataset('segmentation_labels', data=np.unique(seg)[1:]) |
|
h5_file.create_dataset('isotropic_shape', data=isot_shape) |
|
if args.crop: |
|
h5_file.create_dataset('bounding_box_origin', data=bbox[:3]) |
|
h5_file.create_dataset('bounding_box_shape', data=bbox[3:] - bbox[:3]) |
|
print('{}: Segmentation labels {}'.format(img_name, np.unique(seg)[1:])) |
|
h5_file.close() |
|
|
|
zoom_file.to_csv(os.path.join(OUT_DIRECTORY, 'zoom_factors.csv')) |
|
print("Average") |
|
print(zoom_file.mean().to_list()) |
|
|
|
print("Standard deviation") |
|
print(zoom_file.std().to_list()) |
|
|
|
print("Average + STD") |
|
print((zoom_file.mean() + zoom_file.std()).to_list()) |
|
|
|
|
|
|
|
|