Diff of /rocaseg/resample.py [000000] .. [6969be]

Switch to unified view

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()