|
a |
|
b/slice.py |
|
|
1 |
""" |
|
|
2 |
details |
|
|
3 |
------- |
|
|
4 |
1. Get name list of images and labels (/masks/ground truth) |
|
|
5 |
2. Slice each case according to X/Y/Z dim |
|
|
6 |
3. Save a list of [case number, slice number, slicename, labelname, average pixel value of the slice, |
|
|
7 |
total pixel number of ground truth, bounding box (minA, maxA, minB, maxB)] |
|
|
8 |
|
|
|
9 |
This code is adapted from https://github.com/198808xc/OrganSegC2F/blob/master/OrganSegC2F/init.py |
|
|
10 |
""" |
|
|
11 |
|
|
|
12 |
import numpy as np |
|
|
13 |
import os |
|
|
14 |
import sys |
|
|
15 |
import time |
|
|
16 |
from utils import * |
|
|
17 |
|
|
|
18 |
|
|
|
19 |
# read input arguments |
|
|
20 |
data_path = sys.argv[1] + "/" |
|
|
21 |
organ_number = int(sys.argv[2]) |
|
|
22 |
folds = int(sys.argv[3]) |
|
|
23 |
low_range = int(sys.argv[4]) |
|
|
24 |
high_range = int(sys.argv[5]) |
|
|
25 |
|
|
|
26 |
if __name__=="__main__": |
|
|
27 |
# get image list |
|
|
28 |
image_list = [] |
|
|
29 |
image_filename = [] |
|
|
30 |
keyword = '' |
|
|
31 |
for directory, _, file_ in os.walk(image_path): |
|
|
32 |
for filename in sorted(file_): |
|
|
33 |
if keyword in filename: |
|
|
34 |
image_list.append(os.path.join(directory, filename)) |
|
|
35 |
image_filename.append(os.path.splitext(filename)[0]) |
|
|
36 |
|
|
|
37 |
# get label list |
|
|
38 |
label_list = [] |
|
|
39 |
label_filename = [] |
|
|
40 |
for directory, _, file_ in os.walk(label_path): |
|
|
41 |
for filename in sorted(file_): |
|
|
42 |
if keyword in filename: |
|
|
43 |
label_list.append(os.path.join(directory, filename)) |
|
|
44 |
label_filename.append(os.path.splitext(filename)[0]) |
|
|
45 |
|
|
|
46 |
# check if #image equals #labels |
|
|
47 |
if len(image_list) != len(label_list): |
|
|
48 |
exit('Error: the number of labels and the number of images are not equal!') |
|
|
49 |
|
|
|
50 |
|
|
|
51 |
total_samples = len(image_list) |
|
|
52 |
|
|
|
53 |
for plane in ['Z']: |
|
|
54 |
output = open(list_training[plane], 'w') |
|
|
55 |
output.close() |
|
|
56 |
|
|
|
57 |
print 'Initialization starts.' |
|
|
58 |
|
|
|
59 |
# iterate through all samples |
|
|
60 |
for i in range(total_samples): |
|
|
61 |
start_time = time.time() |
|
|
62 |
print 'Processing ' + str(i + 1) + ' out of ' + str(len(image_list)) + ' files.' |
|
|
63 |
|
|
|
64 |
image = np.load(image_list[i]) |
|
|
65 |
label = np.load(label_list[i]) |
|
|
66 |
|
|
|
67 |
# only z for now |
|
|
68 |
for plane in ['Z']: |
|
|
69 |
# slice_number is the number of slices of corresponding dimension (X/Y/Z) |
|
|
70 |
slice_number = label.shape[2] |
|
|
71 |
|
|
|
72 |
image_directory_ = os.path.join(image_path_[plane], image_filename[i]) |
|
|
73 |
if not os.path.exists(image_directory_): |
|
|
74 |
os.makedirs(image_directory_) |
|
|
75 |
|
|
|
76 |
label_directory_ = os.path.join(label_path_[plane], label_filename[i]) |
|
|
77 |
if not os.path.exists(label_directory_): |
|
|
78 |
os.makedirs(label_directory_) |
|
|
79 |
|
|
|
80 |
print ' Slicing data: ' + str(time.time() - start_time) + ' second(s) elapsed.' |
|
|
81 |
# for storing the total number of pixels of ground truth mask |
|
|
82 |
sum_ = np.zeros((slice_number, organ_number + 1), dtype = np.int) |
|
|
83 |
# for storing bounding boxes of ground truth masks (A_min, A_max, B_min, B_max) |
|
|
84 |
minA = np.zeros((slice_number, organ_number + 1), dtype = np.int) |
|
|
85 |
maxA = np.zeros((slice_number, organ_number + 1), dtype = np.int) |
|
|
86 |
minB = np.zeros((slice_number, organ_number + 1), dtype = np.int) |
|
|
87 |
maxB = np.zeros((slice_number, organ_number + 1), dtype = np.int) |
|
|
88 |
# for storing mean pixel value of each slice |
|
|
89 |
average = np.zeros((slice_number), dtype = np.float) |
|
|
90 |
|
|
|
91 |
# iterate through all slices of current case i and current plane |
|
|
92 |
for j in range(0, slice_number): |
|
|
93 |
# image_filename_ sample dir: image_X / 0001 / 0001.npy |
|
|
94 |
# plane/ case num / slice num |
|
|
95 |
image_filename_ = os.path.join( \ |
|
|
96 |
image_path_[plane], image_filename[i], '{:0>4}'.format(j) + '.npy') |
|
|
97 |
|
|
|
98 |
label_filename_ = os.path.join( \ |
|
|
99 |
label_path_[plane], label_filename[i], '{:0>4}'.format(j) + '.npy') |
|
|
100 |
|
|
|
101 |
image_ = image[:, :, j] |
|
|
102 |
label_ = label[:, :, j] |
|
|
103 |
|
|
|
104 |
# threshold image to specified range ([-100, 240] for pancreas) |
|
|
105 |
image_[image_ < low_range] = low_range |
|
|
106 |
image_[image_ > high_range] = high_range |
|
|
107 |
|
|
|
108 |
# save sliced image and label |
|
|
109 |
if not os.path.isfile(image_filename_) or not os.path.isfile(label_filename_): |
|
|
110 |
np.save(image_filename_, image_) |
|
|
111 |
np.save(label_filename_, label_) |
|
|
112 |
|
|
|
113 |
# compute the mean value of the slice |
|
|
114 |
average[j] = float(image_.sum()) / (image_.shape[0] * image_.shape[1]) |
|
|
115 |
|
|
|
116 |
for o in range(1, organ_number + 1): |
|
|
117 |
# this is the sum of pixel numbers of a ground truth mask |
|
|
118 |
sum_[j, o] = (is_organ(label_, o)).sum() |
|
|
119 |
# record the coordinates of ground truth mask pixels |
|
|
120 |
arr = np.nonzero(is_organ(label_, o)) |
|
|
121 |
|
|
|
122 |
# save the bounding box of ground truth mask (A_min, A_max, B_min, B_max) |
|
|
123 |
minA[j, o] = 0 if not len(arr[0]) else min(arr[0]) |
|
|
124 |
maxA[j, o] = 0 if not len(arr[0]) else max(arr[0]) |
|
|
125 |
minB[j, o] = 0 if not len(arr[1]) else min(arr[1]) |
|
|
126 |
maxB[j, o] = 0 if not len(arr[1]) else max(arr[1]) |
|
|
127 |
|
|
|
128 |
# iterate each slice of current case i |
|
|
129 |
for j in range(0, slice_number): |
|
|
130 |
image_filename_ = os.path.join( \ |
|
|
131 |
image_path_[plane], image_filename[i], '{:0>4}'.format(j) + '.npy') |
|
|
132 |
|
|
|
133 |
label_filename_ = os.path.join( \ |
|
|
134 |
label_path_[plane], label_filename[i], '{:0>4}'.format(j) + '.npy') |
|
|
135 |
|
|
|
136 |
# append the following output to training_X/Y/Z.txt |
|
|
137 |
output = open(list_training[plane], 'a+') |
|
|
138 |
# case number, slice number |
|
|
139 |
output.write(str(i) + ' ' + str(j)) |
|
|
140 |
# image file name, label file name |
|
|
141 |
output.write(' ' + image_filename_ + ' ' + label_filename_) |
|
|
142 |
# average pixel value of slice j, case i, and current plane |
|
|
143 |
output.write(' ' + str(average[j])) |
|
|
144 |
# sum of ground truth pixels, and bounding box of gt mask (A_min, A_max, B_min, B_max) |
|
|
145 |
for o in range(1, organ_number + 1): |
|
|
146 |
output.write(' ' + str(sum_[j, o]) + ' ' + str(minA[j, o]) + \ |
|
|
147 |
' ' + str(maxA[j, o]) + ' ' + str(minB[j, o]) + ' ' + str(maxB[j, o])) |
|
|
148 |
|
|
|
149 |
output.write('\n') |
|
|
150 |
|
|
|
151 |
output.close() |
|
|
152 |
|
|
|
153 |
print ' ' + plane + ' plane is done: ' + \ |
|
|
154 |
str(time.time() - start_time) + ' second(s) elapsed.' |
|
|
155 |
|
|
|
156 |
print 'Processed ' + str(i + 1) + ' out of ' + str(len(image_list)) + ' files: ' + \ |
|
|
157 |
str(time.time() - start_time) + ' second(s) elapsed.' |
|
|
158 |
|
|
|
159 |
|
|
|
160 |
# create the 4 training image lists |
|
|
161 |
print 'Writing training image list.' |
|
|
162 |
for f in range(folds): |
|
|
163 |
list_training_ = training_set_filename(f) |
|
|
164 |
output = open(list_training_, 'w') |
|
|
165 |
for i in range(total_samples): |
|
|
166 |
if in_training_set(total_samples, i, folds, f): |
|
|
167 |
output.write(str(i) + ' ' + image_list[i] + ' ' + label_list[i] + '\n') |
|
|
168 |
output.close() |
|
|
169 |
|
|
|
170 |
# create the 4 test image lists |
|
|
171 |
print 'Writing testing image list.' |
|
|
172 |
for f in range(folds): |
|
|
173 |
list_testing_ = testing_set_filename(f) |
|
|
174 |
output = open(list_testing_, 'w') |
|
|
175 |
for i in range(total_samples): |
|
|
176 |
if not in_training_set(total_samples, i, folds, f): |
|
|
177 |
output.write(str(i) + ' ' + image_list[i] + ' ' + label_list[i] + '\n') |
|
|
178 |
output.close() |
|
|
179 |
|
|
|
180 |
print 'Initialization is done.' |