package gdsc.threshold; import gdsc.UsageTracker; /*----------------------------------------------------------------------------- * GDSC Plugins for ImageJ * * Copyright (C) 2011 Alex Herbert * Genome Damage and Stability Centre * University of Sussex, UK * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. *---------------------------------------------------------------------------*/ import gdsc.core.ij.Utils; import gdsc.core.threshold.AutoThreshold; import ij.IJ; import ij.ImagePlus; import ij.ImageStack; import ij.WindowManager; import ij.gui.GenericDialog; import ij.plugin.filter.PlugInFilter; import ij.process.ImageProcessor; import java.util.ArrayList; /** * Create a mask from a source image and apply it to a target image. All pixels outside the mask will be set to zero. * The mask can be created using: an existing mask; thresholding or the minimum display value. The source image for the * mask can be a different image but the dimensions must match. */ public class ApplyMask implements PlugInFilter { private static final String TITLE = "Apply Mask"; private static String selectedImage = ""; private static int selectedOption = MaskCreater.OPTION_MASK; private static String selectedThresholdMethod = AutoThreshold.Method.OTSU.name; private static int selectedChannel = 0; private static int selectedSlice = 0; private static int selectedFrame = 0; private ImagePlus imp; private ImagePlus maskImp; private int option; private String thresholdMethod; private int channel = 0; private int slice = 0; private int frame = 0; /* (non-Javadoc) * @see ij.plugin.filter.PlugInFilter#setup(java.lang.String, ij.ImagePlus) */ public int setup(String arg, ImagePlus imp) { UsageTracker.recordPlugin(this.getClass(), arg); if (imp == null) { IJ.noImage(); return DONE; } this.imp = imp; if (showDialog()) { applyMask(); } return DONE; } /* (non-Javadoc) * @see ij.plugin.filter.PlugInFilter#run(ij.process.ImageProcessor) */ public void run(ImageProcessor ip) { // All process already done } private boolean showDialog() { String sourceImage = "(Use target)"; ArrayList<String> imageList = new ArrayList<String>(); imageList.add(sourceImage); for (int id : Utils.getIDList()) { ImagePlus imp = WindowManager.getImage(id); if (imp != null) { imageList.add(imp.getTitle()); } } GenericDialog gd = new GenericDialog(TITLE); gd.addMessage("Create a mask from a source image and apply it.\nPixels outside the mask will be set to zero."); gd.addChoice("Mask_Image", imageList.toArray(new String[0]), selectedImage); gd.addChoice("Option", MaskCreater.options, MaskCreater.options[selectedOption]); gd.addChoice("Threshold_Method", AutoThreshold.getMethods(), selectedThresholdMethod); gd.addNumericField("Channel", selectedChannel, 0); gd.addNumericField("Slice", selectedSlice, 0); gd.addNumericField("Frame", selectedFrame, 0); gd.addHelp(gdsc.help.URL.UTILITY); gd.showDialog(); if (gd.wasCanceled()) return false; selectedImage = gd.getNextChoice(); selectedOption = gd.getNextChoiceIndex(); selectedThresholdMethod = gd.getNextChoice(); selectedChannel = (int) gd.getNextNumber(); selectedSlice = (int) gd.getNextNumber(); selectedFrame = (int) gd.getNextNumber(); setMaskImp(getImp()); if (!selectedImage.equals(sourceImage)) setMaskImp(WindowManager.getImage(selectedImage)); setOption(selectedOption); setThresholdMethod(selectedThresholdMethod); setChannel(selectedChannel); setSlice(selectedSlice); setFrame(selectedFrame); return true; } public ApplyMask() { init(null, MaskCreater.OPTION_MASK); } public ApplyMask(ImagePlus imp) { init(imp, MaskCreater.OPTION_MASK); } public ApplyMask(ImagePlus imp, int option) { init(imp, option); } private void init(ImagePlus imp, int option) { this.imp = imp; this.option = option; } /** * Create a mask from a source image and apply it to a target image. All pixels outside the mask will be set to zero. */ public void applyMask() { if (imp == null) return; MaskCreater mc = new MaskCreater(); mc.setImp(maskImp); mc.setOption(selectedOption); mc.setThresholdMethod(selectedThresholdMethod); mc.setChannel(selectedChannel); mc.setSlice(selectedSlice); mc.setFrame(selectedFrame); maskImp = mc.createMask(); // Check the mask has the correct dimensions if (maskImp == null) { IJ.error(TITLE, "No mask calculated"); return; } if (imp.getWidth() != maskImp.getWidth() || imp.getHeight() != maskImp.getHeight()) { IJ.error(TITLE, "Calculated mask does not match the target image dimensions"); return; } // Apply the mask to the correct stack dimensions int[] dimensions = imp.getDimensions(); int[] channels = createArray(dimensions[2]); int[] slices = createArray(dimensions[3]); int[] frames = createArray(dimensions[4]); ImageStack imageStack = imp.getStack(); ImageStack maskStack = maskImp.getStack(); for (int frame : frames) for (int slice : slices) for (int channel : channels) { ImageProcessor ip = imageStack.getProcessor(imp.getStackIndex(channel, slice, frame)); // getStackIndex will clip to the mask dimensions ImageProcessor maskIp = maskStack.getProcessor(maskImp.getStackIndex(channel, slice, frame)); for (int i = maskIp.getPixelCount(); i-- > 0;) { if (maskIp.get(i) == 0) { ip.set(i, 0); } } } imp.updateAndDraw(); } private int[] createArray(int total) { int[] array = new int[total]; for (int i = 0; i < array.length; i++) array[i] = i + 1; return array; } /** * @param imp * the target image for the masking */ public void setImp(ImagePlus imp) { this.imp = imp; } /** * @return the target image for the masking */ public ImagePlus getImp() { return imp; } /** * @param imp * the source image for the mask generation */ public void setMaskImp(ImagePlus imp) { this.maskImp = imp; } /** * @return the source image for the mask generation */ public ImagePlus getMaskImp() { return maskImp; } /** * @param option * the option for defining the mask */ public void setOption(int option) { this.option = option; } /** * @return the option for defining the mask */ public int getOption() { return option; } /** * @param thresholdMethod * the thresholdMethod to set */ public void setThresholdMethod(String thresholdMethod) { this.thresholdMethod = thresholdMethod; } /** * @return the thresholdMethod */ public String getThresholdMethod() { return thresholdMethod; } /** * @param channel * the channel to set */ public void setChannel(int channel) { this.channel = channel; } /** * @return the channel */ public int getChannel() { return channel; } /** * @param frame * the frame to set */ public void setFrame(int frame) { this.frame = frame; } /** * @return the frame */ public int getFrame() { return frame; } /** * @param slice * the slice to set */ public void setSlice(int slice) { this.slice = slice; } /** * @return the slice */ public int getSlice() { return slice; } }