/** * TODO * * @param cumulativeMinCutoff * @param cumulativeMaxCutoff * @param state * @param setupAssignments */ public static void initBrightness( final double cumulativeMinCutoff, final double cumulativeMaxCutoff, final ViewerState state, final SetupAssignments setupAssignments) { final Source<?> source = state.getSources().get(state.getCurrentSource()).getSpimSource(); final int timepoint = state.getCurrentTimepoint(); if (!source.isPresent(timepoint)) return; if (!UnsignedShortType.class.isInstance(source.getType())) return; @SuppressWarnings("unchecked") final RandomAccessibleInterval<UnsignedShortType> img = (RandomAccessibleInterval<UnsignedShortType>) source.getSource(timepoint, source.getNumMipmapLevels() - 1); final long z = (img.min(2) + img.max(2) + 1) / 2; final int numBins = 6535; final Histogram1d<UnsignedShortType> histogram = new Histogram1d<UnsignedShortType>( Views.iterable(Views.hyperSlice(img, 2, z)), new Real1dBinMapper<UnsignedShortType>(0, 65535, numBins, false)); final DiscreteFrequencyDistribution dfd = histogram.dfd(); final long[] bin = new long[] {0}; double cumulative = 0; int i = 0; for (; i < numBins && cumulative < cumulativeMinCutoff; ++i) { bin[0] = i; cumulative += dfd.relativeFrequency(bin); } final int min = i * 65535 / numBins; for (; i < numBins && cumulative < cumulativeMaxCutoff; ++i) { bin[0] = i; cumulative += dfd.relativeFrequency(bin); } final int max = i * 65535 / numBins; final MinMaxGroup minmax = setupAssignments.getMinMaxGroups().get(0); minmax.getMinBoundedValue().setCurrentValue(min); minmax.getMaxBoundedValue().setCurrentValue(max); }
@Override public long computeBin(final Histogram1d<T> hist) { long[] histogram = hist.toLongArray(); // Otsu's threshold algorithm // C++ code by Jordan Bevik <*****@*****.**> // ported to ImageJ plugin by G.Landini int k, kStar; // k = the current threshold; kStar = optimal threshold int L = histogram.length; // The total intensity of the image long N1, N; // N1 = # points with intensity <=k; N = total number of // points long Sk; // The total intensity for all histogram points <=k long S; double BCV, BCVmax; // The current Between Class Variance and maximum // BCV double num, denom; // temporary bookkeeping // Initialize values: S = 0; N = 0; for (k = 0; k < L; k++) { S += k * histogram[k]; // Total histogram intensity N += histogram[k]; // Total number of data points } Sk = 0; N1 = histogram[0]; // The entry for zero intensity BCV = 0; BCVmax = 0; kStar = 0; // Look at each possible threshold value, // calculate the between-class variance, and decide if it's a max for (k = 1; k < L - 1; k++) { // No need to check endpoints k = 0 or k = // L-1 Sk += k * histogram[k]; N1 += histogram[k]; // The float casting here is to avoid compiler warning about loss of // precision and // will prevent overflow in the case of large saturated images denom = (double) (N1) * (N - N1); // Maximum value of denom is // (N^2)/4 = // approx. 3E10 if (denom != 0) { // Float here is to avoid loss of precision when dividing num = ((double) N1 / N) * S - Sk; // Maximum value of num = // 255*N = // approx 8E7 BCV = (num * num) / denom; } else BCV = 0; if (BCV >= BCVmax) { // Assign the best threshold found so far BCVmax = BCV; kStar = k; } } // kStar += 1; // Use QTI convention that intensity -> 1 if intensity >= // k // (the algorithm was developed for I-> 1 if I <= k.) return kStar; }