예제 #1
0
  /**
   * Saito-Toriwaki algorithm for Euclidian Distance Transformation. Direct application of Algorithm
   * 1. Bob Dougherty 8/8/2006
   *
   * <ul>
   *   <li>Version S1A: lower memory usage.
   *   <li>Version S1A.1 A fixed indexing bug for 666-bin data set
   *   <li>Version S1A.2 Aug. 9, 2006. Changed noResult value.
   *   <li>Version S1B Aug. 9, 2006. Faster.
   *   <li>Version S1B.1 Sept. 6, 2006. Changed comments.
   *   <li>Version S1C Oct. 1, 2006. Option for inverse case. <br>
   *       Fixed inverse behavior in y and z directions.
   *   <li>Version D July 30, 2007. Multithread processing for step 2.
   * </ul>
   *
   * <p>This version assumes the input stack is already in memory, 8-bit, and outputs to a new
   * 32-bit stack. Versions that are more stingy with memory may be forthcoming.
   *
   * @param imp 8-bit (binary) ImagePlus
   */
  private float[][] geometryToDistanceMap(ImagePlus imp, boolean inv) {
    final int w = imp.getWidth();
    final int h = imp.getHeight();
    final int d = imp.getStackSize();
    int nThreads = Runtime.getRuntime().availableProcessors();

    // Create references to input data
    ImageStack stack = imp.getStack();
    byte[][] data = new byte[d][];
    for (int k = 0; k < d; k++) data[k] = (byte[]) stack.getPixels(k + 1);

    // Create 32 bit floating point stack for output, s. Will also use it
    // for g in Transformation 1.
    float[][] s = new float[d][];
    for (int k = 0; k < d; k++) {
      ImageProcessor ipk = new FloatProcessor(w, h);
      s[k] = (float[]) ipk.getPixels();
    }
    float[] sk;
    // Transformation 1. Use s to store g.
    IJ.showStatus("EDT transformation 1/3");
    Step1Thread[] s1t = new Step1Thread[nThreads];
    for (int thread = 0; thread < nThreads; thread++) {
      s1t[thread] = new Step1Thread(thread, nThreads, w, h, d, inv, s, data);
      s1t[thread].start();
    }
    try {
      for (int thread = 0; thread < nThreads; thread++) {
        s1t[thread].join();
      }
    } catch (InterruptedException ie) {
      IJ.error("A thread was interrupted in step 1 .");
    }
    // Transformation 2. g (in s) -> h (in s)
    IJ.showStatus("EDT transformation 2/3");
    Step2Thread[] s2t = new Step2Thread[nThreads];
    for (int thread = 0; thread < nThreads; thread++) {
      s2t[thread] = new Step2Thread(thread, nThreads, w, h, d, s);
      s2t[thread].start();
    }
    try {
      for (int thread = 0; thread < nThreads; thread++) {
        s2t[thread].join();
      }
    } catch (InterruptedException ie) {
      IJ.error("A thread was interrupted in step 2 .");
    }
    // Transformation 3. h (in s) -> s
    IJ.showStatus("EDT transformation 3/3");
    Step3Thread[] s3t = new Step3Thread[nThreads];
    for (int thread = 0; thread < nThreads; thread++) {
      s3t[thread] = new Step3Thread(thread, nThreads, w, h, d, inv, s, data);
      s3t[thread].start();
    }
    try {
      for (int thread = 0; thread < nThreads; thread++) {
        s3t[thread].join();
      }
    } catch (InterruptedException ie) {
      IJ.error("A thread was interrupted in step 3 .");
    }
    // Find the largest distance for scaling
    // Also fill in the background values.
    float distMax = 0;
    final int wh = w * h;
    float dist;
    for (int k = 0; k < d; k++) {
      sk = s[k];
      for (int ind = 0; ind < wh; ind++) {
        if (((data[k][ind] & 255) < 128) ^ inv) {
          sk[ind] = 0;
        } else {
          dist = (float) Math.sqrt(sk[ind]);
          sk[ind] = dist;
          distMax = (dist > distMax) ? dist : distMax;
        }
      }
    }
    IJ.showProgress(1.0);
    IJ.showStatus("Done");
    return s;
  }
예제 #2
0
  /**
   * DistanceRidgetoLocalThickness
   *
   * <p>Input: Distance Ridge (32-bit stack) (Output from Distance Ridge.java) Output: Local
   * Thickness. Overwrites the input.
   *
   * <ul>
   *   <li>Version 1: September 6, 2006.
   *   <li>Version 2: September 25, 2006. Fixed several bugs that resulted in non-symmetrical output
   *       from symmetrical input.
   *   <li>Version 2.1 Oct. 1, 2006. Fixed a rounding error that caused some points to be missed.
   *   <li>Version 3 July 31, 2007. Parallel processing version.
   *   <li>Version 3.1 Multiplies the output by 2 to conform with the definition of local thickness
   * </ul>
   *
   * @param imp
   */
  private void distanceRidgetoLocalThickness(ImagePlus imp, float[][] s) {
    final int w = imp.getWidth();
    final int h = imp.getHeight();
    final int d = imp.getStackSize();
    float[] sk;
    // Count the distance ridge points on each slice
    int[] nRidge = new int[d];
    int ind, nr, iR;
    IJ.showStatus("Local Thickness: scanning stack ");
    for (int k = 0; k < d; k++) {
      sk = s[k];
      nr = 0;
      for (int j = 0; j < h; j++) {
        final int wj = w * j;
        for (int i = 0; i < w; i++) {
          ind = i + wj;
          if (sk[ind] > 0) nr++;
        }
      }
      nRidge[k] = nr;
    }
    int[][] iRidge = new int[d][];
    int[][] jRidge = new int[d][];
    float[][] rRidge = new float[d][];
    // Pull out the distance ridge points
    int[] iRidgeK, jRidgeK;
    float[] rRidgeK;
    float sMax = 0;
    for (int k = 0; k < d; k++) {
      nr = nRidge[k];
      iRidge[k] = new int[nr];
      jRidge[k] = new int[nr];
      rRidge[k] = new float[nr];
      sk = s[k];
      iRidgeK = iRidge[k];
      jRidgeK = jRidge[k];
      rRidgeK = rRidge[k];
      iR = 0;
      for (int j = 0; j < h; j++) {
        final int wj = w * j;
        for (int i = 0; i < w; i++) {
          ind = i + wj;
          if (sk[ind] > 0) {;
            iRidgeK[iR] = i;
            jRidgeK[iR] = j;
            rRidgeK[iR++] = sk[ind];
            if (sk[ind] > sMax) sMax = sk[ind];
            sk[ind] = 0;
          }
        }
      }
    }
    int nThreads = Runtime.getRuntime().availableProcessors();
    final Object[] resources = new Object[d]; // For synchronization
    for (int k = 0; k < d; k++) {
      resources[k] = new Object();
    }
    LTThread[] ltt = new LTThread[nThreads];
    for (int thread = 0; thread < nThreads; thread++) {
      ltt[thread] =
          new LTThread(thread, nThreads, w, h, d, nRidge, s, iRidge, jRidge, rRidge, resources);
      ltt[thread].start();
    }
    try {
      for (int thread = 0; thread < nThreads; thread++) {
        ltt[thread].join();
      }
    } catch (InterruptedException ie) {
      IJ.error("A thread was interrupted .");
    }

    // Fix the square values and apply factor of 2
    IJ.showStatus("Local Thickness: square root ");
    for (int k = 0; k < d; k++) {
      sk = s[k];
      for (int j = 0; j < h; j++) {
        final int wj = w * j;
        for (int i = 0; i < w; i++) {
          ind = i + wj;
          sk[ind] = (float) (2 * Math.sqrt(sk[ind]));
        }
      }
    }
    IJ.showStatus("Local Thickness complete");
    return;
  }
 /**
  * Create a Thread[] array as large as the number of processors available. From Stephan
  * Preibisch's Multithreading.java class. See:
  * http://repo.or.cz/w/trakem2.git?a=blob;f=mpi/fruitfly/general/MultiThreading.java;hb=HEAD
  */
 private Thread[] newThreadArray() {
   int n_cpus = Runtime.getRuntime().availableProcessors();
   return new Thread[n_cpus];
 }