package gdsc.smlm.ij.plugins;
/*-----------------------------------------------------------------------------
* GDSC SMLM Software
*
* Copyright (C) 2013 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 3 of the License, or
* (at your option) any later version.
*---------------------------------------------------------------------------*/
import gdsc.core.ij.Utils;
import ij.IJ;
import ij.ImagePlus;
import ij.gui.GenericDialog;
import ij.plugin.ZProjector;
import ij.plugin.filter.GaussianBlur;
import ij.plugin.filter.PlugInFilter;
import ij.process.ImageProcessor;
import org.apache.commons.math3.util.FastMath;
/**
* Produces a background intensity image and a mask from a sample image.
* <p>
* The input image should be representative of the super-resolution imaging conditions and so will produce suitable
* input for the Create Data plugin to create realistic images.
*/
public class ImageBackground implements PlugInFilter
{
private final static String TITLE = "Image Background";
private static float bias = 500;
private static double sigma = 2;
private int flags = DOES_16 | DOES_8G | DOES_32 | NO_CHANGES;
private ImagePlus imp;
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.PlugInFilter#setup(java.lang.String, ij.ImagePlus)
*/
public int setup(String arg, ImagePlus imp)
{
SMLMUsageTracker.recordPlugin(this.getClass(), arg);
if (imp == null)
{
IJ.noImage();
return DONE;
}
this.imp = imp;
return showDialog();
}
private int showDialog()
{
GenericDialog gd = new GenericDialog(TITLE);
gd.addHelp(About.HELP_URL);
gd.addMessage("Creates a background and mask image from a sample input stack\nusing a median projection");
gd.addNumericField("Bias", bias, 0);
gd.addSlider("Blur", 0, 20, sigma);
gd.showDialog();
if (gd.wasCanceled())
return DONE;
bias = (float) gd.getNextNumber();
sigma = gd.getNextNumber();
// Check arguments
try
{
Parameters.isPositive("Bias", bias);
}
catch (IllegalArgumentException e)
{
IJ.error(TITLE, e.getMessage());
return DONE;
}
return flags;
}
/*
* (non-Javadoc)
*
* @see ij.plugin.filter.PlugInFilter#run(ij.process.ImageProcessor)
*/
public void run(ImageProcessor ip)
{
ImageProcessor median = getProjection();
//Utils.display("Median", median);
ImageProcessor background = applyBlur(median);
subtractBias(background);
Utils.display("Background", background);
// Q. Is there a better way to do the thresholding for foreground pixels.
// Ideally we want to outline cell shapes.
ImageProcessor mask = median.convertToByte(true);
mask.autoThreshold();
Utils.display("Mask", mask);
}
private ImageProcessor getProjection()
{
// Get median intensity projection
ZProjector p = new ZProjector(imp);
p.setMethod(ZProjector.MEDIAN_METHOD);
p.doProjection();
ImageProcessor median = p.getProjection().getProcessor();
return median;
}
private ImageProcessor applyBlur(ImageProcessor median)
{
ImageProcessor blur = median;
if (sigma > 0)
{
blur = median.duplicate();
GaussianBlur gb = new GaussianBlur();
gb.blurGaussian(blur, sigma, sigma, 0.0002);
}
return blur;
}
private void subtractBias(ImageProcessor background)
{
float[] data = (float[]) background.getPixels();
for (int i = 0; i < data.length; i++)
data[i] = (float) FastMath.max(0f, data[i] - bias);
background.resetMinAndMax();
}
}