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-2023 Wilhelm Burger, Mark J. Burge. All rights reserved.
007 * Visit https://imagingbook.com for additional details.
008 ******************************************************************************/
009package Ch02_Histograms_Statistics;
010
011import ij.IJ;
012import ij.ImagePlus;
013import ij.WindowManager;
014import ij.gui.Roi;
015import ij.plugin.filter.PlugInFilter;
016import ij.process.ByteProcessor;
017import ij.process.ImageProcessor;
018import imagingbook.common.ij.DialogUtils;
019import imagingbook.common.image.IntegralImage;
020import imagingbook.core.jdoc.JavaDocHelp;
021import imagingbook.sampleimages.GeneralSampleImage;
022
023import java.awt.Rectangle;
024
025import static imagingbook.common.ij.IjUtils.noCurrentImage;
026
027/**
028 * <p>
029 * This ImageJ plugin first calculates the integral image for the current image (8 bit grayscale only) and uses it to
030 * find the mean and variance inside the specified rectangle (ROI). Requires a rectangular ROI to be selected. Note that
031 * these values are directly obtained from the integral images and do not require any iterations over image pixels or
032 * other arrays. Thus such calculations are extremely quick. See Sec. 2.8 of [1] for additional details.
033 * </p>
034 * <p>
035 * [1] W. Burger, M.J. Burge, <em>Digital Image Processing &ndash; An Algorithmic Introduction</em>, 3rd ed, Springer
036 * (2022).
037 * </p>
038 *
039 * @author WB
040 * @see IntegralImage
041 */
042public class Integral_Image_GetRoiStatistics implements PlugInFilter, JavaDocHelp {
043        
044        private ImagePlus im = null;
045
046        /** Constructor, asks to open a predefined sample image if no other image is currently open. */
047        public Integral_Image_GetRoiStatistics() {
048                if (noCurrentImage()) {
049                        if (DialogUtils.askForSampleImage(GeneralSampleImage.IrishManor)) {
050                                ImagePlus cim = WindowManager.getCurrentImage();
051                                // set up some ROI
052                                cim.setRoi(new Rectangle(85, 65, 200, 150));
053                        }
054                }
055        }
056
057        @Override
058        public int setup(String arg0, ImagePlus im) {
059                this.im = im;
060                return DOES_8G + ROI_REQUIRED + NO_CHANGES;
061        }
062
063        @Override
064        public void run(ImageProcessor ip) {
065                Roi roi = im.getRoi();
066                if (roi.getType() != Roi.RECTANGLE) {
067                        IJ.error("Rectangular selection required!");
068                        return;
069                }
070                
071                Rectangle rect = roi.getBounds();       
072                int u0 = rect.x;
073                int v0 = rect.y;
074                int u1 = u0 + rect.width - 1;
075                int v1 = v0 + rect.height - 1;
076                
077                IntegralImage iI = new IntegralImage((ByteProcessor) ip);
078                double mean = iI.getMean(u0, v0, u1, v1);
079                double var = iI.getVariance(u0, v0, u1, v1);
080                
081                IJ.log("ROI rectangle = " + rect);
082                IJ.log("ROI area = " + rect.width * rect.height);
083                IJ.log("ROI mean = " + String.format("%.3f", mean));
084                IJ.log("ROI variance = " + String.format("%.3f", var));
085                IJ.log("ROI stddev = " + String.format("%.3f", Math.sqrt(var)));
086
087        }
088}