
import ij.IJ;
import ij.ImagePlus;
import ij.gui.GenericDialog;
import ij.gui.Line;
import ij.gui.Overlay;
import ij.gui.PolygonRoi;
import ij.gui.ProfilePlot;
import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import java.awt.Color;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;

    private double midLineWidth = 15.0;
    private double normRegionWidth = 20.0;

    float[][] calcWeightedCoords(ImageProcessor ip) {
        int width = ip.getWidth();
        int height = ip.getHeight();
        float[][] output = new float[2][width];
        for (int x = 0; x < width; x++) {
            float sumWeights = 0.0f;
            float weightedSum = 0.0f;
            for (int y = 0; y < height; y++) {
                float p = ip.getPixelValue(x, y);
                weightedSum += y * p;
                sumWeights += p;
            }
            output[0][x] = x;
            output[1][x] = weightedSum / sumWeights;
        }
        return output;
    }

    boolean showDialog() {
        GenericDialog gd = new GenericDialog("Projection Analyser");
        gd.addNumericField("Specify midline extent", midLineWidth, 0, 3, "%");
        gd.addNumericField("Specify normalisation region extent", normRegionWidth, 0, 3, "%");
        gd.showDialog();
        if (!gd.wasOKed()) {
            return false;
        }
        midLineWidth = gd.getNextNumber();
        normRegionWidth = gd.getNextNumber();
        return true;
    }

    ImagePlus normImage(ImageProcessor ip, double[] profileData) {
        FloatProcessor fp = ip.convertToFloatProcessor();
        ImagePlus output = new ImagePlus("Normalised " + imp.getShortTitle(), fp);
        DescriptiveStatistics stats = new DescriptiveStatistics();
        int extent = (int) Math.round(normRegionWidth * ip.getWidth() / 100.0);
        for (int i = 0; i < extent; i++) {
            stats.addValue(profileData[i]);
        }
        fp.multiply(1.0 / stats.getMean());
        fp.resetMinAndMax();
        output.resetDisplayRange();
        return output;
    }

	ImagePlus imp = IJ.getImage();		
	if (!showDialog()) {
	    return;
	}
	float[][] weightedMidLine = calcWeightedCoords(imp.getProcessor());
	PolygonRoi roi = new PolygonRoi(weightedMidLine[0], weightedMidLine[1], weightedMidLine[0].length, PolygonRoi.POLYLINE);
	roi.fitSpline();
	roi.setStrokeWidth(imp.getHeight() * midLineWidth / 100.0);
	imp.setRoi(roi);
	ProfilePlot pp1 = new ProfilePlot(imp);
	ImagePlus norm = normImage(imp.getProcessor().duplicate(), pp1.getProfile());
	imp.deleteRoi();
	norm.setRoi(roi);
	ProfilePlot pp2 = new ProfilePlot(norm);
	pp2.createWindow();
	Overlay o = new Overlay();
	int width = imp.getWidth();
	int height = imp.getHeight();
	double xr = width * normRegionWidth / 100.0;
	o.add(new Line(xr, 0.0, xr, height - 1.0));
	o.setStrokeColor(Color.red);
	norm.setOverlay(o);
	norm.show();
