@Override public void run(final String arg0) { final GenericDialogPlus dialog = new GenericDialogPlus("Inverse Compositional Image Alignment"); dialog.addImageChoice("template", null); dialog.addImageChoice("image to align", null); dialog.addNumericField("max iterations", 50, 0); dialog.addNumericField("min parameter change", 0.001, 4); dialog.showDialog(); if (dialog.wasCanceled()) return; ImagePlus impTemplate = dialog.getNextImage(); ImagePlus impImage = dialog.getNextImage(); int maxIterations = (int) dialog.getNextNumber(); double minParameterChange = dialog.getNextNumber(); if (impTemplate == null || impImage == null) { IJ.showMessage("Please select two images."); return; } RandomAccessibleInterval<FloatType> template = ImageJFunctions.convertFloat(impTemplate); RandomAccessibleInterval<FloatType> image = ImageJFunctions.convertFloat(impImage); if (image == null || template == null) { IJ.showMessage("Image type not supported."); return; } Align<FloatType> align = new Align<>(template, new ArrayImgFactory<>()); AffineTransform transform = align.align(image, maxIterations, minParameterChange); // TODO: // 1.) Use ImageJFunctions.wrapRGBA(), wrapByte(), etc. to get a Img<T> wrapping impImage // with T according to the type of the ImagePlus. // 2.) Show the transformed Img<T>. Maybe put this functionality into a generic method to // avoid having to re-implement each case. switch (impTemplate.getType()) { case ImagePlus.GRAY8: // TODO break; case ImagePlus.GRAY16: // TODO break; case ImagePlus.GRAY32: // TODO break; case ImagePlus.COLOR_RGB: // TODO break; default: IJ.showMessage("Image type not supported."); } }
public <T extends RealType<T>> void process(Img<T> img) { // compute the gradient on the image Img<FloatType> gradient = gradient(img); // show the new Img that contains the gradient ImageJFunctions.show(gradient); }
public Example1c() { // create the ImgFactory based on cells (cellsize = 5x5x5...x5) that will // instantiate the Img final ImgFactory<FloatType> imgFactory = new CellImgFactory<FloatType>(5); // create an 3d-Img with dimensions 20x30x40 (here cellsize is 5x5x5)Ø final Img<FloatType> img1 = imgFactory.create(new long[] {20, 30, 40}, new FloatType()); // create another image with the same size // note that the input provides the size for the new image as it implements // the Interval interface final Img<FloatType> img2 = imgFactory.create(img1, img1.firstElement()); // display both (but they are empty) ImageJFunctions.show(img1); ImageJFunctions.show(img2); }
public Example6a1() throws ImgIOException { // open with ImgOpener as a FloatType Img<FloatType> image = new ImgOpener().openImg("DrosophilaWing.tif", new FloatType()); // perform gaussian convolution with float precision double[] sigma = new double[image.numDimensions()]; for (int d = 0; d < image.numDimensions(); ++d) sigma[d] = 8; // convolve & display ImageJFunctions.show(Gauss.toFloat(sigma, image)); }
public void run(String arg0) { // get the current ImageJ ImagePlus ImagePlus imp = WindowManager.getCurrentImage(); // test if an image is open if (imp == null) { IJ.log("No image open"); return; } // wrap it into an ImgLib2 Img (no copying) Img<RealType> img = ImageJFunctions.wrapReal(imp); // test if it could be wrapped if (img == null) { IJ.log("Cannot wrap image"); return; } // process wrapped image with ImgLib2 process(img); }
public static void main(final String[] args) { final int N_BLOBS = 20; final double RADIUS = 5; // µm final Random RAN = new Random(); final double WIDTH = 100; // µm final double HEIGHT = 100; // µm final double DEPTH = 50; // µm final double[] CALIBRATION = new double[] {0.5f, 0.5f, 1}; final AxisType[] AXES = new AxisType[] {Axes.X, Axes.Y, Axes.Z}; // Create 3D image final Img<UnsignedByteType> source = new ArrayImgFactory<UnsignedByteType>() .create( new int[] { (int) (WIDTH / CALIBRATION[0]), (int) (HEIGHT / CALIBRATION[1]), (int) (DEPTH / CALIBRATION[2]) }, new UnsignedByteType()); final ImgPlus<UnsignedByteType> img = new ImgPlus<UnsignedByteType>(source, "Test", AXES, CALIBRATION); // Random blobs final double[] radiuses = new double[N_BLOBS]; final ArrayList<double[]> centers = new ArrayList<double[]>(N_BLOBS); final int[] intensities = new int[N_BLOBS]; double x, y, z; for (int i = 0; i < N_BLOBS; i++) { radiuses[i] = RADIUS + RAN.nextGaussian(); x = WIDTH * RAN.nextFloat(); y = HEIGHT * RAN.nextFloat(); z = DEPTH * RAN.nextFloat(); centers.add(i, new double[] {x, y, z}); intensities[i] = RAN.nextInt(100) + 100; } // Put the blobs in the image for (int i = 0; i < N_BLOBS; i++) { final Spot tmpSpot = new Spot(centers.get(i)[0], centers.get(i)[1], centers.get(i)[2], radiuses[i], -1d); tmpSpot.putFeature(Spot.RADIUS, radiuses[i]); final SpotNeighborhood<UnsignedByteType> sphere = new SpotNeighborhood<UnsignedByteType>(tmpSpot, img); for (final UnsignedByteType pixel : sphere) { pixel.set(intensities[i]); } } // Instantiate detector final LogDetector<UnsignedByteType> detector = new LogDetector<UnsignedByteType>( img, img, TMUtils.getSpatialCalibration(img), RADIUS, 0, true, false); // Segment final long start = System.currentTimeMillis(); if (!detector.checkInput() || !detector.process()) { System.out.println(detector.getErrorMessage()); return; } final Collection<Spot> spots = detector.getResult(); final long end = System.currentTimeMillis(); // Display image ImageJFunctions.show(img); // Display results final int spot_found = spots.size(); System.out.println("Segmentation took " + (end - start) + " ms."); System.out.println("Found " + spot_found + " blobs.\n"); Point3d p1, p2; double dist, min_dist; int best_index = 0; double[] best_match; final ArrayList<Spot> spot_list = new ArrayList<Spot>(spots); Spot best_spot = null; final double[] coords = new double[3]; final String[] posFeats = Spot.POSITION_FEATURES; while (!spot_list.isEmpty() && !centers.isEmpty()) { min_dist = Float.POSITIVE_INFINITY; for (final Spot s : spot_list) { int index = 0; for (final String pf : posFeats) { coords[index++] = s.getFeature(pf).doubleValue(); } p1 = new Point3d(coords); for (int j = 0; j < centers.size(); j++) { p2 = new Point3d(centers.get(j)); dist = p1.distance(p2); if (dist < min_dist) { min_dist = dist; best_index = j; best_spot = s; } } } spot_list.remove(best_spot); best_match = centers.remove(best_index); int index = 0; for (final String pf : posFeats) { coords[index++] = best_spot.getFeature(pf).doubleValue(); } System.out.println("Blob coordinates: " + Util.printCoordinates(coords)); System.out.println( String.format( " Best matching center at distance %.1f with coords: " + Util.printCoordinates(best_match), min_dist)); } System.out.println(); System.out.println("Unmatched centers:"); for (int i = 0; i < centers.size(); i++) System.out.println("Center " + i + " at position: " + Util.printCoordinates(centers.get(i))); }
public static void main(final String[] args) { // TEST 2D case // Parameters final int size_x = 200; final int size_y = 200; final long a = 10; final long b = 5; final double phi_r = Math.toRadians(30); final long max_radius = Math.max(a, b); final double[] calibration = new double[] {1, 1}; // Create blank image final Img<UnsignedByteType> img = new ArrayImgFactory<UnsignedByteType>() .create(new int[] {200, 200}, new UnsignedByteType()); final ImgPlus<UnsignedByteType> imgplus = new ImgPlus<UnsignedByteType>(img); for (int d = 0; d < imgplus.numDimensions(); d++) { imgplus.setAxis(new DefaultLinearAxis(imgplus.axis(d).type(), calibration[d]), d); } final byte on = (byte) 255; // Create an ellipse long start = System.currentTimeMillis(); System.out.println(String.format("Creating an ellipse with a = %d, b = %d", a, b)); System.out.println(String.format("phi = %.1f", Math.toDegrees(phi_r))); final long[] center = new long[] {size_x / 2, size_y / 2}; final long[] radiuses = new long[] {max_radius, max_radius}; final EllipseNeighborhood<UnsignedByteType> disc = new EllipseNeighborhood<UnsignedByteType>(img, center, radiuses); final EllipseCursor<UnsignedByteType> sc = disc.cursor(); double r2, phi, term; double cosphi, sinphi; while (sc.hasNext()) { sc.fwd(); r2 = sc.getDistanceSquared(); phi = sc.getPhi(); cosphi = Math.cos(phi - phi_r); sinphi = Math.sin(phi - phi_r); term = r2 * cosphi * cosphi / a / a + r2 * sinphi * sinphi / b / b; if (term <= 1) sc.get().set(on); } final long end = System.currentTimeMillis(); System.out.println("Ellipse creation done in " + (end - start) + " ms."); System.out.println(); ij.ImageJ.main(args); ImageJFunctions.show(imgplus); start = System.currentTimeMillis(); final Spot spot = new Spot(center[0], center[1], 0d, max_radius, -1d); final SpotMorphologyAnalyzer<UnsignedByteType> bm = new SpotMorphologyAnalyzer<UnsignedByteType>(imgplus, null); bm.process(spot); System.out.println("Blob morphology analyzed in " + (end - start) + " ms."); double phiv, thetav, lv; for (int j = 0; j < 2; j++) { lv = spot.getFeature(featurelist_sa[j]); phiv = spot.getFeature(featurelist_phi[j]); thetav = spot.getFeature(featurelist_theta[j]); System.out.println( String.format( "For axis of semi-length %.1f, orientation is phi = %.1f°, theta = %.1f°", lv, Math.toDegrees(phiv), Math.toDegrees(thetav))); } System.out.println(spot.echo()); // TEST 3D case /* * * // Parameters int size_x = 200; int size_y = 200; int size_z = 200; * * double a = 5.5f; double b = 4.9f; double c = 5; double theta_r = * (double) Math.toRadians(0); // I am unable to have it working for * theta_r != 0 double phi_r = (double) Math.toRadians(45); * * double max_radius = Math.max(a, Math.max(b, c)); double[] calibration * = new double[] {1, 1, 1}; * * // Create blank image Image<UnsignedByteType> img = new * ImageFactory<UnsignedByteType>( new UnsignedByteType(), new * ArrayContainerFactory() ).createImage(new int[] {200, 200, 200}); * final byte on = (byte) 255; * * // Create an ellipse long start = System.currentTimeMillis(); * System.out.println(String.format( * "Creating an ellipse with a = %.1f, b = %.1f, c = %.1f", a, b, c)); * System.out.println(String.format("phi = %.1f and theta = %.1f", * Math.toDegrees(phi_r), Math.toDegrees(theta_r))); double[] center = * new double[] { size_x/2, size_y/2, size_z/2 }; * SphereCursor<UnsignedByteType> sc = new * SphereCursor<UnsignedByteType>(img, center, max_radius, calibration); * double r2, theta, phi, term; double cosphi, sinphi, costheta, * sintheta; while (sc.hasNext()) { sc.fwd(); r2 = * sc.getDistanceSquared(); phi = sc.getPhi(); theta = sc.getTheta(); * cosphi = Math.cos(phi-phi_r); sinphi = Math.sin(phi-phi_r); costheta * = Math.cos(theta-theta_r); sintheta = Math.sin(theta-theta_r); term = * r2*cosphi*cosphi*sintheta*sintheta/a/a + * r2*sinphi*sinphi*sintheta*sintheta/b/b + r2*costheta*costheta/c/c; if * (term <= 1) sc.getType().set(on); } sc.close(); long end = * System.currentTimeMillis(); * System.out.println("Ellipse creation done in " + (end-start) + * " ms."); System.out.println(); * * ij.ImageJ.main(args); img.getDisplay().setMinMax(); * ImageJFunctions.copyToImagePlus(img).show(); * * start = System.currentTimeMillis(); BlobMorphology<UnsignedByteType> * bm = new BlobMorphology<UnsignedByteType>(img, calibration); SpotImp * spot = new SpotImp(center); spot.putFeature(Feature.RADIUS, * max_radius); bm.process(spot); end = System.currentTimeMillis(); * System.out.println("Blob morphology analyzed in " + (end-start) + * " ms."); double phiv, thetav, lv; for (int j = 0; j < 3; j++) { lv = * spot.getFeature(featurelist_sa[j]); phiv = * spot.getFeature(featurelist_phi[j]); thetav = * spot.getFeature(featurelist_theta[j]); * System.out.println(String.format( * "For axis of semi-length %.1f, orientation is phi = %.1f°, theta = %.1f°" * , lv, Math.toDegrees(phiv), Math.toDegrees(thetav))); } * System.out.println(spot.echo()); */ }
/** * Fuses one stack, i.e. all angles/illuminations for one timepoint and channel * * @param timepoint * @param channel * @return */ public boolean fuseStacksAndGetPSFs( final TimePoint timepoint, final Channel channel, final ImgFactory<FloatType> imgFactory, final int osemIndex, double osemspeedup, WeightType weightType, final HashMap<Channel, ChannelPSF> extractPSFLabels, final long[] psfSize, final HashMap<Channel, ArrayList<Pair<Pair<Angle, Illumination>, String>>> psfFiles, final boolean transformLoadedPSFs) { // TODO: get rid of this hack if (files != null) { weightType = WeightType.LOAD_WEIGHTS; IOFunctions.println("WARNING: LOADING WEIGHTS FROM IMAGES, files.length()=" + files.length); } // get all views that are fused for this timepoint & channel this.viewDescriptions = FusionHelper.assembleInputData(spimData, timepoint, channel, viewIdsToProcess); if (this.viewDescriptions.size() == 0) return false; this.imgs = new HashMap<ViewId, RandomAccessibleInterval<FloatType>>(); this.weights = new HashMap<ViewId, RandomAccessibleInterval<FloatType>>(); final Img<FloatType> overlapImg; if (weightType == WeightType.WEIGHTS_ONLY) overlapImg = imgFactory.create(bb.getDimensions(), new FloatType()); else overlapImg = null; final boolean extractPSFs = (extractPSFLabels != null) && (extractPSFLabels.get(channel).getLabel() != null); final boolean loadPSFs = (psfFiles != null); if (extractPSFs) ePSF = new ExtractPSF<FloatType>(); else if (loadPSFs) ePSF = loadPSFs(channel, viewDescriptions, psfFiles, transformLoadedPSFs); else { ePSF = assignOtherChannel(channel, extractPSFLabels); } if (ePSF == null) return false; // remember the extracted or loaded PSFs extractPSFLabels.get(channel).setExtractPSFInstance(ePSF); // we will need to run some batches until all is fused for (int i = 0; i < viewDescriptions.size(); ++i) { final ViewDescription vd = viewDescriptions.get(i); IOFunctions.println( "Transforming view " + i + " of " + (viewDescriptions.size() - 1) + " (viewsetup=" + vd.getViewSetupId() + ", tp=" + vd.getTimePointId() + ")"); IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Reserving memory for transformed & weight image."); // creating the output RandomAccessibleInterval<FloatType> transformedImg; // might be null if WEIGHTS_ONLY final RandomAccessibleInterval<FloatType> weightImg; // never null (except LOAD_WEIGHTS which is not implemented yet) if (weightType == WeightType.WEIGHTS_ONLY) transformedImg = overlapImg; else transformedImg = imgFactory.create(bb.getDimensions(), new FloatType()); IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Transformed image factory: " + imgFactory.getClass().getSimpleName()); // loading the input if necessary final RandomAccessibleInterval<FloatType> img; if (weightType == WeightType.WEIGHTS_ONLY && !extractPSFs) { img = null; } else { IOFunctions.println("(" + new Date(System.currentTimeMillis()) + "): Loading image."); img = ProcessFusion.getImage(new FloatType(), spimData, vd, true); if (Img.class.isInstance(img)) IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Input image factory: " + ((Img<FloatType>) img).factory().getClass().getSimpleName()); } // initializing weights IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Initializing transformation & weights: " + weightType.name()); spimData.getViewRegistrations().getViewRegistration(vd).updateModel(); final AffineTransform3D transform = spimData.getViewRegistrations().getViewRegistration(vd).getModel(); final long[] offset = new long[] {bb.min(0), bb.min(1), bb.min(2)}; if (weightType == WeightType.PRECOMPUTED_WEIGHTS || weightType == WeightType.WEIGHTS_ONLY) weightImg = imgFactory.create(bb.getDimensions(), new FloatType()); else if (weightType == WeightType.NO_WEIGHTS) weightImg = Views.interval( new ConstantRandomAccessible<FloatType>( new FloatType(1), transformedImg.numDimensions()), transformedImg); else if (weightType == WeightType.VIRTUAL_WEIGHTS) { final Blending blending = getBlending(img, blendingBorder, blendingRange, vd); weightImg = new TransformedRealRandomAccessibleInterval<FloatType>( blending, new FloatType(), transformedImg, transform, offset); } else // if ( processType == ProcessType.LOAD_WEIGHTS ) { IOFunctions.println("WARNING: LOADING WEIGHTS FROM: '" + new File(files[i]) + "'"); ImagePlus imp = StackImgLoaderIJ.open(new File(files[i])); weightImg = imgFactory.create(bb.getDimensions(), new FloatType()); StackImgLoaderIJ.imagePlus2ImgLib2Img(imp, (Img<FloatType>) weightImg, false); imp.close(); if (debugImport) { imp = ImageJFunctions.show(weightImg); imp.setTitle("ViewSetup " + vd.getViewSetupId() + " Timepoint " + vd.getTimePointId()); } } // split up into many parts for multithreading final Vector<ImagePortion> portions = FusionHelper.divideIntoPortions( Views.iterable(transformedImg).size(), Threads.numThreads() * 4); // set up executor service final ExecutorService taskExecutor = Executors.newFixedThreadPool(Threads.numThreads()); final ArrayList<Callable<String>> tasks = new ArrayList<Callable<String>>(); IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Transforming image & computing weights."); for (final ImagePortion portion : portions) { if (weightType == WeightType.WEIGHTS_ONLY) { final Interval imgInterval = new FinalInterval( ViewSetupUtils.getSizeOrLoad( vd.getViewSetup(), vd.getTimePoint(), spimData.getSequenceDescription().getImgLoader())); final Blending blending = getBlending(imgInterval, blendingBorder, blendingRange, vd); tasks.add( new TransformWeights( portion, imgInterval, blending, transform, overlapImg, weightImg, offset)); } else if (weightType == WeightType.PRECOMPUTED_WEIGHTS) { final Blending blending = getBlending(img, blendingBorder, blendingRange, vd); tasks.add( new TransformInputAndWeights( portion, img, blending, transform, transformedImg, weightImg, offset)); } else if (weightType == WeightType.NO_WEIGHTS || weightType == WeightType.VIRTUAL_WEIGHTS || weightType == WeightType.LOAD_WEIGHTS) { tasks.add(new TransformInput(portion, img, transform, transformedImg, offset)); } else { throw new RuntimeException(weightType.name() + " not implemented yet."); } } try { // invokeAll() returns when all tasks are complete taskExecutor.invokeAll(tasks); } catch (final InterruptedException e) { IOFunctions.println("Failed to compute fusion: " + e); e.printStackTrace(); return false; } taskExecutor.shutdown(); // extract PSFs if wanted if (extractPSFs) { final ArrayList<double[]> llist = getLocationsOfCorrespondingBeads( timepoint, vd, extractPSFLabels.get(channel).getLabel()); IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Extracting PSF for viewsetup " + vd.getViewSetupId() + " using label '" + extractPSFLabels.get(channel).getLabel() + "'" + " (" + llist.size() + " corresponding detections available)"); ePSF.extractNextImg(img, vd, transform, llist, psfSize); } if (weightType != WeightType.WEIGHTS_ONLY) imgs.put(vd, transformedImg); weights.put(vd, weightImg); } // normalize the weights final ArrayList<RandomAccessibleInterval<FloatType>> weightsSorted = new ArrayList<RandomAccessibleInterval<FloatType>>(); for (final ViewDescription vd : viewDescriptions) weightsSorted.add(weights.get(vd)); IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Computing weight normalization for deconvolution."); final WeightNormalizer wn; if (weightType == WeightType.WEIGHTS_ONLY || weightType == WeightType.PRECOMPUTED_WEIGHTS || weightType == WeightType.LOAD_WEIGHTS) wn = new WeightNormalizer(weightsSorted); else if (weightType == WeightType.VIRTUAL_WEIGHTS) wn = new WeightNormalizer(weightsSorted, imgFactory); else // if ( processType == ProcessType.NO_WEIGHTS ) wn = null; if (wn != null && !wn.process()) return false; // put the potentially modified weights back for (int i = 0; i < viewDescriptions.size(); ++i) weights.put(viewDescriptions.get(i), weightsSorted.get(i)); this.minOverlappingViews = wn.getMinOverlappingViews(); this.avgOverlappingViews = wn.getAvgOverlappingViews(); IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Minimal number of overlapping views: " + getMinOverlappingViews() + ", using " + (this.minOverlappingViews = Math.max(1, this.minOverlappingViews))); IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Average number of overlapping views: " + getAvgOverlappingViews() + ", using " + (this.avgOverlappingViews = Math.max(1, this.avgOverlappingViews))); if (osemIndex == 1) osemspeedup = getMinOverlappingViews(); else if (osemIndex == 2) osemspeedup = getAvgOverlappingViews(); IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Adjusting for OSEM speedup = " + osemspeedup); if (weightType == WeightType.WEIGHTS_ONLY) displayWeights(osemspeedup, weightsSorted, overlapImg, imgFactory); else adjustForOSEM(weights, weightType, osemspeedup); IOFunctions.println( "(" + new Date(System.currentTimeMillis()) + "): Finished precomputations for deconvolution."); return true; }
/** Saves image using imageJ */ public void saveImage(final String file) { ImagePlus ips = ImageJFunctions.show(getImage()); FileSaver fs = new FileSaver(ips); fs.saveAsTiff(file); }
/** Shows image using fiji */ public void showImage(final String title) { ImageJFunctions.show(getImage()).setTitle(title); }