def testInversion_invertible():
    displacement_clean=tf.create_invertible_displacement_field(256, 256, 0.5, 8)
    detJacobian=rcommon.computeJacobianField(displacement_clean)
    plt.figure()
    plt.imshow(detJacobian)
    print 'Range:', detJacobian.min(), detJacobian.max()
    X1,X0=np.mgrid[0:displacement_clean.shape[0], 0:displacement_clean.shape[1]]
    CS=plt.contour(X0,X1,detJacobian,levels=[0.0], colors='b')
    plt.clabel(CS, inline=1, fontsize=10)
    plt.title('det(J(displacement))')
    displacement=displacement_clean+np.random.normal(0.0, 1.1, displacement_clean.shape)
    #displacement=np.array(displacement_clean)
    #inverse=rcommon.invert_vector_field_fixed_point(displacement, 100, 1e-7)
    #inverse=np.array(tf.invert_vector_field(displacement, 0.1, 100, 1e-7))
    lambdaParam=5.0
    #########Jacobi##########
    inverse=np.array(tf.invert_vector_field(displacement, lambdaParam, 100, 1e-6))
    residual, stats=tf.compose_vector_fields(displacement_clean, inverse)
    residual=np.array(residual)
    print 'Jacobi. Max:',stats[0], '. Mean:',stats[1],'Std:',stats[2]
    [d,invd,res, detJ]=rcommon.plotDiffeomorphism(displacement, inverse, residual, 'Jacobi', 7)
    #########Fixed point######
    inverse=np.array(tf.invert_vector_field_fixed_point(displacement, 100, 1e-6))
    residual, stats=tf.compose_vector_fields(displacement_clean, inverse)
    residual=np.array(residual)
    print 'Fixed point. Max:',stats[0], '. Mean:',stats[1],'Std:',stats[2]
    [d,invd,res, detJ]=rcommon.plotDiffeomorphism(displacement, inverse, residual, 'Fixed point', 7)
    #########TV-L2###########
    inverse=np.array(tf.invert_vector_field_tv_l2(displacement, lambdaParam, 3000, 1e-6))
    residual, stats=tf.compose_vector_fields(displacement_clean, inverse)
    residual=np.array(residual)
    print 'TV-L2. Max:',stats[0], '. Mean:',stats[1],'Std:',stats[2]
    [d,invd,res, detJ]=rcommon.plotDiffeomorphism(displacement, inverse, residual, 'TV-L2', 7)
Example #2
0
def estimateMonomodalSyNField2DMultiScale(movingPyramid, fixedPyramid,
                                          lambdaParam, maxOuterIter, level,
                                          displacementList):
    n = len(movingPyramid)
    if (level == (n - 1)):
        totalF, totalFInv, totalM, totalMInv = estimateNewMonomodalSyNField2D(
            movingPyramid[level], fixedPyramid[level], None, None, None, None,
            lambdaParam, maxOuterIter[level])
        if (displacementList != None):
            displacementList.insert(0, totalM)
        return totalF, totalFInv, totalM, totalMInv
    subF, subFInv, subM, subMInv = estimateMonomodalSyNField2DMultiScale(
        movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, level + 1,
        displacementList)
    sh = np.array(fixedPyramid[level].shape).astype(np.int32)
    upF = np.array(tf.upsample_displacement_field(subF, sh)) * 2
    upFInv = np.array(tf.upsample_displacement_field(subFInv, sh)) * 2
    upM = np.array(tf.upsample_displacement_field(subM, sh)) * 2
    upMInv = np.array(tf.upsample_displacement_field(subMInv, sh)) * 2
    totalF, totalFInv, totalM, totalMInv = estimateNewMonomodalSyNField2D(
        movingPyramid[level], fixedPyramid[level], upF, upFInv, upM, upMInv,
        lambdaParam, maxOuterIter[level])
    if (displacementList != None):
        displacementList.insert(0, totalM)
    if (level == 0):
        totalF = np.array(tf.compose_vector_fields(totalF, totalMInv))
        totalM = np.array(tf.compose_vector_fields(totalM, totalFInv))
        return totalM, totalF
    return totalF, totalFInv, totalM, totalMInv
def testCircleToCMonomodalDiffeomorphic(lambdaParam):
    import numpy as np
    import tensorFieldUtils as tf
    import matplotlib.pyplot as plt
    import registrationCommon as rcommon
    fname0='data/circle.png'
    #fname0='data/C_trans.png'
    fname1='data/C.png'
    circleToCDisplacementName='circleToCDisplacement.npy'
    circleToCDisplacementInverseName='circleToCDisplacementInverse.npy'
    nib_moving=plt.imread(fname0)
    nib_fixed=plt.imread(fname1)
    moving=nib_moving[:,:,0]
    fixed=nib_fixed[:,:,1]
    moving=(moving-moving.min())/(moving.max() - moving.min())
    fixed=(fixed-fixed.min())/(fixed.max() - fixed.min())
    level=3
    maskMoving=moving>0
    maskFixed=fixed>0
    movingPyramid=[img for img in rcommon.pyramid_gaussian_2D(moving, level, np.ones_like(maskMoving))]
    fixedPyramid=[img for img in rcommon.pyramid_gaussian_2D(fixed, level, np.ones_like(maskFixed))]
    rcommon.plotOverlaidPyramids(movingPyramid, fixedPyramid)
    displacementList=[]
    maxOuterIter=[10,50,100,100,100,100,100,100,100]
    if(os.path.exists(circleToCDisplacementName)):
        displacement=np.load(circleToCDisplacementName)
        inverse=np.load(circleToCDisplacementInverseName)
    else:
        displacement, inverse=estimateMonomodalDiffeomorphicField2DMultiScale(movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, 0,displacementList)
        np.save(circleToCDisplacementName, displacement)
        np.save(circleToCDisplacementInverseName, inverse)    
    X1,X0=np.mgrid[0:displacement.shape[0], 0:displacement.shape[1]]
    detJacobian=rcommon.computeJacobianField(displacement)
    plt.figure()
    plt.imshow(detJacobian)
    CS=plt.contour(X0,X1,detJacobian,levels=[0.0], colors='b')
    plt.clabel(CS, inline=1, fontsize=10)
    plt.title('det(J(displacement))')
    print 'J range:', '[', detJacobian.min(), detJacobian.max(),']'
    #directInverse=np.array(tf.invert_vector_field(displacement, 0.5, 1000, 1e-7))
    directInverse=np.array(tf.invert_vector_field_fixed_point(displacement, 100, 1e-7))
    detJacobianInverse=rcommon.computeJacobianField(directInverse)
    plt.figure()
    plt.imshow(detJacobianInverse)
    CS=plt.contour(X0,X1,detJacobianInverse, levels=[0.0],colors='w')
    plt.clabel(CS, inline=1, fontsize=10)
    plt.title('det(J(displacement^-1))')
    print 'J^-1 range:', '[', detJacobianInverse.min(), detJacobianInverse.max(),']'
    #directInverse=rcommon.invert_vector_field_fixed_point(displacement, 1000, 1e-7)
    residual, stats=tf.compose_vector_fields(displacement, inverse)
    residual=np.array(residual)
    directResidual,stats=tf.compose_vector_fields(displacement, directInverse)
    directResidual=np.array(directResidual)
#    warpPyramid=[rcommon.warpImage(movingPyramid[i], displacementList[i]) for i in range(level+1)]
#    rcommon.plotOverlaidPyramids(warpPyramid, fixedPyramid)
#    rcommon.overlayImages(warpPyramid[0], fixedPyramid[0])
    rcommon.plotDiffeomorphism(displacement, inverse, residual, 'inv-joint', 7)
    rcommon.plotDiffeomorphism(displacement, directInverse, directResidual, 'inv-direct', 7)
    tf.write_double_buffer(displacement.reshape(-1), 'displacement.bin')
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 testEstimateMonomodalDiffeomorphicField2DMultiScale(lambdaParam):
    fname0='IBSR_01_to_02.nii.gz'
    fname1='data/t1/IBSR18/IBSR_02/IBSR_02_ana_strip.nii.gz'
    nib_moving = nib.load(fname0)
    nib_fixed= nib.load(fname1)
    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')
    sl=moving.shape
    sr=fixed.shape
    level=5
    #---sagital---
    moving=moving[sl[0]//2,:,:].copy()
    fixed=fixed[sr[0]//2,:,:].copy()
    #---coronal---
    #moving=moving[:,sl[1]//2,:].copy()
    #fixed=fixed[:,sr[1]//2,:].copy()
    #---axial---
    #moving=moving[:,:,sl[2]//2].copy()
    #fixed=fixed[:,:,sr[2]//2].copy()
    maskMoving=moving>0
    maskFixed=fixed>0
    movingPyramid=[img for img in rcommon.pyramid_gaussian_2D(moving, level, maskMoving)]
    fixedPyramid=[img for img in rcommon.pyramid_gaussian_2D(fixed, level, maskFixed)]
    rcommon.plotOverlaidPyramids(movingPyramid, fixedPyramid)
    displacementList=[]
    maxIter=200
    displacement, inverse=estimateMonomodalDiffeomorphicField2DMultiScale(movingPyramid, fixedPyramid, lambdaParam, maxIter, 0,displacementList)
    residual=tf.compose_vector_fields(displacement, inverse)
    warpPyramid=[rcommon.warpImage(movingPyramid[i], displacementList[i]) for i in range(level+1)]
    rcommon.plotOverlaidPyramids(warpPyramid, fixedPyramid)
    rcommon.overlayImages(warpPyramid[0], fixedPyramid[0])
    rcommon.plotDiffeomorphism(displacement, inverse, residual)
Example #6
0
def testCircleToCMonomodalSyNEM(lambdaParam, maxOuterIter):
    fname0='data/circle.png'
    #fname0='data/C_trans.png'
    fname1='data/C.png'
    nib_moving=plt.imread(fname0)
    nib_fixed=plt.imread(fname1)
    moving=nib_moving[:,:,0]
    fixed=nib_fixed[:,:,1]
    moving=(moving-moving.min())/(moving.max() - moving.min())
    fixed=(fixed-fixed.min())/(fixed.max() - fixed.min())
    level=3
    maskMoving=moving>0
    maskFixed=fixed>0
    movingPyramid=[img for img in rcommon.pyramid_gaussian_2D(moving, level, maskMoving)]
    fixedPyramid=[img for img in rcommon.pyramid_gaussian_2D(fixed, level, maskFixed)]
    rcommon.plotOverlaidPyramids(movingPyramid, fixedPyramid)
    displacementList=[]
    displacement, dinv=estimateMonomodalSyNField2DMultiScale(movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, 0,displacementList)
    inverse=np.array(tf.invert_vector_field(displacement, 0.75, 300, 1e-7))
    residual, stats=tf.compose_vector_fields(displacement, inverse)
    residual=np.array(residual)
    warpPyramid=[rcommon.warpImage(movingPyramid[i], displacementList[i]) for i in range(level+1)]
    rcommon.plotOverlaidPyramids(warpPyramid, fixedPyramid)
    rcommon.overlayImages(warpPyramid[0], fixedPyramid[0])
    rcommon.plotDiffeomorphism(displacement, inverse, residual, '',7)
Example #7
0
def testCircleToCMonomodalSyNEM(lambdaParam, maxOuterIter):
    fname0 = 'data/circle.png'
    #fname0='data/C_trans.png'
    fname1 = 'data/C.png'
    nib_moving = plt.imread(fname0)
    nib_fixed = plt.imread(fname1)
    moving = nib_moving[:, :, 0]
    fixed = nib_fixed[:, :, 1]
    moving = (moving - moving.min()) / (moving.max() - moving.min())
    fixed = (fixed - fixed.min()) / (fixed.max() - fixed.min())
    level = 3
    maskMoving = moving > 0
    maskFixed = fixed > 0
    movingPyramid = [
        img for img in rcommon.pyramid_gaussian_2D(moving, level, maskMoving)
    ]
    fixedPyramid = [
        img for img in rcommon.pyramid_gaussian_2D(fixed, level, maskFixed)
    ]
    rcommon.plotOverlaidPyramids(movingPyramid, fixedPyramid)
    displacementList = []
    displacement, dinv = estimateMonomodalSyNField2DMultiScale(
        movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, 0,
        displacementList)
    inverse = np.array(tf.invert_vector_field(displacement, 0.75, 300, 1e-7))
    residual, stats = tf.compose_vector_fields(displacement, inverse)
    residual = np.array(residual)
    warpPyramid = [
        rcommon.warpImage(movingPyramid[i], displacementList[i])
        for i in range(level + 1)
    ]
    rcommon.plotOverlaidPyramids(warpPyramid, fixedPyramid)
    rcommon.overlayImages(warpPyramid[0], fixedPyramid[0])
    rcommon.plotDiffeomorphism(displacement, inverse, residual, '', 7)
def testInversion(lambdaParam):
    fname0='data/circle.png'
    fname1='data/C.png'
    circleToCDisplacementName='circleToCDisplacement.npy'
    circleToCDisplacementInverseName='circleToCDisplacementInverse.npy'
    nib_moving=plt.imread(fname0)
    nib_fixed=plt.imread(fname1)
    moving=nib_moving[:,:,0]
    fixed=nib_fixed[:,:,1]
    moving=(moving-moving.min())/(moving.max() - moving.min())
    fixed=(fixed-fixed.min())/(fixed.max() - fixed.min())
    level=3
    maskMoving=moving>0
    maskFixed=fixed>0
    movingPyramid=[img for img in rcommon.pyramid_gaussian_2D(moving, level, np.ones_like(maskMoving))]
    fixedPyramid=[img for img in rcommon.pyramid_gaussian_2D(fixed, level, np.ones_like(maskFixed))]
    rcommon.plotOverlaidPyramids(movingPyramid, fixedPyramid)
    displacementList=[]
    maxOuterIter=[10,50,100,100,100,100,100,100,100]
    if(os.path.exists(circleToCDisplacementName)):
        displacement=np.load(circleToCDisplacementName)
        inverse=np.load(circleToCDisplacementInverseName)
    else:
        displacement, inverse=estimateMonomodalDiffeomorphicField2DMultiScale(movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, 0,displacementList)
        np.save(circleToCDisplacementName, displacement)
        np.save(circleToCDisplacementInverseName, inverse)
    print 'vector field exponential'
    expd, invexpd=tf.vector_field_exponential(displacement, True)
    print 'vector field inversion'
    directInverse=tf.invert_vector_field(displacement, 1.0, 10000, 1e-7)
    print 'vector field inversion'
    directExpInverse=tf.invert_vector_field(expd, 1.0, 10000, 1e-7)
    ###Now compare inversions###
    residualJoint=np.array(tf.compose_vector_fields(displacement, inverse)[0])
    residualDirect=np.array(tf.compose_vector_fields(displacement, directInverse)[0])
    residualExpJoint=np.array(tf.compose_vector_fields(expd, invexpd)[0])
    residualExpDirect=np.array(tf.compose_vector_fields(expd, directExpInverse)[0])
    rcommon.plotDiffeomorphism(displacement, inverse, residualJoint, 'D-joint')
    rcommon.plotDiffeomorphism(expd, invexpd, residualExpJoint, 'expD-joint')
    d,invd,res,jacobian=rcommon.plotDiffeomorphism(displacement, directInverse, residualDirect, 'D-direct')
    rcommon.plotDiffeomorphism(expd, directExpInverse, residualExpDirect, 'expD-direct')
    sp.misc.imsave('circleToC_deformation.png', d)
    sp.misc.imsave('circleToC_inverse_deformation.png', invd)
    sp.misc.imsave('circleToC_residual_deformation.png', res)
    tf.write_double_buffer(np.array(displacement).reshape(-1), '../inverse/experiments/displacement.bin')
    tf.write_double_buffer(np.array(displacement).reshape(-1), '../inverse/experiments/displacement_clean.bin')
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 testInversion_invertible():
    displacement_clean = tf.create_invertible_displacement_field(
        256, 256, 0.5, 8)
    detJacobian = rcommon.computeJacobianField(displacement_clean)
    plt.figure()
    plt.imshow(detJacobian)
    print 'Range:', detJacobian.min(), detJacobian.max()
    X1, X0 = np.mgrid[0:displacement_clean.shape[0],
                      0:displacement_clean.shape[1]]
    CS = plt.contour(X0, X1, detJacobian, levels=[0.0], colors='b')
    plt.clabel(CS, inline=1, fontsize=10)
    plt.title('det(J(displacement))')
    displacement = displacement_clean + np.random.normal(
        0.0, 1.1, displacement_clean.shape)
    #displacement=np.array(displacement_clean)
    #inverse=rcommon.invert_vector_field_fixed_point(displacement, 100, 1e-7)
    #inverse=np.array(tf.invert_vector_field(displacement, 0.1, 100, 1e-7))
    lambdaParam = 5.0
    #########Jacobi##########
    inverse = np.array(
        tf.invert_vector_field(displacement, lambdaParam, 100, 1e-6))
    residual, stats = tf.compose_vector_fields(displacement_clean, inverse)
    residual = np.array(residual)
    print 'Jacobi. Max:', stats[0], '. Mean:', stats[1], 'Std:', stats[2]
    [d, invd, res, detJ] = rcommon.plotDiffeomorphism(displacement, inverse,
                                                      residual, 'Jacobi', 7)
    #########Fixed point######
    inverse = np.array(
        tf.invert_vector_field_fixed_point(displacement, 100, 1e-6))
    residual, stats = tf.compose_vector_fields(displacement_clean, inverse)
    residual = np.array(residual)
    print 'Fixed point. Max:', stats[0], '. Mean:', stats[1], 'Std:', stats[2]
    [d, invd, res,
     detJ] = rcommon.plotDiffeomorphism(displacement, inverse, residual,
                                        'Fixed point', 7)
    #########TV-L2###########
    inverse = np.array(
        tf.invert_vector_field_tv_l2(displacement, lambdaParam, 3000, 1e-6))
    residual, stats = tf.compose_vector_fields(displacement_clean, inverse)
    residual = np.array(residual)
    print 'TV-L2. Max:', stats[0], '. Mean:', stats[1], 'Std:', stats[2]
    [d, invd, res, detJ] = rcommon.plotDiffeomorphism(displacement, inverse,
                                                      residual, 'TV-L2', 7)
Example #11
0
 def update(new_displacement, current_displacement):
     dim = len(new_displacement.shape)-1
     mse = np.sqrt(np.sum((current_displacement**2), -1)).mean()
     if dim == 2:
         updated, stats = tf.compose_vector_fields(new_displacement, 
                                                   current_displacement)
     else:
         updated, stats = tf.compose_vector_fields3D(new_displacement, 
                                                     current_displacement)
     return np.array(updated), np.array(mse)
Example #12
0
def estimateMonomodalSyNField2DMultiScale(movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, level, displacementList):
    n=len(movingPyramid)
    if(level==(n-1)):
        totalF, totalFInv, totalM, totalMInv=estimateNewMonomodalSyNField2D(movingPyramid[level], fixedPyramid[level], None, None, None, None, lambdaParam, maxOuterIter[level])
        if(displacementList!=None):
            displacementList.insert(0,totalM)
        return totalF, totalFInv, totalM, totalMInv
    subF, subFInv, subM, subMInv=estimateMonomodalSyNField2DMultiScale(movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, level+1, displacementList)
    sh=np.array(fixedPyramid[level].shape).astype(np.int32)
    upF=np.array(tf.upsample_displacement_field(subF, sh))*2
    upFInv=np.array(tf.upsample_displacement_field(subFInv, sh))*2
    upM=np.array(tf.upsample_displacement_field(subM, sh))*2
    upMInv=np.array(tf.upsample_displacement_field(subMInv, sh))*2
    totalF, totalFInv, totalM, totalMInv=estimateNewMonomodalSyNField2D(movingPyramid[level], fixedPyramid[level], upF, upFInv, upM, upMInv, lambdaParam, maxOuterIter[level])
    if(displacementList!=None):
        displacementList.insert(0, totalM)
    if(level==0):
        totalF=np.array(tf.compose_vector_fields(totalF, totalMInv))
        totalM=np.array(tf.compose_vector_fields(totalM, totalFInv))
        return totalM, totalF
    return totalF, totalFInv, totalM, totalMInv
Example #13
0
 def compute_inversion_error(self):
     r'''
     Returns the inversion error of the displacement fields
     TO-DO: the inversion error should take into account the affine
     transformations as well.
     '''
     if self.dim == 2:
         residual, stats = tf.compose_vector_fields(self.forward,
                                                    self.backward)
     else:
         residual, stats = tf.compose_vector_fields3D(self.forward,
                                                      self.backward)
     return residual, stats
Example #14
0
 def compose(self, applyFirst):
     r'''
     Computes the composition G(F(.)) where G is this transformation and
     F is the transformation given as parameter
     '''
     B=applyFirst.affine_post
     C=self.affine_pre
     if B==None:
         affine_prod=C
     elif C==None:
         affine_prod=B
     else:
         affine_prod=C.dot(B)
     if affine_prod!=None:
         affine_prod_inv=linalg.inv(affine_prod).copy(order='C')
     else:
         affine_prod_inv=None
     if self.dim == 2:
         forward=applyFirst.forward.copy()
         tf.append_affine_to_displacement_field_2d(forward, affine_prod)
         forward, stats = tf.compose_vector_fields(forward,
                                                   self.forward)
         backward=self.backward.copy()
         tf.append_affine_to_displacement_field_2d(backward, affine_prod_inv)
         backward, stats = tf.compose_vector_fields(backward, 
                                                    applyFirst.backward)
     else:
         forward=applyFirst.forward.copy()
         tf.append_affine_to_displacement_field_3d(forward, affine_prod)
         forward, stats = tf.compose_vector_fields3D(forward,
                                                   self.forward)
         backward=self.backward.copy()
         tf.append_affine_to_displacement_field_3d(backward, affine_prod_inv)
         backward, stats = tf.compose_vector_fields3D(backward, 
                                                    applyFirst.backward)
     composition=TransformationModel(forward, backward, 
                                     applyFirst.affine_pre, self.affine_post)
     return composition
Example #15
0
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 testEstimateMonomodalDiffeomorphicField2DMultiScale(lambdaParam):
    fname0 = 'IBSR_01_to_02.nii.gz'
    fname1 = 'data/t1/IBSR18/IBSR_02/IBSR_02_ana_strip.nii.gz'
    nib_moving = nib.load(fname0)
    nib_fixed = nib.load(fname1)
    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')
    sl = moving.shape
    sr = fixed.shape
    level = 5
    #---sagital---
    moving = moving[sl[0] // 2, :, :].copy()
    fixed = fixed[sr[0] // 2, :, :].copy()
    #---coronal---
    #moving=moving[:,sl[1]//2,:].copy()
    #fixed=fixed[:,sr[1]//2,:].copy()
    #---axial---
    #moving=moving[:,:,sl[2]//2].copy()
    #fixed=fixed[:,:,sr[2]//2].copy()
    maskMoving = moving > 0
    maskFixed = fixed > 0
    movingPyramid = [
        img for img in rcommon.pyramid_gaussian_2D(moving, level, maskMoving)
    ]
    fixedPyramid = [
        img for img in rcommon.pyramid_gaussian_2D(fixed, level, maskFixed)
    ]
    rcommon.plotOverlaidPyramids(movingPyramid, fixedPyramid)
    displacementList = []
    maxIter = 200
    displacement, inverse = estimateMonomodalDiffeomorphicField2DMultiScale(
        movingPyramid, fixedPyramid, lambdaParam, maxIter, 0, displacementList)
    residual = tf.compose_vector_fields(displacement, inverse)
    warpPyramid = [
        rcommon.warpImage(movingPyramid[i], displacementList[i])
        for i in range(level + 1)
    ]
    rcommon.plotOverlaidPyramids(warpPyramid, fixedPyramid)
    rcommon.overlayImages(warpPyramid[0], fixedPyramid[0])
    rcommon.plotDiffeomorphism(displacement, inverse, residual)
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 testCircleToCMonomodalDiffeomorphic(lambdaParam):
    import numpy as np
    import tensorFieldUtils as tf
    import matplotlib.pyplot as plt
    import registrationCommon as rcommon
    fname0 = 'data/circle.png'
    #fname0='data/C_trans.png'
    fname1 = 'data/C.png'
    circleToCDisplacementName = 'circleToCDisplacement.npy'
    circleToCDisplacementInverseName = 'circleToCDisplacementInverse.npy'
    nib_moving = plt.imread(fname0)
    nib_fixed = plt.imread(fname1)
    moving = nib_moving[:, :, 0]
    fixed = nib_fixed[:, :, 1]
    moving = (moving - moving.min()) / (moving.max() - moving.min())
    fixed = (fixed - fixed.min()) / (fixed.max() - fixed.min())
    level = 3
    maskMoving = moving > 0
    maskFixed = fixed > 0
    movingPyramid = [
        img for img in rcommon.pyramid_gaussian_2D(moving, level,
                                                   np.ones_like(maskMoving))
    ]
    fixedPyramid = [
        img for img in rcommon.pyramid_gaussian_2D(fixed, level,
                                                   np.ones_like(maskFixed))
    ]
    rcommon.plotOverlaidPyramids(movingPyramid, fixedPyramid)
    displacementList = []
    maxOuterIter = [10, 50, 100, 100, 100, 100, 100, 100, 100]
    if (os.path.exists(circleToCDisplacementName)):
        displacement = np.load(circleToCDisplacementName)
        inverse = np.load(circleToCDisplacementInverseName)
    else:
        displacement, inverse = estimateMonomodalDiffeomorphicField2DMultiScale(
            movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, 0,
            displacementList)
        np.save(circleToCDisplacementName, displacement)
        np.save(circleToCDisplacementInverseName, inverse)
    X1, X0 = np.mgrid[0:displacement.shape[0], 0:displacement.shape[1]]
    detJacobian = rcommon.computeJacobianField(displacement)
    plt.figure()
    plt.imshow(detJacobian)
    CS = plt.contour(X0, X1, detJacobian, levels=[0.0], colors='b')
    plt.clabel(CS, inline=1, fontsize=10)
    plt.title('det(J(displacement))')
    print 'J range:', '[', detJacobian.min(), detJacobian.max(), ']'
    #directInverse=np.array(tf.invert_vector_field(displacement, 0.5, 1000, 1e-7))
    directInverse = np.array(
        tf.invert_vector_field_fixed_point(displacement, 100, 1e-7))
    detJacobianInverse = rcommon.computeJacobianField(directInverse)
    plt.figure()
    plt.imshow(detJacobianInverse)
    CS = plt.contour(X0, X1, detJacobianInverse, levels=[0.0], colors='w')
    plt.clabel(CS, inline=1, fontsize=10)
    plt.title('det(J(displacement^-1))')
    print 'J^-1 range:', '[', detJacobianInverse.min(), detJacobianInverse.max(
    ), ']'
    #directInverse=rcommon.invert_vector_field_fixed_point(displacement, 1000, 1e-7)
    residual, stats = tf.compose_vector_fields(displacement, inverse)
    residual = np.array(residual)
    directResidual, stats = tf.compose_vector_fields(displacement,
                                                     directInverse)
    directResidual = np.array(directResidual)
    #    warpPyramid=[rcommon.warpImage(movingPyramid[i], displacementList[i]) for i in range(level+1)]
    #    rcommon.plotOverlaidPyramids(warpPyramid, fixedPyramid)
    #    rcommon.overlayImages(warpPyramid[0], fixedPyramid[0])
    rcommon.plotDiffeomorphism(displacement, inverse, residual, 'inv-joint', 7)
    rcommon.plotDiffeomorphism(displacement, directInverse, directResidual,
                               'inv-direct', 7)
    tf.write_double_buffer(displacement.reshape(-1), 'displacement.bin')
Example #20
0
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 estimateNewMultimodalDiffeomorphicField2D(moving, fixed, lambdaDisplacement, quantizationLevels, maxOuterIter, previousDisplacement, previousDisplacementInverse):
    innerTolerance=1e-4
    outerTolerance=1e-3
    sh=moving.shape
    X0,X1=np.mgrid[0:sh[0], 0:sh[1]]
    displacement     =np.empty(shape=(moving.shape)+(2,), dtype=np.float64)
    residuals=np.zeros(shape=(moving.shape), 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
    fixedQ=None
    grayLevels=None
    fixedQ, grayLevels, hist=tf.quantizePositiveImageCYTHON(fixed, quantizationLevels)
    fixedQ=np.array(fixedQ, dtype=np.int32)
    finished=False
    outerIter=0
    maxDisplacement=None
    maxVariation=None
    maxResidual=0
    while((not finished) and (outerIter<maxOuterIter)):
        outerIter+=1
        #---E step---
        warped=ndimage.map_coordinates(moving, [X0+totalDisplacement[...,0], X1+totalDisplacement[...,1]], prefilter=True)
        movingMask=((moving>0)*1.0)*((fixed>0)*1.0)
        warpedMovingMask=ndimage.map_coordinates(movingMask, [X0+totalDisplacement[...,0], X1+totalDisplacement[...,1]], order=0, prefilter=False)
        warpedMovingMask=warpedMovingMask.astype(np.int32)
        means, variances=tf.computeMaskedImageClassStatsCYTHON(warpedMovingMask, warped, quantizationLevels, fixedQ)            
        means[0]=0
        means=np.array(means)
        variances=np.array(variances)
        sigmaField=variances[fixedQ]
        deltaField=means[fixedQ]-warped#########Delta-field using Arce's rule
        #--M step--
        g0, g1=sp.gradient(warped)
        gradientField[:,:,0]=g0
        gradientField[:,:,1]=g1
        maxVariation=1+innerTolerance
        innerIter=0
        maxInnerIter=1000
        displacement[...]=0
        while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)):
            innerIter+=1
            maxVariation=tf.iterateDisplacementField2DCYTHON(deltaField, sigmaField, gradientField,  lambdaDisplacement, totalDisplacement, displacement, residuals)
            opt=np.max(residuals)
            if(maxResidual<opt):
                maxResidual=opt
        #--accumulate displacement--
        expd, invexpd=tf.vector_field_exponential(displacement)
        totalDisplacement=tf.compose_vector_fields(expd, totalDisplacement)
        totalDisplacementInverse=tf.compose_vector_fields(totalDisplacementInverse, invexpd)
        #--check stop condition--
        nrm=np.sqrt(displacement[...,0]**2+displacement[...,1]**2)
        #maxDisplacement=np.max(nrm)
        maxDisplacement=np.mean(nrm)
        if((maxDisplacement<outerTolerance)or(outerIter>=maxOuterIter)):
            finished=True
#            plt.figure()
#            plt.subplot(1,3,1)
#            plt.imshow(means[fixedQ],cmap=plt.cm.gray)    
#            plt.title("Estimated warped modality")
#            plt.subplot(1,3,2)
#            plt.imshow(fixedQ,cmap=plt.cm.gray)
#            plt.title("Quantized")
#            plt.subplot(1,3,3)
#            plt.plot(means)
#            plt.title("Means")
    print "Iter: ",outerIter, "Mean displacement:", maxDisplacement, "Max variation:",maxVariation, "Max residual:", maxResidual
    if(previousDisplacement!=None):
        return totalDisplacement-previousDisplacement, totalDisplacementInverse
    return totalDisplacement, totalDisplacementInverse
def estimateNewMultimodalDiffeomorphicField2D(moving, fixed,
                                              lambdaDisplacement,
                                              quantizationLevels, maxOuterIter,
                                              previousDisplacement,
                                              previousDisplacementInverse):
    innerTolerance = 1e-4
    outerTolerance = 1e-3
    sh = moving.shape
    X0, X1 = np.mgrid[0:sh[0], 0:sh[1]]
    displacement = np.empty(shape=(moving.shape) + (2, ), dtype=np.float64)
    residuals = np.zeros(shape=(moving.shape), 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
    fixedQ = None
    grayLevels = None
    fixedQ, grayLevels, hist = tf.quantizePositiveImageCYTHON(
        fixed, quantizationLevels)
    fixedQ = np.array(fixedQ, dtype=np.int32)
    finished = False
    outerIter = 0
    maxDisplacement = None
    maxVariation = None
    maxResidual = 0
    while ((not finished) and (outerIter < maxOuterIter)):
        outerIter += 1
        #---E step---
        warped = ndimage.map_coordinates(
            moving,
            [X0 + totalDisplacement[..., 0], X1 + totalDisplacement[..., 1]],
            prefilter=True)
        movingMask = ((moving > 0) * 1.0) * ((fixed > 0) * 1.0)
        warpedMovingMask = ndimage.map_coordinates(
            movingMask,
            [X0 + totalDisplacement[..., 0], X1 + totalDisplacement[..., 1]],
            order=0,
            prefilter=False)
        warpedMovingMask = warpedMovingMask.astype(np.int32)
        means, variances = tf.computeMaskedImageClassStatsCYTHON(
            warpedMovingMask, warped, quantizationLevels, fixedQ)
        means[0] = 0
        means = np.array(means)
        variances = np.array(variances)
        sigmaField = variances[fixedQ]
        deltaField = means[
            fixedQ] - warped  #########Delta-field using Arce's rule
        #--M step--
        g0, g1 = sp.gradient(warped)
        gradientField[:, :, 0] = g0
        gradientField[:, :, 1] = g1
        maxVariation = 1 + innerTolerance
        innerIter = 0
        maxInnerIter = 1000
        displacement[...] = 0
        while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)):
            innerIter += 1
            maxVariation = tf.iterateDisplacementField2DCYTHON(
                deltaField, sigmaField, gradientField, lambdaDisplacement,
                totalDisplacement, displacement, residuals)
            opt = np.max(residuals)
            if (maxResidual < opt):
                maxResidual = opt
        #--accumulate displacement--
        expd, invexpd = tf.vector_field_exponential(displacement)
        totalDisplacement = tf.compose_vector_fields(expd, totalDisplacement)
        totalDisplacementInverse = tf.compose_vector_fields(
            totalDisplacementInverse, invexpd)
        #--check stop condition--
        nrm = np.sqrt(displacement[..., 0]**2 + displacement[..., 1]**2)
        #maxDisplacement=np.max(nrm)
        maxDisplacement = np.mean(nrm)
        if ((maxDisplacement < outerTolerance) or (outerIter >= maxOuterIter)):
            finished = True


#            plt.figure()
#            plt.subplot(1,3,1)
#            plt.imshow(means[fixedQ],cmap=plt.cm.gray)
#            plt.title("Estimated warped modality")
#            plt.subplot(1,3,2)
#            plt.imshow(fixedQ,cmap=plt.cm.gray)
#            plt.title("Quantized")
#            plt.subplot(1,3,3)
#            plt.plot(means)
#            plt.title("Means")
    print "Iter: ", outerIter, "Mean displacement:", maxDisplacement, "Max variation:", maxVariation, "Max residual:", maxResidual
    if (previousDisplacement != None):
        return totalDisplacement - previousDisplacement, totalDisplacementInverse
    return totalDisplacement, totalDisplacementInverse
def runArcesExperiment(rootDir, lambdaParam, maxOuterIter):
    #---Load displacement field---
    dxName = rootDir + 'Vx.dat'
    dyName = rootDir + 'Vy.dat'
    dx = np.loadtxt(dxName)
    dy = np.loadtxt(dyName)
    GT_in = np.ndarray(shape=dx.shape + (2, ), dtype=np.float64)
    GT_in[..., 0] = dy
    GT_in[..., 1] = dx
    GT, GTinv = tf.vector_field_exponential(GT_in)
    GTres = tf.compose_vector_fields(GT, GTinv)
    #---Load input images---
    fnameT1 = rootDir + 't1.jpg'
    fnameT2 = rootDir + 't2.jpg'
    fnamePD = rootDir + 'pd.jpg'
    fnameMask = rootDir + 'Mascara.bmp'
    t1 = plt.imread(fnameT1)[..., 0].astype(np.float64)
    t2 = plt.imread(fnameT2)[..., 0].astype(np.float64)
    pd = plt.imread(fnamePD)[..., 0].astype(np.float64)
    t1 = (t1 - t1.min()) / (t1.max() - t1.min())
    t2 = (t2 - t2.min()) / (t2.max() - t2.min())
    pd = (pd - pd.min()) / (pd.max() - pd.min())
    mask = plt.imread(fnameMask).astype(np.float64)
    fixed = t1
    moving = t2
    maskMoving = mask > 0
    maskFixed = mask > 0
    fixed *= mask
    moving *= mask
    plt.figure()
    plt.subplot(1, 4, 1)
    plt.imshow(t1, cmap=plt.cm.gray)
    plt.title('Input T1')
    plt.subplot(1, 4, 2)
    plt.imshow(t2, cmap=plt.cm.gray)
    plt.title('Input T2')
    plt.subplot(1, 4, 3)
    plt.imshow(pd, cmap=plt.cm.gray)
    plt.title('Input PD')
    plt.subplot(1, 4, 4)
    plt.imshow(mask, cmap=plt.cm.gray)
    plt.title('Input Mask')
    #-------------------------
    warpedFixed = rcommon.warpImage(fixed, GT)
    print 'Registering T2 (template) to deformed T1 (template)...'
    level = 3
    movingPyramid = [
        img for img in rcommon.pyramid_gaussian_2D(moving, level, maskMoving)
    ]
    fixedPyramid = [
        img
        for img in rcommon.pyramid_gaussian_2D(warpedFixed, level, maskFixed)
    ]
    plt.figure()
    plt.subplot(1, 2, 1)
    plt.imshow(moving, cmap=plt.cm.gray)
    plt.title('Moving')
    plt.subplot(1, 2, 2)
    plt.imshow(warpedFixed, cmap=plt.cm.gray)
    plt.title('Fixed')
    rcommon.plotOverlaidPyramids(movingPyramid, fixedPyramid)
    displacementList = []
    displacement, inverse = estimateMultimodalDiffeomorphicField2DMultiScale(
        movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, 0,
        displacementList)
    residual = tf.compose_vector_fields(displacement, inverse)
    warpPyramid = [
        rcommon.warpImage(movingPyramid[i], displacementList[i])
        for i in range(level + 1)
    ]
    rcommon.plotOverlaidPyramids(warpPyramid, fixedPyramid)
    rcommon.overlayImages(warpPyramid[0], fixedPyramid[0])
    displacement[..., 0] *= (maskFixed)
    displacement[..., 1] *= (maskFixed)
    #----plot deformations---
    rcommon.plotDiffeomorphism(GT, GTinv, GTres, 7)
    rcommon.plotDiffeomorphism(displacement, inverse, residual, 7)
    #----statistics---
    nrm = np.sqrt(displacement[..., 0]**2 + displacement[..., 1]**2)
    nrm *= maskFixed
    maxNorm = np.max(nrm)
    residual = ((displacement - GT))**2
    meanDisplacementError = np.sqrt(residual.sum(2) * (maskFixed)).mean()
    stdevDisplacementError = np.sqrt(residual.sum(2) * (maskFixed)).std()
    print 'Max global displacement: ', maxNorm
    print 'Mean displacement error: ', meanDisplacementError, '(', stdevDisplacementError, ')'
def testInversion(lambdaParam):
    fname0 = 'data/circle.png'
    fname1 = 'data/C.png'
    circleToCDisplacementName = 'circleToCDisplacement.npy'
    circleToCDisplacementInverseName = 'circleToCDisplacementInverse.npy'
    nib_moving = plt.imread(fname0)
    nib_fixed = plt.imread(fname1)
    moving = nib_moving[:, :, 0]
    fixed = nib_fixed[:, :, 1]
    moving = (moving - moving.min()) / (moving.max() - moving.min())
    fixed = (fixed - fixed.min()) / (fixed.max() - fixed.min())
    level = 3
    maskMoving = moving > 0
    maskFixed = fixed > 0
    movingPyramid = [
        img for img in rcommon.pyramid_gaussian_2D(moving, level,
                                                   np.ones_like(maskMoving))
    ]
    fixedPyramid = [
        img for img in rcommon.pyramid_gaussian_2D(fixed, level,
                                                   np.ones_like(maskFixed))
    ]
    rcommon.plotOverlaidPyramids(movingPyramid, fixedPyramid)
    displacementList = []
    maxOuterIter = [10, 50, 100, 100, 100, 100, 100, 100, 100]
    if (os.path.exists(circleToCDisplacementName)):
        displacement = np.load(circleToCDisplacementName)
        inverse = np.load(circleToCDisplacementInverseName)
    else:
        displacement, inverse = estimateMonomodalDiffeomorphicField2DMultiScale(
            movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, 0,
            displacementList)
        np.save(circleToCDisplacementName, displacement)
        np.save(circleToCDisplacementInverseName, inverse)
    print 'vector field exponential'
    expd, invexpd = tf.vector_field_exponential(displacement, True)
    print 'vector field inversion'
    directInverse = tf.invert_vector_field(displacement, 1.0, 10000, 1e-7)
    print 'vector field inversion'
    directExpInverse = tf.invert_vector_field(expd, 1.0, 10000, 1e-7)
    ###Now compare inversions###
    residualJoint = np.array(
        tf.compose_vector_fields(displacement, inverse)[0])
    residualDirect = np.array(
        tf.compose_vector_fields(displacement, directInverse)[0])
    residualExpJoint = np.array(tf.compose_vector_fields(expd, invexpd)[0])
    residualExpDirect = np.array(
        tf.compose_vector_fields(expd, directExpInverse)[0])
    rcommon.plotDiffeomorphism(displacement, inverse, residualJoint, 'D-joint')
    rcommon.plotDiffeomorphism(expd, invexpd, residualExpJoint, 'expD-joint')
    d, invd, res, jacobian = rcommon.plotDiffeomorphism(
        displacement, directInverse, residualDirect, 'D-direct')
    rcommon.plotDiffeomorphism(expd, directExpInverse, residualExpDirect,
                               'expD-direct')
    sp.misc.imsave('circleToC_deformation.png', d)
    sp.misc.imsave('circleToC_inverse_deformation.png', invd)
    sp.misc.imsave('circleToC_residual_deformation.png', res)
    tf.write_double_buffer(
        np.array(displacement).reshape(-1),
        '../inverse/experiments/displacement.bin')
    tf.write_double_buffer(
        np.array(displacement).reshape(-1),
        '../inverse/experiments/displacement_clean.bin')
def runArcesExperiment(rootDir, lambdaParam, maxOuterIter):
    #---Load displacement field---
    dxName=rootDir+'Vx.dat'
    dyName=rootDir+'Vy.dat'
    dx=np.loadtxt(dxName)
    dy=np.loadtxt(dyName)
    GT_in=np.ndarray(shape=dx.shape+(2,), dtype=np.float64)
    GT_in[...,0]=dy
    GT_in[...,1]=dx
    GT, GTinv=tf.vector_field_exponential(GT_in)
    GTres=tf.compose_vector_fields(GT, GTinv)
    #---Load input images---
    fnameT1=rootDir+'t1.jpg'
    fnameT2=rootDir+'t2.jpg'
    fnamePD=rootDir+'pd.jpg'
    fnameMask=rootDir+'Mascara.bmp'
    t1=plt.imread(fnameT1)[...,0].astype(np.float64)
    t2=plt.imread(fnameT2)[...,0].astype(np.float64)
    pd=plt.imread(fnamePD)[...,0].astype(np.float64)
    t1=(t1-t1.min())/(t1.max()-t1.min())
    t2=(t2-t2.min())/(t2.max()-t2.min())
    pd=(pd-pd.min())/(pd.max()-pd.min())
    mask=plt.imread(fnameMask).astype(np.float64)
    fixed=t1
    moving=t2
    maskMoving=mask>0
    maskFixed=mask>0
    fixed*=mask
    moving*=mask
    plt.figure()
    plt.subplot(1,4,1)
    plt.imshow(t1, cmap=plt.cm.gray)
    plt.title('Input T1')
    plt.subplot(1,4,2)
    plt.imshow(t2, cmap=plt.cm.gray)
    plt.title('Input T2')
    plt.subplot(1,4,3)
    plt.imshow(pd, cmap=plt.cm.gray)
    plt.title('Input PD')
    plt.subplot(1,4,4)
    plt.imshow(mask, cmap=plt.cm.gray)
    plt.title('Input Mask')
    #-------------------------
    warpedFixed=rcommon.warpImage(fixed,GT)
    print 'Registering T2 (template) to deformed T1 (template)...'
    level=3
    movingPyramid=[img for img in rcommon.pyramid_gaussian_2D(moving, level, maskMoving)]
    fixedPyramid=[img for img in rcommon.pyramid_gaussian_2D(warpedFixed, level, maskFixed)]
    plt.figure()
    plt.subplot(1,2,1)
    plt.imshow(moving, cmap=plt.cm.gray)
    plt.title('Moving')
    plt.subplot(1,2,2)
    plt.imshow(warpedFixed, cmap=plt.cm.gray)
    plt.title('Fixed')
    rcommon.plotOverlaidPyramids(movingPyramid, fixedPyramid)
    displacementList=[]
    displacement, inverse=estimateMultimodalDiffeomorphicField2DMultiScale(movingPyramid, fixedPyramid, lambdaParam, maxOuterIter, 0, displacementList)
    residual=tf.compose_vector_fields(displacement, inverse)
    warpPyramid=[rcommon.warpImage(movingPyramid[i], displacementList[i]) for i in range(level+1)]
    rcommon.plotOverlaidPyramids(warpPyramid, fixedPyramid)
    rcommon.overlayImages(warpPyramid[0], fixedPyramid[0])
    displacement[...,0]*=(maskFixed)
    displacement[...,1]*=(maskFixed)
    #----plot deformations---
    rcommon.plotDiffeomorphism(GT, GTinv, GTres, 7)
    rcommon.plotDiffeomorphism(displacement, inverse, residual, 7)
    #----statistics---
    nrm=np.sqrt(displacement[...,0]**2 + displacement[...,1]**2)
    nrm*=maskFixed
    maxNorm=np.max(nrm)
    residual=((displacement-GT))**2
    meanDisplacementError=np.sqrt(residual.sum(2)*(maskFixed)).mean()
    stdevDisplacementError=np.sqrt(residual.sum(2)*(maskFixed)).std()
    print 'Max global displacement: ', maxNorm
    print 'Mean displacement error: ', meanDisplacementError,'(',stdevDisplacementError,')'
Example #26
0
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
Example #27
0
 def update(new_displacement, current_displacement):
     expd, invexpd = tf.vector_field_exponential(new_displacement, True)
     updated, stats = tf.compose_vector_fields(expd, current_displacement)
     return updated, stats[0]
Example #28
0
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'
#    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, ")"