package ie.dcu.segment.util; import ie.dcu.array.Arrays; import ie.dcu.image.binary.MorphOp; import ie.dcu.matrix.*; import ie.dcu.segment.*; import ie.dcu.segment.annotate.Annotation; import ie.dcu.segment.options.Option; import java.util.*; import java.util.logging.*; /** * Abstract implementation of a {@link Segmenter} object. * * @author Kevin McGuinness */ public abstract class AbstractSegmenter implements Segmenter { /** * Segmenter options map. */ private final Map> options; /** * Logger for subclass messages. */ protected final Logger log; /** * Name of the segmentation algorithm. Should be set by subclass during * construction. */ protected String name; /** * Description of the segmentation algorithm. Should be set by subclass * during construction. */ protected String description; /** * Vendor of the segmentation algorithm. Should be set by subclass * during construction. This should be either the author of the * segmentation algorithm, or a company or institution name. */ protected String vendor; /** * Default return value for the {@link #isFast()} method, * false by default. */ protected boolean fast; /** * Flag that indicates if the segmentation algorithm is available on the * current platform. Defaults to true. */ protected boolean available; /** * Constructor. */ public AbstractSegmenter() { options = new LinkedHashMap>(); log = Logger.getLogger(getClass().getSimpleName()); name = ""; description = ""; vendor = ""; available = true; } /** * Default implementation returns the {@link #available} field. */ public boolean isAvailable() { return available; } /** * Default implementation returns the {@link #name} field. */ public String getName() { return name; } /** * Default implementation returns the {@link #description} field. */ public String getDescription() { return description; } /** * Default implementation returns the {@link #vendor} field. */ public String getVendor() { return vendor; } /** * Default implementation returns the {@link #options} map. */ public Collection> getOptions() { return Collections.unmodifiableCollection(options.values()); } /** * Default implementation returns the {@link #fast} field. */ public boolean isFast() { return fast; } /** * Default implementation calls {@link #segment(SegmentationContext)}. */ public void added(SegmentationContext ctx, Annotation a) { segment(ctx); } /** * Default implementation calls {@link #segment(SegmentationContext)}. */ public void removed(SegmentationContext ctx, Annotation a) { segment(ctx); } /** * Default implementation calls {@link #segment(SegmentationContext)}. */ public void update(SegmentationContext ctx) { segment(ctx); } /** * Perform a full update of the segmentation. * * @param ctx * The segmentation context. */ protected abstract void segment(SegmentationContext ctx); /** * Add an option (parameter) to the {@link #options} map. * * @param option * The option */ protected void add(Option option) { options.put(option.getName(), option); } /** * Get an option (parameter) from the {@link #options} map. * * @param * The option type. * @param clazz * The option class. * @param option * The option name. * @return The option. */ protected T get(Class clazz, String option) { Option opt = options.get(option); return clazz.cast(opt.getValue()); } /** * Perform a morphological smooth on the contour of the given segmentation * mask. * * @param mask * A segmentation mask. */ protected void smoothContour(SegmentationMask mask) { // TODO: Maybe optimize this? The old MorphOps.smooth might be faster MorphOp op = new MorphOp.Smooth(); op.setForegroundValue(SegmentationMask.FOREGROUND); op.setBackgroundValue(SegmentationMask.BACKGROUND); op.setInputProvider(mask); ByteMatrix matrix = (ByteMatrix) op.getMatrix(Matrix.Type.Byte, false); Arrays.copy(matrix.values, mask.values); } /** * Copy the non-zero markup pixels to the segmentation mask. * * @param mask * The segmentation mask. * @param markup * The rasterized markup pixels. */ protected void retainMarkup(SegmentationMask mask, byte[] markup) { for (int i = 0; i < markup.length; i++) { if (markup[i] != 0) { mask.values[i] = markup[i]; } } } }