public static <T extends RealType<T>> CompositeImage createOverlay( final T targetType, final ArrayList<ImagePlus> images, final ArrayList<InvertibleBoundable> models, final int dimensionality, final int timepoint, final InterpolatorFactory<FloatType> factory) { final int numImages = images.size(); // the size of the new image final int[] size = new int[dimensionality]; // the offset relative to the output image which starts with its local coordinates (0,0,0) final float[] offset = new float[dimensionality]; // estimate the boundaries of the output image and the offset for fusion (negative coordinates // after transform have to be shifted to 0,0,0) estimateBounds(offset, size, images, models, dimensionality); // for output final ImageFactory<T> f = new ImageFactory<T>(targetType, new ImagePlusContainerFactory()); // the composite final ImageStack stack = new ImageStack(size[0], size[1]); int numChannels = 0; // loop over all images for (int i = 0; i < images.size(); ++i) { final ImagePlus imp = images.get(i); // loop over all channels for (int c = 1; c <= imp.getNChannels(); ++c) { final Image<T> out = f.createImage(size); fuseChannel( out, ImageJFunctions.convertFloat(Hyperstack_rearranger.getImageChunk(imp, c, timepoint)), offset, models.get(i + (timepoint - 1) * numImages), factory); try { final ImagePlus outImp = ((ImagePlusContainer<?, ?>) out.getContainer()).getImagePlus(); for (int z = 1; z <= out.getDimension(2); ++z) stack.addSlice(imp.getTitle(), outImp.getStack().getProcessor(z)); } catch (ImgLibException e) { IJ.log("Output image has no ImageJ type: " + e); } // count all channels ++numChannels; } } // convertXYZCT ... ImagePlus result = new ImagePlus( "overlay " + images.get(0).getTitle() + " ... " + images.get(numImages - 1).getTitle(), stack); // numchannels, z-slices, timepoints (but right now the order is still XYZCT) if (dimensionality == 3) { result.setDimensions(size[2], numChannels, 1); result = OverlayFusion.switchZCinXYCZT(result); } else { result.setDimensions(numChannels, 1, 1); } return new CompositeImage(result, CompositeImage.COMPOSITE); }
// @Override public void run(String arg0) { // get list of image stacks final int[] idList = WindowManager.getIDList(); if (idList == null || idList.length < 2) { IJ.error("You need at least two open images."); return; } final String[] imgList = new String[idList.length]; for (int i = 0; i < idList.length; ++i) imgList[i] = WindowManager.getImage(idList[i]).getTitle(); if (defaultImg1 >= imgList.length || defaultImg2 >= imgList.length) { defaultImg1 = 0; defaultImg2 = 1; } /** The first dialog for choosing the images */ final GenericDialog gd = new GenericDialog("Descriptor based registration"); gd.addChoice("First_image (to register)", imgList, imgList[defaultImg1]); gd.addChoice("Second_image (reference)", imgList, imgList[defaultImg2]); if (lastModel1 != null) gd.addCheckbox("Reapply last model", defaultReApply); gd.addMessage( "Warning: if images are of RGB or 8-bit color they will be converted to hyperstacks."); gd.addMessage( "Please note that the SPIM Registration is based on a publication.\n" + "If you use it successfully for your research please be so kind to cite our work:\n" + "Preibisch et al., Nature Methods (2010), 7(6):418-419\n"); MultiLineLabel text = (MultiLineLabel) gd.getMessage(); Bead_Registration.addHyperLinkListener(text, paperURL); gd.showDialog(); if (gd.wasCanceled()) return; ImagePlus imp1 = WindowManager.getImage(idList[defaultImg1 = gd.getNextChoiceIndex()]); ImagePlus imp2 = WindowManager.getImage(idList[defaultImg2 = gd.getNextChoiceIndex()]); boolean reApply = false; if (lastModel1 != null) { reApply = gd.getNextBoolean(); defaultReApply = reApply; } // if one of the images is rgb or 8-bit color convert them to hyperstack imp1 = Hyperstack_rearranger.convertToHyperStack(imp1); imp2 = Hyperstack_rearranger.convertToHyperStack(imp2); // test if the images are compatible String error = testRegistrationCompatibility(imp1, imp2); if (error != null) { IJ.log(error); return; } // get the parameters final int dimensionality; if (imp1.getNSlices() > 1) dimensionality = 3; else dimensionality = 2; if (imp1.getNFrames() > 1 || imp2.getNFrames() > 2) IJ.log( "WARNING: Images have more than one timepoint, same model as the first timepoint will be applied to all timepoints."); if (imp1.getNFrames() != imp2.getNFrames()) IJ.log( "CRITICAL: Images do not have the same amount of timepoints. Will use the number of timepoints of the smaller series."); // reapply? if (reApply) { if (dimensionality < lastDimensionality) { IJ.log( "Cannot reapply, cannot apply a " + lastModel1.getClass().getSimpleName() + " to " + dimensionality + " data."); defaultReApply = false; return; } else if (dimensionality > lastDimensionality) { IJ.log( "WARNING: applying a " + lastModel1.getClass().getSimpleName() + " to " + dimensionality + " data."); } // just fuse final DescriptorParameters params = new DescriptorParameters(); params.dimensionality = dimensionality; params.reApply = true; params.fuse = 0; params.setPointsRois = false; Matching.descriptorBasedRegistration(imp1, imp2, params); return; } // open a second dialog and query the other parameters final DescriptorParameters params = getParameters(imp1, imp2, dimensionality); if (params == null) return; // compute the actual matching Matching.descriptorBasedRegistration(imp1, imp2, params); }
public static <T extends RealType<T>> ImagePlus createReRegisteredSeries( final T targetType, final ImagePlus imp, final ArrayList<InvertibleBoundable> models, final int dimensionality, final String directory) { final int numImages = imp.getNFrames(); // the size of the new image final int[] size = new int[dimensionality]; // the offset relative to the output image which starts with its local coordinates (0,0,0) final float[] offset = new float[dimensionality]; final int[][] imgSizes = new int[numImages][dimensionality]; for (int i = 0; i < numImages; ++i) { imgSizes[i][0] = imp.getWidth(); imgSizes[i][1] = imp.getHeight(); if (dimensionality == 3) imgSizes[i][2] = imp.getNSlices(); } // estimate the boundaries of the output image and the offset for fusion (negative coordinates // after transform have to be shifted to 0,0,0) estimateBounds(offset, size, imgSizes, models, dimensionality); // use the same size as the first image, this is a little bit ad-hoc if (useSizeOfFirstImage) { for (int d = 0; d < dimensionality; ++d) { size[d] = imgSizes[0][d]; offset[d] = 0; } } // for output final ImageFactory<T> f = new ImageFactory<T>(targetType, new ImagePlusContainerFactory()); // the composite final ImageStack stack = new ImageStack(size[0], size[1]); for (int t = 1; t <= numImages; ++t) { for (int c = 1; c <= imp.getNChannels(); ++c) { final Image<T> out = f.createImage(size); if (useNearestNeighborInterpolation) fuseChannel( out, ImageJFunctions.convertFloat(Hyperstack_rearranger.getImageChunk(imp, c, t)), offset, models.get(t - 1), new NearestNeighborInterpolatorFactory<FloatType>( new OutOfBoundsStrategyValueFactory<FloatType>())); else fuseChannel( out, ImageJFunctions.convertFloat(Hyperstack_rearranger.getImageChunk(imp, c, t)), offset, models.get(t - 1), new LinearInterpolatorFactory<FloatType>( new OutOfBoundsStrategyValueFactory<FloatType>())); try { final ImagePlus outImp = ((ImagePlusContainer<?, ?>) out.getContainer()).getImagePlus(); if (directory == null) { // fuse for (int z = 1; z <= out.getDimension(2); ++z) stack.addSlice(imp.getTitle(), outImp.getStack().getProcessor(z)); } else { // write to disk for (int z = 1; z <= out.getDimension(2); ++z) { final ImagePlus tmp = new ImagePlus( "img_t" + lz(t, numImages) + "_z" + lz(z, out.getDimension(2)) + "_c" + lz(c, imp.getNChannels()), outImp.getStack().getProcessor(z)); final FileSaver fs = new FileSaver(tmp); fs.saveAsTiff(new File(directory, tmp.getTitle()).getAbsolutePath()); tmp.close(); } out.close(); outImp.close(); } } catch (ImgLibException e) { IJ.log("Output image has no ImageJ type: " + e); } } } if (directory != null) return null; // convertXYZCT ... ImagePlus result = new ImagePlus("registered " + imp.getTitle(), stack); // numchannels, z-slices, timepoints (but right now the order is still XYZCT) if (dimensionality == 3) { result.setDimensions(size[2], imp.getNChannels(), imp.getNFrames()); result = OverlayFusion.switchZCinXYCZT(result); return new CompositeImage(result, CompositeImage.COMPOSITE); } else { // IJ.log( "ch: " + imp.getNChannels() ); // IJ.log( "slices: " + imp.getNSlices() ); // IJ.log( "frames: " + imp.getNFrames() ); result.setDimensions(imp.getNChannels(), 1, imp.getNFrames()); if (imp.getNChannels() > 1) return new CompositeImage(result, CompositeImage.COMPOSITE); else return result; } }