package imagetools; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.imageio.ImageIO; import ij.*; import ij.plugin.ContrastEnhancer; import ij.plugin.ZProjector; import ij.plugin.filter.Convolver; import ij.process.FloatProcessor; import ij.process.ImageProcessor; /** * This code comes mainly from the Fiji site as freeware. There are some things * I didnd't know in the math until I worked through the code. It works. I'll * try to revisit this and make it better when I learn more about meshing. FIJI * is really just image j and the script is offered at * http://fiji.sc/Gabor_Filter_script. * * @author ij|aevans * */ public class GaborFilter implements Proximity{ private Image image=Image.getInstance(); private double theta; private double sigma = 8.0; private double gamma = 0.25; private int nangles = 5; private double fx = 3.0; private double psimul = 0.0; public GaborFilter() { } /** * Returns the image object */ @Override public Image getImage(){ return image; } /** * Set the image from a file path */ @Override public void setImage(String inpath) { Pattern p=Pattern.compile("(?mi)(\\.jpg|\\.jpeg|\\.gif|\\.bmp)"); Matcher m=p.matcher(inpath); if(m.find()){ image.setPath(inpath); try { image.setImage(ImageIO.read(new File(image.getPath()))); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }else{ try{ throw new FileTypeException("Image must be a jpg, gif, bmp, or jpeg"); }catch(FileTypeException e){ e.printStackTrace(); } } } /** * Get the fx * @return */ public double getFx() { return fx; } /** * Set the fx * @param fx */ public void setFx(double fx) { this.fx = fx; } /** * Get the PSimul * @return */ public double getPsimul() { return psimul; } /** * Set the Psimul * @param psimul */ public void setPsimul(double psimul) { this.psimul = psimul; } /** * Get the File Path * @return */ @Override public String getPath() { return image.getPath(); } /** * Set the file path * @param fpath */ @Override public void setPath(String fpath) { image.setPath(fpath); } /** * Get the Buffered Image */ @Override public BufferedImage getBufferedImage() { return image.getImage(); } /** * Set the Buffered Image */ @Override public void setImage(BufferedImage inimage) { image.setImage(inimage); } /** * Get theta * @return theta-double */ public double getTheta() { return theta; } /** * Set theta * @param theta -double */ public void setTheta(double theta) { this.theta = theta; } /** * Get sigma * @return sigma -double */ public double getSigma() { return sigma; } /** * Set sigma * @param sigma -double */ public void setSigma(double sigma) { this.sigma = sigma; } /** * Get Gamm * @return gamm -double */ public double getGamma() { return gamma; } /** * Set gamma * @param gamma -double */ public void setGamma(double gamma) { this.gamma = gamma; } /** * Get the number of angles * @return nangles -nangles */ public int getNangles() { return nangles; } /** * Set the number of angles * @param nangles -double */ public void setNangles(int nangles) { this.nangles = nangles; } /** * Private method that performs the Gabor filter */ private void filter() { BufferedImage proxyimage=image.getImage(); ImagePlus original = new ImagePlus("original", proxyimage); ImageProcessor ip; double sigma_x = sigma; double sigma_y = sigma / gamma; double sigma_x2; double sigma_y2; double rotationangle; double xprime; double yprime; double a; double psi = Math.PI / 4.0 * psimul; double c; Convolver conv; float[] kernel; double largersigma = (sigma_x > sigma_y) ? (int) sigma_x : (int) sigma_y; largersigma = (largersigma < 1) ? 1 : largersigma; int filterSizeX = (int) Math.round(6 * largersigma) + 1; int filterSizeY = (int) Math.round(6 * largersigma) + 1; sigma_x2 = sigma_x * sigma_x; sigma_y2 = sigma_y * sigma_y; int middleX = (int) Math.round(filterSizeX) / 2; int middleY = (int) Math.round(filterSizeY) / 2; ImageStack is = new ImageStack(proxyimage.getWidth(), proxyimage.getHeight()); ImageStack kernels = new ImageStack(filterSizeX, filterSizeY); rotationangle = Math.PI / (double) nangles; // calculate complex and real parts for (int i = 0; i < nangles; i++) { theta = rotationangle * i; FloatProcessor filter = new FloatProcessor(filterSizeX, filterSizeY); for (int x = -middleY; x <= middleX; x++) { for (int y = -middleY; y < middleY; y++) { xprime = (double) x * Math.cos(theta) + (double) y * Math.sin(theta); yprime = (double) -x * Math.sin(theta) + (double) y * Math.cos(theta); // this may need to be changed a = (1.0 / (2.0 * Math.PI * sigma_x * sigma_y)) * Math.exp((-0.5) * ((xprime * xprime) / sigma_x2) + ((yprime * yprime) / sigma_y2)); c = Math.cos(2.0 * Math.PI * (fx * xprime / sigma_x2 + yprime * yprime / sigma_y2)); filter.setf((x + middleX), (y + middleY), (float) (a * c)); } } kernels.addSlice("kernal angle = " + theta, filter); } // for showing kernels // ImagePlus ip_kernels=new ImagePlus("kernels",kernels); // ip_kernels.show(); System.out.println("Applying Kernel"); // Apply kernels for (int i = 0; i < nangles; i++) { theta = rotationangle * i; conv = new Convolver(); kernel = (float[]) kernels.getProcessor(i + 1).getPixels(); ip = original.getProcessor().duplicate(); conv.convolve(ip, kernel, filterSizeX, filterSizeY); is.addSlice("gabor angle = " + i, ip); } // normalize stack ContrastEnhancer ce = new ContrastEnhancer(); for (int i = 1; i < is.getSize(); i++) { ce.stretchHistogram(is.getProcessor(i), 0.4); } System.out.println("Running Enhancement Stack"); ImagePlus projectStack = new ImagePlus("filtered stack", is); IJ.run(projectStack, "Enhance Contrast", "saturated=0.4 normalize normalize_all"); ImageStack resultStack = new ImageStack(proxyimage.getWidth(),proxyimage.getHeight()); ZProjector zp = new ZProjector(projectStack); zp.setStopSlice(is.getSize()); for (int i = 0; i < 5; i++) { zp.setMethod(i); zp.doProjection(); resultStack.addSlice("Gabor_" + i + "_" + sigma + "_" + gamma + "_" + (int) (psi / (Math.PI / 4)) + "_" + fx, zp .getProjection().getChannelProcessor()); } System.out.println("Showing"); ImagePlus iplus = new ImagePlus("gabor,sigma=" + sigma + " gamma=" + gamma + " psi=" + psi, is); image.setImage(iplus.getBufferedImage()); // (new // ImagePlus("gabor,sigma="+sigma+" gamma="+gamma+" psi="+psi,is)).show(); // ImagePlus result= new ImagePlus ("Gabor stack projections", // resultStack) ; // IJ.run(result, "Enhance Contrast", // "saturated=0.4 normalize normalize_all"); } /** * Run the filter */ public void run() { filter(); } /** * Save the image */ @Override public void save(){ image.save(); } /** * Delete the image */ @Override public void delete(){ image.delete(); } }