From 7088bd713adde94127ef88ae123162f6b773c8e8 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Sat, 9 May 2020 15:59:58 -0700 Subject: [PATCH 01/91] Update cli.py --- pathflow_mixmatch/cli.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 9943594..96c14b0 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -207,18 +207,18 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari print("Result parameters:") transformation.print() - # plot the results - plt.subplot(131) - plt.imshow(fixed_image.numpy(), cmap='gray') - plt.title('Fixed Image') - - plt.subplot(132) - plt.imshow(moving_image.numpy(), cmap='gray') - plt.title('Moving Image') - - plt.subplot(133) - plt.imshow(warped_image.numpy(), cmap='gray') - plt.title('Warped Moving Image') + # # plot the results + # plt.subplot(131) + # plt.imshow(fixed_image.numpy(), cmap='gray') + # plt.title('Fixed Image') + # + # plt.subplot(132) + # plt.imshow(moving_image.numpy(), cmap='gray') + # plt.title('Moving Image') + # + # plt.subplot(133) + # plt.imshow(warped_image.numpy(), cmap='gray') + # plt.title('Warped Moving Image') if transform_type in ['similarity', 'affine', 'rigid']: transformation_param = transformation._phi_z From 78fd608fdcc5606bbc66bfd0d523a8135e246fd6 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Sat, 9 May 2020 16:06:42 -0700 Subject: [PATCH 02/91] Update cli.py --- pathflow_mixmatch/cli.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 96c14b0..e6a9824 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -100,8 +100,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # load the image data and normalize to [0, 1] # add mask to loss function - fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device=device)#al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# - moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device=device)#al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# + fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# + moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) @@ -124,7 +124,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['similarity', 'affine', 'rigid']: transform_opts=dict(opt_cm=opt_cm) transform_args=[moving_image] - sigma,fixed_image_pyramid,moving_image_pyramid=[[]],[[]],[[]] + sigma,fixed_image_pyramid,moving_image_pyramid=[[]],[fixed_image],[moving_image] else: transform_opts=dict(diffeomorphic=opt_cm, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) transform_args=[moving_image.size] @@ -141,6 +141,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): + mov_im_level,fix_im_level=mov_im_level.to(device),fix_im_level.to(device) + # choose the affine transformation model if transform_type == 'non_parametric': transform_args[0]=mov_im_level[level].size @@ -162,7 +164,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['similarity', 'affine', 'rigid']: # initialize the translation with the center of mass of the fixed image - transformation.init_translation(fixed_image) + transformation.init_translation(fix_im_level) registration.set_transformation(transformation) @@ -174,7 +176,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari ssim=al.loss.pairwise.SSIM) # choose the Mean Squared Error as image loss - image_loss = loss_fns[loss_fn](fixed_image, moving_image) + image_loss = loss_fns[loss_fn](fix_im_level, mov_im_level) registration.set_image_loss([image_loss]) From 38b3540358939a0dd75f76b14a56a8026c6edfd9 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Sat, 9 May 2020 16:10:15 -0700 Subject: [PATCH 03/91] Update cli.py --- pathflow_mixmatch/cli.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index e6a9824..f13ece5 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -141,7 +141,10 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): - mov_im_level,fix_im_level=mov_im_level.to(device),fix_im_level.to(device) + mov_im_level=mov_im_level.to(device) + print(mov_im_level.shape) + fix_im_level=fix_im_level.to(device) + print(fix_im_level.shape) # choose the affine transformation model if transform_type == 'non_parametric': From af1515edb4d4c61d0f6ed784a5927b88bcae0e24 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Sat, 9 May 2020 16:11:26 -0700 Subject: [PATCH 04/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index f13ece5..65224ba 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -155,7 +155,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # microarchitectural details # transform_opts['sigma'] = sigma[level] - transform_opts['sigma'] = (1, 1) + transform_opts['sigma'] = sigma[level]#(1, 1) transformation = transforms[transform_type](*transform_args,**transform_opts) From 9256a2d730fe67de1cbd998f0aef35803fd2ffa9 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Sat, 9 May 2020 16:13:16 -0700 Subject: [PATCH 05/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 65224ba..072e224 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -141,9 +141,9 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): - mov_im_level=mov_im_level.to(device) + mov_im_level=mov_im_level.cuda() print(mov_im_level.shape) - fix_im_level=fix_im_level.to(device) + fix_im_level=fix_im_level.cuda() print(fix_im_level.shape) # choose the affine transformation model From e390f48691f963e9cf1b858a01331465e804ddfb Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Sat, 9 May 2020 16:16:06 -0700 Subject: [PATCH 06/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 072e224..6ea5c2a 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -141,9 +141,9 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): - mov_im_level=mov_im_level.cuda() + mov_im_level=mov_im_level.to(device=device) print(mov_im_level.shape) - fix_im_level=fix_im_level.cuda() + fix_im_level=fix_im_level.to(device=device) print(fix_im_level.shape) # choose the affine transformation model From 5f149982fa81daacd6e3999890e1a76e6114fcc6 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Sat, 9 May 2020 16:17:33 -0700 Subject: [PATCH 07/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 6ea5c2a..73e8803 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -142,9 +142,9 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): mov_im_level=mov_im_level.to(device=device) - print(mov_im_level.shape) + print(mov_im_level.image.shape) fix_im_level=fix_im_level.to(device=device) - print(fix_im_level.shape) + print(fix_im_level.image.shape) # choose the affine transformation model if transform_type == 'non_parametric': From e9c459a1b7d966e7101451209bbe2780ba236ada Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Sat, 9 May 2020 16:24:10 -0700 Subject: [PATCH 08/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 73e8803..bea22ec 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -153,7 +153,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # for bspline, sigma must be positive tuple of ints # for bspline, smaller sigma tuple means less loss of # microarchitectural details - + transform_args[0]=mov_im_level[level].size # transform_opts['sigma'] = sigma[level] transform_opts['sigma'] = sigma[level]#(1, 1) From 26acff475f796eb1c6bca8aa377e29801d22f246 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Sat, 9 May 2020 16:25:28 -0700 Subject: [PATCH 09/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index bea22ec..232a89b 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -148,12 +148,12 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # choose the affine transformation model if transform_type == 'non_parametric': - transform_args[0]=mov_im_level[level].size + transform_args[0]=mov_im_level.size elif transform_type in ['bspline','wendland']: # for bspline, sigma must be positive tuple of ints # for bspline, smaller sigma tuple means less loss of # microarchitectural details - transform_args[0]=mov_im_level[level].size + transform_args[0]=mov_im_level.size # transform_opts['sigma'] = sigma[level] transform_opts['sigma'] = sigma[level]#(1, 1) From e6c28e3546a656b22a793f5e959242904dc99a7b Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 19:05:17 -0700 Subject: [PATCH 10/91] Update cli.py --- pathflow_mixmatch/cli.py | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 232a89b..114fc66 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -84,13 +84,13 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # limitations under the License. -def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similarity', gpu_device=0, opt_cm=True, sigma=[[11,11],[11,11],[3,3]], order=2, pyramid=[[4,4],[2,2]], loss_fn='mse', use_mask=False, interpolation='bicubic'): +def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similarity', gpu_device=0, opt_cm=True, sigma=[[11,11],[11,11],[3,3]], order=2, pyramid=[[4,4],[2,2]], loss_fn='mse', use_mask=False, interpolation='bicubic', half=False): assert use_mask==False, "Masking not implemented" assert transform_type in ['similarity', 'affine', 'rigid', 'non_parametric','bspline','wendland'] start = time.perf_counter() # set the used data type - dtype = th.float32 + dtype = th.float32 if not half else th.half # set the device for the computaion to CPU device = th.device("cuda:{}".format(gpu_device) if gpu_device >=0 else 'cpu') @@ -100,8 +100,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # load the image data and normalize to [0, 1] # add mask to loss function - fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# - moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# + fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32 if not half else th.half, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# + moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32 if not half else th.half, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) @@ -359,7 +359,8 @@ def register_images_(im1_fname='A.npy', sigma=[[11,11],[11,11],[3,3]], order=2, pyramid=[[4,4],[2,2]], - interpolation='bicubic'): + interpolation='bicubic', + half=False): print("Loading images.") @@ -458,7 +459,7 @@ def register_images_(im1_fname='A.npy', print("[{}/{}] - Begin alignment of sections.".format(idx+1,N)) with (suppress_stdout() if not verbose else contextlib.suppress()): - new_img=displace_image(img2,affine_register(img1, img2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation)[0],gpu_device=gpu_device) # new tri, output he as well + new_img=displace_image(img2,affine_register(img1, img2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half)[0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well if gpu_device>=0: th.cuda.empty_cache() @@ -478,7 +479,7 @@ def register_images_(im1_fname='A.npy', print("Performing registration.") with (suppress_stdout() if not verbose else contextlib.suppress()): - new_img=displace_image(im2,affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation)[0],gpu_device=gpu_device) # new tri, output he as well + new_img=displace_image(im2,affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half)[0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well if gpu_device>=0: th.cuda.empty_cache() @@ -550,7 +551,8 @@ def register_images(self, sigma=[[11,11],[11,11],[3,3]], order=2, pyramid=[[4,4],[2,2]], - interpolation='bicubic'): + interpolation='bicubic', + half=False): register_images_(im1_fname=im1, im2_fname=im2, connectivity=connectivity, @@ -576,7 +578,8 @@ def register_images(self, sigma=sigma, order=order, pyramid=pyramid, - interpolation=interpolation) + interpolation=interpolation, + half=half) def main(): fire.Fire(Commands) From dfc19b3129f6a0156d7c61df62b6c295b48f0d9e Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 19:18:50 -0700 Subject: [PATCH 11/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 114fc66..27560f7 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -100,8 +100,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # load the image data and normalize to [0, 1] # add mask to loss function - fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32 if not half else th.half, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# - moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32 if not half else th.half, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# + fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32 if not half else th.float16, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# + moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32 if not half else th.float16, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) From 5d47b7354e67cf588f831873f185ca8a62f0a2bc Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 19:26:54 -0700 Subject: [PATCH 12/91] Update cli.py --- pathflow_mixmatch/cli.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 27560f7..3a2d090 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -100,8 +100,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # load the image data and normalize to [0, 1] # add mask to loss function - fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32 if not half else th.float16, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# - moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32 if not half else th.float16, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# + fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# + moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) @@ -141,9 +141,9 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): - mov_im_level=mov_im_level.to(device=device) + mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) print(mov_im_level.image.shape) - fix_im_level=fix_im_level.to(device=device) + fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) print(fix_im_level.image.shape) # choose the affine transformation model From a2af3a7ee063482d0f2ec9b2835331968c902c69 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 19:59:34 -0700 Subject: [PATCH 13/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 3a2d090..1c6adfa 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -139,6 +139,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type=='wendland': transform_opts['cp_scale']=order + transform_opts['dtype']=dtype + for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) From 41f1176e27d0af2aaaaa0b3374d2f77c2c9cdc84 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 20:16:03 -0700 Subject: [PATCH 14/91] Update cli.py --- pathflow_mixmatch/cli.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 1c6adfa..0037d0e 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -28,6 +28,8 @@ import matplotlib.pyplot as plt from contextlib import contextmanager import sys, os +from apex import amp + @contextmanager def suppress_stdout(): @@ -171,6 +173,10 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # initialize the translation with the center of mass of the fixed image transformation.init_translation(fix_im_level) + opt_level = 'O1' + optimizer = th.optim.Adam(transformation.parameters(), lr=lr, amsgrad=True) + model, optimizer = amp.initialize(model, optimizer, opt_level=opt_level) + registration.set_transformation(transformation) loss_fns=dict(mse=al.loss.pairwise.MSE, @@ -186,7 +192,6 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari registration.set_image_loss([image_loss]) # choose the Adam optimizer to minimize the objective - optimizer = th.optim.Adam(transformation.parameters(), lr=lr, amsgrad=True) registration.set_optimizer(optimizer) registration.set_number_of_iterations(iterations) From 4f1c948e66eba6d9321bb576627b004bef8d709a Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 20:17:37 -0700 Subject: [PATCH 15/91] Update cli.py --- pathflow_mixmatch/cli.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 0037d0e..b0f628c 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -173,9 +173,10 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # initialize the translation with the center of mass of the fixed image transformation.init_translation(fix_im_level) - opt_level = 'O1' + optimizer = th.optim.Adam(transformation.parameters(), lr=lr, amsgrad=True) - model, optimizer = amp.initialize(model, optimizer, opt_level=opt_level) + opt_level = 'O1' + model, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) registration.set_transformation(transformation) From 37acb7f6a854513d41775ebf816930602f66f830 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 20:18:49 -0700 Subject: [PATCH 16/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index b0f628c..62369f6 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -141,7 +141,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type=='wendland': transform_opts['cp_scale']=order - transform_opts['dtype']=dtype + # transform_opts['dtype']=dtype for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): @@ -176,7 +176,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari optimizer = th.optim.Adam(transformation.parameters(), lr=lr, amsgrad=True) opt_level = 'O1' - model, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) + transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) registration.set_transformation(transformation) From e91aa3a5e4769923dc4e2f2b54328a2150b31e7f Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 20:39:07 -0700 Subject: [PATCH 17/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 62369f6..b41bf6c 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -175,7 +175,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari optimizer = th.optim.Adam(transformation.parameters(), lr=lr, amsgrad=True) - opt_level = 'O1' + opt_level = 'O2' transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) registration.set_transformation(transformation) From ce5c5dc175120e2c317b9e38c6cace18aaa34365 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 20:48:50 -0700 Subject: [PATCH 18/91] Update cli.py --- pathflow_mixmatch/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index b41bf6c..0360b9f 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -173,6 +173,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # initialize the translation with the center of mass of the fixed image transformation.init_translation(fix_im_level) + transformation=transformation.to(dtype=th.float32 if not half else th.float16, device=device) optimizer = th.optim.Adam(transformation.parameters(), lr=lr, amsgrad=True) opt_level = 'O2' From e4c5797bec32c3f0b398d53054c939b405761659 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 21:17:58 -0700 Subject: [PATCH 19/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 0360b9f..3423d29 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -242,7 +242,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation_param = transformation._kernel else: pass - return displacement, warped_image, transformation_param, registration.loss.data.item() + return displacement, warped_image, transformation_param, registration.loss#.data.item() def get_loss(im1,im2,gpu_device): From 08f266f020a414fbb98a2711d3912af551c6daa6 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 21:59:41 -0700 Subject: [PATCH 20/91] Update cli.py --- pathflow_mixmatch/cli.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 3423d29..3f26263 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -163,11 +163,11 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation = transforms[transform_type](*transform_args,**transform_opts) - # if level > 0 and transform_type=='bspline': - # constant_flow = al.transformation.utils.upsample_displacement(constant_flow, - # mov_im_level.size, - # interpolation=interpolation) - # transformation.set_constant_flow(constant_flow) + if level > 0 and transform_type in ['bspline','wendland']: + constant_flow = al.transformation.utils.upsample_displacement(constant_flow, + mov_im_level.size, + interpolation=interpolation) + transformation.set_constant_flow(constant_flow) if transform_type in ['similarity', 'affine', 'rigid']: # initialize the translation with the center of mass of the fixed image @@ -201,8 +201,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # start the registration registration.start() - # if transform_type == 'bspline': - # constant_flow = transformation.get_flow() + if transform_type in ['bspline','wendland']: + constant_flow = transformation.get_flow() # set the intensities back to the original for the visualisation fixed_image.image = 1 - fixed_image.image From 9c05b5f1ec8f4dbcc20cd06cf908d400233f6a5c Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 22:03:55 -0700 Subject: [PATCH 21/91] Debug --- bin/install_mixmatch_dependencies | 3 +++ pathflow_mixmatch/cli.py | 1 + setup.py | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 bin/install_mixmatch_dependencies diff --git a/bin/install_mixmatch_dependencies b/bin/install_mixmatch_dependencies new file mode 100644 index 0000000..50fe6c6 --- /dev/null +++ b/bin/install_mixmatch_dependencies @@ -0,0 +1,3 @@ +#!/bin/bash +pip install git+https://github.com/jlevy44/airlab.git --upgrade +pip install git+https://github.com/jlevy44/PathFlow-MixMatch@fix_nonlinear_memory_issues --upgrade diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 3f26263..66c1727 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -164,6 +164,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation = transforms[transform_type](*transform_args,**transform_opts) if level > 0 and transform_type in ['bspline','wendland']: + print(interpolation) constant_flow = al.transformation.utils.upsample_displacement(constant_flow, mov_im_level.size, interpolation=interpolation) diff --git a/setup.py b/setup.py index c55b0d1..1a39a19 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ author='Joshua Levy', author_email='joshualevy44@berkeley.edu', license='MIT', - scripts=[], + scripts=['bin/install_mixmatch_dependencies'], entry_points={ 'console_scripts':['pathflow-mixmatch=pathflow_mixmatch.cli:main'] }, From eb582733111a143867c7e6669e5f4675b024ba79 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 22:14:00 -0700 Subject: [PATCH 22/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 66c1727..0265698 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -135,7 +135,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari fixed_image_pyramid = al.create_image_pyramid(fixed_image, pyramid) moving_image_pyramid = al.create_image_pyramid(moving_image, pyramid) else: - sigma,fixed_image_pyramid,moving_image_pyramid=[[]],[[fixed_image]],[[moving_image]] + sigma,fixed_image_pyramid,moving_image_pyramid=[[]],[fixed_image],[moving_image] if transform_type=='bspline': transform_opts['order']=order if transform_type=='wendland': From 7f918b77229ddc269d442e258175f53d8d3a4950 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 22:34:29 -0700 Subject: [PATCH 23/91] Update cli.py --- pathflow_mixmatch/cli.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 0265698..199b629 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -125,6 +125,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['similarity', 'affine', 'rigid']: transform_opts=dict(opt_cm=opt_cm) + transform_opts['half'] = half transform_args=[moving_image] sigma,fixed_image_pyramid,moving_image_pyramid=[[]],[fixed_image],[moving_image] else: @@ -132,6 +133,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transform_args=[moving_image.size] if transform_type in ['bspline','wendland']: transform_opts['sigma']=sigma + transform_opts['half'] = half fixed_image_pyramid = al.create_image_pyramid(fixed_image, pyramid) moving_image_pyramid = al.create_image_pyramid(moving_image, pyramid) else: @@ -176,8 +178,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation=transformation.to(dtype=th.float32 if not half else th.float16, device=device) - optimizer = th.optim.Adam(transformation.parameters(), lr=lr, amsgrad=True) - opt_level = 'O2' + optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) + opt_level = "O2" if half else "01" transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) registration.set_transformation(transformation) @@ -359,7 +361,7 @@ def register_images_(im1_fname='A.npy', gpu_device=0, max_rotation_vertical_px=0, loss_fn='mse', - lr=0.01, + lr=[0.01]*3, transform_type='rigid', iterations=1000, no_segment_analysis=False, From a5df743032750e5287fed66d142500c2c6e804bc Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 22:37:31 -0700 Subject: [PATCH 24/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 199b629..affc941 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -179,7 +179,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation=transformation.to(dtype=th.float32 if not half else th.float16, device=device) optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) - opt_level = "O2" if half else "01" + opt_level = "O2" if half else "O1" transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) registration.set_transformation(transformation) From 4d7bc2f72939440dd10cc213e150e63a53d2a94f Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 22:40:04 -0700 Subject: [PATCH 25/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index affc941..cf6b0d6 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -176,7 +176,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # initialize the translation with the center of mass of the fixed image transformation.init_translation(fix_im_level) - transformation=transformation.to(dtype=th.float32 if not half else th.float16, device=device) + transformation=transformation.to(dtype=th.float32, device=device)# if not half else th.float16 optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) opt_level = "O2" if half else "O1" From 619498272c3bcaaa8674700afb90554ed0553ad2 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 22:51:57 -0700 Subject: [PATCH 26/91] Update cli.py --- pathflow_mixmatch/cli.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index cf6b0d6..415ea81 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -125,7 +125,6 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['similarity', 'affine', 'rigid']: transform_opts=dict(opt_cm=opt_cm) - transform_opts['half'] = half transform_args=[moving_image] sigma,fixed_image_pyramid,moving_image_pyramid=[[]],[fixed_image],[moving_image] else: @@ -133,7 +132,6 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transform_args=[moving_image.size] if transform_type in ['bspline','wendland']: transform_opts['sigma']=sigma - transform_opts['half'] = half fixed_image_pyramid = al.create_image_pyramid(fixed_image, pyramid) moving_image_pyramid = al.create_image_pyramid(moving_image, pyramid) else: @@ -144,6 +142,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transform_opts['cp_scale']=order # transform_opts['dtype']=dtype + transform_opts['half']=half for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): From 9e4661fc2d19ca4b07ccb59a6f0699a5b448653c Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 23:07:46 -0700 Subject: [PATCH 27/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 415ea81..ce05548 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -113,7 +113,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari moving_image.image = 1 - moving_image.image # create pairwise registration object - registration = al.PairwiseRegistration() + registration = al.PairwiseRegistration(half=half) transforms=dict(similarity=al.transformation.pairwise.SimilarityTransformation, affine=al.transformation.pairwise.AffineTransformation, From df1867172038f6c0b4c46f40aa6f85b41bb0889d Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 23:30:53 -0700 Subject: [PATCH 28/91] Update cli.py --- pathflow_mixmatch/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index ce05548..06a9b39 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -175,11 +175,12 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # initialize the translation with the center of mass of the fixed image transformation.init_translation(fix_im_level) - transformation=transformation.to(dtype=th.float32, device=device)# if not half else th.float16 + # transformation=transformation.to(dtype=th.float32, device=device)# if not half else th.float16 optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) opt_level = "O2" if half else "O1" transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) + print(transformation.state_dict()) registration.set_transformation(transformation) From c5acf5b3b601e1371815c3c6adea3651dddd74ef Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 23:32:07 -0700 Subject: [PATCH 29/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 06a9b39..97efa17 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -175,7 +175,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # initialize the translation with the center of mass of the fixed image transformation.init_translation(fix_im_level) - # transformation=transformation.to(dtype=th.float32, device=device)# if not half else th.float16 + transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) opt_level = "O2" if half else "O1" From 2e8952eca971992064fb9b92afc4ab7120ca465c Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 23:34:02 -0700 Subject: [PATCH 30/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 97efa17..754c3ed 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -92,7 +92,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari start = time.perf_counter() # set the used data type - dtype = th.float32 if not half else th.half + dtype = th.float32# if not half else th.half # set the device for the computaion to CPU device = th.device("cuda:{}".format(gpu_device) if gpu_device >=0 else 'cpu') From 849894b10c2d810a0779fd85b7df571dce303aae Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 23:49:34 -0700 Subject: [PATCH 31/91] Update cli.py --- pathflow_mixmatch/cli.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 754c3ed..3c5d1e9 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -146,11 +146,6 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): - mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) - print(mov_im_level.image.shape) - fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) - print(fix_im_level.image.shape) - # choose the affine transformation model if transform_type == 'non_parametric': transform_args[0]=mov_im_level.size @@ -191,6 +186,12 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari mgf=al.loss.pairwise.NGF, ssim=al.loss.pairwise.SSIM) + fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) + print(fix_im_level.image.shape) + + mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) + print(mov_im_level.image.shape) + # choose the Mean Squared Error as image loss image_loss = loss_fns[loss_fn](fix_im_level, mov_im_level) From 0c5a79bbee861c52b6712b798c281c973ea94686 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Mon, 11 May 2020 23:56:15 -0700 Subject: [PATCH 32/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 3c5d1e9..fb4aaab 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -175,7 +175,6 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) opt_level = "O2" if half else "O1" transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) - print(transformation.state_dict()) registration.set_transformation(transformation) @@ -187,10 +186,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari ssim=al.loss.pairwise.SSIM) fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) - print(fix_im_level.image.shape) - mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) - print(mov_im_level.image.shape) # choose the Mean Squared Error as image loss image_loss = loss_fns[loss_fn](fix_im_level, mov_im_level) From 0544d4295681545705066180a9daddc805052f7a Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 00:20:28 -0700 Subject: [PATCH 33/91] Update cli.py --- pathflow_mixmatch/cli.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index fb4aaab..ec83936 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -141,7 +141,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type=='wendland': transform_opts['cp_scale']=order - # transform_opts['dtype']=dtype + transform_opts['dtype']=th.float32 if not half else th.half transform_opts['half']=half for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): @@ -171,6 +171,9 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation.init_translation(fix_im_level) transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 + if th.cuda.is_available(): + transformation=transformation.cuda() + transformation._device=("cuda:{}".format(gpu_device) if gpu_device >=0 else 'cpu') optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) opt_level = "O2" if half else "O1" From 42873f8f150b8d1e4329d5f213023247d690e66a Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 00:23:30 -0700 Subject: [PATCH 34/91] Update cli.py --- pathflow_mixmatch/cli.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index ec83936..89cd9e1 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -159,6 +159,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation = transforms[transform_type](*transform_args,**transform_opts) + transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 + if level > 0 and transform_type in ['bspline','wendland']: print(interpolation) constant_flow = al.transformation.utils.upsample_displacement(constant_flow, @@ -170,11 +172,6 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # initialize the translation with the center of mass of the fixed image transformation.init_translation(fix_im_level) - transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 - if th.cuda.is_available(): - transformation=transformation.cuda() - transformation._device=("cuda:{}".format(gpu_device) if gpu_device >=0 else 'cpu') - optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) opt_level = "O2" if half else "O1" transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) From 89145749c4a599405955d2afe878acc122760b0b Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 00:24:21 -0700 Subject: [PATCH 35/91] Update cli.py --- pathflow_mixmatch/cli.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 89cd9e1..7ec7a5c 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -141,7 +141,6 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type=='wendland': transform_opts['cp_scale']=order - transform_opts['dtype']=th.float32 if not half else th.half transform_opts['half']=half for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): From cfaa602c57fe75f32ce3ce45c8eb7c5d03e1fa25 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 00:28:45 -0700 Subject: [PATCH 36/91] Update cli.py --- pathflow_mixmatch/cli.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 7ec7a5c..f4ad63f 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -156,6 +156,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # transform_opts['sigma'] = sigma[level] transform_opts['sigma'] = sigma[level]#(1, 1) + fix_im_level=fix_im_level.to(dtype=th.float32, device=device) + transformation = transforms[transform_type](*transform_args,**transform_opts) transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 @@ -184,7 +186,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari mgf=al.loss.pairwise.NGF, ssim=al.loss.pairwise.SSIM) - fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) + if half: + fix_im_level=fix_im_level.half() mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) # choose the Mean Squared Error as image loss From aee804ef2dcc45c7649402c12ab55a5429abd485 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 00:30:08 -0700 Subject: [PATCH 37/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index f4ad63f..9b64b43 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -187,7 +187,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari ssim=al.loss.pairwise.SSIM) if half: - fix_im_level=fix_im_level.half() + fix_im_level=fix_im_level.to(dtype=th.float16) mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) # choose the Mean Squared Error as image loss From ebfec5126d471c88a2b00d84b335f3f7084bf298 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 00:31:41 -0700 Subject: [PATCH 38/91] Update cli.py --- pathflow_mixmatch/cli.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 9b64b43..7320b2c 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -186,8 +186,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari mgf=al.loss.pairwise.NGF, ssim=al.loss.pairwise.SSIM) - if half: - fix_im_level=fix_im_level.to(dtype=th.float16) + fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) # choose the Mean Squared Error as image loss From d536fba639d388b51e7437986769cea07c1c9c34 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 00:35:43 -0700 Subject: [PATCH 39/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 7320b2c..6362c9a 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -160,7 +160,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation = transforms[transform_type](*transform_args,**transform_opts) - transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 + # transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 if level > 0 and transform_type in ['bspline','wendland']: print(interpolation) From 57c4c80566711f262aae1a5194fe47f97369c629 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 00:41:19 -0700 Subject: [PATCH 40/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 6362c9a..7320b2c 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -160,7 +160,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation = transforms[transform_type](*transform_args,**transform_opts) - # transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 + transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 if level > 0 and transform_type in ['bspline','wendland']: print(interpolation) From 4f6744886f72ccc45b8c74e978bb65eabd7e6f2e Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 00:48:21 -0700 Subject: [PATCH 41/91] Update cli.py --- pathflow_mixmatch/cli.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 7320b2c..fccb87e 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -125,7 +125,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['similarity', 'affine', 'rigid']: transform_opts=dict(opt_cm=opt_cm) - transform_args=[moving_image] + transform_args=[0] sigma,fixed_image_pyramid,moving_image_pyramid=[[]],[fixed_image],[moving_image] else: transform_opts=dict(diffeomorphic=opt_cm, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) @@ -155,10 +155,13 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transform_args[0]=mov_im_level.size # transform_opts['sigma'] = sigma[level] transform_opts['sigma'] = sigma[level]#(1, 1) - - fix_im_level=fix_im_level.to(dtype=th.float32, device=device) + else: + mov_im_level=mov_im_level.to(dtype=th.float32, device=device) + transform_args[0]=mov_im_level transformation = transforms[transform_type](*transform_args,**transform_opts) + + mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 @@ -171,7 +174,9 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['similarity', 'affine', 'rigid']: # initialize the translation with the center of mass of the fixed image + fix_im_level=fix_im_level.to(dtype=th.float32, device=device) transformation.init_translation(fix_im_level) + fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) opt_level = "O2" if half else "O1" @@ -186,8 +191,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari mgf=al.loss.pairwise.NGF, ssim=al.loss.pairwise.SSIM) - fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) - mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) + # choose the Mean Squared Error as image loss image_loss = loss_fns[loss_fn](fix_im_level, mov_im_level) From ab2c9e0f1ffc27093bcb5b787edce556db8afe93 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 01:06:15 -0700 Subject: [PATCH 42/91] Update cli.py --- pathflow_mixmatch/cli.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index fccb87e..3f81709 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -145,6 +145,9 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): + fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) + mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) + # choose the affine transformation model if transform_type == 'non_parametric': transform_args[0]=mov_im_level.size @@ -156,12 +159,9 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # transform_opts['sigma'] = sigma[level] transform_opts['sigma'] = sigma[level]#(1, 1) else: - mov_im_level=mov_im_level.to(dtype=th.float32, device=device) transform_args[0]=mov_im_level transformation = transforms[transform_type](*transform_args,**transform_opts) - - mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 @@ -174,9 +174,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['similarity', 'affine', 'rigid']: # initialize the translation with the center of mass of the fixed image - fix_im_level=fix_im_level.to(dtype=th.float32, device=device) transformation.init_translation(fix_im_level) - fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) opt_level = "O2" if half else "O1" From 2612785b5072b8be314d3dd17d123f49f591e0cd Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 01:11:12 -0700 Subject: [PATCH 43/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 3f81709..541674d 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -145,7 +145,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): - fix_im_level=fix_im_level.to(dtype=th.float32 if not half else th.float16, device=device) + fix_im_level=fix_im_level.to(dtype=th.float32, device=device) mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) # choose the affine transformation model @@ -175,6 +175,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['similarity', 'affine', 'rigid']: # initialize the translation with the center of mass of the fixed image transformation.init_translation(fix_im_level) + if half: + fix_im_level=fix_im_level.to(dtype=th.float16, device=device) optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) opt_level = "O2" if half else "O1" From 6c5fa999178280f3b5e4069cef5e7cee5c395e90 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 01:16:54 -0700 Subject: [PATCH 44/91] Update cli.py --- pathflow_mixmatch/cli.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 541674d..5e23943 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -145,9 +145,9 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): - fix_im_level=fix_im_level.to(dtype=th.float32, device=device) - mov_im_level=mov_im_level.to(dtype=th.float32 if not half else th.float16, device=device) + + mov_im_level=mov_im_level.to(dtype=th.float32, device=device) # choose the affine transformation model if transform_type == 'non_parametric': transform_args[0]=mov_im_level.size @@ -163,6 +163,9 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation = transforms[transform_type](*transform_args,**transform_opts) + if half: + mov_im_level=mov_im_level.to(dtype=th.float16, device=device) + transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 if level > 0 and transform_type in ['bspline','wendland']: @@ -172,6 +175,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari interpolation=interpolation) transformation.set_constant_flow(constant_flow) + fix_im_level=fix_im_level.to(dtype=th.float32, device=device) if transform_type in ['similarity', 'affine', 'rigid']: # initialize the translation with the center of mass of the fixed image transformation.init_translation(fix_im_level) From 872b873541ac400f4ca157165c7fbfac6a8cd5c6 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 01:22:41 -0700 Subject: [PATCH 45/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 5e23943..c6d9304 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -166,7 +166,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if half: mov_im_level=mov_im_level.to(dtype=th.float16, device=device) - transformation=transformation.to(device=device)# dtype=th.float32, if not half else th.float16 + transformation=transformation.to(dtype=th.float32, device=device)# dtype=th.float32, if not half else th.float16 if level > 0 and transform_type in ['bspline','wendland']: print(interpolation) From e2372e42f8b895b56e2867becaa78d39bd2f888f Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 01:28:58 -0700 Subject: [PATCH 46/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index c6d9304..7ae535d 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -181,6 +181,10 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation.init_translation(fix_im_level) if half: fix_im_level=fix_im_level.to(dtype=th.float16, device=device) + transformation._dtype=th.float16 + transformation._device=device + + optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) opt_level = "O2" if half else "O1" From d1f1517c1cd32404971398a2029c06a925634a82 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 01:32:37 -0700 Subject: [PATCH 47/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 7ae535d..fdf7939 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -159,7 +159,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # transform_opts['sigma'] = sigma[level] transform_opts['sigma'] = sigma[level]#(1, 1) else: - transform_args[0]=mov_im_level + transform_args[0]=moving_image transformation = transforms[transform_type](*transform_args,**transform_opts) From 2f8dceb23070c60d213f482f2749353968e03ebb Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 01:34:35 -0700 Subject: [PATCH 48/91] Update cli.py --- pathflow_mixmatch/cli.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index fdf7939..9479aab 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -144,9 +144,6 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transform_opts['half']=half for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): - - - mov_im_level=mov_im_level.to(dtype=th.float32, device=device) # choose the affine transformation model if transform_type == 'non_parametric': @@ -159,7 +156,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # transform_opts['sigma'] = sigma[level] transform_opts['sigma'] = sigma[level]#(1, 1) else: - transform_args[0]=moving_image + transform_args[0]=mov_im_level transformation = transforms[transform_type](*transform_args,**transform_opts) From 34829835d5b204109b662f5142bfafe588d3b7d2 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 08:54:52 -0700 Subject: [PATCH 49/91] Working with lower res --- bin/install_mixmatch_dependencies | 2 +- pathflow_mixmatch/cli.py | 34 ++++++++++++++++++++----------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/bin/install_mixmatch_dependencies b/bin/install_mixmatch_dependencies index 50fe6c6..b977c0c 100644 --- a/bin/install_mixmatch_dependencies +++ b/bin/install_mixmatch_dependencies @@ -1,3 +1,3 @@ #!/bin/bash -pip install git+https://github.com/jlevy44/airlab.git --upgrade +pip install git+https://github.com/jlevy44/airlab.git@no_mixed_precision --upgrade pip install git+https://github.com/jlevy44/PathFlow-MixMatch@fix_nonlinear_memory_issues --upgrade diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 9479aab..b6f74c1 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -28,7 +28,7 @@ import matplotlib.pyplot as plt from contextlib import contextmanager import sys, os -from apex import amp +# from apex import amp @contextmanager @@ -89,6 +89,8 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similarity', gpu_device=0, opt_cm=True, sigma=[[11,11],[11,11],[3,3]], order=2, pyramid=[[4,4],[2,2]], loss_fn='mse', use_mask=False, interpolation='bicubic', half=False): assert use_mask==False, "Masking not implemented" assert transform_type in ['similarity', 'affine', 'rigid', 'non_parametric','bspline','wendland'] + if half: + raise NotImplementedError start = time.perf_counter() # set the used data type @@ -141,10 +143,11 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type=='wendland': transform_opts['cp_scale']=order - transform_opts['half']=half + # transform_opts['half']=half for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): mov_im_level=mov_im_level.to(dtype=th.float32, device=device) + fix_im_level=fix_im_level.to(dtype=th.float32, device=device) # choose the affine transformation model if transform_type == 'non_parametric': transform_args[0]=mov_im_level.size @@ -160,10 +163,10 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation = transforms[transform_type](*transform_args,**transform_opts) - if half: - mov_im_level=mov_im_level.to(dtype=th.float16, device=device) + # if half: + # mov_im_level=mov_im_level.to(dtype=th.float16, device=device) - transformation=transformation.to(dtype=th.float32, device=device)# dtype=th.float32, if not half else th.float16 + # transformation=transformation.to(dtype=th.float32, device=device)# dtype=th.float32, if not half else th.float16 if level > 0 and transform_type in ['bspline','wendland']: print(interpolation) @@ -172,20 +175,20 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari interpolation=interpolation) transformation.set_constant_flow(constant_flow) - fix_im_level=fix_im_level.to(dtype=th.float32, device=device) + # if transform_type in ['similarity', 'affine', 'rigid']: # initialize the translation with the center of mass of the fixed image transformation.init_translation(fix_im_level) - if half: - fix_im_level=fix_im_level.to(dtype=th.float16, device=device) - transformation._dtype=th.float16 - transformation._device=device + # if half: + # fix_im_level=fix_im_level.to(dtype=th.float16, device=device) + # transformation._dtype=th.float16 + # transformation._device=device optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) - opt_level = "O2" if half else "O1" - transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) + # opt_level = "O2" if half else "O1" + # transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) registration.set_transformation(transformation) @@ -537,6 +540,13 @@ def apply_drop2_transform(self, new_img=displace_image(source_img, displacement, gpu_device) cv2.imwrite(source_image.replace('.png','_warped.png') if not output_file else output_file,new_img) + def compress_images(self, + im='A.png', + compression_factor=2., + im_out='A.compressed.png'): + fx=fy=1/compression_factor + cv2.imwrite(im_out,cv2.resize(cv2.imread(im),None,fx=fx,fy=fy)) + def register_images(self, im1='A.npy', im2='B.npy', From bf9d96c0d2ef172c990504bcc932fa7ab85c15f5 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 09:21:14 -0700 Subject: [PATCH 50/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index b6f74c1..43fbfbd 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -540,12 +540,12 @@ def apply_drop2_transform(self, new_img=displace_image(source_img, displacement, gpu_device) cv2.imwrite(source_image.replace('.png','_warped.png') if not output_file else output_file,new_img) - def compress_images(self, + def compress_image(self, im='A.png', compression_factor=2., im_out='A.compressed.png'): fx=fy=1/compression_factor - cv2.imwrite(im_out,cv2.resize(cv2.imread(im),None,fx=fx,fy=fy)) + cv2.imwrite(im_out,cv2.resize(cv2.imread(im),None,fx=fx,fy=fy,interpolation=cv2.INTER_CUBIC)) def register_images(self, im1='A.npy', From c9f191050a1a15080f2e065860b70c7fe1c69cc0 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 09:30:52 -0700 Subject: [PATCH 51/91] Added regularization --- pathflow_mixmatch/cli.py | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 43fbfbd..b346905 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -86,7 +86,7 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # limitations under the License. -def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similarity', gpu_device=0, opt_cm=True, sigma=[[11,11],[11,11],[3,3]], order=2, pyramid=[[4,4],[2,2]], loss_fn='mse', use_mask=False, interpolation='bicubic', half=False): +def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similarity', gpu_device=0, opt_cm=True, sigma=[[11,11],[11,11],[3,3]], order=2, pyramid=[[4,4],[2,2]], loss_fn='mse', use_mask=False, interpolation='bicubic', half=False, regularisation_weight=[1,5,50]): assert use_mask==False, "Masking not implemented" assert transform_type in ['similarity', 'affine', 'rigid', 'non_parametric','bspline','wendland'] if half: @@ -206,6 +206,11 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari registration.set_image_loss([image_loss]) + if transform_type in ['non_parametric','wendland','bspline']: + regulariser = al.regulariser.displacement.DiffusionRegulariser(mov_im_level.spacing) + regulariser.SetWeight(regularisation_weight[level]) + registration.set_regulariser_displacement([regulariser]) + # choose the Adam optimizer to minimize the objective registration.set_optimizer(optimizer) @@ -382,7 +387,8 @@ def register_images_(im1_fname='A.npy', order=2, pyramid=[[4,4],[2,2]], interpolation='bicubic', - half=False): + half=False, + regularisation_weight=[1,5,50]): print("Loading images.") @@ -481,7 +487,7 @@ def register_images_(im1_fname='A.npy', print("[{}/{}] - Begin alignment of sections.".format(idx+1,N)) with (suppress_stdout() if not verbose else contextlib.suppress()): - new_img=displace_image(img2,affine_register(img1, img2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half)[0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + new_img=displace_image(img2,affine_register(img1, img2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well if gpu_device>=0: th.cuda.empty_cache() @@ -501,7 +507,7 @@ def register_images_(im1_fname='A.npy', print("Performing registration.") with (suppress_stdout() if not verbose else contextlib.suppress()): - new_img=displace_image(im2,affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half)[0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + new_img=displace_image(im2,affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well if gpu_device>=0: th.cuda.empty_cache() @@ -581,7 +587,8 @@ def register_images(self, order=2, pyramid=[[4,4],[2,2]], interpolation='bicubic', - half=False): + half=False, + regularisation_weight=[1,5,50]): register_images_(im1_fname=im1, im2_fname=im2, connectivity=connectivity, @@ -608,7 +615,8 @@ def register_images(self, order=order, pyramid=pyramid, interpolation=interpolation, - half=half) + half=half, + regularisation_weight=regularisation_weight) def main(): fire.Fire(Commands) From ab03aba26909d447223bff109987559376679827 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 09:36:33 -0700 Subject: [PATCH 52/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index b346905..235d32f 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -208,8 +208,8 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['non_parametric','wendland','bspline']: regulariser = al.regulariser.displacement.DiffusionRegulariser(mov_im_level.spacing) - regulariser.SetWeight(regularisation_weight[level]) - registration.set_regulariser_displacement([regulariser]) + regulariser.SetWeight(regularisation_weight[level]) + registration.set_regulariser_displacement([regulariser]) # choose the Adam optimizer to minimize the objective From faa293b0e8dba05907279b94c2bac1e8670a0f11 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 09:37:55 -0700 Subject: [PATCH 53/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 235d32f..f93aafd 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -115,7 +115,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari moving_image.image = 1 - moving_image.image # create pairwise registration object - registration = al.PairwiseRegistration(half=half) + registration = al.PairwiseRegistration()#half=half transforms=dict(similarity=al.transformation.pairwise.SimilarityTransformation, affine=al.transformation.pairwise.AffineTransformation, From 67e64d3e8347775bb852c385b990faa461925c0a Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 10:28:37 -0700 Subject: [PATCH 54/91] Update cli.py --- pathflow_mixmatch/cli.py | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index f93aafd..def251d 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -1,5 +1,5 @@ import fire -import numpy as np, cv2 +import numpy as np, pandas as pd, cv2 import cv2 from skimage.morphology import watershed from skimage.feature import peak_local_max @@ -388,7 +388,9 @@ def register_images_(im1_fname='A.npy', pyramid=[[4,4],[2,2]], interpolation='bicubic', half=False, - regularisation_weight=[1,5,50]): + regularisation_weight=[1,5,50], + points1='', + points2=''): print("Loading images.") @@ -415,6 +417,7 @@ def register_images_(im1_fname='A.npy', im1=cv2.imread(im1_fname) im2=cv2.imread(im2_fname) + tre=-1 if not no_segment_analysis: if max_rotation_vertical_px: @@ -507,8 +510,13 @@ def register_images_(im1_fname='A.npy', print("Performing registration.") with (suppress_stdout() if not verbose else contextlib.suppress()): - new_img=displace_image(im2,affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + displacement=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[0] + new_img=displace_image(im2,displacement,gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + if points1 and points2 and os.path.exists(points1) and os.path.exists(points2): + tre=al.utils.points.Points.TRE(pd.read_csv(points1,index_col=0).values,al.utils.points.Points.transform(pd.read_csv(points2,index_col=0).values,displacement)) + else: + tre=-1 if gpu_device>=0: th.cuda.empty_cache() @@ -516,6 +524,7 @@ def register_images_(im1_fname='A.npy', cv2.imwrite(img_out1, cv2.cvtColor(im1,cv2.COLOR_BGR2RGB)) cv2.imwrite(img_out2, cv2.cvtColor(new_img,cv2.COLOR_BGR2RGB)) + return tre class Commands(object): def __init__(self): @@ -588,8 +597,11 @@ def register_images(self, pyramid=[[4,4],[2,2]], interpolation='bicubic', half=False, - regularisation_weight=[1,5,50]): - register_images_(im1_fname=im1, + regularisation_weight=[1,5,50], + points1='', + points2='', + tre_dictionary='results.p'): + tre=register_images_(im1_fname=im1, im2_fname=im2, connectivity=connectivity, apply_watershed=False, @@ -616,7 +628,15 @@ def register_images(self, pyramid=pyramid, interpolation=interpolation, half=half, - regularisation_weight=regularisation_weight) + regularisation_weight=regularisation_weight, + points1=points1, + points2=points2) + if os.path.exists(tre_dictionary): + tre_dictionary=pickle.load(open(tre_dictionary,'rb')) + else: + tre_dictionary=dict() + tre_dictionary[transform_type,loss_fn]=tre + pickle.dump(tre_dictionary,open(tre_dictionary,'wb')) def main(): fire.Fire(Commands) From b2fe73f231b85d68b43a88f13b576ec7fb971f57 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 12:57:11 -0700 Subject: [PATCH 55/91] Update cli.py --- pathflow_mixmatch/cli.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index def251d..175bc02 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -208,7 +208,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['non_parametric','wendland','bspline']: regulariser = al.regulariser.displacement.DiffusionRegulariser(mov_im_level.spacing) - regulariser.SetWeight(regularisation_weight[level]) + regulariser.set_weight(regularisation_weight[level]) registration.set_regulariser_displacement([regulariser]) # choose the Adam optimizer to minimize the objective @@ -260,7 +260,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation_param = transformation._kernel else: pass - return displacement, warped_image, transformation_param, registration.loss#.data.item() + return displacement, mov_im_level, transformation_param, registration.loss#.data.item() def get_loss(im1,im2,gpu_device): @@ -349,7 +349,7 @@ def match_image_size(img1,img2,black_background=False): img2 = cv2.copyMakeBorder(img2, 0, 0, dw//2+dw%2, dw//2, cv2.BORDER_CONSTANT, value=fill_color) elif img1.shape[1]=0: From ebb6c5858c226fab359b6a3d2a44c3a9325e7ea7 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 13:06:30 -0700 Subject: [PATCH 56/91] Update cli.py --- pathflow_mixmatch/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 175bc02..1e0070d 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -28,6 +28,7 @@ import matplotlib.pyplot as plt from contextlib import contextmanager import sys, os +import pickle # from apex import amp From 81d73fcb0ccb99aa238668a0f58e158c7c87f973 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 13:09:22 -0700 Subject: [PATCH 57/91] Update cli.py --- pathflow_mixmatch/cli.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 1e0070d..71e853c 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -639,11 +639,11 @@ def register_images(self, points1=points1, points2=points2) if os.path.exists(tre_dictionary): - tre_dictionary=pickle.load(open(tre_dictionary,'rb')) + tre_dict=pickle.load(open(tre_dictionary,'rb')) else: - tre_dictionary=dict() - tre_dictionary[transform_type,loss_fn]=tre - pickle.dump(tre_dictionary,open(tre_dictionary,'wb')) + tre_dict=dict() + tre_dict[transform_type,loss_fn]=tre + pickle.dump(tre_dict,open(tre_dictionary,'wb')) def main(): fire.Fire(Commands) From 61f3ef32868c1f85347927567b7ed2f043f42375 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 13:38:46 -0700 Subject: [PATCH 58/91] Update cli.py --- pathflow_mixmatch/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 71e853c..cf885b3 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -66,6 +66,7 @@ def get_matched_tissue(props,props2): def displace_image(img, displacement, gpu_device, dtype=th.float32): channels=[] + print(displacement) for i in range(3): im=sitk.GetImageFromArray(img[...,i]) im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) From 0377429946f145ba45a22e6ca203add1ad789808 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 13:41:03 -0700 Subject: [PATCH 59/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index cf885b3..5d0c9d4 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -66,8 +66,8 @@ def get_matched_tissue(props,props2): def displace_image(img, displacement, gpu_device, dtype=th.float32): channels=[] - print(displacement) for i in range(3): + print(displacement) im=sitk.GetImageFromArray(img[...,i]) im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) channels.append(al.transformation.utils.warp_image(im, displacement).numpy()) From ff3d0610545236d3cc8f8266d0412e629b32608e Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:23:27 -0700 Subject: [PATCH 60/91] Update cli.py --- pathflow_mixmatch/cli.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 5d0c9d4..d355dd3 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -66,12 +66,20 @@ def get_matched_tissue(props,props2): def displace_image(img, displacement, gpu_device, dtype=th.float32): channels=[] - for i in range(3): - print(displacement) - im=sitk.GetImageFromArray(img[...,i]) - im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) - channels.append(al.transformation.utils.warp_image(im, displacement).numpy()) - return np.uint8(np.stack(channels).transpose((1,2,0))) + image=sitk.GetImageFromArray(img)#[...,i] + image_size = image.size + grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) + out=image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) + if len(image_size==2): + out.image = al.transformation.utils.F.grid_sample(image.image, displacement + grid) + else: + for i in range(image_size[-1]): + out.image[...,i] = al.transformation.utils.F.grid_sample(image.image[...,i], displacement + grid) + # for i in range(3): + # + # im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) + # channels.append(al.transformation.utils.warp_image(im, displacement).numpy()) + return np.uint8(out.image.numpy())#np.stack(channels).transpose((1,2,0)) # Copyright 2018 University of Basel, Center for medical Image Analysis and Navigation # @@ -230,7 +238,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # warp the moving image with the final transformation result displacement = transformation.get_displacement() - warped_image = al.transformation.utils.warp_image(moving_image, displacement) + # warped_image = al.transformation.utils.warp_image(moving_image, displacement) end = time.perf_counter() @@ -262,7 +270,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation_param = transformation._kernel else: pass - return displacement, mov_im_level, transformation_param, registration.loss#.data.item() + return displacement, moving_image, transformation_param, registration.loss#.data.item() def get_loss(im1,im2,gpu_device): From 74f8fad413a89a3f3b1e9c629857423c78f093c6 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:26:04 -0700 Subject: [PATCH 61/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index d355dd3..c1bcaf8 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -66,7 +66,7 @@ def get_matched_tissue(props,props2): def displace_image(img, displacement, gpu_device, dtype=th.float32): channels=[] - image=sitk.GetImageFromArray(img)#[...,i] + image=al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(img), device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')#[...,i] image_size = image.size grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) out=image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) From 1ff1d9528922593a246eca6465e0d7acb7f82051 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:26:54 -0700 Subject: [PATCH 62/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index c1bcaf8..80694b4 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -66,7 +66,7 @@ def get_matched_tissue(props,props2): def displace_image(img, displacement, gpu_device, dtype=th.float32): channels=[] - image=al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(img), device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')#[...,i] + image=al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(img), device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] image_size = image.size grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) out=image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) From 92ac621c84f3cb0077cd961234db1e1d1697423d Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:28:31 -0700 Subject: [PATCH 63/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 80694b4..08a3152 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -69,7 +69,7 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): image=al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(img), device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] image_size = image.size grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) - out=image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) + out=al.image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) if len(image_size==2): out.image = al.transformation.utils.F.grid_sample(image.image, displacement + grid) else: From ef0a4223fb6f6e1646b911329c998c64b541b14f Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:31:55 -0700 Subject: [PATCH 64/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 08a3152..0dc595a 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -66,7 +66,7 @@ def get_matched_tissue(props,props2): def displace_image(img, displacement, gpu_device, dtype=th.float32): channels=[] - image=al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(img), device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] + image=al.image_from_numpy(img, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] image_size = image.size grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) out=al.image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) From f7e01fa921c74f74316681a905321a2d46065b8c Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:34:11 -0700 Subject: [PATCH 65/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 0dc595a..e10e6bd 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -66,7 +66,7 @@ def get_matched_tissue(props,props2): def displace_image(img, displacement, gpu_device, dtype=th.float32): channels=[] - image=al.image_from_numpy(img, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] + image=al.image_from_numpy(img,(),(), device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] image_size = image.size grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) out=al.image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) From 82eb6a9001a897db3bd99aa35dfb4a7902e8de87 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:40:34 -0700 Subject: [PATCH 66/91] Update cli.py --- pathflow_mixmatch/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index e10e6bd..4aa6845 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -65,8 +65,9 @@ def get_matched_tissue(props,props2): return enumerate(pd.DataFrame(sklearn.metrics.pairwise.pairwise_distances(x[:props.shape[0]],x[props.shape[0]:],'euclidean')).values.argmin(1))#pd.DataFrame(sklearn.metrics.pairwise.cosine_similarity(pd.DataFrame(x).T)).iloc[:props.shape[0],props.shape[0]:]#pd.DataFrame(x).T.corr()>0.95 def displace_image(img, displacement, gpu_device, dtype=th.float32): - channels=[] + # channels=[] image=al.image_from_numpy(img,(),(), device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] + image.size = img.shape image_size = image.size grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) out=al.image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) From 5f7e171cbdad370d695e051b1b8b5f134fc3aef4 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:45:56 -0700 Subject: [PATCH 67/91] Update cli.py --- pathflow_mixmatch/cli.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 4aa6845..c73c43f 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -67,11 +67,10 @@ def get_matched_tissue(props,props2): def displace_image(img, displacement, gpu_device, dtype=th.float32): # channels=[] image=al.image_from_numpy(img,(),(), device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] - image.size = img.shape image_size = image.size grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) out=al.image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) - if len(image_size==2): + if len(image_size)==2: out.image = al.transformation.utils.F.grid_sample(image.image, displacement + grid) else: for i in range(image_size[-1]): From 7c7d9ce83a62b9672a44b16062f8c4e20fa20524 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:47:12 -0700 Subject: [PATCH 68/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index c73c43f..40b929f 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -79,7 +79,7 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # # im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) # channels.append(al.transformation.utils.warp_image(im, displacement).numpy()) - return np.uint8(out.image.numpy())#np.stack(channels).transpose((1,2,0)) + return np.uint8(out.image.detach().cpu().numpy())#np.stack(channels).transpose((1,2,0)) # Copyright 2018 University of Basel, Center for medical Image Analysis and Navigation # From d2f0f5b838f2ce1b941241ad05761f9ebf69b0d5 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:50:01 -0700 Subject: [PATCH 69/91] Update cli.py --- pathflow_mixmatch/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 40b929f..c6719c5 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -68,6 +68,7 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # channels=[] image=al.image_from_numpy(img,(),(), device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] image_size = image.size + print(image_size) grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) out=al.image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) if len(image_size)==2: From 7193512a77aee4f1684d2a94052bcaa53b400fb1 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:53:15 -0700 Subject: [PATCH 70/91] Update cli.py --- pathflow_mixmatch/cli.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index c6719c5..2754283 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -66,7 +66,7 @@ def get_matched_tissue(props,props2): def displace_image(img, displacement, gpu_device, dtype=th.float32): # channels=[] - image=al.image_from_numpy(img,(),(), device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] + image=al.image_from_numpy(img,(),(), dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] image_size = image.size print(image_size) grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) @@ -80,6 +80,8 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # # im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) # channels.append(al.transformation.utils.warp_image(im, displacement).numpy()) + print(out.image) + print(out.image.max()) return np.uint8(out.image.detach().cpu().numpy())#np.stack(channels).transpose((1,2,0)) # Copyright 2018 University of Basel, Center for medical Image Analysis and Navigation From 18ffff077098c89e7105ce984b8f7f5da2de7e28 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:55:08 -0700 Subject: [PATCH 71/91] Update cli.py --- pathflow_mixmatch/cli.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 2754283..9527143 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -80,9 +80,10 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # # im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) # channels.append(al.transformation.utils.warp_image(im, displacement).numpy()) - print(out.image) - print(out.image.max()) - return np.uint8(out.image.detach().cpu().numpy())#np.stack(channels).transpose((1,2,0)) + img=np.uint8(out.image.detach().cpu().numpy()) + print(img) + print(img.max()) + return img#np.stack(channels).transpose((1,2,0)) # Copyright 2018 University of Basel, Center for medical Image Analysis and Navigation # From 3cc424537781493b9ae21c24be80b0892c7d2008 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:55:20 -0700 Subject: [PATCH 72/91] Update cli.py --- pathflow_mixmatch/cli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 9527143..ababd7a 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -83,6 +83,7 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): img=np.uint8(out.image.detach().cpu().numpy()) print(img) print(img.max()) + print(img.shape) return img#np.stack(channels).transpose((1,2,0)) # Copyright 2018 University of Basel, Center for medical Image Analysis and Navigation From 4b629e19656e768e181836aa754b8cf72a4d014e Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 14:56:47 -0700 Subject: [PATCH 73/91] Update cli.py --- pathflow_mixmatch/cli.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index ababd7a..837fb03 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -81,10 +81,10 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) # channels.append(al.transformation.utils.warp_image(im, displacement).numpy()) img=np.uint8(out.image.detach().cpu().numpy()) - print(img) - print(img.max()) - print(img.shape) - return img#np.stack(channels).transpose((1,2,0)) + # print(img) + # print(img.max()) + # print(img.shape) + return img[0][0]#np.stack(channels).transpose((1,2,0)) # Copyright 2018 University of Basel, Center for medical Image Analysis and Navigation # From 6d744daea0f55d40cc10aed2d275458b562927c9 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 15:10:05 -0700 Subject: [PATCH 74/91] Update cli.py --- pathflow_mixmatch/cli.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 837fb03..aea0257 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -130,7 +130,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari moving_image.image = 1 - moving_image.image # create pairwise registration object - registration = al.PairwiseRegistration()#half=half + registration = (al.PairwiseRegistration if transform_type != 'non_parametric' else al.DemonsRegistraion)()#half=half transforms=dict(similarity=al.transformation.pairwise.SimilarityTransformation, affine=al.transformation.pairwise.AffineTransformation, @@ -222,7 +222,10 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari registration.set_image_loss([image_loss]) if transform_type in ['non_parametric','wendland','bspline']: - regulariser = al.regulariser.displacement.DiffusionRegulariser(mov_im_level.spacing) + if transform_type=='non_parametric': + regulariser = al.regulariser.demons.GaussianRegulariser.DiffusionRegulariser(mov_im_level.spacing,sigma=sigma[level], dtype=dtype, device=device) + else: + regulariser = al.regulariser.displacement.DiffusionRegulariser(mov_im_level.spacing) regulariser.set_weight(regularisation_weight[level]) registration.set_regulariser_displacement([regulariser]) From 342f07febc28c7eba01ae3a5f70ffd15151f6984 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 15:10:46 -0700 Subject: [PATCH 75/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index aea0257..023c75b 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -223,7 +223,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['non_parametric','wendland','bspline']: if transform_type=='non_parametric': - regulariser = al.regulariser.demons.GaussianRegulariser.DiffusionRegulariser(mov_im_level.spacing,sigma=sigma[level], dtype=dtype, device=device) + regulariser = al.regulariser.demons.GaussianRegulariser(mov_im_level.spacing,sigma=sigma[level], dtype=dtype, device=device) else: regulariser = al.regulariser.displacement.DiffusionRegulariser(mov_im_level.spacing) regulariser.set_weight(regularisation_weight[level]) From 97377c7363be955ad13a624bbbd52fc7a73efd74 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 15:12:21 -0700 Subject: [PATCH 76/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 023c75b..4895cb0 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -152,7 +152,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari fixed_image_pyramid = al.create_image_pyramid(fixed_image, pyramid) moving_image_pyramid = al.create_image_pyramid(moving_image, pyramid) else: - sigma,fixed_image_pyramid,moving_image_pyramid=[[]],[fixed_image],[moving_image] + fixed_image_pyramid,moving_image_pyramid=[fixed_image],[moving_image] if transform_type=='bspline': transform_opts['order']=order if transform_type=='wendland': From 29fb2acaa792bf24c4f183cc009983fedb3077a4 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 15:14:46 -0700 Subject: [PATCH 77/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 4895cb0..dd472b7 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -226,7 +226,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari regulariser = al.regulariser.demons.GaussianRegulariser(mov_im_level.spacing,sigma=sigma[level], dtype=dtype, device=device) else: regulariser = al.regulariser.displacement.DiffusionRegulariser(mov_im_level.spacing) - regulariser.set_weight(regularisation_weight[level]) + regulariser.set_weight(regularisation_weight[level]) registration.set_regulariser_displacement([regulariser]) # choose the Adam optimizer to minimize the objective From 45e7dc0cad24d3a270b36145a27a0fc5fecd4db4 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 15:18:28 -0700 Subject: [PATCH 78/91] Update cli.py --- pathflow_mixmatch/cli.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index dd472b7..d8f6027 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -224,10 +224,11 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari if transform_type in ['non_parametric','wendland','bspline']: if transform_type=='non_parametric': regulariser = al.regulariser.demons.GaussianRegulariser(mov_im_level.spacing,sigma=sigma[level], dtype=dtype, device=device) + registration.set_regulariser([regulariser]) else: regulariser = al.regulariser.displacement.DiffusionRegulariser(mov_im_level.spacing) regulariser.set_weight(regularisation_weight[level]) - registration.set_regulariser_displacement([regulariser]) + registration.set_regulariser_displacement([regulariser]) # choose the Adam optimizer to minimize the objective From 6b8444802369205357fcea93c7b050c8e9f39058 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 15:56:15 -0700 Subject: [PATCH 79/91] Update cli.py --- pathflow_mixmatch/cli.py | 41 +++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index d8f6027..f200b5d 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -101,7 +101,7 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # limitations under the License. -def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similarity', gpu_device=0, opt_cm=True, sigma=[[11,11],[11,11],[3,3]], order=2, pyramid=[[4,4],[2,2]], loss_fn='mse', use_mask=False, interpolation='bicubic', half=False, regularisation_weight=[1,5,50]): +def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similarity', gpu_device=0, opt_cm=True, sigma=[[11,11],[11,11],[3,3]], order=2, pyramid=[[4,4],[2,2]], loss_fn='mse', use_mask=False, interpolation='bicubic', half=False, regularisation_weight=[1,5,50], moving_image=None): assert use_mask==False, "Masking not implemented" assert transform_type in ['similarity', 'affine', 'rigid', 'non_parametric','bspline','wendland'] if half: @@ -120,9 +120,10 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # load the image data and normalize to [0, 1] # add mask to loss function fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# - moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# - fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) + if not isinstance(moving_image,type(None)): + moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# + fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) # convert intensities so that the object intensities are 1 and the background 0. This is important in order to # calculate the center of mass of the object @@ -247,7 +248,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # warp the moving image with the final transformation result displacement = transformation.get_displacement() - # warped_image = al.transformation.utils.warp_image(moving_image, displacement) + warped_image = al.transformation.utils.warp_image(moving_image, displacement) end = time.perf_counter() @@ -279,7 +280,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation_param = transformation._kernel else: pass - return displacement, moving_image, transformation_param, registration.loss#.data.item() + return displacement, (warped_image, moving_image), transformation_param, registration.loss#.data.item() def get_loss(im1,im2,gpu_device): @@ -409,7 +410,8 @@ def register_images_(im1_fname='A.npy', half=False, regularisation_weight=[1,5,50], points1='', - points2=''): + points2='', + pre_transform='rigid'): print("Loading images.") @@ -528,18 +530,29 @@ def register_images_(im1_fname='A.npy', print("Performing registration.") + displacements=[] with (suppress_stdout() if not verbose else contextlib.suppress()): - displacement,m_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[:2] - new_img=displace_image(im2,displacement,gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[:2] + displacements.append([displacement,warp_mv_im]) + displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, moving_image=warped_image)[:2] + displacements.append([displacement,warp_mv_im]) + + new_img=displace_image(im2,displacement[0][0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + new_img=displace_image(new_img,displacement[1][0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well if points1 and points2 and os.path.exists(points1) and os.path.exists(points2): - displacement = al.transformation.utils.unit_displacement_to_displacement(displacement) # unit measures to image domain measures - displacement = al.create_displacement_image_from_image(displacement, m_im) + displacements_final=[] + for displacement,(warp,m_im) in displacements: + displacement = al.transformation.utils.unit_displacement_to_displacement(displacement) # unit measures to image domain measures + displacement = al.create_displacement_image_from_image(displacement, m_im) + displacements_final.append(displacement) points1=pd.read_csv(points1,index_col=0).values points2=pd.read_csv(points2,index_col=0).values points2[:,0]+=dw points2[:,1]+=dh - tre=al.utils.points.Points.TRE(points1,al.utils.points.Points.transform(points2,displacement)) + for displacement in displacements_final: + points2=al.utils.points.Points.transform(points2,displacement) + tre=al.utils.points.Points.TRE(points1,points2) else: tre=-1 if gpu_device>=0: @@ -625,7 +638,8 @@ def register_images(self, regularisation_weight=[1,5,50], points1='', points2='', - tre_dictionary='results.p'): + tre_dictionary='results.p', + pre_transform='rigid'): tre=register_images_(im1_fname=im1, im2_fname=im2, connectivity=connectivity, @@ -655,7 +669,8 @@ def register_images(self, half=half, regularisation_weight=regularisation_weight, points1=points1, - points2=points2) + points2=points2, + pre_transform=pre_transform) if os.path.exists(tre_dictionary): tre_dict=pickle.load(open(tre_dictionary,'rb')) else: From 6a4a34784faeedd9d83078516c372390f9ca72e1 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 15:56:41 -0700 Subject: [PATCH 80/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index f200b5d..5922b57 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -639,7 +639,7 @@ def register_images(self, points1='', points2='', tre_dictionary='results.p', - pre_transform='rigid'): + pre_transform='affine'): tre=register_images_(im1_fname=im1, im2_fname=im2, connectivity=connectivity, From 8af9515c0acee65919ca1e8d61c6f259bb50d2f6 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 15:58:57 -0700 Subject: [PATCH 81/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 5922b57..9bc78a5 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -121,7 +121,7 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # add mask to loss function fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# - if not isinstance(moving_image,type(None)): + if isinstance(moving_image,type(None)): moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) From bfb88d9ea2e24fa77228db5225576939e9ec1925 Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 16:01:02 -0700 Subject: [PATCH 82/91] Update cli.py --- pathflow_mixmatch/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 9bc78a5..50bc8c8 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -534,7 +534,7 @@ def register_images_(im1_fname='A.npy', with (suppress_stdout() if not verbose else contextlib.suppress()): displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[:2] displacements.append([displacement,warp_mv_im]) - displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, moving_image=warped_image)[:2] + displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, moving_image=warp_mv_im[1])[:2] displacements.append([displacement,warp_mv_im]) new_img=displace_image(im2,displacement[0][0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well From 22df400019a6dbbf7e1a7ab494fbce2aa71ef1fa Mon Sep 17 00:00:00 2001 From: jlevy44 Date: Tue, 12 May 2020 16:13:11 -0700 Subject: [PATCH 83/91] Update cli.py --- pathflow_mixmatch/cli.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 50bc8c8..b2b225b 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -411,7 +411,7 @@ def register_images_(im1_fname='A.npy', regularisation_weight=[1,5,50], points1='', points2='', - pre_transform='rigid'): + pre_transform=''): print("Loading images.") @@ -532,13 +532,15 @@ def register_images_(im1_fname='A.npy', displacements=[] with (suppress_stdout() if not verbose else contextlib.suppress()): - displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[:2] - displacements.append([displacement,warp_mv_im]) - displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, moving_image=warp_mv_im[1])[:2] + if pre_transform: + displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[:2] + displacements.append([displacement,warp_mv_im]) + displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, moving_image=(None if not pre_transform else warp_mv_im[1]))[:2] displacements.append([displacement,warp_mv_im]) new_img=displace_image(im2,displacement[0][0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well - new_img=displace_image(new_img,displacement[1][0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + if pre_transform: + new_img=displace_image(new_img,displacement[1][0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well if points1 and points2 and os.path.exists(points1) and os.path.exists(points2): displacements_final=[] From 10efa8f0486172eec432eab522fb3913a2a79cf4 Mon Sep 17 00:00:00 2001 From: Sumanth Ratna Date: Thu, 25 Jun 2020 10:50:49 -0400 Subject: [PATCH 84/91] Register on joint domain --- pathflow_mixmatch/cli.py | 82 ++++++++++++++++++++++++++++++---------- 1 file changed, 63 insertions(+), 19 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index b2b225b..5bcc038 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -101,7 +101,22 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # limitations under the License. -def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similarity', gpu_device=0, opt_cm=True, sigma=[[11,11],[11,11],[3,3]], order=2, pyramid=[[4,4],[2,2]], loss_fn='mse', use_mask=False, interpolation='bicubic', half=False, regularisation_weight=[1,5,50], moving_image=None): +def affine_register(im1, im2, + iterations=1000, + lr=0.01, + transform_type='similarity', + gpu_device=0, + opt_cm=True, + sigma=[[11,11],[11,11],[3,3]], + order=2, + pyramid=[[4,4],[2,2]], + loss_fn='mse', + use_mask=False, + interpolation='bicubic', + half=False, + regularisation_weight=[1,5,50], + moving_image=None, + register_joint_domain=False): assert use_mask==False, "Masking not implemented" assert transform_type in ['similarity', 'affine', 'rigid', 'non_parametric','bspline','wendland'] if half: @@ -120,10 +135,15 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # load the image data and normalize to [0, 1] # add mask to loss function fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# - - if isinstance(moving_image,type(None)): - moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/2.png", dtype=dtype, device=device)#th.tensor(img2,device='cuda',dtype=dtype)# - fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) + cm_displacement = None + if not moving_image: + if isinstance(im2, np.ndarray): + moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu') + elif isinstance(im2, al.utils.image.Image): + moving_image = im2 + fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) + if register_joint_domain: + fixed_image, f_mask, moving_image, m_mask, cm_displacement = al.get_joint_domain_images(fixed_image, moving_image, default_value=1, cm_alignment=False, compute_masks=False) # convert intensities so that the object intensities are 1 and the background 0. This is important in order to # calculate the center of mass of the object @@ -201,8 +221,13 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari # transformation._device=device - - optimizer = th.optim.Adam(transformation.parameters(), lr=lr[level], amsgrad=True) + if isinstance(lr, float): + optim_lm = lr + elif isinstance(lr, list): + optim_lr = lr[level] + else: + pass + optimizer = th.optim.Adam(transformation.parameters(), lr=optim_lm, amsgrad=True) # opt_level = "O2" if half else "O1" # transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) @@ -280,7 +305,14 @@ def affine_register(im1, im2, iterations=1000, lr=0.01, transform_type='similari transformation_param = transformation._kernel else: pass - return displacement, (warped_image, moving_image), transformation_param, registration.loss#.data.item() + return { + 'displacement': displacement, + 'warped_image': warped_image, + 'moving_image': moving_image, + 'transformation_param': transformation_param, + 'loss': registration.loss, + 'cm_displacement': cm_displacement + } def get_loss(im1,im2,gpu_device): @@ -295,10 +327,10 @@ def get_loss(im1,im2,gpu_device): elif im1.shape[1]=0: th.cuda.empty_cache() - return loss + return affine_output['loss'] def rotate_detector(im1,im2,gpu_device): angles={} @@ -511,7 +543,7 @@ def register_images_(im1_fname='A.npy', print("[{}/{}] - Begin alignment of sections.".format(idx+1,N)) with (suppress_stdout() if not verbose else contextlib.suppress()): - new_img=displace_image(img2,affine_register(img1, img2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + new_img=displace_image(img2,affine_register(img1, img2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)['displacement'],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well if gpu_device>=0: th.cuda.empty_cache() @@ -533,14 +565,23 @@ def register_images_(im1_fname='A.npy', displacements=[] with (suppress_stdout() if not verbose else contextlib.suppress()): if pre_transform: - displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[:2] - displacements.append([displacement,warp_mv_im]) - displacement,warp_mv_im=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, moving_image=(None if not pre_transform else warp_mv_im[1]))[:2] - displacements.append([displacement,warp_mv_im]) - - new_img=displace_image(im2,displacement[0][0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well - if pre_transform: - new_img=displace_image(new_img,displacement[1][0],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + print('Using pre_transform {}'.format(pre_transform)) + reg1 = affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, register_joint_domain=True) + displacement_1 = reg1['displacement'] + new_img = displace_image(im2, displacement_1, gpu_device) + + reg2 = affine_register(im1, im2, moving_image=reg1['moving_image'], gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid, interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, register_joint_domain=True) + displacement_2 = reg2['displacement'] + new_img = displace_image(new_img, displacement_2, gpu_device) + displacements = [ + [displacement_2, (reg2['warped_image'], reg2['moving_image'])], + [displacement_1, (reg1['warped_image'], reg1['moving_image'])], + ] + else: + reg = affine_register(im1, im2, transform_type=transform_type, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, register_joint_domain=True) + displacement = reg['displacement'] + displacements.append([displacement, (reg['warped_image'], reg['moving_image'])]) + new_img = displace_image(im2, displacement, gpu_device) if points1 and points2 and os.path.exists(points1) and os.path.exists(points2): displacements_final=[] @@ -562,6 +603,9 @@ def register_images_(im1_fname='A.npy', print("Writing registered section to file.") + if isinstance(new_img, al.utils.image.Image): + new_img = new_img.numpy() + cv2.imwrite(img_out1, cv2.cvtColor(im1,cv2.COLOR_BGR2RGB)) cv2.imwrite(img_out2, cv2.cvtColor(new_img,cv2.COLOR_BGR2RGB)) return tre From 7d321aa5e365aa2eeb0763126b284aa36b94c7de Mon Sep 17 00:00:00 2001 From: Sumanth Ratna Date: Thu, 25 Jun 2020 20:23:26 -0400 Subject: [PATCH 85/91] Fix image shape conflicts There are still issues with shapes for B-spline. --- pathflow_mixmatch/cli.py | 144 +++++++++++++++++++++++++++++++++------ 1 file changed, 122 insertions(+), 22 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index 5bcc038..d39cda8 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -66,16 +66,33 @@ def get_matched_tissue(props,props2): def displace_image(img, displacement, gpu_device, dtype=th.float32): # channels=[] - image=al.image_from_numpy(img,(),(), dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] + image=al.image_from_numpy(np.squeeze(img),(),(), dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] image_size = image.size print(image_size) grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) - out=al.image_from_numpy(np.empty(image_size),(),(),device=image.device,dtype=image.dtype) - if len(image_size)==2: - out.image = al.transformation.utils.F.grid_sample(image.image, displacement + grid) + + displacement, grid, _, _ = match_image_size(np.squeeze(displacement.cpu().numpy()), np.squeeze(grid.cpu().numpy())) + if displacement.ndim == 2: + displacement = displacement[:, :, np.newaxis] + # elif displacement.ndim == 3: + # displacement = displacement[:, np.newaxis] + flow_field_grid = displacement + grid + if isinstance(flow_field_grid, th.Tensor): + flow_field_grid = flow_field_grid.cpu().numpy() + + out_shape = list(flow_field_grid.shape) # tuples are immutable + out_shape[-1] = 3 # change 2 to 3 in last axis + out = al.image_from_numpy(np.empty(out_shape), (), (), device=image.device, dtype=image.dtype) + + if out.ndim == 2: + im1, im2 = match_image_size(image.image, flow_field_grid) + out.image = al.transformation.utils.F.grid_sample(im1, im2) else: - for i in range(image_size[-1]): - out.image[...,i] = al.transformation.utils.F.grid_sample(image.image[...,i], displacement + grid) + for i in range(out_shape[-1]): # iterate over last axis + flow_field_grid, image_slice, _, _ = match_image_size(np.squeeze(flow_field_grid), np.squeeze(image.image[...,i].cpu().numpy())) + # https://numpy.org/doc/stable/reference/generated/numpy.expand_dims.html + # https://pytorch.org/docs/stable/nn.functional.html#grid-sample + out.image[..., i] = al.transformation.utils.F.grid_sample(th.from_numpy(image_slice[np.newaxis][np.newaxis]), th.from_numpy(flow_field_grid[np.newaxis])) # for i in range(3): # # im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) @@ -84,7 +101,7 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # print(img) # print(img.max()) # print(img.shape) - return img[0][0]#np.stack(channels).transpose((1,2,0)) + return np.squeeze(img) # img[0][0] # np.stack(channels).transpose((1,2,0)) # Copyright 2018 University of Basel, Center for medical Image Analysis and Navigation # @@ -142,13 +159,28 @@ def affine_register(im1, im2, elif isinstance(im2, al.utils.image.Image): moving_image = im2 fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) - if register_joint_domain: - fixed_image, f_mask, moving_image, m_mask, cm_displacement = al.get_joint_domain_images(fixed_image, moving_image, default_value=1, cm_alignment=False, compute_masks=False) # convert intensities so that the object intensities are 1 and the background 0. This is important in order to # calculate the center of mass of the object - fixed_image.image = 1 - fixed_image.image - moving_image.image = 1 - moving_image.image + fixed_image.image = 1. - fixed_image.image + moving_image.image = 1. - moving_image.image + + if register_joint_domain: + # TODO: check this control flow + if transform_type == 'bspline': + joint_domain_interpolation = 3 + elif interpolation == 'linear': + joint_domain_interpolation = 2 + else: + joint_domain_interpolation = 1 + fixed_image, f_mask, moving_image, m_mask, cm_displacement = al.get_joint_domain_images(fixed_image, moving_image, default_value=0, interpolator=joint_domain_interpolation, cm_alignment=True, compute_masks=False) + if cm_displacement is not None: + # the domains are not equal and the images were resampled + # https://github.com/airlab-unibas/airlab/blob/80c9d487c012892c395d63c6d937a67303c321d1/airlab/utils/domain.py#L124-L133 + if isinstance(cm_displacement, np.ndarray): + # cm_displacement = th.as_tensor(cm_displacement, dtype=im2.dtype, device=device) + cm_displacement = th.as_tensor(cm_displacement, dtype=th.float, device=device) + im2 = displace_image(im2, cm_displacement, gpu_device) # create pairwise registration object registration = (al.PairwiseRegistration if transform_type != 'non_parametric' else al.DemonsRegistraion)()#half=half @@ -182,8 +214,11 @@ def affine_register(im1, im2, # transform_opts['half']=half for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): - mov_im_level=mov_im_level.to(dtype=th.float32, device=device) - fix_im_level=fix_im_level.to(dtype=th.float32, device=device) + mov_im_level, fix_im_level, _, _ = match_image_size(mov_im_level, fix_im_level) + + mov_im_level = mov_im_level.to(dtype=th.float32, device=device) + fix_im_level = fix_im_level.to(dtype=th.float32, device=device) + # choose the affine transformation model if transform_type == 'non_parametric': transform_args[0]=mov_im_level.size @@ -192,8 +227,7 @@ def affine_register(im1, im2, # for bspline, smaller sigma tuple means less loss of # microarchitectural details transform_args[0]=mov_im_level.size - # transform_opts['sigma'] = sigma[level] - transform_opts['sigma'] = sigma[level]#(1, 1) + transform_opts['sigma'] = sigma[level] else: transform_args[0]=mov_im_level @@ -202,14 +236,15 @@ def affine_register(im1, im2, # if half: # mov_im_level=mov_im_level.to(dtype=th.float16, device=device) - # transformation=transformation.to(dtype=th.float32, device=device)# dtype=th.float32, if not half else th.float16 + transformation=transformation.to(dtype=th.float32, device=device) # dtype=th.float32, if not half else th.float16 if level > 0 and transform_type in ['bspline','wendland']: print(interpolation) constant_flow = al.transformation.utils.upsample_displacement(constant_flow, mov_im_level.size, interpolation=interpolation) - transformation.set_constant_flow(constant_flow) + constant_flow, fix_im_level, _, _ = match_image_size(constant_flow, fix_im_level) + transformation.set_constant_flow(constant_flow.to(device=device)) # if transform_type in ['similarity', 'affine', 'rigid']: @@ -240,9 +275,11 @@ def affine_register(im1, im2, mgf=al.loss.pairwise.NGF, ssim=al.loss.pairwise.SSIM) + # the loss function requires that both images are on the same device + # https://github.com/airlab-unibas/airlab/blob/80c9d487c012892c395d63c6d937a67303c321d1/airlab/loss/pairwise.py#L47 + mov_im_level = mov_im_level.to(dtype=th.float32, device=device) + fix_im_level = fix_im_level.to(dtype=th.float32, device=device) - - # choose the Mean Squared Error as image loss image_loss = loss_fns[loss_fn](fix_im_level, mov_im_level) registration.set_image_loss([image_loss]) @@ -266,14 +303,15 @@ def affine_register(im1, im2, if transform_type in ['bspline','wendland']: constant_flow = transformation.get_flow() + constant_flow, fix_im_level, _, _ = match_image_size(constant_flow, fix_im_level) # set the intensities back to the original for the visualisation - fixed_image.image = 1 - fixed_image.image - moving_image.image = 1 - moving_image.image + fixed_image.image = 1. - fixed_image.image + moving_image.image = 1. - moving_image.image # warp the moving image with the final transformation result displacement = transformation.get_displacement() - warped_image = al.transformation.utils.warp_image(moving_image, displacement) + warped_image = al.transformation.utils.warp_image(moving_image.to(device=displacement.device), displacement) end = time.perf_counter() @@ -389,6 +427,21 @@ def rotate_image(mat, angle): return rotated_mat def match_image_size(img1,img2,black_background=False): + ret_type_img1 = 'numpy' # either numpy, airlab, or torch + ret_type_img2 = 'numpy' # either numpy, airlab, or torch + if isinstance(img1, al.utils.image.Image): + img1 = img1.numpy() + ret_type_img1 = 'airlab' + elif isinstance(img1, th.Tensor): + img1 = img1.cpu().numpy() + ret_type_img1 = 'torch' + if isinstance(img2, al.utils.image.Image): + img2 = img2.numpy() + ret_type_img2 = 'airlab' + elif isinstance(img2, th.Tensor): + img2 = img1.cpu().numpy() + ret_type_img2 = 'torch' + white=int(black_background==False) fill_color=(np.array([255,255,255])*white).astype(int).tolist() dh=int(np.abs((img1.shape[0]-img2.shape[0]))) @@ -401,6 +454,17 @@ def match_image_size(img1,img2,black_background=False): img2 = cv2.copyMakeBorder(img2, 0, 0, dw//2+dw%2, dw//2, cv2.BORDER_CONSTANT, value=fill_color) elif img1.shape[1] Date: Mon, 29 Jun 2020 16:29:29 -0400 Subject: [PATCH 86/91] Use Python.gitignore https://github.com/github/gitignore/blob/18aa6d83774d514da479d73a4beb864cd4220231/Python.gitignore --- .gitignore | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 138 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2fc8ce3..a81c8ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,138 @@ -build -dist -*.egg-info +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ From 7e1c1a58f7807787da9c2f7cdfb4e1e7c738c46a Mon Sep 17 00:00:00 2001 From: Sumanth Ratna Date: Mon, 29 Jun 2020 18:02:54 -0400 Subject: [PATCH 87/91] Fix optim_lr --- pathflow_mixmatch/cli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index d39cda8..bc49e0b 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -257,12 +257,12 @@ def affine_register(im1, im2, if isinstance(lr, float): - optim_lm = lr - elif isinstance(lr, list): + optim_lr = lr + elif isinstance(lr, (list, tuple)): optim_lr = lr[level] else: pass - optimizer = th.optim.Adam(transformation.parameters(), lr=optim_lm, amsgrad=True) + optimizer = th.optim.Adam(transformation.parameters(), lr=optim_lr, amsgrad=True) # opt_level = "O2" if half else "O1" # transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) From 48643c4b9b1c27dc456721e46d1b01ab9aa8b620 Mon Sep 17 00:00:00 2001 From: Sumanth Ratna Date: Mon, 29 Jun 2020 18:13:55 -0400 Subject: [PATCH 88/91] Add .pylintrc --- .pylintrc | 595 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 595 insertions(+) create mode 100644 .pylintrc diff --git a/.pylintrc b/.pylintrc new file mode 100644 index 0000000..aa94ea9 --- /dev/null +++ b/.pylintrc @@ -0,0 +1,595 @@ +[MASTER] + +# A comma-separated list of package or module names from where C extensions may +# be loaded. Extensions are loading into the active Python interpreter and may +# run arbitrary code. +extension-pkg-whitelist=fire,numpy,pandas,cv2,skimage,scipy,sklearn,SimpleITK,matplotlib,torch, + +# Specify a score threshold to be exceeded before program exits with error. +fail-under=10 + +# Add files or directories to the blacklist. They should be base names, not +# paths. +ignore=CVS + +# Add files or directories matching the regex patterns to the blacklist. The +# regex matches against base names, not paths. +ignore-patterns= + +# Python code to execute, usually for sys.path manipulation such as +# pygtk.require(). +#init-hook= + +# Use multiple processes to speed up Pylint. Specifying 0 will auto-detect the +# number of processors available to use. +jobs=1 + +# Control the amount of potential inferred values when inferring a single +# object. This can help the performance when dealing with large functions or +# complex, nested conditions. +limit-inference-results=100 + +# List of plugins (as comma separated values of python module names) to load, +# usually to register additional checkers. +load-plugins= + +# Pickle collected data for later comparisons. +persistent=yes + +# When enabled, pylint would attempt to guess common misconfiguration and emit +# user-friendly hints instead of false-positive error messages. +suggestion-mode=yes + +# Allow loading of arbitrary C extensions. Extensions are imported into the +# active Python interpreter and may run arbitrary code. +unsafe-load-any-extension=no + + +[MESSAGES CONTROL] + +# Only show warnings with the listed confidence levels. Leave empty to show +# all. Valid levels: HIGH, INFERENCE, INFERENCE_FAILURE, UNDEFINED. +confidence= + +# Disable the message, report, category or checker with the given id(s). You +# can either give multiple identifiers separated by comma (,) or put this +# option multiple times (only on the command line, not in the configuration +# file where it should appear only once). You can also use "--disable=all" to +# disable everything first and then reenable specific checks. For example, if +# you want to run only the similarities checker, you can use "--disable=all +# --enable=similarities". If you want to run only the classes checker, but have +# no Warning level messages displayed, use "--disable=all --enable=classes +# --disable=W". +disable=print-statement, + parameter-unpacking, + unpacking-in-except, + old-raise-syntax, + backtick, + long-suffix, + old-ne-operator, + old-octal-literal, + import-star-module-level, + non-ascii-bytes-literal, + raw-checker-failed, + bad-inline-option, + locally-disabled, + file-ignored, + suppressed-message, + useless-suppression, + deprecated-pragma, + use-symbolic-message-instead, + apply-builtin, + basestring-builtin, + buffer-builtin, + cmp-builtin, + coerce-builtin, + execfile-builtin, + file-builtin, + long-builtin, + raw_input-builtin, + reduce-builtin, + standarderror-builtin, + unicode-builtin, + xrange-builtin, + coerce-method, + delslice-method, + getslice-method, + setslice-method, + no-absolute-import, + old-division, + dict-iter-method, + dict-view-method, + next-method-called, + metaclass-assignment, + indexing-exception, + raising-string, + reload-builtin, + oct-method, + hex-method, + nonzero-method, + cmp-method, + input-builtin, + round-builtin, + intern-builtin, + unichr-builtin, + map-builtin-not-iterating, + zip-builtin-not-iterating, + range-builtin-not-iterating, + filter-builtin-not-iterating, + using-cmp-argument, + eq-without-hash, + div-method, + idiv-method, + rdiv-method, + exception-message-attribute, + invalid-str-codec, + sys-max-int, + bad-python3-import, + deprecated-string-function, + deprecated-str-translate-call, + deprecated-itertools-function, + deprecated-types-field, + next-method-defined, + dict-items-not-iterating, + dict-keys-not-iterating, + dict-values-not-iterating, + deprecated-operator-function, + deprecated-urllib-function, + xreadlines-attribute, + deprecated-sys-function, + exception-escape, + comprehension-escape + +# Enable the message, report, category or checker with the given id(s). You can +# either give multiple identifier separated by comma (,) or put this option +# multiple time (only on the command line, not in the configuration file where +# it should appear only once). See also the "--disable" option for examples. +enable=c-extension-no-member + + +[REPORTS] + +# Python expression which should return a score less than or equal to 10. You +# have access to the variables 'error', 'warning', 'refactor', and 'convention' +# which contain the number of messages in each category, as well as 'statement' +# which is the total number of statements analyzed. This score is used by the +# global evaluation report (RP0004). +evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10) + +# Template used to display messages. This is a python new-style format string +# used to format the message information. See doc for all details. +#msg-template= + +# Set the output format. Available formats are text, parseable, colorized, json +# and msvs (visual studio). You can also give a reporter class, e.g. +# mypackage.mymodule.MyReporterClass. +output-format=text + +# Tells whether to display a full report or only the messages. +reports=no + +# Activate the evaluation score. +score=yes + + +[REFACTORING] + +# Maximum number of nested blocks for function / method body +max-nested-blocks=5 + +# Complete name of functions that never returns. When checking for +# inconsistent-return-statements if a never returning function is called then +# it will be considered as an explicit return statement and no message will be +# printed. +never-returning-functions=sys.exit + + +[STRING] + +# This flag controls whether inconsistent-quotes generates a warning when the +# character used as a quote delimiter is used inconsistently within a module. +check-quote-consistency=no + +# This flag controls whether the implicit-str-concat should generate a warning +# on implicit string concatenation in sequences defined over several lines. +check-str-concat-over-line-jumps=no + + +[SPELLING] + +# Limits count of emitted suggestions for spelling mistakes. +max-spelling-suggestions=4 + +# Spelling dictionary name. Available dictionaries: none. To make it work, +# install the python-enchant package. +spelling-dict= + +# List of comma separated words that should not be checked. +spelling-ignore-words= + +# A path to a file that contains the private dictionary; one word per line. +spelling-private-dict-file= + +# Tells whether to store unknown words to the private dictionary (see the +# --spelling-private-dict-file option) instead of raising a message. +spelling-store-unknown-words=no + + +[TYPECHECK] + +# List of decorators that produce context managers, such as +# contextlib.contextmanager. Add to this list to register other decorators that +# produce valid context managers. +contextmanager-decorators=contextlib.contextmanager + +# List of members which are set dynamically and missed by pylint inference +# system, and so shouldn't trigger E1101 when accessed. Python regular +# expressions are accepted. +generated-members= + +# Tells whether missing members accessed in mixin class should be ignored. A +# mixin class is detected if its name ends with "mixin" (case insensitive). +ignore-mixin-members=yes + +# Tells whether to warn about missing members when the owner of the attribute +# is inferred to be None. +ignore-none=yes + +# This flag controls whether pylint should warn about no-member and similar +# checks whenever an opaque object is returned when inferring. The inference +# can return multiple potential results while evaluating a Python object, but +# some branches might not be evaluated, which results in partial inference. In +# that case, it might be useful to still emit no-member and other checks for +# the rest of the inferred objects. +ignore-on-opaque-inference=yes + +# List of class names for which member attributes should not be checked (useful +# for classes with dynamically set attributes). This supports the use of +# qualified names. +ignored-classes=optparse.Values,thread._local,_thread._local + +# List of module names for which member attributes should not be checked +# (useful for modules/projects where namespaces are manipulated during runtime +# and thus existing member attributes cannot be deduced by static analysis). It +# supports qualified module names, as well as Unix pattern matching. +ignored-modules= + +# Show a hint with possible names when a member name was not found. The aspect +# of finding the hint is based on edit distance. +missing-member-hint=yes + +# The minimum edit distance a name should have in order to be considered a +# similar match for a missing member name. +missing-member-hint-distance=1 + +# The total number of similar names that should be taken in consideration when +# showing a hint for a missing member. +missing-member-max-choices=1 + +# List of decorators that change the signature of a decorated function. +signature-mutators= + + +[BASIC] + +# Naming style matching correct argument names. +argument-naming-style=snake_case + +# Regular expression matching correct argument names. Overrides argument- +# naming-style. +#argument-rgx= + +# Naming style matching correct attribute names. +attr-naming-style=snake_case + +# Regular expression matching correct attribute names. Overrides attr-naming- +# style. +#attr-rgx= + +# Bad variable names which should always be refused, separated by a comma. +bad-names=foo, + bar, + baz, + toto, + tutu, + tata + +# Bad variable names regexes, separated by a comma. If names match any regex, +# they will always be refused +bad-names-rgxs= + +# Naming style matching correct class attribute names. +class-attribute-naming-style=any + +# Regular expression matching correct class attribute names. Overrides class- +# attribute-naming-style. +#class-attribute-rgx= + +# Naming style matching correct class names. +class-naming-style=PascalCase + +# Regular expression matching correct class names. Overrides class-naming- +# style. +#class-rgx= + +# Naming style matching correct constant names. +const-naming-style=UPPER_CASE + +# Regular expression matching correct constant names. Overrides const-naming- +# style. +#const-rgx= + +# Minimum line length for functions/classes that require docstrings, shorter +# ones are exempt. +docstring-min-length=-1 + +# Naming style matching correct function names. +function-naming-style=snake_case + +# Regular expression matching correct function names. Overrides function- +# naming-style. +#function-rgx= + +# Good variable names which should always be accepted, separated by a comma. +good-names=i, + j, + k, + ex, + Run, + _ + +# Good variable names regexes, separated by a comma. If names match any regex, +# they will always be accepted +good-names-rgxs= + +# Include a hint for the correct naming format with invalid-name. +include-naming-hint=no + +# Naming style matching correct inline iteration names. +inlinevar-naming-style=any + +# Regular expression matching correct inline iteration names. Overrides +# inlinevar-naming-style. +#inlinevar-rgx= + +# Naming style matching correct method names. +method-naming-style=snake_case + +# Regular expression matching correct method names. Overrides method-naming- +# style. +#method-rgx= + +# Naming style matching correct module names. +module-naming-style=snake_case + +# Regular expression matching correct module names. Overrides module-naming- +# style. +#module-rgx= + +# Colon-delimited sets of names that determine each other's naming style when +# the name regexes allow several styles. +name-group= + +# Regular expression which should only match function or class names that do +# not require a docstring. +no-docstring-rgx=^_ + +# List of decorators that produce properties, such as abc.abstractproperty. Add +# to this list to register other decorators that produce valid properties. +# These decorators are taken in consideration only for invalid-name. +property-classes=abc.abstractproperty + +# Naming style matching correct variable names. +variable-naming-style=snake_case + +# Regular expression matching correct variable names. Overrides variable- +# naming-style. +#variable-rgx= + + +[SIMILARITIES] + +# Ignore comments when computing similarities. +ignore-comments=yes + +# Ignore docstrings when computing similarities. +ignore-docstrings=yes + +# Ignore imports when computing similarities. +ignore-imports=no + +# Minimum lines number of a similarity. +min-similarity-lines=4 + + +[MISCELLANEOUS] + +# List of note tags to take in consideration, separated by a comma. +notes=FIXME, + XXX, + TODO + +# Regular expression of note tags to take in consideration. +#notes-rgx= + + +[LOGGING] + +# The type of string formatting that logging methods do. `old` means using % +# formatting, `new` is for `{}` formatting. +logging-format-style=old + +# Logging modules to check that the string format arguments are in logging +# function parameter format. +logging-modules=logging + + +[VARIABLES] + +# List of additional names supposed to be defined in builtins. Remember that +# you should avoid defining new builtins when possible. +additional-builtins= + +# Tells whether unused global variables should be treated as a violation. +allow-global-unused-variables=yes + +# List of strings which can identify a callback function by name. A callback +# name must start or end with one of those strings. +callbacks=cb_, + _cb + +# A regular expression matching the name of dummy variables (i.e. expected to +# not be used). +dummy-variables-rgx=_+$|(_[a-zA-Z0-9_]*[a-zA-Z0-9]+?$)|dummy|^ignored_|^unused_ + +# Argument names that match this expression will be ignored. Default to name +# with leading underscore. +ignored-argument-names=_.*|^ignored_|^unused_ + +# Tells whether we should check for unused import in __init__ files. +init-import=no + +# List of qualified module names which can have objects that can redefine +# builtins. +redefining-builtins-modules=six.moves,past.builtins,future.builtins,builtins,io + + +[FORMAT] + +# Expected format of line ending, e.g. empty (any line ending), LF or CRLF. +expected-line-ending-format= + +# Regexp for a line that is allowed to be longer than the limit. +ignore-long-lines=^\s*(# )??$ + +# Number of spaces of indent required inside a hanging or continued line. +indent-after-paren=4 + +# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1 +# tab). +indent-string=' ' + +# Maximum number of characters on a single line. +max-line-length=100 + +# Maximum number of lines in a module. +max-module-lines=1000 + +# List of optional constructs for which whitespace checking is disabled. `dict- +# separator` is used to allow tabulation in dicts, etc.: {1 : 1,\n222: 2}. +# `trailing-comma` allows a space between comma and closing bracket: (a, ). +# `empty-line` allows space-only lines. +no-space-check=trailing-comma, + dict-separator + +# Allow the body of a class to be on the same line as the declaration if body +# contains single statement. +single-line-class-stmt=no + +# Allow the body of an if to be on the same line as the test if there is no +# else. +single-line-if-stmt=no + + +[IMPORTS] + +# List of modules that can be imported at any level, not just the top level +# one. +allow-any-import-level= + +# Allow wildcard imports from modules that define __all__. +allow-wildcard-with-all=no + +# Analyse import fallback blocks. This can be used to support both Python 2 and +# 3 compatible code, which means that the block might have code that exists +# only in one or another interpreter, leading to false positives when analysed. +analyse-fallback-blocks=no + +# Deprecated modules which should not be used, separated by a comma. +deprecated-modules=optparse,tkinter.tix + +# Create a graph of external dependencies in the given file (report RP0402 must +# not be disabled). +ext-import-graph= + +# Create a graph of every (i.e. internal and external) dependencies in the +# given file (report RP0402 must not be disabled). +import-graph= + +# Create a graph of internal dependencies in the given file (report RP0402 must +# not be disabled). +int-import-graph= + +# Force import order to recognize a module as part of the standard +# compatibility libraries. +known-standard-library= + +# Force import order to recognize a module as part of a third party library. +known-third-party=enchant + +# Couples of modules and preferred modules, separated by a comma. +preferred-modules= + + +[DESIGN] + +# Maximum number of arguments for function / method. +max-args=5 + +# Maximum number of attributes for a class (see R0902). +max-attributes=7 + +# Maximum number of boolean expressions in an if statement (see R0916). +max-bool-expr=5 + +# Maximum number of branch for function / method body. +max-branches=12 + +# Maximum number of locals for function / method body. +max-locals=15 + +# Maximum number of parents for a class (see R0901). +max-parents=7 + +# Maximum number of public methods for a class (see R0904). +max-public-methods=20 + +# Maximum number of return / yield for function / method body. +max-returns=6 + +# Maximum number of statements in function / method body. +max-statements=50 + +# Minimum number of public methods for a class (see R0903). +min-public-methods=2 + + +[CLASSES] + +# List of method names used to declare (i.e. assign) instance attributes. +defining-attr-methods=__init__, + __new__, + setUp, + __post_init__ + +# List of member names, which should be excluded from the protected access +# warning. +exclude-protected=_asdict, + _fields, + _replace, + _source, + _make + +# List of valid names for the first argument in a class method. +valid-classmethod-first-arg=cls + +# List of valid names for the first argument in a metaclass class method. +valid-metaclass-classmethod-first-arg=cls + + +[EXCEPTIONS] + +# Exceptions that will emit a warning when being caught. Defaults to +# "BaseException, Exception". +overgeneral-exceptions=BaseException, + Exception From 37b6240010aa86cd309e3761b514c7bac8140df9 Mon Sep 17 00:00:00 2001 From: Sumanth Ratna Date: Mon, 29 Jun 2020 18:15:38 -0400 Subject: [PATCH 89/91] Fix tuple unpacking --- pathflow_mixmatch/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index bc49e0b..d7feef3 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -85,7 +85,7 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): out = al.image_from_numpy(np.empty(out_shape), (), (), device=image.device, dtype=image.dtype) if out.ndim == 2: - im1, im2 = match_image_size(image.image, flow_field_grid) + im1, im2, _, _ = match_image_size(image.image, flow_field_grid) out.image = al.transformation.utils.F.grid_sample(im1, im2) else: for i in range(out_shape[-1]): # iterate over last axis @@ -173,7 +173,7 @@ def affine_register(im1, im2, joint_domain_interpolation = 2 else: joint_domain_interpolation = 1 - fixed_image, f_mask, moving_image, m_mask, cm_displacement = al.get_joint_domain_images(fixed_image, moving_image, default_value=0, interpolator=joint_domain_interpolation, cm_alignment=True, compute_masks=False) + fixed_image, _, moving_image, _, cm_displacement = al.get_joint_domain_images(fixed_image, moving_image, default_value=0, interpolator=joint_domain_interpolation, cm_alignment=True, compute_masks=False) if cm_displacement is not None: # the domains are not equal and the images were resampled # https://github.com/airlab-unibas/airlab/blob/80c9d487c012892c395d63c6d937a67303c321d1/airlab/utils/domain.py#L124-L133 From e526da2d7cb0ff3a23e81838e948631bcceec027 Mon Sep 17 00:00:00 2001 From: "Joshua J. Levy" Date: Wed, 23 Sep 2020 16:01:30 -0400 Subject: [PATCH 90/91] Added mask and hematoxylin alignment --- pathflow_mixmatch/cli.py | 1503 +++++++++++++++++++------------------- setup.py | 3 +- 2 files changed, 767 insertions(+), 739 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index d7feef3..c6431eb 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -29,79 +29,85 @@ from contextlib import contextmanager import sys, os import pickle +from skimage.exposure import rescale_intensity +from skimage.color import rgb2hed +from airlab.utils.image import Image + + + # from apex import amp @contextmanager def suppress_stdout(): - with open(os.devnull, "w") as devnull: - old_stdout = sys.stdout - sys.stdout = devnull - try: - yield - finally: - sys.stdout = old_stdout + with open(os.devnull, "w") as devnull: + old_stdout = sys.stdout + sys.stdout = devnull + try: + yield + finally: + sys.stdout = old_stdout def label_objects(I, min_object_size, threshold=220, connectivity=8, kernel=8, apply_watershed=False): - #try: - BW = (cv2.cvtColor(I, cv2.COLOR_BGR2GRAY)0.95 + x=PCA(n_components=4,random_state=42).fit_transform(pd.concat((props,props2)))#n_components=2 StandardScaler().fit_transform() + return enumerate(pd.DataFrame(sklearn.metrics.pairwise.pairwise_distances(x[:props.shape[0]],x[props.shape[0]:],'euclidean')).values.argmin(1))#pd.DataFrame(sklearn.metrics.pairwise.cosine_similarity(pd.DataFrame(x).T)).iloc[:props.shape[0],props.shape[0]:]#pd.DataFrame(x).T.corr()>0.95 def displace_image(img, displacement, gpu_device, dtype=th.float32): - # channels=[] - image=al.image_from_numpy(np.squeeze(img),(),(), dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] - image_size = image.size - print(image_size) - grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) - - displacement, grid, _, _ = match_image_size(np.squeeze(displacement.cpu().numpy()), np.squeeze(grid.cpu().numpy())) - if displacement.ndim == 2: - displacement = displacement[:, :, np.newaxis] - # elif displacement.ndim == 3: - # displacement = displacement[:, np.newaxis] - flow_field_grid = displacement + grid - if isinstance(flow_field_grid, th.Tensor): - flow_field_grid = flow_field_grid.cpu().numpy() - - out_shape = list(flow_field_grid.shape) # tuples are immutable - out_shape[-1] = 3 # change 2 to 3 in last axis - out = al.image_from_numpy(np.empty(out_shape), (), (), device=image.device, dtype=image.dtype) - - if out.ndim == 2: - im1, im2, _, _ = match_image_size(image.image, flow_field_grid) - out.image = al.transformation.utils.F.grid_sample(im1, im2) - else: - for i in range(out_shape[-1]): # iterate over last axis - flow_field_grid, image_slice, _, _ = match_image_size(np.squeeze(flow_field_grid), np.squeeze(image.image[...,i].cpu().numpy())) - # https://numpy.org/doc/stable/reference/generated/numpy.expand_dims.html - # https://pytorch.org/docs/stable/nn.functional.html#grid-sample - out.image[..., i] = al.transformation.utils.F.grid_sample(th.from_numpy(image_slice[np.newaxis][np.newaxis]), th.from_numpy(flow_field_grid[np.newaxis])) - # for i in range(3): - # - # im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) - # channels.append(al.transformation.utils.warp_image(im, displacement).numpy()) - img=np.uint8(out.image.detach().cpu().numpy()) - # print(img) - # print(img.max()) - # print(img.shape) - return np.squeeze(img) # img[0][0] # np.stack(channels).transpose((1,2,0)) + # channels=[] + image=al.image_from_numpy(np.squeeze(img),(),(), dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu'))#[...,i] + image_size = image.size + print(image_size) + grid = al.transformation.utils.compute_grid(image_size[:2], dtype=image.dtype, device=image.device) + + displacement, grid, _, _ = match_image_size(np.squeeze(displacement.cpu().numpy()), np.squeeze(grid.cpu().numpy())) + if displacement.ndim == 2: + displacement = displacement[:, :, np.newaxis] + # elif displacement.ndim == 3: + # displacement = displacement[:, np.newaxis] + flow_field_grid = displacement + grid + if isinstance(flow_field_grid, th.Tensor): + flow_field_grid = flow_field_grid.cpu().numpy() + + out_shape = list(flow_field_grid.shape) # tuples are immutable + out_shape[-1] = 3 # change 2 to 3 in last axis + out = al.image_from_numpy(np.empty(out_shape), (), (), device=image.device, dtype=image.dtype) + + if out.ndim == 2: + im1, im2, _, _ = match_image_size(image.image, flow_field_grid) + out.image = al.transformation.utils.F.grid_sample(im1, im2) + else: + for i in range(out_shape[-1]): # iterate over last axis + flow_field_grid, image_slice, _, _ = match_image_size(np.squeeze(flow_field_grid), np.squeeze(image.image[...,i].cpu().numpy())) + # https://numpy.org/doc/stable/reference/generated/numpy.expand_dims.html + # https://pytorch.org/docs/stable/nn.functional.html#grid-sample + out.image[..., i] = al.transformation.utils.F.grid_sample(th.from_numpy(image_slice[np.newaxis][np.newaxis]), th.from_numpy(flow_field_grid[np.newaxis])) + # for i in range(3): + # + # im=al.utils.image.create_tensor_image_from_itk_image(im, dtype=dtype, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) + # channels.append(al.transformation.utils.warp_image(im, displacement).numpy()) + img=np.uint8(out.image.detach().cpu().numpy()) + # print(img) + # print(img.max()) + # print(img.shape) + return np.squeeze(img) # img[0][0] # np.stack(channels).transpose((1,2,0)) # Copyright 2018 University of Basel, Center for medical Image Analysis and Navigation # @@ -117,715 +123,736 @@ def displace_image(img, displacement, gpu_device, dtype=th.float32): # See the License for the specific language governing permissions and # limitations under the License. +def img2h(img): + hed=rgb2hed(img) + return rescale_intensity(hed[:, :, 0], out_range=(0, 1)) def affine_register(im1, im2, - iterations=1000, - lr=0.01, - transform_type='similarity', - gpu_device=0, - opt_cm=True, - sigma=[[11,11],[11,11],[3,3]], - order=2, - pyramid=[[4,4],[2,2]], - loss_fn='mse', - use_mask=False, - interpolation='bicubic', - half=False, - regularisation_weight=[1,5,50], - moving_image=None, - register_joint_domain=False): - assert use_mask==False, "Masking not implemented" - assert transform_type in ['similarity', 'affine', 'rigid', 'non_parametric','bspline','wendland'] - if half: - raise NotImplementedError - start = time.perf_counter() - - # set the used data type - dtype = th.float32# if not half else th.half - # set the device for the computaion to CPU - device = th.device("cuda:{}".format(gpu_device) if gpu_device >=0 else 'cpu') - - # In order to use a GPU uncomment the following line. The number is the device index of the used GPU - # Here, the GPU with the index 0 is used. - # device = th.device("cuda:0") - - # load the image data and normalize to [0, 1] - # add mask to loss function - fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# - cm_displacement = None - if not moving_image: - if isinstance(im2, np.ndarray): - moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32, device='cpu') - elif isinstance(im2, al.utils.image.Image): - moving_image = im2 - fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) - - # convert intensities so that the object intensities are 1 and the background 0. This is important in order to - # calculate the center of mass of the object - fixed_image.image = 1. - fixed_image.image - moving_image.image = 1. - moving_image.image - - if register_joint_domain: - # TODO: check this control flow - if transform_type == 'bspline': - joint_domain_interpolation = 3 - elif interpolation == 'linear': - joint_domain_interpolation = 2 - else: - joint_domain_interpolation = 1 - fixed_image, _, moving_image, _, cm_displacement = al.get_joint_domain_images(fixed_image, moving_image, default_value=0, interpolator=joint_domain_interpolation, cm_alignment=True, compute_masks=False) - if cm_displacement is not None: - # the domains are not equal and the images were resampled - # https://github.com/airlab-unibas/airlab/blob/80c9d487c012892c395d63c6d937a67303c321d1/airlab/utils/domain.py#L124-L133 - if isinstance(cm_displacement, np.ndarray): - # cm_displacement = th.as_tensor(cm_displacement, dtype=im2.dtype, device=device) - cm_displacement = th.as_tensor(cm_displacement, dtype=th.float, device=device) - im2 = displace_image(im2, cm_displacement, gpu_device) - - # create pairwise registration object - registration = (al.PairwiseRegistration if transform_type != 'non_parametric' else al.DemonsRegistraion)()#half=half - - transforms=dict(similarity=al.transformation.pairwise.SimilarityTransformation, - affine=al.transformation.pairwise.AffineTransformation, - rigid=al.transformation.pairwise.RigidTransformation, - non_parametric=al.transformation.pairwise.NonParametricTransformation, - wendland=al.transformation.pairwise.WendlandKernelTransformation, - bspline=al.transformation.pairwise.BsplineTransformation) - constant_flow=None - - if transform_type in ['similarity', 'affine', 'rigid']: - transform_opts=dict(opt_cm=opt_cm) - transform_args=[0] - sigma,fixed_image_pyramid,moving_image_pyramid=[[]],[fixed_image],[moving_image] - else: - transform_opts=dict(diffeomorphic=opt_cm, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) - transform_args=[moving_image.size] - if transform_type in ['bspline','wendland']: - transform_opts['sigma']=sigma - fixed_image_pyramid = al.create_image_pyramid(fixed_image, pyramid) - moving_image_pyramid = al.create_image_pyramid(moving_image, pyramid) - else: - fixed_image_pyramid,moving_image_pyramid=[fixed_image],[moving_image] - if transform_type=='bspline': - transform_opts['order']=order - if transform_type=='wendland': - transform_opts['cp_scale']=order - - # transform_opts['half']=half - - for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): - mov_im_level, fix_im_level, _, _ = match_image_size(mov_im_level, fix_im_level) - - mov_im_level = mov_im_level.to(dtype=th.float32, device=device) - fix_im_level = fix_im_level.to(dtype=th.float32, device=device) - - # choose the affine transformation model - if transform_type == 'non_parametric': - transform_args[0]=mov_im_level.size - elif transform_type in ['bspline','wendland']: - # for bspline, sigma must be positive tuple of ints - # for bspline, smaller sigma tuple means less loss of - # microarchitectural details - transform_args[0]=mov_im_level.size - transform_opts['sigma'] = sigma[level] - else: - transform_args[0]=mov_im_level - - transformation = transforms[transform_type](*transform_args,**transform_opts) - - # if half: - # mov_im_level=mov_im_level.to(dtype=th.float16, device=device) - - transformation=transformation.to(dtype=th.float32, device=device) # dtype=th.float32, if not half else th.float16 - - if level > 0 and transform_type in ['bspline','wendland']: - print(interpolation) - constant_flow = al.transformation.utils.upsample_displacement(constant_flow, - mov_im_level.size, - interpolation=interpolation) - constant_flow, fix_im_level, _, _ = match_image_size(constant_flow, fix_im_level) - transformation.set_constant_flow(constant_flow.to(device=device)) - - # - if transform_type in ['similarity', 'affine', 'rigid']: - # initialize the translation with the center of mass of the fixed image - transformation.init_translation(fix_im_level) - # if half: - # fix_im_level=fix_im_level.to(dtype=th.float16, device=device) - # transformation._dtype=th.float16 - # transformation._device=device - - - if isinstance(lr, float): - optim_lr = lr - elif isinstance(lr, (list, tuple)): - optim_lr = lr[level] - else: - pass - optimizer = th.optim.Adam(transformation.parameters(), lr=optim_lr, amsgrad=True) - # opt_level = "O2" if half else "O1" - # transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) - - registration.set_transformation(transformation) - - loss_fns=dict(mse=al.loss.pairwise.MSE, - ncc=al.loss.pairwise.NCC, - lcc=al.loss.pairwise.LCC, - mi=al.loss.pairwise.MI, - mgf=al.loss.pairwise.NGF, - ssim=al.loss.pairwise.SSIM) - - # the loss function requires that both images are on the same device - # https://github.com/airlab-unibas/airlab/blob/80c9d487c012892c395d63c6d937a67303c321d1/airlab/loss/pairwise.py#L47 - mov_im_level = mov_im_level.to(dtype=th.float32, device=device) - fix_im_level = fix_im_level.to(dtype=th.float32, device=device) - - image_loss = loss_fns[loss_fn](fix_im_level, mov_im_level) - - registration.set_image_loss([image_loss]) - - if transform_type in ['non_parametric','wendland','bspline']: - if transform_type=='non_parametric': - regulariser = al.regulariser.demons.GaussianRegulariser(mov_im_level.spacing,sigma=sigma[level], dtype=dtype, device=device) - registration.set_regulariser([regulariser]) - else: - regulariser = al.regulariser.displacement.DiffusionRegulariser(mov_im_level.spacing) - regulariser.set_weight(regularisation_weight[level]) - registration.set_regulariser_displacement([regulariser]) - - # choose the Adam optimizer to minimize the objective - - registration.set_optimizer(optimizer) - registration.set_number_of_iterations(iterations) - - # start the registration - registration.start() - - if transform_type in ['bspline','wendland']: - constant_flow = transformation.get_flow() - constant_flow, fix_im_level, _, _ = match_image_size(constant_flow, fix_im_level) - - # set the intensities back to the original for the visualisation - fixed_image.image = 1. - fixed_image.image - moving_image.image = 1. - moving_image.image - - # warp the moving image with the final transformation result - displacement = transformation.get_displacement() - warped_image = al.transformation.utils.warp_image(moving_image.to(device=displacement.device), displacement) - - end = time.perf_counter() - - print("=================================================================") - - print("Registration done in:", end - start, "s") - if transform_type in ['similarity', 'affine', 'rigid']: - print("Result parameters:") - transformation.print() - - # # plot the results - # plt.subplot(131) - # plt.imshow(fixed_image.numpy(), cmap='gray') - # plt.title('Fixed Image') - # - # plt.subplot(132) - # plt.imshow(moving_image.numpy(), cmap='gray') - # plt.title('Moving Image') - # - # plt.subplot(133) - # plt.imshow(warped_image.numpy(), cmap='gray') - # plt.title('Warped Moving Image') - - if transform_type in ['similarity', 'affine', 'rigid']: - transformation_param = transformation._phi_z - elif transform_type == 'non_parametric': - transformation_param = transformation.trans_parameters - elif transform_type == 'bspline' or transform_type == 'wendland': - transformation_param = transformation._kernel - else: - pass - return { - 'displacement': displacement, - 'warped_image': warped_image, - 'moving_image': moving_image, - 'transformation_param': transformation_param, - 'loss': registration.loss, - 'cm_displacement': cm_displacement - } + iterations=1000, + lr=0.01, + transform_type='similarity', + gpu_device=0, + opt_cm=True, + sigma=[[11,11],[11,11],[3,3]], + order=2, + pyramid=[[4,4],[2,2]], + loss_fn='mse', + use_mask=False, + interpolation='bicubic', + half=False, + regularisation_weight=[1,5,50], + moving_image=None, + register_joint_domain=False, + use_hematoxylin=False, + mask1=None, + mask2=None): +# assert use_mask==False, "Masking not implemented" + if use_mask: assert transform_type in ['similarity', 'affine', 'rigid'] + assert transform_type in ['similarity', 'affine', 'rigid', 'non_parametric','bspline','wendland'] + if half: + raise NotImplementedError + start = time.perf_counter() + + # set the used data type + dtype = th.float32# if not half else th.half + # set the device for the computaion to CPU + device = th.device("cuda:{}".format(gpu_device) if gpu_device >=0 else 'cpu') + + # In order to use a GPU uncomment the following line. The number is the device index of the used GPU + # Here, the GPU with the index 0 is used. + # device = th.device("cuda:0") + + # load the image data and normalize to [0, 1] + # add mask to loss function + + mask1,mask2=None,None + + if use_mask and mask1 is None and mask2 is None: + from pathflowai.utils import generate_tissue_mask + mask1,mask2=th.tensor(generate_tissue_mask(im1).astype(float)),th.tensor(generate_tissue_mask(im2).astype(float)) + + fixed_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY) if not use_hematoxylin else img2h(im1)), dtype=th.float32, device='cpu')#device,al.read_image_as_tensor("./practice_reg/1.png", dtype=dtype, device=device)#th.tensor(img1,device='cuda',dtype=dtype)# + cm_displacement = None + if not moving_image: + if isinstance(im2, np.ndarray): + moving_image = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY) if not use_hematoxylin else img2h(im2)), dtype=th.float32, device='cpu') + elif isinstance(im2, al.utils.image.Image): + moving_image = im2 + fixed_image, moving_image = al.utils.normalize_images(fixed_image, moving_image) + + # convert intensities so that the object intensities are 1 and the background 0. This is important in order to + # calculate the center of mass of the object + fixed_image.image = 1. - fixed_image.image + moving_image.image = 1. - moving_image.image + + if register_joint_domain: + # TODO: check this control flow + if transform_type == 'bspline': + joint_domain_interpolation = 3 + elif interpolation == 'linear': + joint_domain_interpolation = 2 + else: + joint_domain_interpolation = 1 + fixed_image, _, moving_image, _, cm_displacement = al.get_joint_domain_images(fixed_image, moving_image, default_value=0, interpolator=joint_domain_interpolation, cm_alignment=True, compute_masks=False) + if cm_displacement is not None: + # the domains are not equal and the images were resampled + # https://github.com/airlab-unibas/airlab/blob/80c9d487c012892c395d63c6d937a67303c321d1/airlab/utils/domain.py#L124-L133 + if isinstance(cm_displacement, np.ndarray): + # cm_displacement = th.as_tensor(cm_displacement, dtype=im2.dtype, device=device) + cm_displacement = th.as_tensor(cm_displacement, dtype=th.float, device=device) + im2 = displace_image(im2, cm_displacement, gpu_device) + + if use_mask: + mask1,mask2=Image(mask1, fixed_image.size, fixed_image.spacing, fixed_image.origin),Image(mask2, moving_image.size, moving_image.spacing, moving_image.origin) + + # create pairwise registration object + registration = (al.PairwiseRegistration if transform_type != 'non_parametric' else al.DemonsRegistraion)()#half=half + + transforms=dict(similarity=al.transformation.pairwise.SimilarityTransformation, + affine=al.transformation.pairwise.AffineTransformation, + rigid=al.transformation.pairwise.RigidTransformation, + non_parametric=al.transformation.pairwise.NonParametricTransformation, + wendland=al.transformation.pairwise.WendlandKernelTransformation, + bspline=al.transformation.pairwise.BsplineTransformation) + constant_flow=None + + if transform_type in ['similarity', 'affine', 'rigid']: + transform_opts=dict(opt_cm=opt_cm) + transform_args=[0] + sigma,fixed_image_pyramid,moving_image_pyramid=[[]],[fixed_image],[moving_image] + else: + transform_opts=dict(diffeomorphic=opt_cm, device=('cuda:{}'.format(gpu_device) if gpu_device>=0 else 'cpu')) + transform_args=[moving_image.size] + if transform_type in ['bspline','wendland']: + transform_opts['sigma']=sigma + fixed_image_pyramid = al.create_image_pyramid(fixed_image, pyramid) + moving_image_pyramid = al.create_image_pyramid(moving_image, pyramid) + else: + fixed_image_pyramid,moving_image_pyramid=[fixed_image],[moving_image] + if transform_type=='bspline': + transform_opts['order']=order + if transform_type=='wendland': + transform_opts['cp_scale']=order + + # transform_opts['half']=half + + for level, (mov_im_level, fix_im_level) in enumerate(zip(moving_image_pyramid, fixed_image_pyramid)): + mov_im_level, fix_im_level, _, _ = match_image_size(mov_im_level, fix_im_level) + + mov_im_level = mov_im_level.to(dtype=th.float32, device=device) + fix_im_level = fix_im_level.to(dtype=th.float32, device=device) + + # choose the affine transformation model + if transform_type == 'non_parametric': + transform_args[0]=mov_im_level.size + elif transform_type in ['bspline','wendland']: + # for bspline, sigma must be positive tuple of ints + # for bspline, smaller sigma tuple means less loss of + # microarchitectural details + transform_args[0]=mov_im_level.size + transform_opts['sigma'] = sigma[level] + else: + transform_args[0]=mov_im_level + + transformation = transforms[transform_type](*transform_args,**transform_opts) + + # if half: + # mov_im_level=mov_im_level.to(dtype=th.float16, device=device) + + transformation=transformation.to(dtype=th.float32, device=device) # dtype=th.float32, if not half else th.float16 + + if level > 0 and transform_type in ['bspline','wendland']: + print(interpolation) + constant_flow = al.transformation.utils.upsample_displacement(constant_flow, + mov_im_level.size, + interpolation=interpolation) + constant_flow, fix_im_level, _, _ = match_image_size(constant_flow, fix_im_level) + transformation.set_constant_flow(constant_flow.to(device=device)) + + # + if transform_type in ['similarity', 'affine', 'rigid']: + # initialize the translation with the center of mass of the fixed image + transformation.init_translation(fix_im_level) + # if half: + # fix_im_level=fix_im_level.to(dtype=th.float16, device=device) + # transformation._dtype=th.float16 + # transformation._device=device + + + if isinstance(lr, float): + optim_lr = lr + elif isinstance(lr, (list, tuple)): + optim_lr = lr[level] + else: + pass + optimizer = th.optim.Adam(transformation.parameters(), lr=optim_lr, amsgrad=True) + # opt_level = "O2" if half else "O1" + # transformation, optimizer = amp.initialize(transformation, optimizer, opt_level=opt_level) + + registration.set_transformation(transformation) + + loss_fns=dict(mse=al.loss.pairwise.MSE, + ncc=al.loss.pairwise.NCC, + lcc=al.loss.pairwise.LCC, + mi=al.loss.pairwise.MI, + mgf=al.loss.pairwise.NGF, + ssim=al.loss.pairwise.SSIM) + + # the loss function requires that both images are on the same device + # https://github.com/airlab-unibas/airlab/blob/80c9d487c012892c395d63c6d937a67303c321d1/airlab/loss/pairwise.py#L47 + mov_im_level = mov_im_level.to(dtype=th.float32, device=device) + fix_im_level = fix_im_level.to(dtype=th.float32, device=device) + + if use_mask: + mask1 = mask1.to(dtype=th.float32, device=device) + mask2 = mask2.to(dtype=th.float32, device=device) + + image_loss = loss_fns[loss_fn](fix_im_level, mov_im_level, fixed_mask=mask1, moving_mask=mask2) + + registration.set_image_loss([image_loss]) + + if transform_type in ['non_parametric','wendland','bspline']: + if transform_type=='non_parametric': + regulariser = al.regulariser.demons.GaussianRegulariser(mov_im_level.spacing,sigma=sigma[level], dtype=dtype, device=device) + registration.set_regulariser([regulariser]) + else: + regulariser = al.regulariser.displacement.DiffusionRegulariser(mov_im_level.spacing) + regulariser.set_weight(regularisation_weight[level]) + registration.set_regulariser_displacement([regulariser]) + + # choose the Adam optimizer to minimize the objective + + registration.set_optimizer(optimizer) + registration.set_number_of_iterations(iterations) + + # start the registration + registration.start() + + if transform_type in ['bspline','wendland']: + constant_flow = transformation.get_flow() + constant_flow, fix_im_level, _, _ = match_image_size(constant_flow, fix_im_level) + + # set the intensities back to the original for the visualisation + fixed_image.image = 1. - fixed_image.image + moving_image.image = 1. - moving_image.image + + # warp the moving image with the final transformation result + displacement = transformation.get_displacement() + warped_image = al.transformation.utils.warp_image(moving_image.to(device=displacement.device), displacement) + + end = time.perf_counter() + + print("=================================================================") + + print("Registration done in:", end - start, "s") + if transform_type in ['similarity', 'affine', 'rigid']: + print("Result parameters:") + transformation.print() + + # # plot the results + # plt.subplot(131) + # plt.imshow(fixed_image.numpy(), cmap='gray') + # plt.title('Fixed Image') + # + # plt.subplot(132) + # plt.imshow(moving_image.numpy(), cmap='gray') + # plt.title('Moving Image') + # + # plt.subplot(133) + # plt.imshow(warped_image.numpy(), cmap='gray') + # plt.title('Warped Moving Image') + + if transform_type in ['similarity', 'affine', 'rigid']: + transformation_param = list(transformation.named_parameters())#._phi_z + elif transform_type == 'non_parametric': + transformation_param = transformation.trans_parameters + elif transform_type == 'bspline' or transform_type == 'wendland': + transformation_param = transformation._kernel + else: + pass + return { + 'displacement': displacement, + 'warped_image': warped_image, + 'moving_image': moving_image, + 'transformation_param': transformation_param, + 'loss': registration.loss, + 'cm_displacement': cm_displacement + } def get_loss(im1,im2,gpu_device): - dh=int(np.abs((im1.shape[0]-im2.shape[0]))) - if im1.shape[0]>im2.shape[0]: - img2 = cv2.copyMakeBorder(im2, dh, 0, 0, 0, cv2.BORDER_CONSTANT, value=[255,255,255]) - elif im1.shape[0]im2.shape[1]: - im2 = cv2.copyMakeBorder(im2, 0, 0, 0, dw, cv2.BORDER_CONSTANT, value=[255,255,255]) - elif im1.shape[1]=0: - th.cuda.empty_cache() - return affine_output['loss'] + dh=int(np.abs((im1.shape[0]-im2.shape[0]))) + if im1.shape[0]>im2.shape[0]: + img2 = cv2.copyMakeBorder(im2, dh, 0, 0, 0, cv2.BORDER_CONSTANT, value=[255,255,255]) + elif im1.shape[0]im2.shape[1]: + im2 = cv2.copyMakeBorder(im2, 0, 0, 0, dw, cv2.BORDER_CONSTANT, value=[255,255,255]) + elif im1.shape[1]=0: + th.cuda.empty_cache() + return affine_output['loss'] def rotate_detector(im1,im2,gpu_device): - angles={} - for k,angle in enumerate([0, 90, 180, 270]): - im_test=np.rot90(im2,k)#rotate(im2,angle, resize=True, center=None, order=1, mode='constant', cval=255., clip=False, preserve_range=False) - angles[angle]=get_loss(im1,im_test,gpu_device) - return angles + angles={} + for k,angle in enumerate([0, 90, 180, 270]): + im_test=np.rot90(im2,k)#rotate(im2,angle, resize=True, center=None, order=1, mode='constant', cval=255., clip=False, preserve_range=False) + angles[angle]=get_loss(im1,im_test,gpu_device) + return angles def correct_rotation(im1, im2, scaling_factor=4, gpu_device=0): - print("Resizing image 1 for rotation check.") - # im1_small=resize(im1, (im1.shape[0] // scaling_factor, im1.shape[1] // scaling_factor), - # anti_aliasing=True)*255. - im1_small=cv2.resize(im1,(int(im1.shape[1] // scaling_factor), int(im1.shape[0] // scaling_factor))) - print("Resizing image 2 for rotation check.") - # im2_small=resize(im2, (im2.shape[0] // scaling_factor, im2.shape[1] // scaling_factor), - # anti_aliasing=True)*255. - im2_small=cv2.resize(im2,(int(im2.shape[1] // scaling_factor), int(im2.shape[0] // scaling_factor))) - - print("Detecting ideal rotation.") - with suppress_stdout(): - rotation_loss_dict=rotate_detector(im1_small,im2_small,gpu_device) - - if gpu_device>=0: - th.cuda.empty_cache() - - rotations=np.array(list(rotation_loss_dict.items())) - angle=int(rotations[np.argmin(rotations[:,1]),0]) - print("Ideal rotation angle: {}.".format(angle)) - return np.rot90(im2,angle//90) + print("Resizing image 1 for rotation check.") + # im1_small=resize(im1, (im1.shape[0] // scaling_factor, im1.shape[1] // scaling_factor), + # anti_aliasing=True)*255. + im1_small=cv2.resize(im1,(int(im1.shape[1] // scaling_factor), int(im1.shape[0] // scaling_factor))) + print("Resizing image 2 for rotation check.") + # im2_small=resize(im2, (im2.shape[0] // scaling_factor, im2.shape[1] // scaling_factor), + # anti_aliasing=True)*255. + im2_small=cv2.resize(im2,(int(im2.shape[1] // scaling_factor), int(im2.shape[0] // scaling_factor))) + + print("Detecting ideal rotation.") + with suppress_stdout(): + rotation_loss_dict=rotate_detector(im1_small,im2_small,gpu_device) + + if gpu_device>=0: + th.cuda.empty_cache() + + rotations=np.array(list(rotation_loss_dict.items())) + angle=int(rotations[np.argmin(rotations[:,1]),0]) + print("Ideal rotation angle: {}.".format(angle)) + return np.rot90(im2,angle//90) def rotate_image(mat, angle): - """ - https://stackoverflow.com/questions/43892506/opencv-python-rotate-image-without-cropping-sides/47248339 - Rotates an image (angle in degrees) and expands image to avoid cropping - """ + """ + https://stackoverflow.com/questions/43892506/opencv-python-rotate-image-without-cropping-sides/47248339 + Rotates an image (angle in degrees) and expands image to avoid cropping + """ - height, width = mat.shape[:2] # image shape has 3 dimensions - image_center = (width/2, height/2) # getRotationMatrix2D needs coordinates in reverse order (width, height) compared to shape + height, width = mat.shape[:2] # image shape has 3 dimensions + image_center = (width/2, height/2) # getRotationMatrix2D needs coordinates in reverse order (width, height) compared to shape - rotation_mat = cv2.getRotationMatrix2D(image_center, angle, 1.) + rotation_mat = cv2.getRotationMatrix2D(image_center, angle, 1.) - # rotation calculates the cos and sin, taking absolutes of those. - abs_cos = np.abs(rotation_mat[0,0]) - abs_sin = np.abs(rotation_mat[0,1]) + # rotation calculates the cos and sin, taking absolutes of those. + abs_cos = np.abs(rotation_mat[0,0]) + abs_sin = np.abs(rotation_mat[0,1]) - # find the new width and height bounds - bound_w = int(height * abs_sin + width * abs_cos) - bound_h = int(height * abs_cos + width * abs_sin) + # find the new width and height bounds + bound_w = int(height * abs_sin + width * abs_cos) + bound_h = int(height * abs_cos + width * abs_sin) - # subtract old image center (bringing image back to origo) and adding the new image center coordinates - rotation_mat[0, 2] += bound_w/2 - image_center[0] - rotation_mat[1, 2] += bound_h/2 - image_center[1] + # subtract old image center (bringing image back to origo) and adding the new image center coordinates + rotation_mat[0, 2] += bound_w/2 - image_center[0] + rotation_mat[1, 2] += bound_h/2 - image_center[1] - # rotate image with the new bounds and translated rotation matrix - rotated_mat = cv2.warpAffine(mat, rotation_mat, (bound_w, bound_h), borderValue=(255,255,255)) - return rotated_mat + # rotate image with the new bounds and translated rotation matrix + rotated_mat = cv2.warpAffine(mat, rotation_mat, (bound_w, bound_h), borderValue=(255,255,255)) + return rotated_mat def match_image_size(img1,img2,black_background=False): - ret_type_img1 = 'numpy' # either numpy, airlab, or torch - ret_type_img2 = 'numpy' # either numpy, airlab, or torch - if isinstance(img1, al.utils.image.Image): - img1 = img1.numpy() - ret_type_img1 = 'airlab' - elif isinstance(img1, th.Tensor): - img1 = img1.cpu().numpy() - ret_type_img1 = 'torch' - if isinstance(img2, al.utils.image.Image): - img2 = img2.numpy() - ret_type_img2 = 'airlab' - elif isinstance(img2, th.Tensor): - img2 = img1.cpu().numpy() - ret_type_img2 = 'torch' - - white=int(black_background==False) - fill_color=(np.array([255,255,255])*white).astype(int).tolist() - dh=int(np.abs((img1.shape[0]-img2.shape[0]))) - if img1.shape[0]>img2.shape[0]: - img2 = cv2.copyMakeBorder(img2, dh//2+dh%2, dh//2, 0, 0, cv2.BORDER_CONSTANT, value=fill_color) - elif img1.shape[0]img2.shape[1]: - img2 = cv2.copyMakeBorder(img2, 0, 0, dw//2+dw%2, dw//2, cv2.BORDER_CONSTANT, value=fill_color) - elif img1.shape[1]img2.shape[0]: + img2 = cv2.copyMakeBorder(img2, dh//2+dh%2, dh//2, 0, 0, cv2.BORDER_CONSTANT, value=fill_color) + elif img1.shape[0]img2.shape[1]: + img2 = cv2.copyMakeBorder(img2, 0, 0, dw//2+dw%2, dw//2, cv2.BORDER_CONSTANT, value=fill_color) + elif img1.shape[1]=0: - th.cuda.empty_cache() - - print("Locating Sections.") - - mask,labels=label_objects(im1, connectivity=connectivity, min_object_size=min_object_size, apply_watershed=apply_watershed) - mask2,labels2=label_objects(im2, connectivity=connectivity, min_object_size=min_object_size, apply_watershed=apply_watershed) - - print("Estimating section properties.") - - props = pd.DataFrame(measure.regionprops_table(labels, cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY),properties=properties)) - props2 = pd.DataFrame(measure.regionprops_table(labels2, cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY),properties=properties)) - - bboxes=pd.DataFrame(measure.regionprops_table(labels,cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY),properties=['bbox'])) - bboxes2=pd.DataFrame(measure.regionprops_table(labels2,cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY),properties=['bbox'])) - - print("Matching tissue sections.") - - sections=list(get_matched_tissue(props,props2)) - - N=len(sections) - - if file_ext=='.npy': - - del im1, im2 - - im1=np.load(im1_fname,mmap_mode='r+') - im2=np.load(im2_fname,mmap_mode='r+') - - print("Performing alignments on pairs of sections.") - - for idx,(i,j) in enumerate(sections): - if os.path.exists(img_out1)==False or os.path.exists(img_out1)==False or overwrite: - - try: - print("[{}/{}] - Extracting and rotating sections {} and {}".format(idx+1,N,i,j)) - angle=-props.loc[i,'orientation']*180./(np.pi) - img=im1[bboxes.iloc[i,0]:bboxes.iloc[i,2],bboxes.iloc[i,1]:bboxes.iloc[i,3]].copy()#.copy() - img[labels[bboxes.iloc[i,0]:bboxes.iloc[i,2],bboxes.iloc[i,1]:bboxes.iloc[i,3]]!=(i+1)]=255. - img1=rotate_image(img, angle)#np.uint8(rotate(img, -props.loc[i,'orientation']*180./(np.pi), resize=True, center=None, order=1, mode='constant', cval=1., clip=clip, preserve_range=False)*255.) - - angle=-props2.loc[j,'orientation']*180./(np.pi) - img=im2[bboxes2.iloc[j,0]:bboxes2.iloc[j,2],bboxes2.iloc[j,1]:bboxes2.iloc[j,3]].copy()#.copy() - img[labels2[bboxes2.iloc[j,0]:bboxes2.iloc[j,2],bboxes2.iloc[j,1]:bboxes2.iloc[j,3]]!=(j+1)]=255. - img2=rotate_image(img, angle)#np.uint8(rotate(img, -props2.loc[j,'orientation']*180./(np.pi), resize=True, center=None, order=1, mode='constant', cval=1., clip=clip, preserve_range=False)*255.) - - print("[{}/{}] - Trimming sections to proper W & H".format(idx+1,N)) - - c=int(img1.shape[1]/2.) - w=max(int(props.loc[i,'minor_axis_length']/2),int(props2.loc[j,'minor_axis_length']/2*mult_factor)) - h=max(int(img1.shape[0]/2.),int(img2.shape[1]/2.)) - img1=img1[:,c-w:c+w] - - c=int(img2.shape[1]/2.) - img2=img2[:,c-w:c+w] - - img1,img2=match_image_size(img1,img2,black_background=black_background)[:2] - - print("[{}/{}] - Begin alignment of sections.".format(idx+1,N)) - - with (suppress_stdout() if not verbose else contextlib.suppress()): - new_img=displace_image(img2,affine_register(img1, img2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)['displacement'],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well - - if gpu_device>=0: - th.cuda.empty_cache() - - print("[{}/{}] - Writing registered sections to file.".format(idx+1,N)) - - cv2.imwrite(img_out1,cv2.cvtColor(img1,cv2.COLOR_BGR2RGB)) - cv2.imwrite(img_out2,cv2.cvtColor(new_img,cv2.COLOR_BGR2RGB)) - - except Exception as e: - print(str(e)) - - else: + im2_fname='B.npy', + connectivity=8, + apply_watershed=False, + overwrite=False, + min_object_size=50000, + clip=True, + fix_rotation=True, + mult_factor=2.0, + scaling_factor=4., + output_dir='practice_reg_results/images', + properties=['area', + 'convex_area', + 'eccentricity', + 'major_axis_length', + 'minor_axis_length', + 'inertia_tensor', + 'inertia_tensor_eigvals', + 'perimeter', + 'orientation'], + gpu_device=0, + max_rotation_vertical_px=0, + loss_fn='mse', + lr=[0.01]*3, + transform_type='rigid', + iterations=1000, + no_segment_analysis=False, + black_background=False, + verbose=False, + opt_cm=True, + sigma=[[11,11],[11,11],[3,3]], + order=2, + pyramid=[[4,4],[2,2]], + interpolation='bicubic', + half=False, + regularisation_weight=[1,5,50], + points1='', + points2='', + pre_transform=''): + + print("Loading images.") + + _, file_ext = os.path.splitext(im1_fname) + + # TODO: don't rerun splitext, see variable file_ext + os.makedirs(output_dir, exist_ok=True) + # img_splitext1 and img_splitext2 are pairs, (root, ext) + img_splitext1 = os.path.splitext(os.path.basename(im1_fname)) + img_out1 = os.path.join( + output_dir, + f"{img_splitext1[0]}_registered{img_splitext1[1]}" + ) + img_splitext2 = os.path.splitext(os.path.basename(im2_fname)) + img_out2 = os.path.join( + output_dir, + f"{img_splitext2[0]}_registered{img_splitext2[1]}" + ) + + # TODO: load images with airlab.utils.image.read_image_as_tensor + # https://airlab.readthedocs.io/en/latest/_modules/airlab/utils/image.html#read_image_as_tensor + + if file_ext=='.npy': + im1=np.load(im1_fname) + im2=np.load(im2_fname) + else: + im1=cv2.imread(im1_fname) + im2=cv2.imread(im2_fname) + + tre=-1 + if not no_segment_analysis: + + if max_rotation_vertical_px: + scaling_factor=((sum(im1.shape[:2])+sum(im2.shape[:2]))/4.)/float(max_rotation_vertical_px) + print("New scaling factor: {}".format(scaling_factor)) + + if fix_rotation: + print("Adjusting 90 degree rotations.") + + im2=correct_rotation(im1, im2, scaling_factor=scaling_factor, gpu_device=gpu_device) + + if gpu_device>=0: + th.cuda.empty_cache() + + print("Locating Sections.") + + mask,labels=label_objects(im1, connectivity=connectivity, min_object_size=min_object_size, apply_watershed=apply_watershed) + mask2,labels2=label_objects(im2, connectivity=connectivity, min_object_size=min_object_size, apply_watershed=apply_watershed) + + print("Estimating section properties.") + + props = pd.DataFrame(measure.regionprops_table(labels, cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY),properties=properties)) + props2 = pd.DataFrame(measure.regionprops_table(labels2, cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY),properties=properties)) + + bboxes=pd.DataFrame(measure.regionprops_table(labels,cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY),properties=['bbox'])) + bboxes2=pd.DataFrame(measure.regionprops_table(labels2,cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY),properties=['bbox'])) + + print("Matching tissue sections.") + + sections=list(get_matched_tissue(props,props2)) + + N=len(sections) + + if file_ext=='.npy': + + del im1, im2 + + im1=np.load(im1_fname,mmap_mode='r+') + im2=np.load(im2_fname,mmap_mode='r+') + + print("Performing alignments on pairs of sections.") + + for idx,(i,j) in enumerate(sections): + if os.path.exists(img_out1)==False or os.path.exists(img_out1)==False or overwrite: + + try: + print("[{}/{}] - Extracting and rotating sections {} and {}".format(idx+1,N,i,j)) + angle=-props.loc[i,'orientation']*180./(np.pi) + img=im1[bboxes.iloc[i,0]:bboxes.iloc[i,2],bboxes.iloc[i,1]:bboxes.iloc[i,3]].copy()#.copy() + img[labels[bboxes.iloc[i,0]:bboxes.iloc[i,2],bboxes.iloc[i,1]:bboxes.iloc[i,3]]!=(i+1)]=255. + img1=rotate_image(img, angle)#np.uint8(rotate(img, -props.loc[i,'orientation']*180./(np.pi), resize=True, center=None, order=1, mode='constant', cval=1., clip=clip, preserve_range=False)*255.) + + angle=-props2.loc[j,'orientation']*180./(np.pi) + img=im2[bboxes2.iloc[j,0]:bboxes2.iloc[j,2],bboxes2.iloc[j,1]:bboxes2.iloc[j,3]].copy()#.copy() + img[labels2[bboxes2.iloc[j,0]:bboxes2.iloc[j,2],bboxes2.iloc[j,1]:bboxes2.iloc[j,3]]!=(j+1)]=255. + img2=rotate_image(img, angle)#np.uint8(rotate(img, -props2.loc[j,'orientation']*180./(np.pi), resize=True, center=None, order=1, mode='constant', cval=1., clip=clip, preserve_range=False)*255.) + + print("[{}/{}] - Trimming sections to proper W & H".format(idx+1,N)) + + c=int(img1.shape[1]/2.) + w=max(int(props.loc[i,'minor_axis_length']/2),int(props2.loc[j,'minor_axis_length']/2*mult_factor)) + h=max(int(img1.shape[0]/2.),int(img2.shape[1]/2.)) + img1=img1[:,c-w:c+w] + + c=int(img2.shape[1]/2.) + img2=img2[:,c-w:c+w] + + img1,img2=match_image_size(img1,img2,black_background=black_background)[:2] + + print("[{}/{}] - Begin alignment of sections.".format(idx+1,N)) + + with (suppress_stdout() if not verbose else contextlib.suppress()): + new_img=displace_image(img2,affine_register(img1, img2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)['displacement'],gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + + if gpu_device>=0: + th.cuda.empty_cache() + + print("[{}/{}] - Writing registered sections to file.".format(idx+1,N)) + + cv2.imwrite(img_out1,cv2.cvtColor(img1,cv2.COLOR_BGR2RGB)) + cv2.imwrite(img_out2,cv2.cvtColor(new_img,cv2.COLOR_BGR2RGB)) + + except Exception as e: + print(str(e)) + + else: - im1,im2,dw,dh=match_image_size(im1,im2,black_background=black_background) + im1,im2,dw,dh=match_image_size(im1,im2,black_background=black_background) - print("Performing registration.") + print("Performing registration.") - displacements=[] - with (suppress_stdout() if not verbose else contextlib.suppress()): - if pre_transform: - # tensor_img1 = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32) - # tensor_img2 = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32) - # displacement_1,warp_mv_im_1=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[:2] - # fixed_image, moving_image = al.utils.normalize_images(al.utils.image.image_from_numpy(im1), al.utils.image.image_from_numpy(im2)) - # fixed_image, f_mask, moving_image, m_mask, cm_displacement = al.get_joint_domain_images(im1, im2, default_value=0, interpolator=2, cm_alignment=True, compute_masks=False) - # output_reg=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight,register_joint_domain=True) - # cm_displacement,displacement_1,warp_mv_im_1=output_reg['cm_displacement'],output_reg['displacement'], output_reg['warped_image']) - # new_img = warp_mv_im_1 + displacements=[] + with (suppress_stdout() if not verbose else contextlib.suppress()): + if pre_transform: + # tensor_img1 = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)), dtype=th.float32) + # tensor_img2 = al.utils.image.create_tensor_image_from_itk_image(sitk.GetImageFromArray(cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)), dtype=th.float32) + # displacement_1,warp_mv_im_1=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[:2] + # fixed_image, moving_image = al.utils.normalize_images(al.utils.image.image_from_numpy(im1), al.utils.image.image_from_numpy(im2)) + # fixed_image, f_mask, moving_image, m_mask, cm_displacement = al.get_joint_domain_images(im1, im2, default_value=0, interpolator=2, cm_alignment=True, compute_masks=False) + # output_reg=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight,register_joint_domain=True) + # cm_displacement,displacement_1,warp_mv_im_1=output_reg['cm_displacement'],output_reg['displacement'], output_reg['warped_image']) + # new_img = warp_mv_im_1 - print('Using pre_transform {}'.format(pre_transform)) - reg1 = affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, register_joint_domain=True) - displacement_1 = reg1['displacement'] - new_img = displace_image(im2, displacement_1, gpu_device) + print('Using pre_transform {}'.format(pre_transform)) + reg1 = affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, register_joint_domain=True) + displacement_1 = reg1['displacement'] + new_img = displace_image(im2, displacement_1, gpu_device) - reg2 = affine_register(im1, im2, moving_image=reg1['moving_image'], gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid, interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, register_joint_domain=True) - displacement_2 = reg2['displacement'] - new_img = displace_image(new_img, displacement_2, gpu_device) - displacements = [ - [displacement_2, (reg2['warped_image'], reg2['moving_image'])], - [displacement_1, (reg1['warped_image'], reg1['moving_image'])], - ] - - # print(cm_displacement) - # print(type(cm_displacement)) - - # displacement_1,warp_mv_im_1=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[:2] - # displacements.append([displacement_1,warp_mv_im_1]) - # displacement_2,warp_mv_im_2=affine_register(im1, warp_mv_im_1[0], gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, moving_image=warp_mv_im_1[1])[:2] - # displacements.append([displacement_2,warp_mv_im_2]) - # new_img=displace_image(fixed_image.numpy(),cm_displacement,gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well - # new_img=displace_image(new_img,displacement_2,gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well - - # mask,labels=label_objects(im1, connectivity=connectivity, min_object_size=min_object_size, apply_watershed=apply_watershed) - # mask2,labels2=label_objects(im2, connectivity=connectivity, min_object_size=min_object_size, apply_watershed=apply_watershed) - # - # print("Estimating section properties.") - # - # props = pd.DataFrame(measure.regionprops_table(labels, cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY),properties=['bbox', 'area', 'orientation'])) - # props2 = pd.DataFrame(measure.regionprops_table(labels2, cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY),properties=['bbox', 'area', 'orientation'])) - # print(props) - # print(props2) - # - # - # bboxes=pd.DataFrame(measure.regionprops_table(labels,cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY),properties=['bbox'])) - # bboxes2=pd.DataFrame(measure.regionprops_table(labels2,cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY),properties=['bbox'])) - else: - reg = affine_register(im1, im2, transform_type=transform_type, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, register_joint_domain=True) - displacement = reg['displacement'] - displacements.append([displacement, (reg['warped_image'], reg['moving_image'])]) - new_img = displace_image(im2, displacement, gpu_device) - - if points1 and points2 and os.path.exists(points1) and os.path.exists(points2): - displacements_final=[] - for displacement,(warp,m_im) in displacements: - displacement = al.transformation.utils.unit_displacement_to_displacement(displacement) # unit measures to image domain measures - displacement = al.create_displacement_image_from_image(displacement, m_im) - displacements_final.append(displacement) - points1=pd.read_csv(points1,index_col=0).values - points2=pd.read_csv(points2,index_col=0).values - points2[:,0]+=dw - points2[:,1]+=dh - for displacement in displacements_final: - points2=al.utils.points.Points.transform(points2,displacement) - tre=al.utils.points.Points.TRE(points1,points2) - else: - tre=-1 - if gpu_device>=0: - th.cuda.empty_cache() - - print("Writing registered section to file.") - - if isinstance(new_img, al.utils.image.Image): - new_img = new_img.numpy() - - cv2.imwrite(img_out1, cv2.cvtColor(im1,cv2.COLOR_BGR2RGB)) - cv2.imwrite(img_out2, cv2.cvtColor(new_img,cv2.COLOR_BGR2RGB)) - return tre + reg2 = affine_register(im1, im2, moving_image=reg1['moving_image'], gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid, interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, register_joint_domain=True) + displacement_2 = reg2['displacement'] + new_img = displace_image(new_img, displacement_2, gpu_device) + displacements = [ + [displacement_2, (reg2['warped_image'], reg2['moving_image'])], + [displacement_1, (reg1['warped_image'], reg1['moving_image'])], + ] + + # print(cm_displacement) + # print(type(cm_displacement)) + + # displacement_1,warp_mv_im_1=affine_register(im1, im2, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=pre_transform, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight)[:2] + # displacements.append([displacement_1,warp_mv_im_1]) + # displacement_2,warp_mv_im_2=affine_register(im1, warp_mv_im_1[0], gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, transform_type=transform_type, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, moving_image=warp_mv_im_1[1])[:2] + # displacements.append([displacement_2,warp_mv_im_2]) + # new_img=displace_image(fixed_image.numpy(),cm_displacement,gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + # new_img=displace_image(new_img,displacement_2,gpu_device=gpu_device, dtype=th.float32 if not half else th.half) # new tri, output he as well + + # mask,labels=label_objects(im1, connectivity=connectivity, min_object_size=min_object_size, apply_watershed=apply_watershed) + # mask2,labels2=label_objects(im2, connectivity=connectivity, min_object_size=min_object_size, apply_watershed=apply_watershed) + # + # print("Estimating section properties.") + # + # props = pd.DataFrame(measure.regionprops_table(labels, cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY),properties=['bbox', 'area', 'orientation'])) + # props2 = pd.DataFrame(measure.regionprops_table(labels2, cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY),properties=['bbox', 'area', 'orientation'])) + # print(props) + # print(props2) + # + # + # bboxes=pd.DataFrame(measure.regionprops_table(labels,cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY),properties=['bbox'])) + # bboxes2=pd.DataFrame(measure.regionprops_table(labels2,cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY),properties=['bbox'])) + else: + reg = affine_register(im1, im2, transform_type=transform_type, gpu_device=gpu_device, lr=lr, loss_fn=loss_fn, iterations=iterations, opt_cm=opt_cm, sigma=sigma, order=order, pyramid=pyramid,interpolation=interpolation, half=half, regularisation_weight=regularisation_weight, register_joint_domain=True) + displacement = reg['displacement'] + displacements.append([displacement, (reg['warped_image'], reg['moving_image'])]) + new_img = displace_image(im2, displacement, gpu_device) + + if points1 and points2 and os.path.exists(points1) and os.path.exists(points2): + displacements_final=[] + for displacement,(warp,m_im) in displacements: + displacement = al.transformation.utils.unit_displacement_to_displacement(displacement) # unit measures to image domain measures + displacement = al.create_displacement_image_from_image(displacement, m_im) + displacements_final.append(displacement) + points1=pd.read_csv(points1,index_col=0).values + points2=pd.read_csv(points2,index_col=0).values + points2[:,0]+=dw + points2[:,1]+=dh + for displacement in displacements_final: + points2=al.utils.points.Points.transform(points2,displacement) + tre=al.utils.points.Points.TRE(points1,points2) + else: + tre=-1 + if gpu_device>=0: + th.cuda.empty_cache() + + print("Writing registered section to file.") + + if isinstance(new_img, al.utils.image.Image): + new_img = new_img.numpy() + + cv2.imwrite(img_out1, cv2.cvtColor(im1,cv2.COLOR_BGR2RGB)) + cv2.imwrite(img_out2, cv2.cvtColor(new_img,cv2.COLOR_BGR2RGB)) + return tre class Commands(object): - def __init__(self): - pass - - def apply_drop2_transform(self, - source_image='A.png', - ref_image='B.png', - dx='warp_field_x.nii.gz', - dy='warp_field_y.nii.gz', - gpu_device=-1, - output_file=''):# list of -1s and 1s - import nibabel - assert source_image.split('.')[-1]=='png' and ref_image.split('.')[-1]=='png' - assert os.path.exists(source_image) - assert os.path.exists(ref_image) - flip_pattern=[1,1,1,1] - flip_xy=False - source_img=cv2.imread(source_image)#cv2.cvtColor(,cv2.COLOR_BGR2RGB) - ref_img=cv2.imread(ref_image) - source_img=cv2.resize(source_img,ref_img.shape[-2::-1]) - dx,dy=nibabel.load(dx).get_fdata(),nibabel.load(dy).get_fdata() - displacement=th.tensor(np.concatenate([dx[::flip_pattern[0],::flip_pattern[1]],dy[::flip_pattern[2],::flip_pattern[3]]][::(-1 if flip_xy else 1)],-1)[::1,::1,...].copy()).unsqueeze(0).float().permute(0,2,1,3) - for dim in range(displacement.shape[-1]): - displacement[...,dim]=2.0*displacement[...,dim]/float(displacement.shape[-dim - 2] - 1) - if gpu_device >= 0: - displacement=displacement.cuda() - new_img=displace_image(source_img, displacement, gpu_device) - cv2.imwrite(source_image.replace('.png','_warped.png') if not output_file else output_file,new_img) - - def compress_image(self, - im='A.png', - compression_factor=2., - im_out='A.compressed.png'): - fx=fy=1/compression_factor - cv2.imwrite(im_out,cv2.resize(cv2.imread(im),None,fx=fx,fy=fy,interpolation=cv2.INTER_CUBIC)) - - def register_images(self, - im1='A.npy', - im2='B.npy', - connectivity=8, - overwrite=False, - clip=True, - min_object_size=50000, - fix_rotation=True, - mult_factor=1.8, - scaling_factor=4., - max_rotation_vertical_px=0, - output_dir='reg_results/images', - properties=['area', - 'convex_area', - 'eccentricity', - 'major_axis_length', - 'minor_axis_length', - 'inertia_tensor', - 'inertia_tensor_eigvals', - 'perimeter', - 'orientation'], - gpu_device=0, - loss_fn='mse', - lr=0.01, - transform_type='rigid', - iterations=1000, - no_segment_analysis=False, - black_background=False, - verbose=False, - opt_cm=True, - sigma=[[11,11],[11,11],[3,3]], - order=2, - pyramid=[[4,4],[2,2]], - interpolation='bicubic', - half=False, - regularisation_weight=[1,5,50], - points1='', - points2='', - tre_dictionary='results.p', - pre_transform='affine'): - tre=register_images_(im1_fname=im1, - im2_fname=im2, - connectivity=connectivity, - apply_watershed=False, - overwrite=overwrite, - min_object_size=min_object_size, - clip=clip, - fix_rotation=fix_rotation, - mult_factor=mult_factor, - scaling_factor=scaling_factor, - output_dir=output_dir, - properties=properties, - gpu_device=gpu_device, - max_rotation_vertical_px=max_rotation_vertical_px, - loss_fn=loss_fn, - lr=lr, - transform_type=transform_type, - iterations=iterations, - no_segment_analysis=no_segment_analysis, - black_background=black_background, - verbose=verbose, - opt_cm=opt_cm, - sigma=sigma, - order=order, - pyramid=pyramid, - interpolation=interpolation, - half=half, - regularisation_weight=regularisation_weight, - points1=points1, - points2=points2, - pre_transform=pre_transform) - if os.path.exists(tre_dictionary): - tre_dict=pickle.load(open(tre_dictionary,'rb')) - else: - tre_dict=dict() - tre_dict[transform_type,loss_fn]=tre - pickle.dump(tre_dict,open(tre_dictionary,'wb')) + def __init__(self): + pass + + def apply_drop2_transform(self, + source_image='A.png', + ref_image='B.png', + dx='warp_field_x.nii.gz', + dy='warp_field_y.nii.gz', + gpu_device=-1, + output_file=''):# list of -1s and 1s + import nibabel + assert source_image.split('.')[-1]=='png' and ref_image.split('.')[-1]=='png' + assert os.path.exists(source_image) + assert os.path.exists(ref_image) + flip_pattern=[1,1,1,1] + flip_xy=False + source_img=cv2.imread(source_image)#cv2.cvtColor(,cv2.COLOR_BGR2RGB) + ref_img=cv2.imread(ref_image) + source_img=cv2.resize(source_img,ref_img.shape[-2::-1]) + dx,dy=nibabel.load(dx).get_fdata(),nibabel.load(dy).get_fdata() + displacement=th.tensor(np.concatenate([dx[::flip_pattern[0],::flip_pattern[1]],dy[::flip_pattern[2],::flip_pattern[3]]][::(-1 if flip_xy else 1)],-1)[::1,::1,...].copy()).unsqueeze(0).float().permute(0,2,1,3) + for dim in range(displacement.shape[-1]): + displacement[...,dim]=2.0*displacement[...,dim]/float(displacement.shape[-dim - 2] - 1) + if gpu_device >= 0: + displacement=displacement.cuda() + new_img=displace_image(source_img, displacement, gpu_device) + cv2.imwrite(source_image.replace('.png','_warped.png') if not output_file else output_file,new_img) + + def compress_image(self, + im='A.png', + compression_factor=2., + im_out='A.compressed.png'): + fx=fy=1/compression_factor + cv2.imwrite(im_out,cv2.resize(cv2.imread(im),None,fx=fx,fy=fy,interpolation=cv2.INTER_CUBIC)) + + def register_images(self, + im1='A.npy', + im2='B.npy', + connectivity=8, + overwrite=False, + clip=True, + min_object_size=50000, + fix_rotation=True, + mult_factor=1.8, + scaling_factor=4., + max_rotation_vertical_px=0, + output_dir='reg_results/images', + properties=['area', + 'convex_area', + 'eccentricity', + 'major_axis_length', + 'minor_axis_length', + 'inertia_tensor', + 'inertia_tensor_eigvals', + 'perimeter', + 'orientation'], + gpu_device=0, + loss_fn='mse', + lr=0.01, + transform_type='rigid', + iterations=1000, + no_segment_analysis=False, + black_background=False, + verbose=False, + opt_cm=True, + sigma=[[11,11],[11,11],[3,3]], + order=2, + pyramid=[[4,4],[2,2]], + interpolation='bicubic', + half=False, + regularisation_weight=[1,5,50], + points1='', + points2='', + tre_dictionary='results.p', + pre_transform='affine'): + tre=register_images_(im1_fname=im1, + im2_fname=im2, + connectivity=connectivity, + apply_watershed=False, + overwrite=overwrite, + min_object_size=min_object_size, + clip=clip, + fix_rotation=fix_rotation, + mult_factor=mult_factor, + scaling_factor=scaling_factor, + output_dir=output_dir, + properties=properties, + gpu_device=gpu_device, + max_rotation_vertical_px=max_rotation_vertical_px, + loss_fn=loss_fn, + lr=lr, + transform_type=transform_type, + iterations=iterations, + no_segment_analysis=no_segment_analysis, + black_background=black_background, + verbose=verbose, + opt_cm=opt_cm, + sigma=sigma, + order=order, + pyramid=pyramid, + interpolation=interpolation, + half=half, + regularisation_weight=regularisation_weight, + points1=points1, + points2=points2, + pre_transform=pre_transform) + if os.path.exists(tre_dictionary): + tre_dict=pickle.load(open(tre_dictionary,'rb')) + else: + tre_dict=dict() + tre_dict[transform_type,loss_fn]=tre + pickle.dump(tre_dict,open(tre_dictionary,'wb')) def main(): - fire.Fire(Commands) + fire.Fire(Commands) if __name__=='__main__': - main() + main() diff --git a/setup.py b/setup.py index 1a39a19..9475338 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,8 @@ 'torch', 'airlab', 'fire', - 'nibabel'] + 'nibabel', + 'pathflowai'] with open('README.md','r', encoding='utf-8') as f: long_description = f.read() From db3a18f8d684e8fe2e27216caeb47388a43ca4d6 Mon Sep 17 00:00:00 2001 From: "Joshua J. Levy" Date: Sun, 11 Oct 2020 19:25:28 -0400 Subject: [PATCH 91/91] update --- pathflow_mixmatch/cli.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pathflow_mixmatch/cli.py b/pathflow_mixmatch/cli.py index c6431eb..300178a 100644 --- a/pathflow_mixmatch/cli.py +++ b/pathflow_mixmatch/cli.py @@ -426,7 +426,7 @@ def correct_rotation(im1, im2, scaling_factor=4, gpu_device=0): print("Ideal rotation angle: {}.".format(angle)) return np.rot90(im2,angle//90) -def rotate_image(mat, angle): +def rotate_image(mat, angle, center=None): """ https://stackoverflow.com/questions/43892506/opencv-python-rotate-image-without-cropping-sides/47248339 Rotates an image (angle in degrees) and expands image to avoid cropping @@ -435,7 +435,7 @@ def rotate_image(mat, angle): height, width = mat.shape[:2] # image shape has 3 dimensions image_center = (width/2, height/2) # getRotationMatrix2D needs coordinates in reverse order (width, height) compared to shape - rotation_mat = cv2.getRotationMatrix2D(image_center, angle, 1.) + rotation_mat = cv2.getRotationMatrix2D(image_center if center is None else center, angle, 1.) # rotation calculates the cos and sin, taking absolutes of those. abs_cos = np.abs(rotation_mat[0,0])