Exemple #1
0
def estimateNewMultimodalSyNField3D(moving,
                                    fixed,
                                    fWarp,
                                    fInv,
                                    mWarp,
                                    mInv,
                                    initAffine,
                                    lambdaDisplacement,
                                    quantizationLevels,
                                    maxOuterIter,
                                    reportProgress=False):
    '''
        fwWarp: forward warp, the displacement field that warps moving towards fixed
        bwWarp: backward warp, the displacement field that warps fixed towards moving
        initAffine: the affine transformation to bring moving over fixed (this part is not symmetric)
    '''
    print 'Moving shape:', moving.shape, '. Fixed shape:', fixed.shape
    innerTolerance = 1e-3
    outerTolerance = 1e-3
    fixedMask = (fixed > 0).astype(np.int32)
    movingMask = (moving > 0).astype(np.int32)
    if (fWarp != None):
        totalF = fWarp
        totalFInv = fInv
    else:
        totalF = np.zeros(shape=(fixed.shape) + (3, ), dtype=np.float64)
        totalFInv = np.zeros(shape=(fixed.shape) + (3, ), dtype=np.float64)
    if (mWarp != None):
        totalM = mWarp
        totalMInv = mInv
    else:
        totalM = np.zeros(shape=(moving.shape) + (3, ), dtype=np.float64)
        totalMInv = np.zeros(shape=(moving.shape) + (3, ), dtype=np.float64)
    finished = False
    outerIter = 0
    while ((not finished) and (outerIter < maxOuterIter)):
        outerIter += 1
        if (reportProgress):
            print 'Iter:', outerIter, '/', maxOuterIter
        #---E step---
        wmoving = np.array(tf.warp_volume(moving, totalMInv, initAffine))
        wmovingMask = np.array(
            tf.warp_discrete_volumeNN(movingMask, totalMInv,
                                      initAffine)).astype(np.int32)
        wfixed = np.array(tf.warp_volume(fixed, totalFInv))
        wfixedMask = np.array(tf.warp_discrete_volumeNN(
            fixedMask, totalFInv)).astype(np.int32)
        fixedQ, grayLevels, hist = tf.quantizePositiveVolumeCYTHON(
            wfixed, quantizationLevels)
        fixedQ = np.array(fixedQ, dtype=np.int32)
        movingQ, grayLevels, hist = tf.quantizePositiveVolumeCYTHON(
            wmoving, quantizationLevels)
        movingQ = np.array(movingQ, dtype=np.int32)
        trust = wfixedMask * wmovingMask
        meansMoving, variancesMoving = tf.computeMaskedVolumeClassStatsCYTHON(
            trust, wmoving, quantizationLevels, fixedQ)
        meansFixed, variancesFixed = tf.computeMaskedVolumeClassStatsCYTHON(
            trust, wfixed, quantizationLevels, movingQ)
        meansMoving[0] = 0
        meansFixed[0] = 0
        meansMoving = np.array(meansMoving)
        meansFixed = np.array(meansFixed)
        variancesMoving = np.array(variancesMoving)
        sigmaFieldMoving = variancesMoving[fixedQ]
        variancesFixed = np.array(variancesFixed)
        sigmaFieldFixed = variancesFixed[movingQ]
        deltaFieldMoving = meansMoving[fixedQ] - wmoving
        deltaFieldFixed = meansFixed[movingQ] - wfixed
        #--M step--
        movingGradient = np.empty(shape=(moving.shape) + (3, ),
                                  dtype=np.float64)
        movingGradient[:, :, :,
                       0], movingGradient[:, :, :,
                                          1], movingGradient[:, :, :,
                                                             2] = sp.gradient(
                                                                 wmoving)
        #iterate forward field
        maxVariation = 1 + innerTolerance
        innerIter = 0
        maxInnerIter = 100
        fw = np.zeros_like(totalF)
        while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)):
            innerIter += 1
            maxVariation = tf.iterateDisplacementField3DCYTHON(
                deltaFieldMoving, sigmaFieldMoving, movingGradient,
                lambdaDisplacement, totalF, fw, None)
        del movingGradient
        fw *= 0.5
        totalF = np.array(tf.compose_vector_fields3D(
            fw, totalF))  #Multiply fw by 0.5??
        nrm = np.sqrt(fw[..., 0]**2 + fw[..., 1]**2 + fw[..., 2]**2)
        del fw
        #iterate backward field
        fixedGradient = np.empty(shape=(fixed.shape) + (3, ), dtype=np.float64)
        fixedGradient[:, :, :,
                      0], fixedGradient[:, :, :,
                                        1], fixedGradient[:, :, :,
                                                          2] = sp.gradient(
                                                              wfixed)
        maxVariation = 1 + innerTolerance
        innerIter = 0
        maxInnerIter = 100
        mw = np.zeros_like(totalM)
        while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)):
            innerIter += 1
            maxVariation = tf.iterateDisplacementField3DCYTHON(
                deltaFieldFixed, sigmaFieldFixed, fixedGradient,
                lambdaDisplacement, totalM, mw, None)
        del fixedGradient
        mw *= 0.5
        totalM = np.array(tf.compose_vector_fields3D(
            mw, totalM))  #Multiply bw by 0.5??
        nrm = np.sqrt(mw[..., 0]**2 + mw[..., 1]**2 + mw[..., 2]**2)
        del mw
        #invert fields
        totalFInv = np.array(
            tf.invert_vector_field_fixed_point3D(totalF, 20, 1e-6))
        totalMInv = np.array(
            tf.invert_vector_field_fixed_point3D(totalM, 20, 1e-6))
        totalF = np.array(
            tf.invert_vector_field_fixed_point3D(totalFInv, 20, 1e-6))
        totalM = np.array(
            tf.invert_vector_field_fixed_point3D(totalMInv, 20, 1e-6))
        maxDisplacement = np.mean(nrm)
        if ((maxDisplacement < outerTolerance) or (outerIter >= maxOuterIter)):
            finished = True
    print "Iter: ", outerIter, "Mean displacement:", maxDisplacement, "Max variation:", maxVariation
    return totalF, totalFInv, totalM, totalMInv
def estimateNewMultimodalDiffeomorphicField3D(moving,
                                              fixed,
                                              initAffine,
                                              lambdaDisplacement,
                                              quantizationLevels,
                                              maxOuterIter,
                                              previousDisplacement,
                                              reportProgress=False):
    innerTolerance = 1e-3
    outerTolerance = 1e-3
    displacement = np.empty(shape=(fixed.shape) + (3, ), dtype=np.float64)
    residuals = np.zeros(shape=(fixed.shape), dtype=np.float64)
    gradientField = np.empty(shape=(fixed.shape) + (3, ), dtype=np.float64)
    totalDisplacement = np.zeros(shape=(fixed.shape) + (3, ), dtype=np.float64)
    if (previousDisplacement != None):
        totalDisplacement[...] = previousDisplacement
    fixedQ = None
    grayLevels = None
    fixedQ, grayLevels, hist = tf.quantizePositiveVolumeCYTHON(
        fixed, quantizationLevels)
    fixedQ = np.array(fixedQ, dtype=np.int32)
    finished = False
    outerIter = 0
    maxDisplacement = None
    maxVariation = None
    maxResidual = 0
    fixedMask = (fixed > 0).astype(np.int32)
    movingMask = (moving > 0).astype(np.int32)
    trustRegion = fixedMask * np.array(
        tf.warp_discrete_volumeNNAffine(
            movingMask, np.array(fixedMask.shape, dtype=np.int32),
            initAffine))  #consider only the overlap after affine registration
    while ((not finished) and (outerIter < maxOuterIter)):
        outerIter += 1
        if (reportProgress):
            print 'Iter:', outerIter, '/', maxOuterIter
            #sys.stdout.flush()
        #---E step---
        #print "Warping..."
        #sys.stdout.flush()
        warped = np.array(tf.warp_volume(moving, totalDisplacement,
                                         initAffine))
        warpedMask = np.array(
            tf.warp_discrete_volumeNN(
                trustRegion, totalDisplacement, np.eye(4))).astype(
                    np.int32)  #the affine mapping was already applied
        #print "Warping NN..."
        #sys.stdout.flush()
        #warpedMovingMask=np.array(tf.warp_volumeNN(movingMask, totalDisplacement)).astype(np.int32)
        #print "Class stats..."
        #sys.stdout.flush()
        means, variances = tf.computeMaskedVolumeClassStatsCYTHON(
            warpedMask, 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, g2 = sp.gradient(warped)
        gradientField[:, :, :, 0] = g0
        gradientField[:, :, :, 1] = g1
        gradientField[:, :, :, 2] = g2
        maxVariation = 1 + innerTolerance
        innerIter = 0
        maxInnerIter = 100
        displacement[...] = 0
        #print "Iterating..."
        #sys.stdout.flush()
        while ((maxVariation > innerTolerance) and (innerIter < maxInnerIter)):
            innerIter += 1
            maxVariation = tf.iterateDisplacementField3DCYTHON(
                deltaField, sigmaField, gradientField, lambdaDisplacement,
                totalDisplacement, displacement, residuals)
            opt = np.max(residuals)
            if (maxResidual < opt):
                maxResidual = opt
        #--accumulate displacement--
        #print "Exponential3D. Range D:", displacement.min(), displacement.max()
        #sys.stdout.flush()
        expd, inverseNone = tf.vector_field_exponential3D(displacement, False)
        expd = np.array(expd)
        #print "Range expd:", expd.min(), expd.max(), "Range TD:", totalDisplacement.min(), totalDisplacement.max()
        #print "Compose vector fields..."
        #sys.stdout.flush()
        totalDisplacement, stats = tf.compose_vector_fields3D(
            expd, totalDisplacement)
        totalDisplacement = np.array(totalDisplacement)
        #print "Composed rage:", totalDisplacement.min(), totalDisplacement.max()
        #sys.stdout.flush()
        #--check stop condition--
        nrm = np.sqrt(displacement[..., 0]**2 + displacement[..., 1]**2 +
                      displacement[..., 2]**2)
        #maxDisplacement=np.max(nrm)
        maxDisplacement = np.mean(nrm)
        if ((maxDisplacement < outerTolerance) or (outerIter >= maxOuterIter)):
            finished = True
    print "Iter: ", outerIter, "Mean displacement:", maxDisplacement, "Max variation:", maxVariation, "Max residual:", maxResidual
    #sh=fixed.shape
    #rcommon.overlayImages(warped[:,sh[1]//2,:], fixed[:,sh[1]//2,:])
    #rcommon.overlayImages(warped[:,sh[1]//2,:]*warpedMask[:,sh[1]//2,:], fixed[:,sh[1]//2,:])
    #sys.stdout.flush()
    if (previousDisplacement != None):
        #print 'Range TD:', totalDisplacement.min(), totalDisplacement.max(),'. Range PD:', previousDisplacement.min(), previousDisplacement.max()
        #sys.stdout.flush()
        return totalDisplacement - previousDisplacement
    return totalDisplacement
Exemple #3
0
def estimateNewMultimodalSyNField3D(moving, fixed, fWarp, fInv, mWarp, mInv, initAffine, lambdaDisplacement, quantizationLevels, maxOuterIter, reportProgress=False):
    '''
        fwWarp: forward warp, the displacement field that warps moving towards fixed
        bwWarp: backward warp, the displacement field that warps fixed towards moving
        initAffine: the affine transformation to bring moving over fixed (this part is not symmetric)
    '''
    print 'Moving shape:',moving.shape,'. Fixed shape:',fixed.shape
    innerTolerance=1e-3
    outerTolerance=1e-3
    fixedMask=(fixed>0).astype(np.int32)
    movingMask=(moving>0).astype(np.int32)
    if(fWarp!=None):
        totalF=fWarp
        totalFInv=fInv
    else:
        totalF    =np.zeros(shape=(fixed.shape)+(3,), dtype=np.float64)
        totalFInv =np.zeros(shape=(fixed.shape)+(3,), dtype=np.float64)
    if(mWarp!=None):
        totalM=mWarp
        totalMInv=mInv
    else:
        totalM   =np.zeros(shape=(moving.shape)+(3,), dtype=np.float64)
        totalMInv=np.zeros(shape=(moving.shape)+(3,), dtype=np.float64)
    finished=False
    outerIter=0
    while((not finished) and (outerIter<maxOuterIter)):
        outerIter+=1
        if(reportProgress):
            print 'Iter:',outerIter,'/',maxOuterIter
        #---E step---
        wmoving=np.array(tf.warp_volume(moving, totalMInv, initAffine))
        wmovingMask=np.array(tf.warp_discrete_volumeNN(movingMask, totalMInv, initAffine)).astype(np.int32)
        wfixed=np.array(tf.warp_volume(fixed, totalFInv))
        wfixedMask=np.array(tf.warp_discrete_volumeNN(fixedMask, totalFInv)).astype(np.int32)
        fixedQ, grayLevels, hist=tf.quantizePositiveVolumeCYTHON(wfixed, quantizationLevels)
        fixedQ=np.array(fixedQ, dtype=np.int32)
        movingQ, grayLevels, hist=tf.quantizePositiveVolumeCYTHON(wmoving, quantizationLevels)
        movingQ=np.array(movingQ, dtype=np.int32)
        trust=wfixedMask*wmovingMask
        meansMoving, variancesMoving=tf.computeMaskedVolumeClassStatsCYTHON(trust, wmoving, quantizationLevels, fixedQ)
        meansFixed, variancesFixed=tf.computeMaskedVolumeClassStatsCYTHON(trust, wfixed, quantizationLevels, movingQ)
        meansMoving[0]=0
        meansFixed[0]=0
        meansMoving=np.array(meansMoving)
        meansFixed=np.array(meansFixed)
        variancesMoving=np.array(variancesMoving)
        sigmaFieldMoving=variancesMoving[fixedQ]
        variancesFixed=np.array(variancesFixed)
        sigmaFieldFixed=variancesFixed[movingQ]
        deltaFieldMoving=meansMoving[fixedQ]-wmoving
        deltaFieldFixed=meansFixed[movingQ]-wfixed
        #--M step--
        movingGradient  =np.empty(shape=(moving.shape)+(3,), dtype=np.float64)
        movingGradient[:,:,:,0], movingGradient[:,:,:,1], movingGradient[:,:,:,2]=sp.gradient(wmoving)
        #iterate forward field
        maxVariation=1+innerTolerance
        innerIter=0
        maxInnerIter=100
        fw=np.zeros_like(totalF)
        while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)):
            innerIter+=1
            maxVariation=tf.iterateDisplacementField3DCYTHON(deltaFieldMoving, sigmaFieldMoving, movingGradient,  lambdaDisplacement, totalF, fw, None)
        del movingGradient
        fw*=0.5
        totalF=np.array(tf.compose_vector_fields3D(fw, totalF))#Multiply fw by 0.5??
        nrm=np.sqrt(fw[...,0]**2+fw[...,1]**2+fw[...,2]**2)
        del fw        
        #iterate backward field
        fixedGradient   =np.empty(shape=(fixed.shape)+(3,), dtype=np.float64)
        fixedGradient[:,:,:,0], fixedGradient[:,:,:,1], fixedGradient[:,:,:,2]=sp.gradient(wfixed)
        maxVariation=1+innerTolerance
        innerIter=0
        maxInnerIter=100
        mw=np.zeros_like(totalM)
        while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)):
            innerIter+=1
            maxVariation=tf.iterateDisplacementField3DCYTHON(deltaFieldFixed, sigmaFieldFixed, fixedGradient,  lambdaDisplacement, totalM, mw, None)
        del fixedGradient
        mw*=0.5
        totalM=np.array(tf.compose_vector_fields3D(mw, totalM))#Multiply bw by 0.5??
        nrm=np.sqrt(mw[...,0]**2+mw[...,1]**2+mw[...,2]**2)
        del mw        
        #invert fields
        totalFInv=np.array(tf.invert_vector_field_fixed_point3D(totalF, 20, 1e-6))
        totalMInv=np.array(tf.invert_vector_field_fixed_point3D(totalM, 20, 1e-6))
        totalF=np.array(tf.invert_vector_field_fixed_point3D(totalFInv, 20, 1e-6))
        totalM=np.array(tf.invert_vector_field_fixed_point3D(totalMInv, 20, 1e-6))
        maxDisplacement=np.mean(nrm)
        if((maxDisplacement<outerTolerance)or(outerIter>=maxOuterIter)):
            finished=True
    print "Iter: ",outerIter, "Mean displacement:", maxDisplacement, "Max variation:",maxVariation
    return totalF, totalFInv, totalM, totalMInv
def estimateNewMultimodalDiffeomorphicField3D(moving, fixed, initAffine, lambdaDisplacement, quantizationLevels, maxOuterIter, previousDisplacement, reportProgress=False):
    innerTolerance=1e-3
    outerTolerance=1e-3
    displacement     =np.empty(shape=(fixed.shape)+(3,), dtype=np.float64)
    residuals=np.zeros(shape=(fixed.shape), dtype=np.float64)
    gradientField    =np.empty(shape=(fixed.shape)+(3,), dtype=np.float64)
    totalDisplacement=np.zeros(shape=(fixed.shape)+(3,), dtype=np.float64)
    if(previousDisplacement!=None):
        totalDisplacement[...]=previousDisplacement
    fixedQ=None
    grayLevels=None
    fixedQ, grayLevels, hist=tf.quantizePositiveVolumeCYTHON(fixed, quantizationLevels)
    fixedQ=np.array(fixedQ, dtype=np.int32)
    finished=False
    outerIter=0
    maxDisplacement=None
    maxVariation=None
    maxResidual=0
    fixedMask=(fixed>0).astype(np.int32)
    movingMask=(moving>0).astype(np.int32)
    trustRegion=fixedMask*np.array(tf.warp_discrete_volumeNNAffine(movingMask, np.array(fixedMask.shape, dtype=np.int32), initAffine))#consider only the overlap after affine registration
    while((not finished) and (outerIter<maxOuterIter)):
        outerIter+=1
        if(reportProgress):
            print 'Iter:',outerIter,'/',maxOuterIter
            #sys.stdout.flush()
        #---E step---
        #print "Warping..."
        #sys.stdout.flush()
        warped=np.array(tf.warp_volume(moving, totalDisplacement, initAffine))
        warpedMask=np.array(tf.warp_discrete_volumeNN(trustRegion, totalDisplacement, np.eye(4))).astype(np.int32)#the affine mapping was already applied
        #print "Warping NN..."
        #sys.stdout.flush()
        #warpedMovingMask=np.array(tf.warp_volumeNN(movingMask, totalDisplacement)).astype(np.int32)
        #print "Class stats..."
        #sys.stdout.flush()
        means, variances=tf.computeMaskedVolumeClassStatsCYTHON(warpedMask, 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, g2=sp.gradient(warped)
        gradientField[:,:,:,0]=g0
        gradientField[:,:,:,1]=g1
        gradientField[:,:,:,2]=g2
        maxVariation=1+innerTolerance
        innerIter=0
        maxInnerIter=100
        displacement[...]=0
        #print "Iterating..."
        #sys.stdout.flush()
        while((maxVariation>innerTolerance)and(innerIter<maxInnerIter)):
            innerIter+=1
            maxVariation=tf.iterateDisplacementField3DCYTHON(deltaField, sigmaField, gradientField,  lambdaDisplacement, totalDisplacement, displacement, residuals)
            opt=np.max(residuals)
            if(maxResidual<opt):
                maxResidual=opt
        #--accumulate displacement--
        #print "Exponential3D. Range D:", displacement.min(), displacement.max()
        #sys.stdout.flush()
        expd, inverseNone=tf.vector_field_exponential3D(displacement, False)
        expd=np.array(expd)
        #print "Range expd:", expd.min(), expd.max(), "Range TD:", totalDisplacement.min(), totalDisplacement.max()
        #print "Compose vector fields..."
        #sys.stdout.flush()
        totalDisplacement, stats=tf.compose_vector_fields3D(expd, totalDisplacement)
        totalDisplacement=np.array(totalDisplacement)
        #print "Composed rage:", totalDisplacement.min(), totalDisplacement.max()
        #sys.stdout.flush()
        #--check stop condition--
        nrm=np.sqrt(displacement[...,0]**2+displacement[...,1]**2+displacement[...,2]**2)
        #maxDisplacement=np.max(nrm)
        maxDisplacement=np.mean(nrm)
        if((maxDisplacement<outerTolerance)or(outerIter>=maxOuterIter)):
            finished=True
    print "Iter: ",outerIter, "Mean displacement:", maxDisplacement, "Max variation:",maxVariation, "Max residual:", maxResidual
    #sh=fixed.shape
    #rcommon.overlayImages(warped[:,sh[1]//2,:], fixed[:,sh[1]//2,:])
    #rcommon.overlayImages(warped[:,sh[1]//2,:]*warpedMask[:,sh[1]//2,:], fixed[:,sh[1]//2,:])
    #sys.stdout.flush()
    if(previousDisplacement!=None):
        #print 'Range TD:', totalDisplacement.min(), totalDisplacement.max(),'. Range PD:', previousDisplacement.min(), previousDisplacement.max()
        #sys.stdout.flush()
        return totalDisplacement-previousDisplacement
    return totalDisplacement