# ------------------------------------------------------------ # # # file : utils/learning/patch/extraction.py # author : CM # Function to extract patch from input dataset # # ------------------------------------------------------------ # import sys from random import randint import numpy as np from keras.utils import to_categorical # ----- Patch Extraction ----- # -- Single Patch # exctract a patch from an image def extractPatch(d, patch_size_x, patch_size_y, patch_size_z, x, y, z): patch = d[x:x+patch_size_x,y:y+patch_size_y,z:z+patch_size_z] return patch # extract a patch from an image. The patch can be out of the image (0 padding) def extractPatchOut(d, patch_size_x, patch_size_y, patch_size_z, x_, y_, z_): patch = np.zeros((patch_size_x, patch_size_y, patch_size_z), dtype='float16') for x in range(0,patch_size_x): for y in range(0, patch_size_y): for z in range(0, patch_size_z): if(x+x_ >= 0 and x+x_ < d.shape[0] and y+y_ >= 0 and y+y_ < d.shape[1] and z+z_ >= 0 and z+z_ < d.shape[2]): patch[x,y,z] = d[x+x_,y+y_,z+z_] return patch # create random patch for an image def generateRandomPatch(d, patch_size_x, patch_size_y, patch_size_z): x = randint(0, d.shape[0]-patch_size_x) y = randint(0, d.shape[1]-patch_size_y) z = randint(0, d.shape[2]-patch_size_z) data = extractPatch(d, patch_size_x, patch_size_y, patch_size_z, x, y, z) return data # -- Multiple Patchs # create random patchs for an image def generateRandomPatchs(d, patch_size_x, patch_size_y, patch_size_z, patch_number): # max_patch_nb = (d.shape[0]-patch_size_x)*(d.shape[1]-patch_size_y)*(d.shape[2]-patch_size_z) data = np.empty((patch_number, patch_size_x, patch_size_y, patch_size_z), dtype='float16') for i in range(0,patch_number): data[i] = generateRandomPatch(d, patch_size_x, patch_size_y, patch_size_z) return data # divide the full image into patchs # todo : missing data if shape%patch_size is not 0 def generateFullPatchs(d, patch_size_x, patch_size_y, patch_size_z): patch_nb = int((d.shape[0]/patch_size_x)*(d.shape[1]/patch_size_y)*(d.shape[2]/patch_size_z)) data = np.empty((patch_nb, patch_size_x, patch_size_y, patch_size_z), dtype='float16') i = 0 for x in range(0,d.shape[0], patch_size_x): for y in range(0, d.shape[1], patch_size_y): for z in range(0,d.shape[2], patch_size_z): data[i] = extractPatch(d, patch_size_x, patch_size_y, patch_size_z, x, y, z) i = i+1 return data def generateFullPatchsPlus(d, patch_size_x, patch_size_y, patch_size_z, dx, dy, dz): patch_nb = int((d.shape[0]/dx)*(d.shape[1]/dy)*(d.shape[2]/dz)) data = np.empty((patch_nb, patch_size_x, patch_size_y, patch_size_z), dtype='float16') i = 0 for x in range(0,d.shape[0]-dx, dx): for y in range(0, d.shape[1]-dy, dy): for z in range(0,d.shape[2]-dz, dz): data[i] = extractPatch(d, patch_size_x, patch_size_y, patch_size_z, x, y, z) i = i+1 return data def noNeg(x): if(x>0): return x else: return 0 def generateFullPatchsCentered(d, patch_size_x, patch_size_y, patch_size_z): patch_nb = int(2*(d.shape[0]/patch_size_x)*2*(d.shape[1]/patch_size_y)*2*(d.shape[2]/patch_size_z)) data = np.zeros((patch_nb, patch_size_x, patch_size_y, patch_size_z), dtype='float16') i = 0 psx = int(patch_size_x/2) psy = int(patch_size_y/2) psz = int(patch_size_z/2) for x in range(-int(patch_size_x/4),d.shape[0]-3*int(patch_size_x/4)+1, psx): for y in range(-int(patch_size_y/4), d.shape[1]-3*int(patch_size_y/4)+1, psy): for z in range(-int(patch_size_z/4),d.shape[2]-3*int(patch_size_z/4)+1, psz): # patch = np.zeros((psx,psy,psz), dtype='float16') # patch = d[noNeg(x):noNeg(x)+patch_size_x,noNeg(y):noNeg(y)+patch_size_y,noNeg(z):noNeg(z)+patch_size_z] patch = extractPatchOut(d,patch_size_x, patch_size_y, patch_size_z, x, y, z) data[i] = patch i = i+1 return data # ----- Patch Extraction Generator ----- # Generator of random patchs of size 32*32*32 def generatorRandomPatchs(features, labels, batch_size, patch_size_x, patch_size_y, patch_size_z): batch_features = np.zeros((batch_size, patch_size_x, patch_size_y, patch_size_z, features.shape[4]), dtype='float16') batch_labels = np.zeros((batch_size, patch_size_x, patch_size_y, patch_size_z, labels.shape[4]), dtype='float16') while True: for i in range(batch_size): id = randint(0,features.shape[0]-1) x = randint(0, features.shape[1]-patch_size_x) y = randint(0, features.shape[2]-patch_size_y) z = randint(0, features.shape[3]-patch_size_z) batch_features[i] = extractPatch(features[id], patch_size_x, patch_size_y, patch_size_z, x, y, z) batch_labels[i] = extractPatch(labels[id], patch_size_x, patch_size_y, patch_size_z, x, y, z) yield batch_features, batch_labels # Generator of random patchs of size 32*32*32 and 16*16*16 def generatorRandomPatchs3216(features, labels, batch_size): batch_features = np.zeros((batch_size, 32, 32, 32, features.shape[4]), dtype='float16') batch_labels = np.zeros((batch_size, 16, 16, 16, labels.shape[4]), dtype='float16') while True: for i in range(batch_size): id = randint(0,features.shape[0]-1) x = randint(0, features.shape[1]-32) y = randint(0, features.shape[2]-32) z = randint(0, features.shape[3]-32) batch_features[i] = extractPatch(features[id], 32, 32, 32, x, y, z) batch_labels[i] = extractPatch(labels[id], 16, 16, 16, x+16, y+16, z+16) yield batch_features, batch_labels def generatorRandomPatchsLabelCentered(features, labels, batch_size, patch_size_x, patch_size_y, patch_size_z): patch_centered_size_x = int(patch_size_x/2) patch_centered_size_y = int(patch_size_y/2) patch_centered_size_z = int(patch_size_z/2) batch_features = np.zeros((batch_size, patch_size_x, patch_size_y, patch_size_z, features.shape[4]), dtype=features.dtype) batch_labels = np.zeros((batch_size, patch_centered_size_x, patch_centered_size_y, patch_centered_size_z, labels.shape[4]), dtype=labels.dtype) while True: for i in range(batch_size): id = randint(0,features.shape[0]-1) x = randint(0, features.shape[1]-patch_size_x) y = randint(0, features.shape[2]-patch_size_y) z = randint(0, features.shape[3]-patch_size_z) batch_features[i] = extractPatch(features[id], patch_size_x, patch_size_y, patch_size_z, x, y, z) batch_labels[i] = extractPatch(labels[id], patch_centered_size_x, patch_centered_size_y, patch_centered_size_z, int(x+patch_size_x/4), int(y+patch_size_y/4), int(z+patch_size_z/4)) yield batch_features, batch_labels def generatorRandomPatchsDolz(features, labels, batch_size, patch_size_x, patch_size_y, patch_size_z): batch_features = np.zeros((batch_size, patch_size_x, patch_size_y, patch_size_z, features.shape[4]), dtype=features.dtype) batch_labels = np.zeros((batch_size, int(patch_size_x / 2) * int(patch_size_y / 2) * int(patch_size_z / 2), 2), dtype=labels.dtype) while True: for i in range(batch_size): id = randint(0,features.shape[0]-1) x = randint(0, features.shape[1]-patch_size_x) y = randint(0, features.shape[2]-patch_size_y) z = randint(0, features.shape[3]-patch_size_z) batch_features[i] = extractPatch(features[id], patch_size_x, patch_size_y, patch_size_z, x, y, z) tmpPatch = extractPatch(labels[id], int(patch_size_x/2), int(patch_size_y/2), int(patch_size_z/2), int(x+patch_size_x/4), int(y+patch_size_y/4), int(z+patch_size_z/4)) batch_labels[i] = to_categorical(tmpPatch.flatten(),2) """ count = 0 for x in range(0, tmpPatch.shape[0]): for y in range(0, tmpPatch.shape[1]): for z in range(0, tmpPatch.shape[2]): if(tmpPatch[x,y,z,0] == 1): batch_labels[i,count,1] = 1 else: batch_labels[i,count,0] = 1 count += 1 """ yield batch_features, batch_labels from scipy.ndimage import zoom, rotate # Generate random patchs with random linear transformation # translation (random position) rotation, scale # Preconditions : patch_features_ % patch_labels_ = 0 # patch_features_ >= patch_labels_ # todo : scale def generatorRandomPatchsLinear(features, labels, patch_features_x, patch_features_y, patch_features_z, patch_labels_x, patch_labels_y, patch_labels_z): patch_features = np.zeros((1, patch_features_x, patch_features_y, patch_features_z, features.shape[4]), dtype=features.dtype) patch_labels = np.zeros((1, patch_labels_x, patch_labels_y, patch_labels_z, labels.shape[4]), dtype=labels.dtype) if(patch_features_x % patch_labels_x != 0 or patch_features_y % patch_labels_y != 0 or patch_features_z % patch_labels_z != 0): sys.exit(0x00F0) if(patch_features_x < patch_labels_x or patch_features_y < patch_labels_y or patch_features_z < patch_labels_z): sys.exit(0x00F1) # middle of patch mx = int(patch_features_x/2) my = int(patch_features_y/2) mz = int(patch_features_z/2) # patch label size/2 sx = int(patch_labels_x / 2) sy = int(patch_labels_y / 2) sz = int(patch_labels_z / 2) while True: id = randint(0, features.shape[0]-1) x = randint(0, features.shape[1]-patch_features_x) y = randint(0, features.shape[2]-patch_features_y) z = randint(0, features.shape[3]-patch_features_z) # todo : check time consumtion and rotation directly on complete image r0 = randint(0, 360)-180 r1 = randint(0, 360)-180 r2 = randint(0, 360)-180 rot_features = rotate(input=features[0], angle=r0, axes=(0, 1), reshape=False) rot_features = rotate(input=rot_features, angle=r1, axes=(1, 2), reshape=False) rot_features = rotate(input=rot_features, angle=r2, axes=(2, 0), reshape=False) rot_labels = rotate(input=labels[0], angle=r0, axes=(0, 1), reshape=False) rot_labels = rotate(input=rot_labels, angle=r1, axes=(1, 2), reshape=False) rot_labels = rotate(input=rot_labels, angle=r2, axes=(2, 0), reshape=False) patch_features[0] = extractPatch(rot_features, patch_features_x, patch_features_y, patch_features_z, x, y, z) patch_labels[0] = extractPatch(rot_labels, patch_labels_x, patch_labels_y, patch_labels_z, x + mx - sx, y + my - sy, z + mz - sz) yield patch_features, patch_labels def randomPatchsAugmented(in_dataset, gd_dataset, patch_number, patch_in_size, patch_gd_size): patchs_in = np.zeros((patch_number, patch_in_size[0], patch_in_size[1], patch_in_size[2]), dtype=in_dataset.dtype) patchs_gd = np.zeros((patch_number, patch_gd_size[0], patch_gd_size[1], patch_gd_size[2]), dtype=gd_dataset.dtype) if(patch_in_size[0] % patch_gd_size[0] != 0 or patch_in_size[1] % patch_gd_size[1] != 0 or patch_in_size[2] % patch_gd_size[2] != 0): sys.exit("ERROR : randomPatchsAugmented patchs size error 1") if(patch_in_size[0] < patch_gd_size[0] or patch_in_size[1] < patch_gd_size[1] or patch_in_size[2] < patch_gd_size[2]): sys.exit("ERROR : randomPatchsAugmented patchs size error 2") # middle of patch mx = int(patch_in_size[0] / 2) my = int(patch_in_size[1] / 2) mz = int(patch_in_size[2] / 2) # patch label size/2 sx = int(patch_gd_size[0] / 2) sy = int(patch_gd_size[1] / 2) sz = int(patch_gd_size[2] / 2) for count in range(patch_number): id = randint(0, in_dataset.shape[0]-1) x = randint(0, in_dataset.shape[1]-patch_in_size[0]) y = randint(0, in_dataset.shape[2]-patch_in_size[1]) z = randint(0, in_dataset.shape[3]-patch_in_size[2]) r0 = randint(0, 3) r1 = randint(0, 3) r2 = randint(0, 3) patchs_in[count] = extractPatch(in_dataset[id], patch_in_size[0], patch_in_size[1], patch_in_size[2], x, y, z) patchs_gd[count] = extractPatch(gd_dataset[id], patch_gd_size[0], patch_gd_size[1], patch_gd_size[2], x + mx - sx, y + my - sy, z + mz - sz) patchs_in[count] = np.rot90(patchs_in[count], r0, (0, 1)) patchs_in[count] = np.rot90(patchs_in[count], r1, (1, 2)) patchs_in[count] = np.rot90(patchs_in[count], r2, (2, 0)) patchs_gd[count] = np.rot90(patchs_gd[count], r0, (0, 1)) patchs_gd[count] = np.rot90(patchs_gd[count], r1, (1, 2)) patchs_gd[count] = np.rot90(patchs_gd[count], r2, (2, 0)) return patchs_in.reshape(patchs_in.shape[0], patchs_in.shape[1], patchs_in.shape[2], patchs_in.shape[3], 1),\ patchs_gd.reshape(patchs_gd.shape[0], patchs_gd.shape[1], patchs_gd.shape[2], patchs_gd.shape[3], 1) def generatorRandomPatchsAugmented(in_dataset, gd_dataset, patch_number, patch_in_size, patch_gd_size): while True: yield randomPatchsAugmented(in_dataset, gd_dataset, patch_number, patch_in_size, patch_gd_size)