def estimateNewMultimodalRigidTransformation3D(left, right, rightQ, numLevels, previousBeta=None): epsilon=1e-9 sh=left.shape center=(np.array(sh)-1)/2.0 X0,X1,X2=np.mgrid[0:sh[0], 0:sh[1], 0:sh[2]] X0=X0-center[0] X1=X1-center[1] X2=X2-center[2] mask=np.ones_like(X0, dtype=np.int32) if((previousBeta!=None) and (np.max(np.abs(previousBeta))>epsilon)): R=rcommon.getRotationMatrix(previousBeta[0:3]) X0new,X1new,X2new=(R[0,0]*X0 + R[0,1]*X1 + R[0,2]*X2 + center[0] + 2.0*previousBeta[3], R[1,0]*X0 + R[1,1]*X1 + R[1,2]*X2 + center[1] + 2.0*previousBeta[4], R[2,0]*X0 + R[2,1]*X1 + R[2,2]*X2 + center[2] + 2.0*previousBeta[5]) left=ndimage.map_coordinates(left, [X0new, X1new, X2new], prefilter=const_prefilter_map_coordinates) mask[...]=(X0new<0) + (X0new>(sh[0]-1)) mask[...]=mask + (X1new<0) + (X1new>(sh[1]-1)) mask[...]=mask + (X2new<0) + (X2new>(sh[2]-1)) mask[...]=1-mask means, variances=tf.computeMaskedVolumeClassStatsCYTHON(mask, left, numLevels, rightQ) means=np.array(means) weights=np.array([1.0/x if(x>0) else 0 for x in variances], dtype=np.float64) g0, g1, g2=sp.gradient(left) q=np.empty(shape=(X0.shape)+(6,), dtype=np.float64) q[...,0]=g2*X1-g1*X2 q[...,1]=g0*X2-g2*X0 q[...,2]=g1*X0-g0*X1 q[...,3]=g0 q[...,4]=g1 q[...,5]=g2 diff=means[rightQ]-left Aw, bw=tf.integrateMaskedWeightedTensorFieldProductsCYTHON(mask, q, diff, numLevels, rightQ, weights) beta=linalg.solve(Aw,bw) return beta
def estimateNewMultimodalRigidTransformation3D(left, right, rightQ, numLevels, previousBeta=None): epsilon = 1e-9 sh = left.shape center = (np.array(sh) - 1) / 2.0 X0, X1, X2 = np.mgrid[0:sh[0], 0:sh[1], 0:sh[2]] X0 = X0 - center[0] X1 = X1 - center[1] X2 = X2 - center[2] mask = np.ones_like(X0, dtype=np.int32) if ((previousBeta != None) and (np.max(np.abs(previousBeta)) > epsilon)): R = rcommon.getRotationMatrix(previousBeta[0:3]) X0new, X1new, X2new = (R[0, 0] * X0 + R[0, 1] * X1 + R[0, 2] * X2 + center[0] + 2.0 * previousBeta[3], R[1, 0] * X0 + R[1, 1] * X1 + R[1, 2] * X2 + center[1] + 2.0 * previousBeta[4], R[2, 0] * X0 + R[2, 1] * X1 + R[2, 2] * X2 + center[2] + 2.0 * previousBeta[5]) left = ndimage.map_coordinates( left, [X0new, X1new, X2new], prefilter=const_prefilter_map_coordinates) mask[...] = (X0new < 0) + (X0new > (sh[0] - 1)) mask[...] = mask + (X1new < 0) + (X1new > (sh[1] - 1)) mask[...] = mask + (X2new < 0) + (X2new > (sh[2] - 1)) mask[...] = 1 - mask means, variances = tf.computeMaskedVolumeClassStatsCYTHON( mask, left, numLevels, rightQ) means = np.array(means) weights = np.array([1.0 / x if (x > 0) else 0 for x in variances], dtype=np.float64) g0, g1, g2 = sp.gradient(left) q = np.empty(shape=(X0.shape) + (6, ), dtype=np.float64) q[..., 0] = g2 * X1 - g1 * X2 q[..., 1] = g0 * X2 - g2 * X0 q[..., 2] = g1 * X0 - g0 * X1 q[..., 3] = g0 q[..., 4] = g1 q[..., 5] = g2 diff = means[rightQ] - left Aw, bw = tf.integrateMaskedWeightedTensorFieldProductsCYTHON( mask, q, diff, numLevels, rightQ, weights) beta = linalg.solve(Aw, bw) return beta
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 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
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