|
a |
|
b/rocaseg/resample.py |
|
|
1 |
import os |
|
|
2 |
import click |
|
|
3 |
from tqdm import tqdm |
|
|
4 |
|
|
|
5 |
import numpy as np |
|
|
6 |
import pandas as pd |
|
|
7 |
import cv2 |
|
|
8 |
|
|
|
9 |
|
|
|
10 |
@click.command() |
|
|
11 |
@click.option('--path_root_in', help='E.g. data/31_OKOA_full_meta') |
|
|
12 |
@click.option('--spacing_in', nargs=2, default=(0.5859375, 0.5859375)) |
|
|
13 |
@click.option('--path_root_out', help='E.g. data/32_OKOA_full_meta_rescaled') |
|
|
14 |
@click.option('--spacing_out', nargs=2, default=(0.36458333, 0.36458333)) |
|
|
15 |
@click.option('--dirname_images', default='images') |
|
|
16 |
@click.option('--dirname_masks', default='masks') |
|
|
17 |
@click.option('--num_threads', default=12, type=click.IntRange(-1, 12)) |
|
|
18 |
@click.option('--margin', default=0, type=int) |
|
|
19 |
@click.option('--update_meta', is_flag=True) |
|
|
20 |
def main(**config): |
|
|
21 |
# Get the index of image files and the corresponding metadata |
|
|
22 |
path_meta = os.path.join(config['path_root_in'], 'meta_base.csv') |
|
|
23 |
if os.path.exists(path_meta): |
|
|
24 |
pass |
|
|
25 |
else: |
|
|
26 |
path_meta = os.path.join(config['path_root_in'], 'meta_dynamic.csv') |
|
|
27 |
|
|
|
28 |
df_meta = pd.read_csv(path_meta, |
|
|
29 |
dtype={'patient': str, |
|
|
30 |
'release': str, |
|
|
31 |
'prefix_var': str, |
|
|
32 |
'sequence': str, |
|
|
33 |
'side': str, |
|
|
34 |
'slice_idx': int, |
|
|
35 |
'pixel_spacing_0': float, |
|
|
36 |
'pixel_spacing_1': float, |
|
|
37 |
'slice_thickness': float, |
|
|
38 |
'KL': int, |
|
|
39 |
'has_mask': int}, |
|
|
40 |
index_col=False) |
|
|
41 |
|
|
|
42 |
df_in = df_meta.sort_values(['patient', 'release', 'sequence', 'side', 'slice_idx']) |
|
|
43 |
|
|
|
44 |
ratio = (np.asarray(config['spacing_in']) / |
|
|
45 |
np.asarray(config['spacing_out'])) |
|
|
46 |
|
|
|
47 |
groupers_stack = ['patient', 'release', 'sequence', 'side', 'slice_idx'] |
|
|
48 |
|
|
|
49 |
# Resample images |
|
|
50 |
if config['dirname_images'] is not None: |
|
|
51 |
for name_gb, df_gb in tqdm(df_in.groupby(groupers_stack), desc='Resample images'): |
|
|
52 |
patient, release, sequence, side, slice_idx = name_gb |
|
|
53 |
|
|
|
54 |
fn_base = f'{slice_idx:03d}.png' |
|
|
55 |
dir_in = os.path.join(config['path_root_in'], |
|
|
56 |
patient, release, sequence, |
|
|
57 |
config['dirname_images']) |
|
|
58 |
dir_out = os.path.join(config['path_root_out'], |
|
|
59 |
patient, release, sequence, |
|
|
60 |
config['dirname_images']) |
|
|
61 |
os.makedirs(dir_out, exist_ok=True) |
|
|
62 |
|
|
|
63 |
path_in = os.path.join(dir_in, fn_base) |
|
|
64 |
path_out = os.path.join(dir_out, fn_base) |
|
|
65 |
|
|
|
66 |
img_in = cv2.imread(path_in, cv2.IMREAD_GRAYSCALE) |
|
|
67 |
|
|
|
68 |
if config['margin'] == 0: |
|
|
69 |
tmp = img_in |
|
|
70 |
else: |
|
|
71 |
tmp = img_in[config['margin']:-config['margin'], |
|
|
72 |
config['margin']:-config['margin']] |
|
|
73 |
|
|
|
74 |
shape_out = tuple(np.floor(tmp.shape * ratio).astype(np.int))[::-1] |
|
|
75 |
tmp = cv2.resize(tmp, shape_out) |
|
|
76 |
img_out = tmp |
|
|
77 |
|
|
|
78 |
cv2.imwrite(path_out, img_out) |
|
|
79 |
|
|
|
80 |
# Resample masks |
|
|
81 |
if config['dirname_masks'] is not None: |
|
|
82 |
for name_gb, df_gb in tqdm(df_in.groupby(groupers_stack), desc='Resample masks'): |
|
|
83 |
patient, release, sequence, side, slice_idx = name_gb |
|
|
84 |
|
|
|
85 |
fn_base = f'{slice_idx:03d}.png' |
|
|
86 |
dir_in = os.path.join(config['path_root_in'], |
|
|
87 |
patient, release, sequence, |
|
|
88 |
config['dirname_masks']) |
|
|
89 |
dir_out = os.path.join(config['path_root_out'], |
|
|
90 |
patient, release, sequence, |
|
|
91 |
config['dirname_masks']) |
|
|
92 |
os.makedirs(dir_out, exist_ok=True) |
|
|
93 |
|
|
|
94 |
path_in = os.path.join(dir_in, fn_base) |
|
|
95 |
if not os.path.exists(path_in): |
|
|
96 |
print(f'No mask found for {name_gb}') |
|
|
97 |
continue |
|
|
98 |
path_out = os.path.join(dir_out, fn_base) |
|
|
99 |
|
|
|
100 |
mask_in = cv2.imread(path_in, cv2.IMREAD_GRAYSCALE) |
|
|
101 |
|
|
|
102 |
if config['margin'] == 0: |
|
|
103 |
tmp = mask_in |
|
|
104 |
else: |
|
|
105 |
tmp = mask_in[config['margin']:-config['margin'], |
|
|
106 |
config['margin']:-config['margin']] |
|
|
107 |
|
|
|
108 |
shape_out = tuple(np.floor(tmp.shape * ratio).astype(np.int))[::-1] |
|
|
109 |
tmp = cv2.resize(tmp, shape_out, interpolation=cv2.INTER_NEAREST) |
|
|
110 |
mask_out = tmp |
|
|
111 |
|
|
|
112 |
cv2.imwrite(path_out, mask_out) |
|
|
113 |
|
|
|
114 |
if config['update_meta']: |
|
|
115 |
df_out = (df_in.assign(pixel_spacing_0=config['spacing_out'][0]) |
|
|
116 |
.assign(pixel_spacing_1=config['spacing_out'][1])) |
|
|
117 |
df_out.to_csv(os.path.join(config['path_root_out'], 'meta_base.csv'), index=False) |
|
|
118 |
|
|
|
119 |
|
|
|
120 |
if __name__ == '__main__': |
|
|
121 |
main() |