def process_patient_images(patient_dir, image_dims, output_dir, patient_id): patient_scan = load_scan(patient_dir) patient_pixels = get_pixels_hu(patient_scan) # utils.show_slices(patient_pixels, str(patient_id) + 'hu', nr_slices=12, cols=4, output_dir=output_dir + 'images') patient_pixels, spacing = resample(patient_pixels, patient_scan, [1, 1, 1]) # utils.show_slices(patient_pixels, str(patient_id) + 'resampled', nr_slices=12, cols=4, output_dir=output_dir + 'images') patient_lung_mask = segment_lung_mask(patient_pixels, True) # utils.show_slices(patient_pixels, str(patient_id) + 'mask', nr_slices=12, cols=4, output_dir=output_dir + 'images') t = Timer('apply lung mask to image volume') patient_pixels = np.ma.masked_where(patient_lung_mask == 0, patient_pixels).filled(fill_value=0) # utils.show_slices(patient_pixels, str(patient_id) + 'masked', nr_slices=12, cols=4, output_dir=output_dir + 'images') t.stop() t = Timer('rotate image for optimal pose ' + patient_dir) rotation_angle = discover_lung_rotation(patient_lung_mask) patient_pixels = rotate(patient_pixels, rotation_angle, (1, 2), reshape=False) # utils.show_slices(patient_pixels, str(patient_id) + 'rotated', nr_slices=12, cols=4, output_dir=output_dir + 'images') t.stop() t = Timer('resize image volume to {}x{}x{}'.format(image_dims[0], image_dims[1], image_dims[2])) bbox = bounding_box(patient_pixels) if (bbox == None): return None bw, bh, bd = bbox_dim(bbox) fit_volume = (image_dims[2], image_dims[1], image_dims[0]) ratio = min(tuple(np.divide(fit_volume, np.subtract(bbox[1], bbox[0])))) logger.debug('ratio=' + str(ratio)) patient_pixels = scipy.ndimage.interpolation.zoom( patient_pixels[bbox[0][2]:bbox[1][2], bbox[0][1]:bbox[1][1], bbox[0][0]:bbox[1][0]], ratio) t.stop() t = Timer('translate to center') fit_volume_center = tuple(np.divide(fit_volume, 2)) bbox = bounding_box(patient_pixels) bbox_center = bounding_box_center(bbox) patient_pixels2 = np.full((image_dims[0], image_dims[1], image_dims[2]), 0) ps = np.shape(patient_pixels) patient_pixels2[:ps[0], :ps[1], :ps[2]] = patient_pixels[:ps[0], :ps[1], : ps[2]] patient_pixels = patient_pixels2 diff = (np.subtract(fit_volume_center, bbox_center)) patient_pixels = shift(patient_pixels, (diff[2], diff[1], diff[0])) t.stop() #add color channel dimension patient_pixels = np.expand_dims(patient_pixels, axis=3) return patient_pixels
def normalize_pixels(image_pixels, min_bound, max_bound, pixels_mean): image_pixels = (image_pixels - min_bound) / (max_bound - min_bound) image_pixels[image_pixels > 1] = 1. image_pixels[image_pixels < 0] = 0. #0-center pixels logger.debug('mean pixels=' + str(np.mean(image_pixels))) image_pixels = image_pixels - pixel_mean return image_pixels
def create_xy_datasets(output_dir, name, image_dims, size): dataset_file = dataset_path(output_dir, name, image_dims) h5f = h5py.File(dataset_file, 'w') x_ds = h5f.create_dataset('X', (size, image_dims[0], image_dims[1], image_dims[2], 1), chunks=(1, image_dims[0], image_dims[1], image_dims[2], 1), dtype='f') y_ds = h5f.create_dataset('Y', (size, 2), dtype='f') logger.debug('input x shape={}'.format(h5f['X'].shape)) x_ds = h5f['X'] y_ds = h5f['Y'] return h5f, x_ds, y_ds
def evaluate_dataset(dataset_path, model): with h5py.File(dataset_path, 'r') as hdf5: X = hdf5['X'] Y = hdf5['Y'] logger.debug('X_test shape ' + str(X.shape)) logger.debug('Y_test shape ' + str(Y.shape)) # for y in Y: # print('y=', y) logger.info('Evaluate performance on dataset '+ dataset_path +'...') acc = model.evaluate(X, Y, batch_size=12) logger.info('Accuracy: ' + str(acc))
def evaluate_dataset(dataset_path, model, batch_size=12, confusion_matrix=False, nr_items=-1): with h5py.File(dataset_path, 'r') as hdf5: X = hdf5['X'][-1:nr_items] Y = hdf5['Y'][-1:nr_items] logger.debug('X_test shape ' + str(X.shape)) logger.debug('Y_test shape ' + str(Y.shape)) logger.info('Evaluate performance on dataset '+ dataset_path +'...') acc = model.evaluate(X, Y, batch_size=batch_size) logger.info('Accuracy: ' + str(acc)) if(confusion_matrix): logger.info('Confusion matrix') Y_pred = model.predict(X) print(sklearn.metrics.confusion_matrix(Y, Y_pred))
def predict_patient(input_dir, patient_id, image_dims, model, output_dir): logger.info('>>> Predict patient_id ' + patient_id) logger.info('Loading pre-processed images for patient') #patient pre-processed image cache dataset_file = utils.dataset_path(output_dir, 'cache-predict', image_dims) patient_pixels = None with h5py.File(dataset_file, 'a') as h5f: try: patient_pixels = h5f[patient_id] logger.debug('Patient image found in cache. Using it.') #disconnect from HDF5 patient_pixels = np.array(patient_pixels) except KeyError: logger.debug('Patient image not found in cache') t = Timer('Preparing patient scan image volume. patient_id=' + patient_id) patient_pixels = lungprepare.process_patient_images(input_dir + patient_id, image_dims) if(patient_pixels is None): logger.warning('Patient lung not found. Skipping.') logger.debug('Storing patient image in cache') h5f[patient_id] = patient_pixels t.stop() t = Timer('Predicting result on CNN (forward)') y = model.predict(np.expand_dims(patient_pixels, axis=0)) logger.info('PATIENT '+ patient_id +' PREDICT=' + str(y)) utils.show_slices(patient_pixels, patient_id) t.stop() return y
def print_same_line(log, use_logger=True): l = "\r{}".format(log) stdout.write(l) stdout.flush() if (use_logger): logger.debug(l)
def segment_lung_mask(image, fill_lung_structures=True): t = Timer('segment_lung_mask') # 0 is treated as background, which we do not want binary_image = np.array(image > -320, dtype=np.int8) + 1 #cleanup some small bubbles inside body before labelling binary_image = scipy.ndimage.morphology.grey_closing(binary_image, 3) labels = measure.label(binary_image) #Determine which label clusters refers to the air/space around the person body and turn it into the same cluster #The various corners are measured in case of volume being broken when the body is not fitted inside scan bgs = [0] si = np.shape(binary_image) si0 = si[0] - 3 si1 = si[1] - 3 si2 = si[2] - 3 for i in (2, si0): for j in (2, si1): for k in (2, si2): bgs.append(labels[i, j, k]) #identify the body label s = np.array(np.shape(labels)) body = find_next_valid(labels[int(s[0] * 0.6), int(s[1] * 0.5)], bgs=bgs) bgs.append(body) logger.debug('bgs' + str(bgs)) #look inside the volume where lung structures is meant to be lung_label = largest_label_volume(labels[int(s[0] * 0.2):int(s[0] * 0.8), int(s[1] * 0.25):int(s[1] * 0.75), int(s[2] * 0.25):int(s[2] * 0.75)], bgs=bgs) logger.debug('lung_label' + str(lung_label)) #remove everything that is not part of the lung logger.debug('remove non lung structures') binary_image[labels != lung_label] = 2 # Method of filling the lung structures (that is superior to something like # morphological closing) if fill_lung_structures: # For every slice we determine the largest solid structure for i, axial_slice in enumerate(binary_image): axial_slice = axial_slice - 1 labeling = measure.label(axial_slice) l_max = largest_label_volume(labeling, bgs=[0]) if l_max is not None: #This slice contains some lung binary_image[i][labeling != l_max] = 1 logger.debug('fill_lung_structures') binary_image -= 1 #Make the image actual binary binary_image = 1 - binary_image # Invert it, lungs are now 1 #dilate mask binary_image = scipy.ndimage.morphology.grey_dilation(binary_image, size=(10, 10, 10)) t.stop() return binary_image
def on_epoch_end(self, epoch, logs={}): logger.debug('epoch end ' + str(epoch) + '/' + str(self.epochs) + ' - ' + str(logs))
def on_batch_end(self, batch, logs={}): logger.debug('batch ' + str(batch) + '/' + str(self.target) + ' - epoch ' + str(self.epoch) + '/' + str(self.epochs) + ' - ' + str(logs))