| |
| import random |
| import cv2 |
| import elasticdeform |
| import numpy as np |
| from scipy.ndimage import gaussian_filter |
|
|
|
|
| def generate_prob_function(mask_shape): |
| sigma = np.random.uniform(3,15) |
| |
| a = np.random.uniform(0, 1, size=(mask_shape[0],mask_shape[1],mask_shape[2])) |
|
|
| |
| |
| a_2 = gaussian_filter(a, sigma=sigma) |
|
|
| scale = np.random.uniform(0.19, 0.21) |
| base = np.random.uniform(0.04, 0.06) |
| a = scale * (a_2 - np.min(a_2)) / (np.max(a_2) - np.min(a_2)) + base |
|
|
| return a |
|
|
| |
| def random_select(mask_scan): |
| |
| z_start, z_end = np.where(np.any(mask_scan, axis=(0, 1)))[0][[0, -1]] |
|
|
| |
| z = round(random.uniform(0.3, 0.7) * (z_end - z_start)) + z_start |
|
|
| liver_mask = mask_scan[..., z] |
|
|
| |
| kernel = np.ones((5,5), dtype=np.uint8) |
| liver_mask = cv2.erode(liver_mask, kernel, iterations=1) |
|
|
| coordinates = np.argwhere(liver_mask == 1) |
| random_index = np.random.randint(0, len(coordinates)) |
| xyz = coordinates[random_index].tolist() |
| xyz.append(z) |
| potential_points = xyz |
|
|
| return potential_points |
|
|
| |
| def get_ellipsoid(x, y, z): |
| """" |
| x, y, z is the radius of this ellipsoid in x, y, z direction respectly. |
| """ |
| sh = (4*x, 4*y, 4*z) |
| out = np.zeros(sh, int) |
| aux = np.zeros(sh) |
| radii = np.array([x, y, z]) |
| com = np.array([2*x, 2*y, 2*z]) |
|
|
| |
| bboxl = np.floor(com-radii).clip(0,None).astype(int) |
| bboxh = (np.ceil(com+radii)+1).clip(None, sh).astype(int) |
| roi = out[tuple(map(slice,bboxl,bboxh))] |
| roiaux = aux[tuple(map(slice,bboxl,bboxh))] |
| logrid = *map(np.square,np.ogrid[tuple( |
| map(slice,(bboxl-com)/radii,(bboxh-com-1)/radii,1j*(bboxh-bboxl)))]), |
| dst = (1-sum(logrid)).clip(0,None) |
| mask = dst>roiaux |
| roi[mask] = 1 |
| np.copyto(roiaux,dst,where=mask) |
|
|
| return out |
|
|
| def get_fixed_geo(mask_scan, tumor_type): |
|
|
| enlarge_x, enlarge_y, enlarge_z = 160, 160, 160 |
| geo_mask = np.zeros((mask_scan.shape[0] + enlarge_x, mask_scan.shape[1] + enlarge_y, mask_scan.shape[2] + enlarge_z), dtype=np.int8) |
| |
| tiny_radius, small_radius, medium_radius, large_radius = 4, 8, 16, 32 |
|
|
| if tumor_type == 'tiny': |
| num_tumor = random.randint(3,10) |
| for _ in range(num_tumor): |
| |
| x = random.randint(int(0.75*tiny_radius), int(1.25*tiny_radius)) |
| y = random.randint(int(0.75*tiny_radius), int(1.25*tiny_radius)) |
| z = random.randint(int(0.75*tiny_radius), int(1.25*tiny_radius)) |
| sigma = random.uniform(0.5,1) |
| |
| geo = get_ellipsoid(x, y, z) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,1)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(1,2)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,2)) |
| point = random_select(mask_scan) |
| new_point = [point[0] + enlarge_x//2, point[1] + enlarge_y//2, point[2] + enlarge_z//2] |
| x_low, x_high = new_point[0] - geo.shape[0]//2, new_point[0] + geo.shape[0]//2 |
| y_low, y_high = new_point[1] - geo.shape[1]//2, new_point[1] + geo.shape[1]//2 |
| z_low, z_high = new_point[2] - geo.shape[2]//2, new_point[2] + geo.shape[2]//2 |
| |
| |
| geo_mask[x_low:x_high, y_low:y_high, z_low:z_high] += geo |
|
|
| if tumor_type == 'small': |
| num_tumor = random.randint(3,10) |
| for _ in range(num_tumor): |
| |
| x = random.randint(int(0.75*small_radius), int(1.25*small_radius)) |
| y = random.randint(int(0.75*small_radius), int(1.25*small_radius)) |
| z = random.randint(int(0.75*small_radius), int(1.25*small_radius)) |
| sigma = random.randint(1, 2) |
| |
| geo = get_ellipsoid(x, y, z) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,1)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(1,2)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,2)) |
| |
| point = random_select(mask_scan) |
| new_point = [point[0] + enlarge_x//2, point[1] + enlarge_y//2, point[2] + enlarge_z//2] |
| x_low, x_high = new_point[0] - geo.shape[0]//2, new_point[0] + geo.shape[0]//2 |
| y_low, y_high = new_point[1] - geo.shape[1]//2, new_point[1] + geo.shape[1]//2 |
| z_low, z_high = new_point[2] - geo.shape[2]//2, new_point[2] + geo.shape[2]//2 |
| |
| |
| geo_mask[x_low:x_high, y_low:y_high, z_low:z_high] += geo |
| |
|
|
| if tumor_type == 'medium': |
| num_tumor = random.randint(2, 5) |
| for _ in range(num_tumor): |
| |
| x = random.randint(int(0.75*medium_radius), int(1.25*medium_radius)) |
| y = random.randint(int(0.75*medium_radius), int(1.25*medium_radius)) |
| z = random.randint(int(0.75*medium_radius), int(1.25*medium_radius)) |
| sigma = random.randint(3, 6) |
| |
| geo = get_ellipsoid(x, y, z) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,1)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(1,2)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,2)) |
| |
| point = random_select(mask_scan) |
| new_point = [point[0] + enlarge_x//2, point[1] + enlarge_y//2, point[2] + enlarge_z//2] |
| x_low, x_high = new_point[0] - geo.shape[0]//2, new_point[0] + geo.shape[0]//2 |
| y_low, y_high = new_point[1] - geo.shape[1]//2, new_point[1] + geo.shape[1]//2 |
| z_low, z_high = new_point[2] - geo.shape[2]//2, new_point[2] + geo.shape[2]//2 |
| |
| |
| geo_mask[x_low:x_high, y_low:y_high, z_low:z_high] += geo |
| |
|
|
| if tumor_type == 'large': |
| num_tumor = random.randint(1,3) |
| for _ in range(num_tumor): |
| |
| x = random.randint(int(0.75*large_radius), int(1.25*large_radius)) |
| y = random.randint(int(0.75*large_radius), int(1.25*large_radius)) |
| z = random.randint(int(0.75*large_radius), int(1.25*large_radius)) |
| sigma = random.randint(5, 10) |
| |
| geo = get_ellipsoid(x, y, z) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,1)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(1,2)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,2)) |
| |
| point = random_select(mask_scan) |
| new_point = [point[0] + enlarge_x//2, point[1] + enlarge_y//2, point[2] + enlarge_z//2] |
| x_low, x_high = new_point[0] - geo.shape[0]//2, new_point[0] + geo.shape[0]//2 |
| y_low, y_high = new_point[1] - geo.shape[1]//2, new_point[1] + geo.shape[1]//2 |
| z_low, z_high = new_point[2] - geo.shape[2]//2, new_point[2] + geo.shape[2]//2 |
| |
| |
| geo_mask[x_low:x_high, y_low:y_high, z_low:z_high] += geo |
| |
|
|
| if tumor_type == "mix": |
| |
| num_tumor = random.randint(3,10) |
| for _ in range(num_tumor): |
| |
| x = random.randint(int(0.75*tiny_radius), int(1.25*tiny_radius)) |
| y = random.randint(int(0.75*tiny_radius), int(1.25*tiny_radius)) |
| z = random.randint(int(0.75*tiny_radius), int(1.25*tiny_radius)) |
| sigma = random.uniform(0.5,1) |
| |
| geo = get_ellipsoid(x, y, z) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,1)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(1,2)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,2)) |
| point = random_select(mask_scan) |
| new_point = [point[0] + enlarge_x//2, point[1] + enlarge_y//2, point[2] + enlarge_z//2] |
| x_low, x_high = new_point[0] - geo.shape[0]//2, new_point[0] + geo.shape[0]//2 |
| y_low, y_high = new_point[1] - geo.shape[1]//2, new_point[1] + geo.shape[1]//2 |
| z_low, z_high = new_point[2] - geo.shape[2]//2, new_point[2] + geo.shape[2]//2 |
| |
| |
| geo_mask[x_low:x_high, y_low:y_high, z_low:z_high] += geo |
|
|
| |
| num_tumor = random.randint(5,10) |
| for _ in range(num_tumor): |
| |
| x = random.randint(int(0.75*small_radius), int(1.25*small_radius)) |
| y = random.randint(int(0.75*small_radius), int(1.25*small_radius)) |
| z = random.randint(int(0.75*small_radius), int(1.25*small_radius)) |
| sigma = random.randint(1, 2) |
| |
| geo = get_ellipsoid(x, y, z) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,1)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(1,2)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,2)) |
| |
| point = random_select(mask_scan) |
| new_point = [point[0] + enlarge_x//2, point[1] + enlarge_y//2, point[2] + enlarge_z//2] |
| x_low, x_high = new_point[0] - geo.shape[0]//2, new_point[0] + geo.shape[0]//2 |
| y_low, y_high = new_point[1] - geo.shape[1]//2, new_point[1] + geo.shape[1]//2 |
| z_low, z_high = new_point[2] - geo.shape[2]//2, new_point[2] + geo.shape[2]//2 |
| |
| |
| geo_mask[x_low:x_high, y_low:y_high, z_low:z_high] += geo |
| |
| |
| |
| num_tumor = random.randint(2, 5) |
| for _ in range(num_tumor): |
| |
| x = random.randint(int(0.75*medium_radius), int(1.25*medium_radius)) |
| y = random.randint(int(0.75*medium_radius), int(1.25*medium_radius)) |
| z = random.randint(int(0.75*medium_radius), int(1.25*medium_radius)) |
| sigma = random.randint(3, 6) |
| |
| geo = get_ellipsoid(x, y, z) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,1)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(1,2)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,2)) |
| |
| point = random_select(mask_scan) |
| new_point = [point[0] + enlarge_x//2, point[1] + enlarge_y//2, point[2] + enlarge_z//2] |
| x_low, x_high = new_point[0] - geo.shape[0]//2, new_point[0] + geo.shape[0]//2 |
| y_low, y_high = new_point[1] - geo.shape[1]//2, new_point[1] + geo.shape[1]//2 |
| z_low, z_high = new_point[2] - geo.shape[2]//2, new_point[2] + geo.shape[2]//2 |
| |
| |
| geo_mask[x_low:x_high, y_low:y_high, z_low:z_high] += geo |
| |
|
|
| |
| num_tumor = random.randint(1,3) |
| for _ in range(num_tumor): |
| |
| x = random.randint(int(0.75*large_radius), int(1.25*large_radius)) |
| y = random.randint(int(0.75*large_radius), int(1.25*large_radius)) |
| z = random.randint(int(0.75*large_radius), int(1.25*large_radius)) |
| sigma = random.randint(5, 10) |
| geo = get_ellipsoid(x, y, z) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,1)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(1,2)) |
| geo = elasticdeform.deform_random_grid(geo, sigma=sigma, points=3, order=0, axis=(0,2)) |
| |
| point = random_select(mask_scan) |
| new_point = [point[0] + enlarge_x//2, point[1] + enlarge_y//2, point[2] + enlarge_z//2] |
| x_low, x_high = new_point[0] - geo.shape[0]//2, new_point[0] + geo.shape[0]//2 |
| y_low, y_high = new_point[1] - geo.shape[1]//2, new_point[1] + geo.shape[1]//2 |
| z_low, z_high = new_point[2] - geo.shape[2]//2, new_point[2] + geo.shape[2]//2 |
| |
| |
| geo_mask[x_low:x_high, y_low:y_high, z_low:z_high] += geo |
| |
|
|
| geo_mask = geo_mask[enlarge_x//2:-enlarge_x//2, enlarge_y//2:-enlarge_y//2, enlarge_z//2:-enlarge_z//2] |
| |
| geo_mask = (geo_mask * mask_scan) >=1 |
| |
| return geo_mask |
|
|
|
|
| def SynthesisTumor(mask_scan, tumor_type, texture): |
| |
| x_start, x_end = np.where(np.any(mask_scan, axis=(1, 2)))[0][[0, -1]] |
| y_start, y_end = np.where(np.any(mask_scan, axis=(0, 2)))[0][[0, -1]] |
| z_start, z_end = np.where(np.any(mask_scan, axis=(0, 1)))[0][[0, -1]] |
|
|
| |
| x_start, x_end = max(0, x_start+1), min(mask_scan.shape[0], x_end-1) |
| y_start, y_end = max(0, y_start+1), min(mask_scan.shape[1], y_end-1) |
| z_start, z_end = max(0, z_start+1), min(mask_scan.shape[2], z_end-1) |
|
|
| liver_mask = get_fixed_geo(mask_scan, tumor_type) |
|
|
| mask_scan[x_start:x_end, y_start:y_end, z_start:z_end] = liver_mask |
|
|
| return mask_scan |
|
|
| if __name__ == 'main': |
| geo_mask = get_fixed_geo(mask_scan, tumor_type) |
| |