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();
}
}