
io.github.rocsg.fijiyama.registration.ItkRegistration Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of fijiyama Show documentation
Show all versions of fijiyama Show documentation
Fijiyama : a versatile registration tool for 3D multimodal time-lapse imaging
/*
*
*/
package io.github.rocsg.fijiyama.registration;
import java.util.ArrayList;
import org.itk.simple.AffineTransform;
import org.itk.simple.CenteredTransformInitializerFilter;
import org.itk.simple.Command;
import org.itk.simple.Euler2DTransform;
import org.itk.simple.Euler3DTransform;
import org.itk.simple.EventEnum;
import org.itk.simple.Image;
import org.itk.simple.ImageRegistrationMethod;
import org.itk.simple.ResampleImageFilter;
import org.itk.simple.Similarity3DTransform;
import org.itk.simple.TranslationTransform;
import org.itk.simple.VectorDouble;
import org.itk.simple.VectorUInt32;
import org.itk.simple.VersorRigid3DTransform;
import org.itk.simple.RecursiveGaussianImageFilter;
import ij.IJ;
import ij.ImagePlus;
import io.github.rocsg.fijiyama.common.ItkImagePlusInterface;
import io.github.rocsg.fijiyama.common.VitiDialogs;
import io.github.rocsg.fijiyama.common.VitimageUtils;
import io.github.rocsg.fijiyama.registration.CenteringStrategy;
import io.github.rocsg.fijiyama.registration.IterationUpdate;
import io.github.rocsg.fijiyama.registration.ItkRegistration;
import io.github.rocsg.fijiyama.registration.ItkTransform;
import io.github.rocsg.fijiyama.registration.MetricType;
import io.github.rocsg.fijiyama.registration.OptimizerType;
import io.github.rocsg.fijiyama.registration.SamplingStrategy;
import io.github.rocsg.fijiyama.registration.ScalerType;
import io.github.rocsg.fijiyama.registration.Transform3DType;
// TODO: Auto-generated Javadoc
/**
* The Class ItkRegistration.
*/
public class ItkRegistration{
/** The additional transform. */
ItkTransform additionalTransform=new ItkTransform();
/** The return composed transformation including the initial transformation given. */
public boolean returnComposedTransformationIncludingTheInitialTransformationGiven=true;
/** The ref range. */
public double[]refRange;
/** The mov range. */
public double[]movRange;
/** The flag range. */
public boolean flagRange=false;
/** The look like optimizer looks. */
boolean lookLikeOptimizerLooks=false;
/** The text info at each iteration. */
boolean textInfoAtEachIteration=false;
/** The movie 3 D. */
boolean movie3D=false;
/** The display registration. */
public int displayRegistration=1;
/** The center transform filter. */
CenteredTransformInitializerFilter centerTransformFilter;
/** The gauss filter. */
private RecursiveGaussianImageFilter gaussFilter;
/** The resampler. */
private ResampleImageFilter resampler;
/** The voxel size reference. */
private double[]voxelSizeReference;
/** The image size reference. */
private int[]imageSizeReference;
/** The itk img view ref. */
private Image itkImgViewRef;
/** The itk img view mov. */
private Image itkImgViewMov;
/** The itk summary ref. */
private Image itkSummaryRef;
/** The itk summary mov. */
private Image itkSummaryMov;
/** The slice view mov. */
private ImagePlus sliceViewMov;
/** The slice view ref. */
private ImagePlus sliceViewRef;
/** The slice view. */
private ImagePlus sliceView;
/** The slice summary ref. */
private ImagePlus sliceSummaryRef;
/** The slice summary mov. */
private ImagePlus sliceSummaryMov;
/** The img mov successive results. */
//private ImagePlus summary;
private ArrayList imgMovSuccessiveResults;
/** The view width. */
private int viewWidth;
/** The view height. */
private int viewHeight;
/** The view slice. */
private int viewSlice;
/** The zoom factor. */
private int zoomFactor;
/** The updater. */
private IterationUpdate updater;
/** The nb levels. */
private ArrayList nbLevels;
/** The shrink factors. */
private ArrayList shrinkFactors;
/** The dimensions. */
private ArrayList dimensions;
/** The sigma factors. */
private ArrayList sigmaFactors;
/** The current level. */
private int currentLevel;
/** The basis. */
private int basis=2;//shrink factor at each level
/** The centering strategies. */
private ArrayList centeringStrategies;
/** The transformation 3 D types. */
private ArrayList transformation3DTypes;
/** The scaler types. */
private ArrayListscalerTypes;
/** The nb step. */
private int nbStep;
/** The current step. */
private int currentStep;
/** The metric type. */
private MetricType metricType;
/** The registration methods. */
private ArrayList registrationMethods;
/** The ij img ref. */
public ImagePlus ijImgRef;
/** The itk img ref. */
private Image itkImgRef;
/** The ij img mov. */
private ImagePlus ijImgMov;
/** The itk img mov. */
private Image itkImgMov;
/** The registration summary. */
private ArrayList registrationSummary;
/** The transform. */
private ItkTransform transform;
/** The weights. */
private ArrayList weights;
/** The scales. */
private ArrayList scales;
/** The font size. */
private int fontSize=12;
/** The registration thread. */
public Thread registrationThread;
/** The itk registration interrupted. */
public volatile boolean itkRegistrationInterrupted=false;
/** The itk is interrupted succeeded. */
public volatile boolean itkIsInterruptedSucceeded=false;
/**
* Free memory.
*/
public void freeMemory(){
if(registrationSummary.size()>0) {
registrationSummary=null;
}
itkImgMov=null;
ijImgMov=null;
itkImgRef=null;
ijImgRef=null;
itkImgViewRef=null;
itkImgViewMov=null;
itkSummaryRef=null;
itkSummaryMov=null;
sliceViewMov=null;
sliceViewRef=null;
sliceView=null;
sliceSummaryRef=null;
sliceSummaryMov=null;
if(imgMovSuccessiveResults.size()>0) {
imgMovSuccessiveResults=null;
}
System.gc();
}
/**
*
* Top level functions : Test function, and main scenarios that will be used by customers classes.
*
* @return the int
*/
public int runTestSequence() {
//MATTES256 SUR VERSOR 2 3 PUIS SIMILITUDE 1 2 , avec AMOEBA et sigma 0.8 , 30 0.5 --> de la tuerie
int nbFailed=0;
ItkRegistration manager=new ItkRegistration();
ImagePlus []imgTab=VitiDialogs.chooseTwoImagesUI("Choose reference image and moving image to register\n\n","Reference image","Moving image");
manager.movie3D=VitiDialogs.getYesNoUI("Compute 3D summary ?","");
ImagePlus imgRef=imgTab[0];
ImagePlus imgMov=imgTab[1];
manager.setMovingImage(imgMov);
manager.setReferenceImage(imgRef);
manager.setViewSlice(20);
manager.setMetric(MetricType.MATTES);
OptimizerType opt=OptimizerType.ITK_AMOEBA ;
SamplingStrategy samplStrat=SamplingStrategy.NONE;
/* addStepToQueue( 30 20
int levelMin,int levelMax,double sigma,Transform3DType typeTransfo,double[]weights,
OptimizerType optimizerType,ScalerType scalerType,double[]scales,
boolean doubleIterAtCoarsestLevels,CenteringStrategy centeringStrategy,SamplingStrategy samplingStrategy
);*/
manager.addStepToQueue( 1 , 4 , 1 , 2*2 , 0.8 , Transform3DType.VERSOR, null,
opt , ScalerType.SCALER_PHYSICAL, null ,
false, CenteringStrategy.MASS_CENTER, samplStrat );
manager.addStepToQueue( 1 , 2 , 0.8 , 3*2, 0.8, Transform3DType.SIMILARITY, null,
opt , ScalerType.SCALER_PHYSICAL, null ,
false, CenteringStrategy.NONE, samplStrat );
manager.register();
freeMemory();
return nbFailed;
}
/**
* Run scenario from gui.
*
* @param transformInit the transform init
* @param imgRef the img ref
* @param imgMov the img mov
* @param transformType the transform type
* @param levelMin the level min
* @param levelMax the level max
* @param nIterations the n iterations
* @param learningRate the learning rate
* @return the itk transform
*/
public ItkTransform runScenarioFromGui(ItkTransform transformInit, ImagePlus imgRef, ImagePlus imgMov, Transform3DType transformType,int levelMin,int levelMax,int nIterations,double learningRate) {
this.setMovingImage(imgMov);
this.setReferenceImage(imgRef);
this.setViewSlice(imgRef.getStackSize()/2);
this.setMetric(MetricType.CORRELATION);
OptimizerType opt=OptimizerType.ITK_AMOEBA ;
SamplingStrategy samplStrat=SamplingStrategy.NONE;
this.addStepToQueue( levelMin, levelMax , 1 , nIterations , learningRate , transformType, null,
opt , ScalerType.NONE/*ScalerType.SCALER_PHYSICAL*/, null ,
false, CenteringStrategy.IMAGE_CENTER, samplStrat );
this.transform=ItkTransform.itkTransformFromCoefs(new double[] {1,0,0,0,0,1,0,0,0,0,1,0});//new ItkTransform(transformInit);
this.register();
if(this.itkRegistrationInterrupted)return null;
if(this.returnComposedTransformationIncludingTheInitialTransformationGiven) return this.transform;
else {
if(transformInit.isDense())return new ItkTransform((transformInit.getInverseOfDenseField()).addTransform(this.transform));
else return new ItkTransform(transformInit.getInverse().addTransform(this.transform));
}
}
/**
* Estimate registration duration.
*
* @param dims the dims
* @param viewRegistrationLevel the view registration level
* @param nbIter the nb iter
* @param levelMin the level min
* @param levelMax the level max
* @return the int
*/
public static int estimateRegistrationDuration(int[]dims,int viewRegistrationLevel,int nbIter,int levelMin,int levelMax) {
double imageSize=dims[0]*dims[1]*dims[2];
double[]imageSizes=new double[levelMax-levelMin+1];
double sumSize=0;
for(int lev=levelMax;lev>=levelMin;lev--) {imageSizes[levelMax-lev]=imageSize/Math.pow(2,(lev-1));sumSize+=imageSizes[levelMax-lev];}
double factorProcess=1E-8;
double factorView=1E-7;
double factorInit=2E-7;
double bonusTime=factorInit*imageSize;
double displayTime=nbIter*factorView*(levelMax-levelMin+1)*viewRegistrationLevel*imageSize;
double processingTime=factorProcess*sumSize*nbIter;
return (int)Math.round(processingTime+displayTime+bonusTime);
}
/**
* Medium level functions : constructor, and managers algorithms. The Manager Handling should follow this order (see below in the commentary)
* In the order :
* call the constructor
* setMovingImage(ijImgMov);
* setReferenceImage(ijImgMov);
* setMetric(MetricType metricType)
* (eventually) setCapillaryHandlingOn
* addStepToQueue( ... )
* addStepToQueue( ... )
* addStepToQueue( ... )
* register();
* ImagePlus resultat=computeRegisteredImage();
*/
public ItkRegistration() {
this.registrationSummary=new ArrayList();
this.metricType=null;
this.transform=null;
this.imgMovSuccessiveResults=new ArrayList();
this.centerTransformFilter=new CenteredTransformInitializerFilter();
this.gaussFilter=new RecursiveGaussianImageFilter();
this.transformation3DTypes=new ArrayList();
this.centeringStrategies=new ArrayList();
this.nbLevels= new ArrayList ();
this.shrinkFactors= new ArrayList ();
this.dimensions= new ArrayList() ;
this.sigmaFactors= new ArrayList ();
this.registrationMethods= new ArrayList ();
this.transformation3DTypes= new ArrayList() ;
this.scalerTypes= new ArrayList();
this.weights= new ArrayList() ;
this.scales= new ArrayList() ;
this.currentLevel=0;
this.zoomFactor=2;
this.nbStep=0;
this.currentStep=0;
return;
}
/**
* Adds the step to queue.
*
* @param levelMin the level min
* @param levelMax the level max
* @param sigma the sigma
* @param iterations the iterations
* @param learning_rate the learning rate
* @param typeTransfo the type transfo
* @param weights the weights
* @param optimizerType the optimizer type
* @param scalerType the scaler type
* @param scales the scales
* @param doubleIterAtCoarsestLevels the double iter at coarsest levels
* @param centeringStrategy the centering strategy
* @param samplingStrategy the sampling strategy
*/
public void addStepToQueue(int levelMin,int levelMax,double sigma, int iterations, double learning_rate, Transform3DType typeTransfo,double[]weights,
OptimizerType optimizerType,ScalerType scalerType,double[]scales,
boolean doubleIterAtCoarsestLevels,CenteringStrategy centeringStrategy,SamplingStrategy samplingStrategy){
int[]shrinkFactors=subSamplingFactorsAtSuccessiveLevels(levelMin,levelMax,doubleIterAtCoarsestLevels,this.basis);
double[]sigmaFactors=sigmaFactorsAtSuccessiveLevels(voxelSizeReference,shrinkFactors,sigma);
int[][]dimensions=imageDimsAtSuccessiveLevels(imageSizeReference,shrinkFactors);
this.shrinkFactors.add(shrinkFactors);
this.dimensions.add(dimensions);
this.sigmaFactors.add(sigmaFactors);
ImageRegistrationMethod reg=new ImageRegistrationMethod();
reg.setShrinkFactorsPerLevel(ItkImagePlusInterface.intArrayToVectorUInt32(shrinkFactors));
reg.setSmoothingSigmasAreSpecifiedInPhysicalUnits(true);
reg.smoothingSigmasAreSpecifiedInPhysicalUnitsOn();
reg.setSmoothingSigmasPerLevel(ItkImagePlusInterface.doubleArrayToVectorDouble(sigmaFactors));
switch(metricType) {
case JOINT:reg.setMetricAsJointHistogramMutualInformation();break;
case MEANSQUARE:reg.setMetricAsMeanSquares();break;
case CORRELATION:reg.setMetricAsCorrelation();break;
case MATTES:reg.setMetricAsMattesMutualInformation(128);break;
case DEMONS:reg.setMetricAsDemons();break;
case ANTS:reg.setMetricAsANTSNeighborhoodCorrelation(3);break;
default:reg.setMetricAsCorrelation(); break;
}
double learningRate=learning_rate;
double minStep = 0.001;
int numberOfIterations = iterations;
double relaxationFactor = 0.8;
double convergenceMinimumValue=1E-6;
int convergenceWindowSize=10;
double stepLength=1;
VectorUInt32 numberOfSteps=ItkImagePlusInterface.intArrayToVectorUInt32(new int[] {4,4,4});//Lets check that, one day.
double simplexDelta=learning_rate;
switch(optimizerType){
case ITK_GRADIENT:reg.setOptimizerAsGradientDescent(learningRate/30.0, numberOfIterations, convergenceMinimumValue, convergenceWindowSize);break;
case ITK_GRADIENT_REGULAR_STEP: reg.setOptimizerAsRegularStepGradientDescent(learningRate, minStep, numberOfIterations,relaxationFactor);break;
case ITK_GRADIENT_LINE_SEARCH: reg.setOptimizerAsGradientDescentLineSearch(learningRate, numberOfIterations,convergenceMinimumValue, convergenceWindowSize);break;
case ITK_GRADIENT_CONJUGATE: reg.setOptimizerAsConjugateGradientLineSearch(learningRate, numberOfIterations,convergenceMinimumValue, convergenceWindowSize);break;
//case LBFGSB: reg.setOptimizerAsLBFGSB(gradientConvergenceTolerance);break;
//case LBFGS2: reg.setOptimizerAsLBFGS2(solutionAccuracy);break;
//case POWELL: reg.setOptimizerAsPowell(numberOfIterations, maximumLineIterations, stepLength,stepTolerance, valueTolerance);break;
//case EVOLUTIONARY: reg.setOptimizerAsOnePlusOneEvolutionary(numberOfIterations);break;
case ITK_EXHAUSTIVE: reg.setOptimizerAsExhaustive(numberOfSteps, stepLength);break;
case ITK_AMOEBA: reg.setOptimizerAsAmoeba(simplexDelta, numberOfIterations);break;
default: reg.setOptimizerAsAmoeba(simplexDelta, numberOfIterations);break;
}
switch(samplingStrategy) {
case NONE: reg.setMetricSamplingStrategy(ImageRegistrationMethod.MetricSamplingStrategyType.NONE);break;
case REGULAR: reg.setMetricSamplingStrategy(ImageRegistrationMethod.MetricSamplingStrategyType.REGULAR);break;
case RANDOM: reg.setMetricSamplingStrategy(ImageRegistrationMethod.MetricSamplingStrategyType.RANDOM);break;
}
// For a test, one day : SetMetricSamplingPercentagePerLevel() : itk::simple::ImageRegistrationMethod
this.transformation3DTypes.add(typeTransfo);
this.scalerTypes.add(scalerType);
this.scales.add(scales);
this.weights.add(weights);
this.centeringStrategies.add(centeringStrategy);
this.registrationMethods.add(reg);
nbStep++;
}
/**
* Run next step.
*/
public void runNextStep(){
if(this.transform==null && currentStep>0) { System.err.println("Pas de transformation calculee a l etape precedente. Exit");return;}
boolean flagCentering=false;
Image itkImgRefTrans=new Image(itkImgRef);
Image itkImgMovTrans=new Image(itkImgMov);
//Centering strategies
switch(centeringStrategies.get(currentStep)) {
case NONE: ;break;
case IMAGE_CENTER:
centerTransformFilter.geometryOn();
centerTransformFilter.setOperationMode(CenteredTransformInitializerFilter.OperationModeType.GEOMETRY);
flagCentering=true;
break;
case MASS_CENTER:
centerTransformFilter.momentsOn();
centerTransformFilter.setOperationMode(CenteredTransformInitializerFilter.OperationModeType.MOMENTS);
flagCentering=true;
break;
}
//Check transform
ItkTransform trPlus=null;
switch(transformation3DTypes.get(currentStep)) {
case EULER: trPlus=new ItkTransform(new Euler3DTransform());break;
case EULER2D: trPlus=new ItkTransform(new Euler2DTransform());break;
case VERSOR:trPlus=new ItkTransform(new VersorRigid3DTransform());break;
case TRANSLATION:trPlus=new ItkTransform(new TranslationTransform(3));break;
case AFFINE:trPlus=new ItkTransform(new AffineTransform(3));break;
case SIMILARITY:trPlus=new ItkTransform(new Similarity3DTransform());break;
default:trPlus=new ItkTransform(new Euler3DTransform());break;
}
if(flagCentering && transformation3DTypes.get(currentStep)!= Transform3DType.TRANSLATION)trPlus=new ItkTransform(centerTransformFilter.execute(this.itkImgRef,this.itkImgMov,trPlus));
if(this.transform==null)this.transform=trPlus;
else this.transform.addTransform(trPlus);
this.registrationMethods.get(currentStep).setInitialTransform(this.transform);
switch(scalerTypes.get(currentStep)) {
case NONE: ;break;
case MANUAL: this.registrationMethods.get(currentStep).setOptimizerScales(ItkImagePlusInterface.doubleArrayToVectorDouble(scales.get(currentStep)));break;
case SCALER_INDEX: this.registrationMethods.get(currentStep).setOptimizerScalesFromIndexShift();break;
case SCALER_PHYSICAL: this.registrationMethods.get(currentStep).setOptimizerScalesFromPhysicalShift();break;
case JACOBIAN_VERSOR: this.registrationMethods.get(currentStep).setOptimizerScalesFromJacobian();break;
}
// PARAMETERS WEIGHTING FOR FOSTERING SOME OR SOME BEHAVIOUR //////////////
if(this.weights.get(this.currentStep)!=null && this.weights.get(this.currentStep).length>0) {
this.registrationMethods.get(currentStep).setOptimizerWeights(ItkImagePlusInterface.doubleArrayToVectorDouble(this.weights.get(currentStep)));
}
//////////// GO ! ////////////////
this.registrationThread= new Thread() { { setPriority(Thread.NORM_PRIORITY); }
public void run() {
try {
registrationMethods.get(currentStep).execute(itkImgRefTrans,itkImgMovTrans);
}catch(Exception e) {System.out.println("Interruption of Itk registration");itkRegistrationInterrupted=true;}
}
};
VitimageUtils.startAndJoin(this.registrationThread);
if(itkRegistrationInterrupted) {
itkIsInterruptedSucceeded=true;
this.currentStep=100000;
}
else this.currentStep++;
}
/**
* Register.
*/
public void register(){
this.currentStep=0;
while(currentStep0) {
this.resampler.setTransform(this.transform);
ImagePlus temp=ItkImagePlusInterface.itkImageToImagePlus(this.resampler.execute(this.itkImgMov));
this.imgMovSuccessiveResults.add(temp);
}
}
displayEndOfRegistrationMessage();
if(this.displayRegistration>0) {
this.sliceView.changes=false;
this.sliceView.close();
}
}
/**
* Functions for displaying, tracking and keep memories of registration results along the computation.
*/
public void displayEndOfRegistrationMessage() {
IJ.log("-----------------------------------------");
IJ.log("-----------------------------------------");
IJ.log("------ End of registration -------");
IJ.log("-----------------------------------------");
IJ.log("Optimizer stop condition: "+registrationMethods.get(nbStep-1).getOptimizerStopConditionDescription()+"\n");
IJ.log(" Iteration: "+registrationMethods.get(nbStep-1).getOptimizerIteration()+"\n");
IJ.log(" Metric value: "+registrationMethods.get(nbStep-1).getMetricValue()+"\n");
}
/**
* Compute registered image.
*
* @return the image plus
*/
public ImagePlus computeRegisteredImage() {
if(transform==null)return null;
ResampleImageFilter resampler = new ResampleImageFilter();
resampler.setReferenceImage(itkImgRef);
resampler.setDefaultPixelValue(0);
resampler.setTransform(transform);
Image imgResultat=resampler.execute(itkImgMov);
ImagePlus res=ItkImagePlusInterface.itkImageToImagePlus(imgResultat);
res.getProcessor().resetMinAndMax();
return res;
}
/**
* Update view.
*
* @param dimensions the dimensions
* @param sigmaFactor the sigma factor
* @param shrinkFactor the shrink factor
* @param viewText the view text
* @param currentTrans the current trans
*/
public void updateView(int []dimensions,double sigmaFactor,int shrinkFactor,String viewText,ItkTransform currentTrans) {
if(this.displayRegistration==0)return;
this.gaussFilter.setSigma(sigmaFactor);
VectorDouble vectVoxSizes=new VectorDouble(3);
vectVoxSizes.set(0,this.voxelSizeReference[0]*this.imageSizeReference[0]/dimensions[0]);
vectVoxSizes.set(1,this.voxelSizeReference[1]*this.imageSizeReference[1]/dimensions[1]);
vectVoxSizes.set(2,this.voxelSizeReference[2]*this.imageSizeReference[2]/dimensions[2]);
//Update reference viewing image and the viewing slice, if needed
this.resampler=new ResampleImageFilter();
this.resampler.setDefaultPixelValue(0);
this.resampler.setTransform(ItkTransform.getTransformForResampling(this.voxelSizeReference, VitimageUtils.getVoxelSizes(this.ijImgMov)));
if(this.lookLikeOptimizerLooks) {
this.resampler.setOutputSpacing(vectVoxSizes);
this.resampler.setSize(ItkImagePlusInterface.intArrayToVectorUInt32(dimensions));
}
else {
this.resampler.setOutputSpacing(ItkImagePlusInterface.doubleArrayToVectorDouble(this.voxelSizeReference));
this.resampler.setSize(ItkImagePlusInterface.intArrayToVectorUInt32(this.imageSizeReference));
}
this.itkImgViewRef=this.resampler.execute(this.itkImgRef);
if(this.lookLikeOptimizerLooks) {
for(int i=0;i<3;i++) {
if(this.imageSizeReference[i]>=4) {
this.gaussFilter.setDirection(i);
itkImgViewRef=this.gaussFilter.execute(this.itkImgViewRef);
}
}
}
this.sliceViewRef=ItkImagePlusInterface.itkImageToImagePlusSlice(this.itkImgViewRef,(int)Math.ceil(this.viewSlice*1.0/(this.lookLikeOptimizerLooks ? shrinkFactor : 1)));
if(this.flagRange)this.sliceViewRef.setDisplayRange(this.refRange[0], this.refRange[1]);
//Update moving image
this.resampler=new ResampleImageFilter();
this.resampler.setDefaultPixelValue(0);
if(this.lookLikeOptimizerLooks) {
this.resampler.setOutputSpacing(vectVoxSizes);
this.resampler.setSize(ItkImagePlusInterface.intArrayToVectorUInt32(dimensions));
}
else {
this.resampler.setOutputSpacing(ItkImagePlusInterface.doubleArrayToVectorDouble(this.voxelSizeReference));
this.resampler.setSize(ItkImagePlusInterface.intArrayToVectorUInt32(this.imageSizeReference));
}
if(this.transform!=null)this.resampler.setTransform(this.transform);
else this.resampler.setTransform(ItkTransform.getTransformForResampling(this.voxelSizeReference, VitimageUtils.getVoxelSizes(this.ijImgMov)));
this.itkImgViewMov=this.resampler.execute(this.itkImgMov);
if(this.lookLikeOptimizerLooks) {
for(int i=0;i<3;i++) {
if(this.imageSizeReference[i]>=4) {
this.gaussFilter.setDirection(i);
itkImgViewRef=this.gaussFilter.execute(this.itkImgViewRef);
}
}
}
this.sliceViewMov=ItkImagePlusInterface.itkImageToImagePlusSlice(this.itkImgViewMov,(int)Math.ceil(this.viewSlice*1.0/(this.lookLikeOptimizerLooks ? shrinkFactor : 1)));
if(this.flagRange)this.sliceViewMov.setDisplayRange(this.movRange[0], this.movRange[1]);
//Compose the images
if(this.sliceView==null || this.sliceViewRef.getWidth() != sliceView.getWidth()) {
if(this.sliceView!=null) {this.sliceView.changes=false;this.sliceView.close();}
if(flagRange)this.sliceView=VitimageUtils.compositeNoAdjustOf(this.sliceViewRef,this.sliceViewMov,"Registration is running. Red=Reference, Green=moving");
else this.sliceView=VitimageUtils.compositeOf(this.sliceViewRef,this.sliceViewMov,"Registration is running. Red=Reference, Green=moving");
this.sliceView.show();
this.sliceView.getWindow().setSize(this.viewWidth,this.viewHeight);
this.sliceView.getCanvas().fitToWindow();
}
else {//Copie en place
ImagePlus temp=null;
if(flagRange)temp=VitimageUtils.compositeNoAdjustOf(this.sliceViewRef,this.sliceViewMov,"Red=Reference, Green=moving");
else temp=VitimageUtils.compositeOf(this.sliceViewRef,this.sliceViewMov,"Red=Reference, Green=moving");
temp=VitimageUtils.writeTextOnImage(viewText,temp,this.fontSize*temp.getWidth()/this.imageSizeReference[0],0);
temp=VitimageUtils.writeTextOnImage(currentTrans.drawableString(),temp,this.fontSize*temp.getWidth()/this.imageSizeReference[0]-2,1);
IJ.run(this.sliceView, "Select All", "");
IJ.run(temp, "Select All", "");
temp.copy();
this.sliceView.paste();
}
//Prepare slices for summary
this.resampler=new ResampleImageFilter();
this.resampler.setDefaultPixelValue(0);
this.resampler.setOutputSpacing(ItkImagePlusInterface.doubleArrayToVectorDouble(this.voxelSizeReference));
this.resampler.setSize(ItkImagePlusInterface.intArrayToVectorUInt32(this.imageSizeReference));
this.resampler.setTransform(ItkTransform.getTransformForResampling(this.voxelSizeReference, this.voxelSizeReference));
this.itkSummaryRef=this.resampler.execute(this.itkImgViewRef);
this.itkSummaryMov=this.resampler.execute(this.itkImgViewMov);
if(movie3D) {
this.sliceSummaryMov=ItkImagePlusInterface.itkImageToImagePlus(this.itkSummaryMov);
this.sliceSummaryRef=ItkImagePlusInterface.itkImageToImagePlus(this.itkSummaryRef);
}
else {
this.sliceSummaryMov=ItkImagePlusInterface.itkImageToImagePlusSlice(this.itkSummaryMov,this.viewSlice);
this.sliceSummaryRef=ItkImagePlusInterface.itkImageToImagePlusSlice(this.itkSummaryRef,this.viewSlice);
}
ImagePlus temp2=VitimageUtils.compositeOf(this.sliceSummaryRef,this.sliceSummaryMov,"Registration is running. Red=Reference, Green=moving");
temp2=VitimageUtils.writeTextOnImage(viewText,temp2,this.fontSize*temp2.getWidth()/this.imageSizeReference[0],0);
temp2=VitimageUtils.writeTextOnImage(currentTrans.drawableString(),temp2,this.fontSize*temp2.getWidth()/this.imageSizeReference[0]-2,1);
this.registrationSummary.add(temp2);
}
/**
* Sets the text info at each iteration on.
*/
public void setTextInfoAtEachIterationOn() {
textInfoAtEachIteration=true;
}
/**
* Sets the text info at each iteration off.
*/
public void setTextInfoAtEachIterationOff() {
textInfoAtEachIteration=false;
}
/**
* Initializers.
*
* @param imgIn the new reference image
*/
public void setReferenceImage(ImagePlus imgIn) {
ImagePlus img=null;
if(imgIn.getType()==ImagePlus.GRAY32)img=VitimageUtils.imageCopy(imgIn);
else if(imgIn.getType()==ImagePlus.GRAY16)img=VitimageUtils.convertShortToFloatWithoutDynamicChanges(imgIn);
else if(imgIn.getType()==ImagePlus.GRAY8)img=VitimageUtils.convertByteToFloatWithoutDynamicChanges(imgIn);
else IJ.log("Warning : unusual type of image in ITKRegistrationManager.setReferenceImage : "+imgIn.getType()+" . Registration will fail shortly");
this.ijImgRef=VitimageUtils.imageCopy(img);
this.viewHeight=ijImgRef.getHeight()*zoomFactor;
this.viewWidth=ijImgRef.getWidth()*zoomFactor;
this.itkImgRef=ItkImagePlusInterface.imagePlusToItkImage(ijImgRef);
this.imageSizeReference=new int[] {ijImgRef.getWidth(),ijImgRef.getHeight(),ijImgRef.getStackSize()};
this.voxelSizeReference=new double[] {ijImgRef.getCalibration().pixelWidth,ijImgRef.getCalibration().pixelHeight,ijImgRef.getCalibration().pixelDepth};
this.viewSlice=(int)Math.round(ijImgRef.getStackSize()/2.0);
}
/**
* Sets the view slice.
*
* @param slic the new view slice
*/
public void setViewSlice(int slic) {
this.viewSlice=slic;
}
/**
* Sets the moving image.
*
* @param imgIn the new moving image
*/
public void setMovingImage(ImagePlus imgIn) {
ImagePlus img=null;
VitimageUtils.printImageResume(imgIn);
if(imgIn.getType()==ImagePlus.GRAY32)img=VitimageUtils.imageCopy(imgIn);
else if(imgIn.getType()==ImagePlus.GRAY16)img=VitimageUtils.convertShortToFloatWithoutDynamicChanges(imgIn);
else if(imgIn.getType()==ImagePlus.GRAY8) {img=VitimageUtils.convertByteToFloatWithoutDynamicChanges(imgIn);}
else IJ.log("Warning : unusual type of image in ITKRegistrationManager.setMovingImage : "+imgIn.getType()+" . Registration will fail shortly");
this.ijImgMov=VitimageUtils.imageCopy(img);
this.itkImgMov=ItkImagePlusInterface.imagePlusToItkImage(ijImgMov);
}
/**
* Sets the metric.
*
* @param metricType the new metric
*/
public void setMetric(MetricType metricType) {
this.metricType=metricType;
}
/**
* Sets the initial transformation.
*
* @param trans the new initial transformation
*/
public void setInitialTransformation(ItkTransform trans) {
if(this.transform !=null || this.currentStep>0) System.err.println("Une transformation initiale est deja existante");
else this.transform=new ItkTransform(trans);
}
/**
* Creates the updater.
*/
public void createUpdater() {
this.updater=new IterationUpdate(this,this.registrationMethods.get(currentStep));
this.registrationMethods.get(this.currentStep).removeAllCommands();
this.registrationMethods.get(this.currentStep).addCommand(EventEnum.sitkIterationEvent,this.updater);
}
/**
* Helper functions to build the pyramidal scheme based on few parameters.
*
* @param levelMin the level min
* @param levelMax the level max
* @param doubleIterAtCoarsestLevels the double iter at coarsest levels
* @param basis the basis
* @return the int[]
*/
public int[] subSamplingFactorsAtSuccessiveLevels(int levelMin,int levelMax,boolean doubleIterAtCoarsestLevels,double basis){
if(levelMax2 ? nbLevels-2 : 0) : 0;
int nbTot=nbLevels+nbDouble;
int []ret=new int[nbTot];
for(int i=0;i<2 && i getNbLevels() {
return nbLevels;
}
/**
* Sets the nb levels.
*
* @param nbLevels the new nb levels
*/
public void setNbLevels(ArrayList nbLevels) {
this.nbLevels = nbLevels;
}
/**
* Gets the current shrink factors.
*
* @return the current shrink factors
*/
public int[] getCurrentShrinkFactors() {
return shrinkFactors.get(currentStep);
}
/**
* Sets the shrink factors.
*
* @param shrinkFactors the new shrink factors
*/
public void setShrinkFactors(ArrayList shrinkFactors) {
this.shrinkFactors = shrinkFactors;
}
/**
* Gets the current dimensions.
*
* @return the current dimensions
*/
public int[][] getCurrentDimensions() {
return dimensions.get(currentStep);
}
/**
* Gets the current sigma factors.
*
* @return the current sigma factors
*/
public double[] getCurrentSigmaFactors() {
return sigmaFactors.get(currentStep);
}
/**
* Gets the current level.
*
* @return the current level
*/
public int getCurrentLevel() {
return currentLevel;
}
/**
* Sets the current level.
*
* @param currentLevel the new current level
*/
public void setCurrentLevel(int currentLevel) {
this.currentLevel = currentLevel;
}
/**
* Gets the scaler types.
*
* @return the scaler types
*/
public ArrayList getScalerTypes() {
return scalerTypes;
}
/**
* Sets the scaler types.
*
* @param scalerTypes the new scaler types
*/
public void setScalerTypes(ArrayList scalerTypes) {
this.scalerTypes = scalerTypes;
}
/**
* Gets the nb steps.
*
* @return the nb steps
*/
public int getNbSteps() {
return nbStep;
}
/**
* Sets the nb steps.
*
* @param nbStep the new nb steps
*/
public void setNbSteps(int nbStep) {
this.nbStep = nbStep;
}
/**
* Gets the current step.
*
* @return the current step
*/
public int getCurrentStep() {
return currentStep;
}
/**
* Sets the current step.
*
* @param currentStep the new current step
*/
public void setCurrentStep(int currentStep) {
this.currentStep = currentStep;
}
/**
* Gets the weights.
*
* @return the weights
*/
public ArrayList getWeights() {
return weights;
}
/**
* Sets the weights.
*
* @param weights the new weights
*/
public void setWeights(ArrayList weights) {
this.weights = weights;
}
/**
* Gets the scales.
*
* @return the scales
*/
public ArrayList getScales() {
return scales;
}
/**
* Sets the scales.
*
* @param scales the new scales
*/
public void setScales(ArrayList scales) {
this.scales = scales;
}
/**
* Gets the current transform.
*
* @return the current transform
*/
public ItkTransform getCurrentTransform() {
return new ItkTransform(this.transform);
}
}
/**
* Listener for gathering optimizer events. It allows the manager to update and display the process state along the running
*/
class IterationUpdate extends Command {
private double initScore=1;
private ImageRegistrationMethod method;
private ItkRegistration manager;
private int [] tabShrink;
private double refreshingPeriod=50;
private int [][]tabSizes;
private double[] tabSigma;
private long memoirePyramide=1000;
private double timeStamp1=0;
private double timeStamp0=0;
private double timeStampInit=0;
private double durationIter=0;
private double durationTot=0;
private double nextViewTime=0+refreshingPeriod;
private double improvement=0;
public IterationUpdate(ItkRegistration manager,ImageRegistrationMethod method) {
super();
this.manager=manager;
this.tabSigma=manager.getCurrentSigmaFactors();
this.tabShrink=manager.getCurrentShrinkFactors();
this.tabSizes=manager.getCurrentDimensions();
this.method=method;
timeStamp1=0;
timeStamp0=0;
timeStampInit=0;
durationTot=0;
durationIter=0;
}
public void execute() {
boolean isNewLevel=(method.getOptimizerIteration()nextViewTime) {
nextViewTime=durationTot+refreshingPeriod;
String st=String.format("Step=%1d/%1d - Level=%1d/%1d - Iter=%3d - Score=%6.4f - Evolution=%4.2f%%",
(manager.getCurrentStep()+1),
manager.getNbSteps(),
(method.getCurrentLevel()+1),tabSigma.length,method.getOptimizerIteration(),-100.0*method.getMetricValue(),improvement);
this.manager.updateView(this.tabSizes[mem],tabSigma[mem],this.tabShrink[mem],st,new ItkTransform(method.getInitialTransform()));
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy