package edu.stanford.rsl.tutorial.atract; import ij.ImageJ; import edu.stanford.rsl.conrad.data.numeric.Grid2D; import edu.stanford.rsl.conrad.data.numeric.Grid2DComplex; import edu.stanford.rsl.conrad.data.numeric.Grid3D; import edu.stanford.rsl.conrad.filtering.RampFilteringTool; import edu.stanford.rsl.conrad.filtering.rampfilters.RamLakRampFilter; import edu.stanford.rsl.conrad.filtering.rampfilters.RampFilter; import edu.stanford.rsl.conrad.utils.Configuration; /** * This class implements the 2D kernel of the atract filter. * @author Marco Boegel (Reco Project 2012 - Individual Project) * */ public class AtractKernel2D extends Grid2DComplex{ public AtractKernel2D(final int sizeX, final int sizeY) { this(sizeX,sizeY,3); } public AtractKernel2D(final int sizeX, final int sizeY, final float zeroValue) { super (sizeX, sizeY); final int paddedSizeRealX = getSize()[0]; final int paddedSizeRealY = getSize()[1]; //Configuration.loadConfiguration(); //final float D = (float) Configuration.getGlobalConfiguration().getGeometry().getSourceToDetectorDistance(); //final float R = (float) Configuration.getGlobalConfiguration().getGeometry().getSourceToAxisDistance(); //final float c = (float) (1/(Math.PI*Math.PI*4)*R/D); final float c=1; setAtIndex(0,0, zeroValue); for(int i = 0; i < paddedSizeRealX/2; i++) { int i2 = i*i; for(int j = 0 ; j < paddedSizeRealY/2; j++) { if (!(i==0 && j==0)) setAtIndex(i,j, c * Math.abs(j)/(i2 + j*j)); } } for(int i = paddedSizeRealX/2; i < paddedSizeRealX; i++) { int tmpI = paddedSizeRealX - i; int tmpI2 = tmpI*tmpI; for(int j = 0; j < paddedSizeRealY/2; j++) { setAtIndex(i,j, c *Math.abs(j)/(tmpI2 + j*j)); } } for(int j = paddedSizeRealY/2 ; j < paddedSizeRealY; j++) { int tmpJ = paddedSizeRealY - j; int tmpJ2 = tmpJ*tmpJ; for(int i = 0; i < paddedSizeRealX/2 ; i++) { setAtIndex(i,j, c*Math.abs(tmpJ)/(i*i+tmpJ2)); } } for(int i = paddedSizeRealX/2 ; i < paddedSizeRealX; i++) { int tmpI = paddedSizeRealX - i; int tmpI2 = tmpI*tmpI; for(int j = paddedSizeRealY/2 ; j < paddedSizeRealY ; j++) { int tmpJ = paddedSizeRealY - j; setAtIndex(i,j, c*Math.abs(tmpJ)/(tmpI2+tmpJ*tmpJ)); } } transformForward(); // getRealSubGrid(0, 0, paddedSizeRealX, paddedSizeRealY).show(); } public void applyToGrid(Grid2D input) { Grid2DComplex subGrid = new Grid2DComplex(input); subGrid.transformForward(); for (int i = 0; i < subGrid.getSize()[0]; ++i) { for(int j = 0; j < subGrid.getSize()[1]; j++) { subGrid.multiplyAtIndex(i,j, getRealAtIndex(i,j), getImagAtIndex(i,j)); } } subGrid.transformInverse(); Grid2D filteredSinoSub = subGrid.getRealSubGrid(0,0, input.getSize()[0], input.getSize()[1]); for(int i = 0 ; i < filteredSinoSub.getSize()[0]; i++){ for(int j = 0; j < filteredSinoSub.getSize()[1]; j++){ input.setAtIndex(i, j, filteredSinoSub.getAtIndex(i, j)); } } } public void applyToGrid(Grid3D input) { int iter = input.getSize()[2]; for(int i = 0; i < iter; i++) { applyToGrid(input.getSubGrid(i)); } } public final static void main(String[] args) { new ImageJ(); int size1 = 1240; int size2 = 960; // 2D example Grid2D in2D = new Grid2D(size1,size2); for (int j = 0; j < in2D.getHeight(); j++) { for (int i = 0; i < in2D.getWidth(); i++) { if (Math.sqrt(Math.pow((i-size1/2),2)+Math.pow((j-size2/2),2)) < 0.25*Math.min(size1, size2)) in2D.setAtIndex(i,j, 2); } } Grid2D in = new Grid2D(in2D); AtractKernel2D r = new AtractKernel2D(size1,size2); r.show("Atract Residual Kernel 2D"); LaplaceKernel2D kernel = new LaplaceKernel2D(); in2D.show("Before"); kernel.applyToGrid(in2D); in2D.show("After Laplace"); r.applyToGrid(in2D); in2D.show("After Residual"); RampFilter rf = new RamLakRampFilter(); try { rf.configure(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } RampFilteringTool rft = new RampFilteringTool(); rft.setRamp(rf); rft.setConfigured(true); rft.applyToolToImage(in).show(); } } /* * Copyright (C) 2010-2014 Marco B�gel * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */