def warp_backward(self, image): r''' Applies this transformation in the backward direction to the given image using tri-linear interpolation ''' if len(image.shape) == 3: if image.dtype is np.dtype('int32'): warped = np.array( tf.warp_discrete_volumeNN( image, self.backward, self.affine_post_inv, self.affine_pre_inv)) elif image.dtype is np.dtype('float64'): warped = np.array( tf.warp_volume( image, self.backward, self.affine_post_inv, self.affine_pre_inv)) else: if image.dtype is np.dtype('int32'): warped = np.array( tf.warp_discrete_imageNN( image, self.backward, self.affine_post_inv, self.affine_pre_inv)) elif image.dtype is np.dtype('float64'): warped = np.array( tf.warp_image( image, self.backward, self.affine_post_inv, self.affine_pre_inv)) return warped
def estimateNewMonomodalDiffeomorphicField2D(moving, fixed, lambdaParam, maxOuterIter, previousDisplacement, previousDisplacementInverse): ''' Warning: in the monomodal case, the parameter lambda must be significantly lower than in the multimodal case. Try lambdaParam=1, as opposed as lambdaParam=150 used in the multimodal case ''' innerTolerance = 1e-4 displacement = np.zeros(shape=(moving.shape) + (2, ), dtype=np.float64) gradientField = np.empty(shape=(moving.shape) + (2, ), dtype=np.float64) totalDisplacement = np.zeros(shape=(moving.shape) + (2, ), dtype=np.float64) totalDisplacementInverse = np.zeros(shape=(moving.shape) + (2, ), dtype=np.float64) if (previousDisplacement != None): totalDisplacement[...] = previousDisplacement totalDisplacementInverse[...] = previousDisplacementInverse outerIter = 0 framesToCapture = 5 maxOuterIter = framesToCapture * ( (maxOuterIter + framesToCapture - 1) / framesToCapture) itersPerCapture = maxOuterIter / framesToCapture plt.figure() while (outerIter < maxOuterIter): outerIter += 1 print 'Outer iter:', outerIter warped = np.array(tf.warp_image(moving, totalDisplacement, None)) if ((outerIter == 1) or (outerIter % itersPerCapture == 0)): plt.subplot(1, framesToCapture + 1, 1 + outerIter / itersPerCapture) rcommon.overlayImages(warped, fixed, False) plt.title('Iter:' + str(outerIter - 1)) sigmaField = np.ones_like(warped, dtype=np.float64) deltaField = fixed - warped gradientField[:, :, 0], gradientField[:, :, 1] = sp.gradient(warped) maxVariation = 1 + innerTolerance innerIter = 0 displacement[...] = 0 maxInnerIter = 200 while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)): innerIter += 1 maxVariation = tf.iterateDisplacementField2DCYTHON( deltaField, sigmaField, gradientField, lambdaParam, displacement, None) #maxDisplacement=np.max(np.abs(displacement)) expd, invexpd = tf.vector_field_exponential(displacement, True) totalDisplacement, stats = tf.compose_vector_fields( displacement, totalDisplacement) #totalDisplacement=np.array(totalDisplacement) totalDisplacementInverse, stats = tf.compose_vector_fields( totalDisplacementInverse, invexpd) #totalDisplacementInverse=np.array(totalDisplacementInverse) #if(maxDisplacement<outerTolerance): #break print "Iter: ", innerIter, "Max variation:", maxVariation return totalDisplacement, totalDisplacementInverse
def test_optimizer_monomodal_2d(): r''' Classical Circle-To-C experiment for 2D Monomodal registration ''' fname_moving = 'data/circle.png' fname_fixed = 'data/C.png' moving = plt.imread(fname_moving) fixed = plt.imread(fname_fixed) moving = moving[:, :, 0].astype(np.float64) fixed = fixed[:, :, 0].astype(np.float64) moving = np.copy(moving, order='C') fixed = np.copy(fixed, order='C') moving = (moving - moving.min()) / (moving.max() - moving.min()) fixed = (fixed - fixed.min()) / (fixed.max() - fixed.min()) ################Configure and run the Optimizer##################### max_iter = [i for i in [20, 100, 100, 100]] similarity_metric = SSDMetric(2, { 'symmetric': True, 'lambda': 5.0, 'stepType': SSDMetric.GAUSS_SEIDEL_STEP }) optimizer_parameters = { 'max_iter': max_iter, 'inversion_iter': 40, 'inversion_tolerance': 1e-3, 'report_status': True } update_rule = UpdateRule.Composition() registration_optimizer = SymmetricRegistrationOptimizer( fixed, moving, None, None, similarity_metric, update_rule, optimizer_parameters) registration_optimizer.optimize() #######################show results################################# displacement = registration_optimizer.get_forward() direct_inverse = registration_optimizer.get_backward() moving_to_fixed = np.array(tf.warp_image(moving, displacement)) fixed_to_moving = np.array(tf.warp_image(fixed, direct_inverse)) rcommon.overlayImages(moving_to_fixed, fixed, True) rcommon.overlayImages(fixed_to_moving, moving, True) direct_residual, stats = tf.compose_vector_fields(displacement, direct_inverse) direct_residual = np.array(direct_residual) rcommon.plotDiffeomorphism(displacement, direct_inverse, direct_residual, 'inv-direct', 7)
def test_optimizer_monomodal_2d(): r''' Classical Circle-To-C experiment for 2D Monomodal registration ''' fname_moving = 'data/circle.png' fname_fixed = 'data/C.png' moving = plt.imread(fname_moving) fixed = plt.imread(fname_fixed) moving = moving[:, :, 0].astype(np.float64) fixed = fixed[:, :, 0].astype(np.float64) moving = np.copy(moving, order = 'C') fixed = np.copy(fixed, order = 'C') moving = (moving-moving.min())/(moving.max() - moving.min()) fixed = (fixed-fixed.min())/(fixed.max() - fixed.min()) ################Configure and run the Optimizer##################### max_iter = [i for i in [20, 100, 100, 100]] similarity_metric = SSDMetric(2, {'symmetric':True, 'lambda':5.0, 'stepType':SSDMetric.GAUSS_SEIDEL_STEP}) optimizer_parameters = { 'max_iter':max_iter, 'inversion_iter':40, 'inversion_tolerance':1e-3, 'report_status':True} update_rule = UpdateRule.Composition() registration_optimizer = SymmetricRegistrationOptimizer(fixed, moving, None, None, similarity_metric, update_rule, optimizer_parameters) registration_optimizer.optimize() #######################show results################################# displacement = registration_optimizer.get_forward() direct_inverse = registration_optimizer.get_backward() moving_to_fixed = np.array(tf.warp_image(moving, displacement)) fixed_to_moving = np.array(tf.warp_image(fixed, direct_inverse)) rcommon.overlayImages(moving_to_fixed, fixed, True) rcommon.overlayImages(fixed_to_moving, moving, True) direct_residual, stats = tf.compose_vector_fields(displacement, direct_inverse) direct_residual = np.array(direct_residual) rcommon.plotDiffeomorphism(displacement, direct_inverse, direct_residual, 'inv-direct', 7)
def test_optimizer_monomodal_2d(): r""" Classical Circle-To-C experiment for 2D Monomodal registration """ fname_moving = "data/circle.png" fname_fixed = "data/C.png" nib_moving = plt.imread(fname_moving) nib_fixed = plt.imread(fname_fixed) moving = nib_moving[:, :, 0].astype(np.float64) fixed = nib_fixed[:, :, 1].astype(np.float64) moving = np.copy(moving, order="C") fixed = np.copy(fixed, order="C") moving = (moving - moving.min()) / (moving.max() - moving.min()) fixed = (fixed - fixed.min()) / (fixed.max() - fixed.min()) ################Configure and run the Optimizer##################### max_iter = [i for i in [25, 100, 100, 100]] similarity_metric = SSDMetric({"lambda": 5.0, "max_inner_iter": 50, "step_type": SSDMetric.GAUSS_SEIDEL_STEP}) update_rule = UpdateRule.Composition() optimizer_parameters = { "max_iter": max_iter, "inversion_iter": 40, "inversion_tolerance": 1e-3, "report_status": True, } registration_optimizer = AsymmetricRegistrationOptimizer( fixed, moving, None, None, similarity_metric, update_rule, optimizer_parameters ) registration_optimizer.optimize() #######################show results################################# displacement = registration_optimizer.get_forward() direct_inverse = registration_optimizer.get_backward() moving_to_fixed = np.array(tf.warp_image(moving, displacement)) fixed_to_moving = np.array(tf.warp_image(fixed, direct_inverse)) rcommon.overlayImages(moving_to_fixed, fixed, True) rcommon.overlayImages(fixed_to_moving, moving, True) direct_residual, stats = tf.compose_vector_fields(displacement, direct_inverse) direct_residual = np.array(direct_residual) rcommon.plotDiffeomorphism(displacement, direct_inverse, direct_residual, "inv-direct", 7)
def estimateNewMonomodalDiffeomorphicField2D(moving, fixed, lambdaParam, maxOuterIter, previousDisplacement, previousDisplacementInverse): ''' Warning: in the monomodal case, the parameter lambda must be significantly lower than in the multimodal case. Try lambdaParam=1, as opposed as lambdaParam=150 used in the multimodal case ''' innerTolerance=1e-4 displacement =np.zeros(shape=(moving.shape)+(2,), dtype=np.float64) gradientField =np.empty(shape=(moving.shape)+(2,), dtype=np.float64) totalDisplacement=np.zeros(shape=(moving.shape)+(2,), dtype=np.float64) totalDisplacementInverse=np.zeros(shape=(moving.shape)+(2,), dtype=np.float64) if(previousDisplacement!=None): totalDisplacement[...]=previousDisplacement totalDisplacementInverse[...]=previousDisplacementInverse outerIter=0 framesToCapture=5 maxOuterIter=framesToCapture*((maxOuterIter+framesToCapture-1)/framesToCapture) itersPerCapture=maxOuterIter/framesToCapture plt.figure() while(outerIter<maxOuterIter): outerIter+=1 print 'Outer iter:', outerIter warped=np.array(tf.warp_image(moving, totalDisplacement, None)) if((outerIter==1) or (outerIter%itersPerCapture==0)): plt.subplot(1,framesToCapture+1, 1+outerIter/itersPerCapture) rcommon.overlayImages(warped, fixed, False) plt.title('Iter:'+str(outerIter-1)) sigmaField=np.ones_like(warped, dtype=np.float64) deltaField=fixed-warped gradientField[:,:,0], gradientField[:,:,1]=sp.gradient(warped) maxVariation=1+innerTolerance innerIter=0 displacement[...]=0 maxInnerIter=200 while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)): innerIter+=1 maxVariation=tf.iterateDisplacementField2DCYTHON(deltaField, sigmaField, gradientField, lambdaParam, displacement, None) #maxDisplacement=np.max(np.abs(displacement)) expd, invexpd=tf.vector_field_exponential(displacement, True) totalDisplacement, stats=tf.compose_vector_fields(displacement, totalDisplacement) #totalDisplacement=np.array(totalDisplacement) totalDisplacementInverse, stats=tf.compose_vector_fields(totalDisplacementInverse, invexpd) #totalDisplacementInverse=np.array(totalDisplacementInverse) #if(maxDisplacement<outerTolerance): #break print "Iter: ",innerIter, "Max variation:",maxVariation return totalDisplacement, totalDisplacementInverse
def estimateNewMonomodalSyNField2D(moving, fixed, fWarp, fInv, mWarp, mInv, lambdaParam, maxOuterIter): ''' Warning: in the monomodal case, the parameter lambda must be significantly lower than in the multimodal case. Try lambdaParam=1, as opposed as lambdaParam=150 used in the multimodal case ''' innerTolerance = 1e-4 outerTolerance = 1e-3 if (mWarp != None): totalM = mWarp totalMInv = mInv else: totalM = np.zeros(shape=(fixed.shape) + (2, ), dtype=np.float64) totalMInv = np.zeros(shape=(fixed.shape) + (2, ), dtype=np.float64) if (fWarp != None): totalF = fWarp totalFInv = fInv else: totalF = np.zeros(shape=(moving.shape) + (2, ), dtype=np.float64) totalFInv = np.zeros(shape=(moving.shape) + (2, ), dtype=np.float64) outerIter = 0 framesToCapture = 5 maxOuterIter = framesToCapture * ( (maxOuterIter + framesToCapture - 1) / framesToCapture) itersPerCapture = maxOuterIter / framesToCapture plt.figure() while (outerIter < maxOuterIter): outerIter += 1 print 'Outer iter:', outerIter wmoving = np.array(tf.warp_image(moving, totalMInv)) wfixed = np.array(tf.warp_image(fixed, totalFInv)) if ((outerIter == 1) or (outerIter % itersPerCapture == 0)): plt.subplot(1, framesToCapture + 1, 1 + outerIter / itersPerCapture) rcommon.overlayImages(wmoving, wfixed, False) plt.title('Iter:' + str(outerIter - 1)) #Compute forward update sigmaField = np.ones_like(wmoving, dtype=np.float64) deltaField = wfixed - wmoving movingGradient = np.empty(shape=(wmoving.shape) + (2, ), dtype=np.float64) movingGradient[:, :, 0], movingGradient[:, :, 1] = sp.gradient(wmoving) maxVariation = 1 + innerTolerance innerIter = 0 fw = np.zeros(shape=(fixed.shape) + (2, ), dtype=np.float64) maxInnerIter = 1000 while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)): innerIter += 1 maxVariation = tf.iterateDisplacementField2DCYTHON( deltaField, sigmaField, movingGradient, lambdaParam, fw, None) #fw*=0.5 totalF, stats = tf.compose_vector_fields(fw, totalF) totalF = np.array(totalF) meanDispF = np.mean(np.abs(fw)) #Compute backward field sigmaField = np.ones_like(wfixed, dtype=np.float64) deltaField = wmoving - wfixed fixedGradient = np.empty(shape=(wfixed.shape) + (2, ), dtype=np.float64) fixedGradient[:, :, 0], fixedGradient[:, :, 1] = sp.gradient(wfixed) maxVariation = 1 + innerTolerance innerIter = 0 mw = np.zeros(shape=(fixed.shape) + (2, ), dtype=np.float64) maxInnerIter = 1000 while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)): innerIter += 1 maxVariation = tf.iterateDisplacementField2DCYTHON( deltaField, sigmaField, fixedGradient, lambdaParam, mw, None) #mw*=0.5 totalM, stats = tf.compose_vector_fields(mw, totalM) totalM = np.array(totalM) meanDispM = np.mean(np.abs(mw)) totalFInv = np.array( tf.invert_vector_field_fixed_point(totalF, None, 20, 1e-3, None)) totalMInv = np.array( tf.invert_vector_field_fixed_point(totalM, None, 20, 1e-3, None)) totalF = np.array( tf.invert_vector_field_fixed_point(totalFInv, None, 20, 1e-3, None)) totalM = np.array( tf.invert_vector_field_fixed_point(totalMInv, None, 20, 1e-3, None)) # totalFInv=np.array(tf.invert_vector_field(totalF, 0.75, 100, 1e-6)) # totalMInv=np.array(tf.invert_vector_field(totalM, 0.75, 100, 1e-6)) # totalF=np.array(tf.invert_vector_field(totalFInv, 0.75, 100, 1e-6)) # totalM=np.array(tf.invert_vector_field(totalMInv, 0.75, 100, 1e-6)) if (meanDispM + meanDispF < 2 * outerTolerance): break print "Iter: ", innerIter, "Mean lateral displacement:", 0.5 * ( meanDispM + meanDispF), "Max variation:", maxVariation return totalF, totalFInv, totalM, totalMInv
def estimateNewMonomodalSyNField2D(moving, fixed, fWarp, fInv, mWarp, mInv, lambdaParam, maxOuterIter): ''' Warning: in the monomodal case, the parameter lambda must be significantly lower than in the multimodal case. Try lambdaParam=1, as opposed as lambdaParam=150 used in the multimodal case ''' innerTolerance=1e-4 outerTolerance=1e-3 if(mWarp!=None): totalM=mWarp totalMInv=mInv else: totalM=np.zeros(shape=(fixed.shape)+(2,), dtype=np.float64) totalMInv=np.zeros(shape=(fixed.shape)+(2,), dtype=np.float64) if(fWarp!=None): totalF=fWarp totalFInv=fInv else: totalF=np.zeros(shape=(moving.shape)+(2,), dtype=np.float64) totalFInv=np.zeros(shape=(moving.shape)+(2,), dtype=np.float64) outerIter=0 framesToCapture=5 maxOuterIter=framesToCapture*((maxOuterIter+framesToCapture-1)/framesToCapture) itersPerCapture=maxOuterIter/framesToCapture plt.figure() while(outerIter<maxOuterIter): outerIter+=1 print 'Outer iter:', outerIter wmoving=np.array(tf.warp_image(moving, totalMInv)) wfixed=np.array(tf.warp_image(fixed, totalFInv)) if((outerIter==1) or (outerIter%itersPerCapture==0)): plt.subplot(1,framesToCapture+1, 1+outerIter/itersPerCapture) rcommon.overlayImages(wmoving, wfixed, False) plt.title('Iter:'+str(outerIter-1)) #Compute forward update sigmaField=np.ones_like(wmoving, dtype=np.float64) deltaField=wfixed-wmoving movingGradient =np.empty(shape=(wmoving.shape)+(2,), dtype=np.float64) movingGradient[:,:,0], movingGradient[:,:,1]=sp.gradient(wmoving) maxVariation=1+innerTolerance innerIter=0 fw =np.zeros(shape=(fixed.shape)+(2,), dtype=np.float64) maxInnerIter=1000 while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)): innerIter+=1 maxVariation=tf.iterateDisplacementField2DCYTHON(deltaField, sigmaField, movingGradient, lambdaParam, fw, None) #fw*=0.5 totalF, stats=tf.compose_vector_fields(fw, totalF) totalF=np.array(totalF); meanDispF=np.mean(np.abs(fw)) #Compute backward field sigmaField=np.ones_like(wfixed, dtype=np.float64) deltaField=wmoving-wfixed fixedGradient =np.empty(shape=(wfixed.shape)+(2,), dtype=np.float64) fixedGradient[:,:,0], fixedGradient[:,:,1]=sp.gradient(wfixed) maxVariation=1+innerTolerance innerIter=0 mw =np.zeros(shape=(fixed.shape)+(2,), dtype=np.float64) maxInnerIter=1000 while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)): innerIter+=1 maxVariation=tf.iterateDisplacementField2DCYTHON(deltaField, sigmaField, fixedGradient, lambdaParam, mw, None) #mw*=0.5 totalM, stats=tf.compose_vector_fields(mw, totalM) totalM=np.array(totalM); meanDispM=np.mean(np.abs(mw)) totalFInv=np.array(tf.invert_vector_field_fixed_point(totalF, None, 20, 1e-3, None)) totalMInv=np.array(tf.invert_vector_field_fixed_point(totalM, None, 20, 1e-3, None)) totalF=np.array(tf.invert_vector_field_fixed_point(totalFInv, None, 20, 1e-3, None)) totalM=np.array(tf.invert_vector_field_fixed_point(totalMInv, None, 20, 1e-3, None)) # totalFInv=np.array(tf.invert_vector_field(totalF, 0.75, 100, 1e-6)) # totalMInv=np.array(tf.invert_vector_field(totalM, 0.75, 100, 1e-6)) # totalF=np.array(tf.invert_vector_field(totalFInv, 0.75, 100, 1e-6)) # totalM=np.array(tf.invert_vector_field(totalMInv, 0.75, 100, 1e-6)) if(meanDispM+meanDispF<2*outerTolerance): break print "Iter: ",innerIter, "Mean lateral displacement:", 0.5*(meanDispM+meanDispF), "Max variation:",maxVariation return totalF, totalFInv, totalM, totalMInv
def test_optimizer_multimodal_2d(lambda_param): r''' Registers one of the mid-slices (axial, coronal or sagital) of each input volume (the volumes are expected to be from diferent modalities and should already be affine-registered, for example Brainweb t1 vs t2) ''' fname_moving = 'data/t2/IBSR_t2template_to_01.nii.gz' fname_fixed = 'data/t1/IBSR_template_to_01.nii.gz' # fnameMoving = 'data/circle.png' # fnameFixed = 'data/C.png' nifti = True if nifti: nib_moving = nib.load(fname_moving) nib_fixed = nib.load(fname_fixed) moving = nib_moving.get_data().squeeze().astype(np.float64) fixed = nib_fixed.get_data().squeeze().astype(np.float64) moving = np.copy(moving, order='C') fixed = np.copy(fixed, order='C') shape_moving = moving.shape shape_fixed = fixed.shape moving = moving[:, shape_moving[1] // 2, :].copy() fixed = fixed[:, shape_fixed[1] // 2, :].copy() moving = (moving - moving.min()) / (moving.max() - moving.min()) fixed = (fixed - fixed.min()) / (fixed.max() - fixed.min()) else: nib_moving = plt.imread(fname_moving) nib_fixed = plt.imread(fname_fixed) moving = nib_moving[:, :, 0].astype(np.float64) fixed = nib_fixed[:, :, 1].astype(np.float64) moving = np.copy(moving, order='C') fixed = np.copy(fixed, order='C') moving = (moving - moving.min()) / (moving.max() - moving.min()) fixed = (fixed - fixed.min()) / (fixed.max() - fixed.min()) max_iter = [i for i in [25, 50, 100]] similarity_metric = EMMetric( 2, { 'symmetric': True, 'lambda': lambda_param, 'stepType': SSDMetric.GAUSS_SEIDEL_STEP, 'q_levels': 256, 'max_inner_iter': 20, 'use_double_gradient': True, 'max_step_length': 0.25 }) optimizer_parameters = { 'max_iter': max_iter, 'inversion_iter': 20, 'inversion_tolerance': 1e-3, 'report_status': True } update_rule = UpdateRule.Composition() print('Generating synthetic field...') #----apply synthetic deformation field to fixed image ground_truth = rcommon.createDeformationField2D_type2( fixed.shape[0], fixed.shape[1], 8) warped_fixed = rcommon.warpImage(fixed, ground_truth) print('Registering T2 (template) to deformed T1 (template)...') plt.figure() rcommon.overlayImages(warped_fixed, moving, False) registration_optimizer = SymmetricRegistrationOptimizer( warped_fixed, moving, None, None, similarity_metric, update_rule, optimizer_parameters) registration_optimizer.optimize() #######################show results################################# displacement = registration_optimizer.get_forward() direct_inverse = registration_optimizer.get_backward() moving_to_fixed = np.array(tf.warp_image(moving, displacement)) fixed_to_moving = np.array(tf.warp_image(warped_fixed, direct_inverse)) rcommon.overlayImages(moving_to_fixed, fixed_to_moving, True) direct_residual, stats = tf.compose_vector_fields(displacement, direct_inverse) direct_residual = np.array(direct_residual) rcommon.plotDiffeomorphism(displacement, direct_inverse, direct_residual, 'inv-direct', 7) residual = ((displacement - ground_truth))**2 mean_displacement_error = np.sqrt(residual.sum(2) * (warped_fixed > 0)).mean() stdev_displacement_error = np.sqrt(residual.sum(2) * (warped_fixed > 0)).std() print('Mean displacement error: %0.6f (%0.6f)' % (mean_displacement_error, stdev_displacement_error))
def test_optimizer_multimodal_2d(lambda_param): r""" Registers one of the mid-slices (axial, coronal or sagital) of each input volume (the volumes are expected to be from diferent modalities and should already be affine-registered, for example Brainweb t1 vs t2) """ fname_moving = "data/t2/IBSR_t2template_to_01.nii.gz" fname_fixed = "data/t1/IBSR_template_to_01.nii.gz" # fname_moving = 'data/circle.png' # fname_fixed = 'data/C.png' nifti = True if nifti: nib_moving = nib.load(fname_moving) nib_fixed = nib.load(fname_fixed) moving = nib_moving.get_data().squeeze().astype(np.float64) fixed = nib_fixed.get_data().squeeze().astype(np.float64) moving = np.copy(moving, order="C") fixed = np.copy(fixed, order="C") moving_shape = moving.shape fixed_shape = fixed.shape moving = moving[:, moving_shape[1] // 2, :].copy() fixed = fixed[:, fixed_shape[1] // 2, :].copy() # moving = histeq(moving) # fixed = histeq(fixed) moving = (moving - moving.min()) / (moving.max() - moving.min()) fixed = (fixed - fixed.min()) / (fixed.max() - fixed.min()) else: nib_moving = plt.imread(fname_moving) nib_fixed = plt.imread(fname_fixed) moving = nib_moving[:, :, 0].astype(np.float64) fixed = nib_fixed[:, :, 1].astype(np.float64) moving = np.copy(moving, order="C") fixed = np.copy(fixed, order="C") moving = (moving - moving.min()) / (moving.max() - moving.min()) fixed = (fixed - fixed.min()) / (fixed.max() - fixed.min()) # max_iter = [i for i in [25,50,100,100]] max_iter = [i for i in [25, 50, 100]] similarity_metric = EMMetric( { "symmetric": True, "lambda": lambda_param, "step_type": SSDMetric.GAUSS_SEIDEL_STEP, "q_levels": 256, "max_inner_iter": 40, "use_double_gradient": True, "max_step_length": 0.25, } ) optimizer_parameters = { "max_iter": max_iter, "inversion_iter": 40, "inversion_tolerance": 1e-3, "report_status": True, } update_rule = UpdateRule.Composition() print "Generating synthetic field..." # ----apply synthetic deformation field to fixed image ground_truth = rcommon.createDeformationField2D_type2(fixed.shape[0], fixed.shape[1], 8) warped_fixed = rcommon.warpImage(fixed, ground_truth) print "Registering T2 (template) to deformed T1 (template)..." plt.figure() rcommon.overlayImages(warped_fixed, moving, False) registration_optimizer = AsymmetricRegistrationOptimizer( warped_fixed, moving, None, None, similarity_metric, update_rule, optimizer_parameters ) registration_optimizer.optimize() #######################show results################################# displacement = registration_optimizer.get_forward() direct_inverse = registration_optimizer.get_backward() moving_to_fixed = np.array(tf.warp_image(moving, displacement)) fixed_to_moving = np.array(tf.warp_image(warped_fixed, direct_inverse)) rcommon.overlayImages(moving_to_fixed, fixed_to_moving, True) direct_residual, stats = tf.compose_vector_fields(displacement, direct_inverse) direct_residual = np.array(direct_residual) rcommon.plotDiffeomorphism(displacement, direct_inverse, direct_residual, "inv-direct", 7) residual = ((displacement - ground_truth)) ** 2 mean_error = np.sqrt(residual.sum(2) * (warped_fixed > 0)).mean() stdev_error = np.sqrt(residual.sum(2) * (warped_fixed > 0)).std() print "Mean displacement error: ", mean_error, "(", stdev_error, ")"
def test_optimizer_multimodal_2d(lambda_param): r''' Registers one of the mid-slices (axial, coronal or sagital) of each input volume (the volumes are expected to be from diferent modalities and should already be affine-registered, for example Brainweb t1 vs t2) ''' fname_moving = 'data/t2/IBSR_t2template_to_01.nii.gz' fname_fixed = 'data/t1/IBSR_template_to_01.nii.gz' # fnameMoving = 'data/circle.png' # fnameFixed = 'data/C.png' nifti = True if nifti: nib_moving = nib.load(fname_moving) nib_fixed = nib.load(fname_fixed) moving = nib_moving.get_data().squeeze().astype(np.float64) fixed = nib_fixed.get_data().squeeze().astype(np.float64) moving = np.copy(moving, order = 'C') fixed = np.copy(fixed, order = 'C') shape_moving = moving.shape shape_fixed = fixed.shape moving = moving[:, shape_moving[1]//2, :].copy() fixed = fixed[:, shape_fixed[1]//2, :].copy() moving = (moving-moving.min())/(moving.max()-moving.min()) fixed = (fixed-fixed.min())/(fixed.max()-fixed.min()) else: nib_moving = plt.imread(fname_moving) nib_fixed = plt.imread(fname_fixed) moving = nib_moving[:, :, 0].astype(np.float64) fixed = nib_fixed[:, :, 1].astype(np.float64) moving = np.copy(moving, order = 'C') fixed = np.copy(fixed, order = 'C') moving = (moving-moving.min())/(moving.max() - moving.min()) fixed = (fixed-fixed.min())/(fixed.max() - fixed.min()) max_iter = [i for i in [25, 50, 100]] similarity_metric = EMMetric(2, {'symmetric':True, 'lambda':lambda_param, 'stepType':SSDMetric.GAUSS_SEIDEL_STEP, 'q_levels':256, 'max_inner_iter':20, 'use_double_gradient':True, 'max_step_length':0.25}) optimizer_parameters = { 'max_iter':max_iter, 'inversion_iter':20, 'inversion_tolerance':1e-3, 'report_status':True} update_rule = UpdateRule.Composition() print('Generating synthetic field...') #----apply synthetic deformation field to fixed image ground_truth = rcommon.createDeformationField2D_type2(fixed.shape[0], fixed.shape[1], 8) warped_fixed = rcommon.warpImage(fixed, ground_truth) print('Registering T2 (template) to deformed T1 (template)...') plt.figure() rcommon.overlayImages(warped_fixed, moving, False) registration_optimizer = SymmetricRegistrationOptimizer(warped_fixed, moving, None, None, similarity_metric, update_rule, optimizer_parameters) registration_optimizer.optimize() #######################show results################################# displacement = registration_optimizer.get_forward() direct_inverse = registration_optimizer.get_backward() moving_to_fixed = np.array(tf.warp_image(moving, displacement)) fixed_to_moving = np.array(tf.warp_image(warped_fixed, direct_inverse)) rcommon.overlayImages(moving_to_fixed, fixed_to_moving, True) direct_residual, stats = tf.compose_vector_fields(displacement, direct_inverse) direct_residual = np.array(direct_residual) rcommon.plotDiffeomorphism(displacement, direct_inverse, direct_residual, 'inv-direct', 7) residual = ((displacement-ground_truth))**2 mean_displacement_error = np.sqrt(residual.sum(2)*(warped_fixed>0)).mean() stdev_displacement_error = np.sqrt(residual.sum(2)*(warped_fixed>0)).std() print('Mean displacement error: %0.6f (%0.6f)'% (mean_displacement_error, stdev_displacement_error))