Example #1
0
  private boolean processSlice(
      final RandomAccessibleInterval<FloatType> src,
      final RandomAccessibleInterval<FloatType> dx,
      final RandomAccessibleInterval<FloatType> dy) {
    // Gaussian filter.
    final ExtendedRandomAccessibleInterval<FloatType, RandomAccessibleInterval<FloatType>>
        extended = Views.extendMirrorSingle(src);
    try {
      Gauss3.gauss(new double[] {sigma, sigma}, extended, src, numThreads);
    } catch (final IncompatibleTypeException e) {
      errorMessage = BASE_ERROR_MSG + "Incompatible types: " + e.getMessage();
      e.printStackTrace();
      return false;
    }

    // Derivatives
    PartialDerivative.gradientCentralDifference(extended, dx, 0);
    PartialDerivative.gradientCentralDifference(extended, dy, 1);

    return true;
  }
  @Override
  public boolean process() {

    /* 0. Instantiate tensor holder, and initialize cursors. */
    long[] tensorDims = new long[input.numDimensions() + 1];
    for (int i = 0; i < input.numDimensions(); i++) {
      tensorDims[i] = input.dimension(i);
    }
    tensorDims[input.numDimensions()] = 3;
    try {
      D = input.factory().imgFactory(new FloatType()).create(tensorDims, new FloatType());
    } catch (IncompatibleTypeException e) {
      errorMessage = BASE_ERROR_MESSAGE + "Failed to create tensor holder:\n" + e.getMessage();
      return false;
    }

    /* 1. Create a smoothed version of the input. */
    Img<FloatType> smoothed = Gauss.toFloat(new double[] {sigma, sigma}, input);

    /* 2. Compute the gradient of the smoothed input, but only algon X & Y */
    boolean[] doDimension = new boolean[input.numDimensions()];
    doDimension[0] = true;
    doDimension[1] = true;
    Gradient<FloatType> gradientCalculator = new Gradient<FloatType>(smoothed, doDimension);
    gradientCalculator.process();
    final Img<FloatType> gradient = gradientCalculator.getResult();

    /* 3. Compute the structure tensor. */

    final Img<FloatType> J = D.factory().create(D, new FloatType());
    final int newDim = input.numDimensions();

    final Vector<Chunk> chunks = SimpleMultiThreading.divideIntoChunks(input.size(), numThreads);
    Thread[] threads = SimpleMultiThreading.newThreads(numThreads);

    for (int i = 0; i < threads.length; i++) {

      final Chunk chunk = chunks.get(i);
      threads[i] =
          new Thread("" + BASE_ERROR_MESSAGE + "thread " + i) {

            @Override
            public void run() {

              float ux, uy;
              Cursor<T> cursor = input.localizingCursor();
              RandomAccess<FloatType> grad_ra = gradient.randomAccess();
              RandomAccess<FloatType> J_ra = J.randomAccess();

              cursor.jumpFwd(chunk.getStartPosition());
              for (long k = 0; k < chunk.getLoopSize(); k++) {

                cursor.fwd();
                for (int i = 0; i < input.numDimensions(); i++) {
                  grad_ra.setPosition(cursor.getLongPosition(i), i);
                  J_ra.setPosition(cursor.getLongPosition(i), i);
                }

                grad_ra.setPosition(0, newDim);
                ux = grad_ra.get().get();
                grad_ra.fwd(newDim);
                uy = grad_ra.get().get();

                J_ra.setPosition(0, newDim);
                J_ra.get().set(ux * ux);
                J_ra.fwd(newDim);
                J_ra.get().set(ux * uy);
                J_ra.fwd(newDim);
                J_ra.get().set(uy * uy);
              }
            }
          };
    }

    SimpleMultiThreading.startAndJoin(threads);

    /* 3.5 Smoooth the structure tensor. */

    Gauss.inFloat(new double[] {rho, rho, 0}, J);

    /* 4. Construct Diffusion tensor. */

    for (int i = 0; i < threads.length; i++) {

      final Chunk chunk = chunks.get(i);
      threads[i] =
          new Thread("" + BASE_ERROR_MESSAGE + "thread " + i) {

            @Override
            public void run() {

              Cursor<T> cursor = input.localizingCursor();
              RandomAccess<FloatType> J_ra = J.randomAccess();
              RandomAccess<FloatType> D_ra = D.randomAccess();

              float Jxx, Jxy, Jyy;
              double tmp, v1x, v1y, v2x, v2y, mag, mu1, mu2, lambda1, lambda2, di;
              double newLambda1, newLambda2, Dxx, Dxy, Dyy;
              double scale;

              cursor.jumpFwd(chunk.getStartPosition());
              for (long k = 0; k < chunk.getLoopSize(); k++) {

                cursor.fwd();

                for (int j = 0; j < input.numDimensions(); j++) {
                  D_ra.setPosition(cursor.getLongPosition(j), j);
                  J_ra.setPosition(cursor.getLongPosition(j), j);
                }

                // Compute eigenvalues

                J_ra.setPosition(0, newDim);
                Jxx = J_ra.get().get();
                J_ra.fwd(newDim);
                Jxy = J_ra.get().get();
                J_ra.fwd(newDim);
                Jyy = J_ra.get().get();

                tmp = Math.sqrt((Jxx - Jyy) * (Jxx - Jyy) + 4 * Jxy * Jxy);
                v2x = 2 * Jxy;
                v2y = Jyy - Jxx + tmp;

                mag = Math.sqrt(v2x * v2x + v2y * v2y);
                v2x /= mag;
                v2y /= mag;

                v1x = -v2y;
                v1y = v2x;

                mu1 = 0.5 * (Jxx + Jyy + tmp);
                mu2 = 0.5 * (Jxx + Jyy - tmp);

                // Large one in abs values must be the 2nd
                if (Math.abs(mu2) > Math.abs(mu1)) {

                  lambda1 = mu1;
                  lambda2 = mu2;

                } else {

                  lambda1 = mu2;
                  lambda2 = mu1;
                }

                di = lambda2 - lambda1;
                scale = Util.pow(di * di, m);
                newLambda1 = alpha + (1 - alpha) * Math.exp(-C / scale);
                newLambda2 = alpha;

                Dxx = newLambda1 * v1x * v1x + newLambda2 * v2x * v2x;
                Dxy = newLambda1 * v1x * v1y + newLambda2 * v2x * v2x;
                Dyy = newLambda1 * v1y * v1y + newLambda2 * v2y * v2y;

                D_ra.setPosition(0, 2);
                D_ra.get().setReal(Dxx);
                D_ra.fwd(2);
                D_ra.get().setReal(Dxy);
                D_ra.fwd(2);
                D_ra.get().setReal(Dyy);
              }
            }
          };
    }

    SimpleMultiThreading.startAndJoin(threads);

    return true;
  }