130 likes | 147 Views
ImageJ Plugin Writing 2. Muharrem Mercimek Lab Presentation 15 May 2009. Contents. Why ImageJ? ImageJ Plugins Plug writing samples. Why ImageJ?. ImageJ is a public domain Java image processing program.
E N D
ImageJ Plugin Writing 2 Muharrem Mercimek Lab Presentation 15 May 2009
Contents • Why ImageJ? • ImageJ Plugins • Plug writing samples
Why ImageJ? • ImageJ is a public domain Java image processing program. • Rather than using expensive, large size commercial image-processing tools developing your own software. • Interactivity and ease of use is are main concerns of software developers, scientists, engineers working with images. • ImageJ is platform-independent. ImageJ is pure Java application and can run on any computer with and JRE. ImageJ also can be used as an applet within a browser though it is mostly run as a stand-alone application. • Dynamic execution model allows new modules (plugins).
ImageJ Plugins • A basic knowledge of Java programming is required towards ImageJ plugin writing. • Plugins can be created, edited, compiled, invoked, and organized through the Plugin menu of the ImageJ’ s main menu. • JRE and a JDK are needed to be installed on your computer. Plugins Folder • ImageJ user plugins have to be located in a sub-folder (since version 1.20) or directly in the folder called “plugins”. The name of your plugin will be seen under the plugins menu. Sub-folder will be submenus of Plugins menu.
ImageJ Plugins .java file name should contain under score _, to be automatically inserted to the plugin menu list C:\ImageJ\plugins Reference to the plugin execution can be replaced manually to another place in the ImageJ menu tree Plugins-Shortcuts-Install Plugin Edit, Compile and Run Plugins .class file Write ImageJ code .java ImageJ locates all the plugins related to their physical locations under Plugins folder automatically .java file should be under plugins folder C:\ImageJ\plugins Plugin: requires no image to be open to start a plugin PlugInFilter: the currently active image is passed to the plugin when started. For image processing operations PlugInFilter is used mostly PlugInFilter must at least implement methods, setup(), and run(). int setup( String arg, ImagePlus imp) ImageJ calls this method first to verify the capabilities of the plugin match the target image. void run (ImageProcessor ip) Actual work is done here, It passed a single argument ip, an object of type ImageProcessor
StackAvarage application, averages the stack import ij.*; import ij.gui.*; import ij.plugin.filter.PlugInFilter; import ij.process.*; import java.awt.*; public class StackAverage_ implements PlugInFilter { protected ImagePlus imp; public int setup(String arg, ImagePlus imp){ this.imp=imp; return DOES_8G+STACK_REQUIRED; } public void run (ImageProcessor ip){ ImageStack stack=imp.getStack(); ImageStack stack2=imp.getStack(); int[] sum; byte[] pixels; int w=ip.getWidth(); int h=ip.getHeight(); int dimension =ip.getWidth()*ip.getHeight(); sum=new int[dimension]; for (int i=1; i<=stack.getSize(); i++){ pixels=(byte[]) stack.getPixels(i); for(int j=1; j<dimension;j++){ sum[j]+=0xff&pixels[j]; } } byte[] average= new byte[dimension]; for (int j=0; j<dimension; j++){ average[j]=(byte)((sum[j]/stack.getSize()) & 0xff); } ImagePlus imp2=NewImage.createImage("Average",w,h,1,8, NewImage.FILL_WHITE); ImageProcessor ip2=imp2.getProcessor(); ip2.setPixels(average); int w2=ip.getWidth(); int h2=ip.getHeight(); imp2.show(); IJ.write((imp.getStackSize())+"");IJ.write(stack.getHeight()+""); IJ.write(stack.getWidth()+""); } } The java and ImageJ class packages they are imported Name of the plugin is StackAverage_ PlugInFilter type plugin, it needs an active, opened image Plugin can handle 8bit images, and image stack is required Plugin’s run method receives an ImageProcessor object ip, ImageProcessor class holds the pixel array and does the actual work on the image In a PlugInFilter currently open stack can be retrieved from the current ImagePlus object Code-1 To access the pixels int[ ] pixels getPixels(), or getPixels(int sliceNumber) are used Each image is based on an image processor the type of it depends on the type of the image. setPixels(int[]) with an ImageProcessor objects is used to set the pixels using an array
import ij.*; import ij.plugin.PlugIn; public class Message_Test implements PlugIn { public void run(String arg) { IJ.showStatus("Plugin Message Test started."); IJ.showProgress(0.0); IJ.error("I need user input!"); String name = IJ.getString("Please enter your name: ", "me"); IJ.showProgress(0.5); IJ.write(" Color Inverter... "); IJ.runPlugIn("ColorInverter_",""); IJ.showProgress(1.0); IJ.showMessage("Finished.",name+", thank you for running this plugin"); } } All we have to implement is the run method. We do not need the argument, so we ignore it. We are going to use some utility functions, which are mainly in ij.IJ.* package Progress bar on the main menu console Code-2 Runs another plugin
ByteProcessor img=new ByteProcessor(width, height); double value=0; double distance=0; int sizex=img.getWidth(); int sizey=img.getHeight(); int xcenter=(sizex)/2+1; int ycenter=(sizey)/2+1; for(int y=0; y<sizey; y++) { for (int x=0; x<sizex; x++) { distance=Math.abs(x-xcenter)*Math.abs(x-xcenter)+ Math.abs(y-ycenter)*Math.abs(y-ycenter); distance=Math.sqrt(distance); value=dc_level*Math.exp((-1*distance*distance)/ (1.4426925*cutoff*cutoff)); img.putPixelValue(x,y,value); } } ImagePlus img_filter2=new ImagePlus("2d_filter",img); img_filter2.show(); ImageStack stack2=new ImageStack(sizex, sizey); IJ.write(sizex+""); IJ.write(sizey+""); import ij.*; import ij.process.*; import ij.gui.*; import ij.measure.*; import ij.plugin.*; import java.awt.*; public class Gaussian_Filter implements PlugIn { static double cutoff =50; static double dc_level =255; public void run(String arg) { if(!showDialog()) return; .... } public boolean showDialog() { GenericDialog gd=new GenericDialog("parameters"); gd.addNumericField("Cutoff frequency:", cutoff, 1); gd.addNumericField("DC-level:", dc_level, 1); gd.addCheckbox("reset",false); gd.showDialog(); if(gd.wasCanceled()) return false; cutoff=gd.getNextNumber(); dc_level=gd.getNextNumber(); boolean reset=gd.getNextBoolean(); return true; } } Code-3
import ij.*; import ij.gui.*; import ij.process.*; import java.awt.*; import java.io.*; import ij.plugin.PlugIn; public class Joint_Histogram implements PlugIn{ private static int index1; private static int index2; private static boolean createFile; private static String deaultDirectory=""; public void run (String arg) { int[] wList=WindowManager.getIDList(); if (wList==null) { IJ.error("No windows open"); return; } String[] titles=new String[wList.length]; for (int i=0; i<wList.length; i++){ ImagePlus img= WindowManager.getImage(wList[i]); if(img!=null) titles[i]=img.getTitle(); else titles[i]=""; } IJ.write(index1+" "+index2+" "+titles.length); if (index1>=titles.length) index1=0; if (index2>=titles.length) index2=0; GenericDialog gd=new GenericDialog(" Joint Histogram", IJ.getInstance()); gd.addChoice("image #1:", titles, titles[index1]); gd.addChoice("image #2:", titles, titles[index2]); gd.addCheckbox("Create file:", createFile); gd.showDialog(); if(gd.wasCanceled()) return; index1=gd.getNextChoiceIndex(); index2=gd.getNextChoiceIndex(); createFile=gd.getNextBoolean(); String title1=titles[index1]; String title2=titles[index2]; ImagePlus imp1=WindowManager.getImage(wList[index1]); ImagePlus imp2=WindowManager.getImage(wList[index2]); if(imp1.getType()!=0 || imp1.getType()!=imp2.getType()) IJ.showMessage(“Joint Histogram", "both images should be 8-bit grayscale"); Joint_H(imp1, imp2); } Code-4
public void Joint_H(ImagePlus imp1, ImagePlus imp2) { ImageProcessor ip1=imp1.getProcessor(); ImageProcessor ip2=imp2.getProcessor(); boolean unsigned=true; int width=imp1.getWidth(); int height=imp1.getHeight(); FloatProcessor ip3=new FloatProcessor( 256, 256); int z1, z2, count=0; int value; int[] histogram; for (int y=0; y<height; y++) for (int x=0; x<width; x++) { z1=ip1.getPixel(x,y); z2=ip2.getPixel(x,y); value=ip3.getPixel(z1,z2); value++; ip3.putPixelValue(z1,255-z2,value); } ImagePlus img3=new ImagePlus("histogram",ip3); img3.updateAndDraw(); img3.show(); }
import ij.*; import ij.process.*; import ij.gui.*; import ij.plugin.filter.Convolver; import ij.plugin.filter.PlugInFilter; public class Image_filtering implements PlugInFilter { ImagePlus imp; public int setup(String arg, ImagePlus imp) { this.imp=imp; return DOES_8G+NO_CHANGES; } public void run(ImageProcessor ip) { float[] h={-1, -1, -1, 0, 0, 0, 1, 1, 1}; Convolver cv=new Convolver(); cv.convolve(ip, h, 3,3); imp.updateAndDraw(); } } Code-4