import java.awt.Frame; import java.util.ArrayList; import ij.IJ; import ij.ImageJ; import ij.ImagePlus; import ij.gui.ImageWindow; import ij.gui.Roi; import ij.plugin.PlugIn; import ij.plugin.frame.RoiManager; import ij.process.ImageStatistics; import javax.swing.JOptionPane; /** * Measures the MTF after Droege et al. "A practical method to measure the MTF of CT scanners". Med Phys 9(5). 758-760. 1982" * In order to use the plugin, use the roi manager to define the following ROIs: * CT_1 the one material of the MTF measurement * CT_2 the other material of the MTF measurement * M_1 * ... the line pair modules of the phantom * M_N * @author akmaier * */ public class Measure_MTF_Droege implements PlugIn { public static ArrayList<ImagePlus> getAvailableImagePlus(){ ArrayList<ImagePlus> list = new ArrayList<ImagePlus>(); Frame [] frames = ImageJ.getFrames(); for (Frame frame: frames){ if (frame instanceof ImageWindow){ ImageWindow window = (ImageWindow)frame; if (! window.isClosed()){ list.add(window.getImagePlus()); } } } return list; } public static ImagePlus [] getAvailableImagePlusAsArray(){ ArrayList<ImagePlus> list = getAvailableImagePlus(); ImagePlus [] array = new ImagePlus[list.size()]; for(int i=0; i< list.size(); i++){ array[i] = list.get(i); } return array; } @Override public String toString() { return "Measure Droege MTF"; } @Override public void run(String arg) { ImagePlus [] images = getAvailableImagePlusAsArray(); ImagePlus image = (ImagePlus) JOptionPane.showInputDialog(null, "Select image to measure MTF: ", "Image Selection", JOptionPane.PLAIN_MESSAGE, null, images, images[0]); boolean configured = false; if (RoiManager.getInstance()!=null){ RoiManager manager = RoiManager.getInstance(); if (manager.getCount() <= 2){ IJ.showMessage("Please define at least 3 ROIs"); } else { configured = true; } } else { IJ.showMessage("Please use the ROI Manager to define at least 3 ROIs"); } RoiManager manager = RoiManager.getInstance(); Roi [] rois = manager.getRoisAsArray(); Roi ct1roi = rois[0]; image.setRoi(ct1roi); ImageStatistics stats = image.getStatistics(); double ct1 = stats.mean; double n1 = stats.stdDev; Roi ct2roi = rois[1]; image.setRoi(ct2roi); stats = image.getStatistics(); double ct2 = stats.mean; double n2 = stats.stdDev; double n0 = Math.sqrt((n1*n1+n2*n2) / 2.0); double m0 = Math.abs(ct2-ct1)/2.0; for (int i = 2; i < rois.length; i++){ image.setRoi(rois[i]); stats = image.getStatistics(); double m=Math.sqrt((stats.stdDev*stats.stdDev - n0*n0)); if (Double.isNaN(m)) m = 0; double mtf = Math.PI * Math.sqrt(2) * 0.25 * m / m0; IJ.log("Roi " + (i-1) + "\t" + mtf); } } } /* * Copyright (C) 2010-2014 - Andreas Maier * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */