001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit http://imagingbook.com for additional details. 008 *******************************************************************************/ 009 010package imagingbook.pub.threshold.adaptive; 011 012import ij.plugin.filter.RankFilters; 013import ij.process.ByteProcessor; 014import imagingbook.pub.threshold.BackgroundMode; 015 016/** 017 * This implementation of Bernsen's thresholder uses a circular support region, 018 * implemented with ImageJ's built-in rank-filter methods. 019 */ 020public class BernsenThresholder extends AdaptiveThresholder { 021 022 public static class Parameters { 023 public int radius = 15; 024 public int cmin = 15; 025 public BackgroundMode bgMode = BackgroundMode.DARK; 026 } 027 028 private final Parameters params; 029 030 public BernsenThresholder() { 031 this.params = new Parameters(); 032 } 033 034 public BernsenThresholder(Parameters params) { 035 this.params = params; 036 } 037 038 @Override 039 public ByteProcessor getThreshold(ByteProcessor I) { 040 final int M = I.getWidth(); 041 final int N = I.getHeight(); 042 ByteProcessor Imin = (ByteProcessor) I.duplicate(); 043 ByteProcessor Imax = (ByteProcessor) I.duplicate(); 044 045 RankFilters rf = new RankFilters(); 046 rf.rank(Imin, params.radius, RankFilters.MIN); 047 rf.rank(Imax, params.radius, RankFilters.MAX); 048 049 int q = (params.bgMode == BackgroundMode.DARK) ? 256 : 0; 050 ByteProcessor Q = new ByteProcessor(M, N); 051 052 for (int v = 0; v < N; v++) { 053 for (int u = 0; u < M; u++) { 054 int gMin = Imin.get(u, v); 055 int gMax = Imax.get(u, v); 056 int c = gMax - gMin; 057 if (c >= params.cmin) 058 Q.set(u, v, (gMin + gMax) / 2); 059 else 060 Q.set(u, v, q); 061 } 062 } 063 return Q; 064 } 065 066}