Spaces:
Running
Running
# ------------------------------------------------------------ # | |
# | |
# 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) | |