/** Splits the specified image into separate channels. */
 public static ImagePlus[] split(ImagePlus imp) {
   if (imp.getType() == ImagePlus.COLOR_RGB) {
     ImageStack[] stacks = splitRGB(imp.getStack(), true);
     ImagePlus[] images = new ImagePlus[3];
     images[0] = new ImagePlus("red", stacks[0]);
     images[1] = new ImagePlus("green", stacks[1]);
     images[2] = new ImagePlus("blue", stacks[2]);
     return images;
   }
   int width = imp.getWidth();
   int height = imp.getHeight();
   int channels = imp.getNChannels();
   int slices = imp.getNSlices();
   int frames = imp.getNFrames();
   int bitDepth = imp.getBitDepth();
   int size = slices * frames;
   Vector images = new Vector();
   HyperStackReducer reducer = new HyperStackReducer(imp);
   for (int c = 1; c <= channels; c++) {
     ImageStack stack2 = new ImageStack(width, height, size); // create empty stack
     stack2.setPixels(
         imp.getProcessor().getPixels(), 1); // can't create ImagePlus will null 1st image
     ImagePlus imp2 = new ImagePlus("C" + c + "-" + imp.getTitle(), stack2);
     stack2.setPixels(null, 1);
     imp.setPosition(c, 1, 1);
     imp2.setDimensions(1, slices, frames);
     imp2.setCalibration(imp.getCalibration());
     reducer.reduce(imp2);
     if (imp.isComposite() && ((CompositeImage) imp).getMode() == IJ.GRAYSCALE)
       IJ.run(imp2, "Grays", "");
     if (imp2.getNDimensions() > 3) imp2.setOpenAsHyperStack(true);
     images.add(imp2);
   }
   ImagePlus[] array = new ImagePlus[images.size()];
   return (ImagePlus[]) images.toArray(array);
 }
Example #2
0
  /** Called by the PlugInFilterRunner to process the image or one frame of a stack */
  public void run(ImageProcessor ip) {
    if (interrupted) return;
    int width = ip.getWidth();
    int height = ip.getHeight();

    int backgroundValue =
        (processType == VORONOI)
            ? (background255 ? 0 : (byte) 255)
            : // Voronoi needs EDM of the background
            (background255 ? (byte) 255 : 0); // all others do EDM of the foreground
    if (USES_WATERSHED[processType]) nPasses = 0; // watershed has its own progress bar
    FloatProcessor floatEdm = makeFloatEDM(ip, backgroundValue, false);

    ByteProcessor maxIp = null;
    if (USES_MAX_FINDER[processType]) {
      if (processType == VORONOI) floatEdm.multiply(-1); // Voronoi starts from minima of EDM
      int maxOutputType =
          USES_WATERSHED[processType] ? MaximumFinder.SEGMENTED : MaximumFinder.SINGLE_POINTS;
      boolean isEDM = processType != VORONOI;
      maxIp =
          maxFinder.findMaxima(
              floatEdm,
              MAXFINDER_TOLERANCE,
              ImageProcessor.NO_THRESHOLD,
              maxOutputType,
              false,
              isEDM);
      if (maxIp == null) { // segmentation cancelled by user?
        interrupted = true;
        return;
      } else if (processType != WATERSHED) {
        if (processType == VORONOI) floatEdm.multiply(-1);
        resetMasked(floatEdm, maxIp, processType == VORONOI ? -1 : 0);
      }
    }

    ImageProcessor outIp = null;
    if (processType == WATERSHED) {
      if (background255) maxIp.invert();
      ip.copyBits(maxIp, 0, 0, Blitter.COPY);
      ip.setBinaryThreshold();
    } else
      switch (outImageType) { // for all these, output contains the values of the EDM
        case FLOAT:
          outIp = floatEdm;
          break;
        case SHORT:
          floatEdm.setMinAndMax(0., 65535.);
          outIp = floatEdm.convertToShort(true);
          break;
        case BYTE:
          floatEdm.setMinAndMax(0., 255.);
          outIp = floatEdm.convertToByte(true);
          break;
        case BYTE_OVERWRITE:
          ip.setPixels(0, floatEdm);
          if (floatEdm.getMax() > 255.) ip.resetMinAndMax(); // otherwise we have max of floatEdm
      }

    if (outImageType != BYTE_OVERWRITE) { // new output image
      if (outStack == null) {
        outImp = new ImagePlus(TITLE_PREFIX[processType] + imp.getShortTitle(), outIp);
      } else outStack.setPixels(outIp.getPixels(), pfr.getSliceNumber());
    }
  } // public void run
  public void Calc_5Fr(ImagePlus imp1, ImagePlus imp2) {
    if (imp1.getType() != imp2.getType()) {
      error();
      return;
    }
    if (imp1.getType() == 0) { // getType returns 0 for 8-bit, 1 for 16-bit
      bitDepth = "8-bit";
      Prefs.set("ps.bitDepth", bitDepth);
    } else {
      bitDepth = "16-bit";
      Prefs.set("ps.bitDepth", bitDepth);
    }
    int width = imp1.getWidth();
    int height = imp1.getHeight();
    if (width != imp2.getWidth() || height != imp2.getHeight()) {
      error();
      return;
    }

    ImageStack stack1 = imp1.getStack();
    //		if (bgStackTitle != "NoBg") ImageStack stack2 = imp2.getStack();
    ImageStack stack2 = imp2.getStack();

    ImageProcessor ip = imp1.getProcessor();
    int dimension = width * height;
    byte[] pixB;
    short[] pixS;
    float[][] pixF = new float[5][dimension];
    float[][] pixFBg = new float[5][dimension];

    float a;
    float b;
    float den;
    float aSmp;
    float bSmp;
    float denSmp;
    float aBg;
    float bBg;
    float denBg;
    float retF;
    float azimF;

    byte[] retB = new byte[dimension];
    short[] retS = new short[dimension];
    byte[] azimB = new byte[dimension];
    short[] azimS = new short[dimension];
    // Derived Variables:
    float swingAngle = 2f * (float) Math.PI * swing;
    float tanSwingAngleDiv2 = (float) Math.tan(swingAngle / 2.f);
    float tanSwingAngleDiv2DivSqrt2 = (float) (Math.tan(swingAngle / 2.f) / Math.sqrt(2));
    float wavelengthDiv2Pi = wavelength / (2f * (float) Math.PI);

    // get the pixels of each slice in the stack and convert to float
    for (int i = 0; i < 5; i++) {
      if (bitDepth == "8-bit") {
        pixB = (byte[]) stack1.getPixels(i + 3);
        for (int j = 0; j < dimension; j++) pixF[i][j] = 0xff & pixB[j];
        if (bgStackTitle != "NoBg") {
          pixB = (byte[]) stack2.getPixels(i + 3);
          for (int j = 0; j < dimension; j++) pixFBg[i][j] = 0xff & pixB[j];
        }
      } else {
        pixS = (short[]) stack1.getPixels(i + 3);
        for (int j = 0; j < dimension; j++) pixF[i][j] = (float) pixS[j];
        if (bgStackTitle != "NoBg") {
          pixS = (short[]) stack2.getPixels(i + 3);
          for (int j = 0; j < dimension; j++) pixFBg[i][j] = (float) pixS[j];
        }
      }
    }

    // Algorithm
    // terms a and b
    for (int j = 0; j < dimension; j++) {
      denSmp = (pixF[1][j] + pixF[2][j] + pixF[3][j] + pixF[4][j] - 4 * pixF[0][j]) / 2;
      denBg = denSmp;
      a = (pixF[4][j] - pixF[1][j]);
      aSmp = a;
      aBg = a;
      b = (pixF[2][j] - pixF[3][j]);
      bSmp = b;
      bBg = b;
      if (bgStackTitle != "NoBg") {
        denBg = (pixFBg[1][j] + pixFBg[2][j] + pixFBg[3][j] + pixFBg[4][j] - 4 * pixFBg[0][j]) / 2;
        aBg = pixFBg[4][j] - pixFBg[1][j];
        bBg = pixFBg[2][j] - pixFBg[3][j];
      }
      // Special case of sample retardance half wave, denSmp = 0
      if (denSmp == 0) {
        retF = (float) wavelength / 4;
        azimF =
            (float) (a == 0 & b == 0 ? 0 : (azimRef + 90 + 90 * Math.atan2(a, b) / Math.PI) % 180);
      } else {
        // Retardance, the background correction can be improved by separately considering sample
        // retardance values larger than a quarter wave
        if (bgStackTitle != "NoBg") {
          a = aSmp / denSmp - aBg / denBg;
          b = bSmp / denSmp - bBg / denBg;
        } else {
          a = aSmp / denSmp;
          b = bSmp / denSmp;
        }
        retF = (float) Math.atan(tanSwingAngleDiv2 * Math.sqrt(a * a + b * b));
        if (denSmp < 0) retF = (float) Math.PI - retF;
        retF = retF * wavelengthDiv2Pi; // convert to nm
        if (retF > retCeiling) retF = retCeiling;

        // Orientation
        if ((bgStackTitle == "NoBg") || ((bgStackTitle != "NoBg") && (Math.abs(denSmp) < 1))) {
          a = aSmp;
          b = bSmp;
        }
        azimF =
            (float) (a == 0 & b == 0 ? 0 : (azimRef + 90 + 90 * Math.atan2(a, b) / Math.PI) % 180);
      }
      if (bitDepth == "8-bit") retB[j] = (byte) (((int) (255 * retF / retCeiling)) & 0xff);
      else retS[j] = (short) (4095 * retF / retCeiling);
      if (mirror == "Yes") azimF = 180 - azimF;
      if (bitDepth == "8-bit") azimB[j] = (byte) (((int) azimF) & 0xff);
      else azimS[j] = (short) (azimF * 10f);
    }
    // show the resulting images in slice 1 and 2
    imp1.setSlice(3);
    if (bitDepth == "8-bit") {
      stack1.setPixels(retB, 1);
      stack1.setPixels(azimB, 2);
    } else {
      stack1.setPixels(retS, 1);
      stack1.setPixels(azimS, 2);
    }
    imp1.setSlice(1);
    IJ.selectWindow(imp1.getTitle());

    Prefs.set("ps.sampleStackTitle", sampleStackTitle);
    Prefs.set("ps.bgStackTitle", bgStackTitle);
    Prefs.set("ps.mirror", mirror);
    Prefs.set("ps.wavelength", wavelength);
    Prefs.set("ps.swing", swing);
    Prefs.set("ps.retCeiling", retCeiling);
    Prefs.set("ps.azimRef", azimRef);
    Prefs.savePreferences();
  }