package edu.stanford.rsl.tutorial;
import ij.ImageJ;
import edu.stanford.rsl.conrad.data.numeric.Grid2D;
import edu.stanford.rsl.tutorial.fan.CosineFilter;
import edu.stanford.rsl.tutorial.fan.FanBeamBackprojector2D;
import edu.stanford.rsl.tutorial.fan.FanBeamProjector2D;
import edu.stanford.rsl.tutorial.fan.redundancy.ParkerWeights;
import edu.stanford.rsl.tutorial.filters.RamLakKernel;
import edu.stanford.rsl.tutorial.parallel.ParallelBackprojector2D;
import edu.stanford.rsl.tutorial.parallel.ParallelProjector2D;
import edu.stanford.rsl.tutorial.phantoms.DotsGrid2D;
import edu.stanford.rsl.tutorial.phantoms.MickeyMouseGrid2D;
import edu.stanford.rsl.tutorial.phantoms.Phantom;
import edu.stanford.rsl.tutorial.phantoms.TestObject1;
import edu.stanford.rsl.tutorial.phantoms.UniformCircleGrid2D;
public class FanBeamParallelBeamComparison {
/**
* @param args
*/
public static void main(String[] args) {
// sinogram params
double focalLength = 800,
maxT = 300,
deltaT = 1.0,
gammaM = Math.atan((maxT / 2.f - 0.5) / focalLength),
maxBeta = Math.PI + 2*gammaM,
deltaBeta = maxBeta / 180;
// image params
int imgSzXMM = 200, // [mm]
imgSzYMM = imgSzXMM; // [mm]
float pxSzXMM = 1.0f, // [mm]
pxSzYMM = pxSzXMM; // [mm]
//float focalLength = 400, maxBeta = (float) Math.PI*2, deltaBeta = maxBeta / 200, maxT = 200, deltaT = 1;
int phantomType = 2; // 0 = circle, 1 = MickeyMouse, 2 = TestObject1,
// 3=DotsGrid
// size in grid units
int imgSzXGU = (int) Math.floor(imgSzXMM / pxSzXMM), // [GU]
imgSzYGU = (int) Math.floor(imgSzYMM / pxSzYMM); // [GU]
new ImageJ();
// image object
Phantom phantom;
switch (phantomType) {
case 0:
phantom = new UniformCircleGrid2D(imgSzXGU, imgSzYGU);
break;
case 1:
phantom = new MickeyMouseGrid2D(imgSzXGU, imgSzYGU);
break;
case 2:
phantom = new TestObject1(imgSzXGU, imgSzYGU);
break;
case 3:
phantom = new DotsGrid2D(imgSzXGU, imgSzYGU);
break;
default:
phantom = new UniformCircleGrid2D(imgSzXGU, imgSzYGU);
break;
}
phantom.setSpacing(pxSzXMM, pxSzYMM);
// origin is given in (negative) world coordinates
phantom.setOrigin(-(imgSzXGU * phantom.getSpacing()[0]) / 2.0,
-(imgSzYGU * phantom.getSpacing()[1]) / 2.0);
phantom.show();
Grid2D grid = phantom;
// Fan Beam Projection
FanBeamProjector2D fanBeamProjector = new FanBeamProjector2D(focalLength, maxBeta, deltaBeta, maxT, deltaT);
Grid2D fanBeamSinoRay = fanBeamProjector.projectRayDriven(grid);
fanBeamSinoRay.show("FB CL Sinogram");
// Parallel for comparison
ParallelProjector2D Projector = new ParallelProjector2D(maxBeta, deltaBeta, maxT, deltaT);
Grid2D pBeamSinoRay = Projector.projectRayDriven(grid);
pBeamSinoRay.show("FB CL Sinogram");
// Parker Weights
ParkerWeights pWeights = new ParkerWeights(focalLength, maxT, deltaT, maxBeta, deltaBeta);
pWeights.show();
pWeights.applyToGrid(fanBeamSinoRay);
fanBeamSinoRay.show("Fan Beam After Parker Weights");
// Cosine Weights
CosineFilter cosFilt = new CosineFilter(focalLength, maxT, deltaT);
// Filtering
RamLakKernel ramLak = new RamLakKernel((int) (maxT / deltaT), deltaT);
for (int theta = 0; theta < fanBeamSinoRay.getSize()[0]; ++theta) {
cosFilt.applyToGrid(fanBeamSinoRay.getSubGrid(theta));
ramLak.applyToGrid(fanBeamSinoRay.getSubGrid(theta));
ramLak.applyToGrid(pBeamSinoRay.getSubGrid(theta));
}
fanBeamSinoRay.show("Fan Beam Filtered Sinogram");
pBeamSinoRay.show("Parallel Beam Filtered Sinogram");
// Backproject fan beam
FanBeamBackprojector2D fbp = new FanBeamBackprojector2D(focalLength, deltaT, deltaBeta, imgSzXMM, imgSzYMM);
Grid2D fanbeamResult = fbp.backprojectPixelDriven(fanBeamSinoRay);
fanbeamResult.show("Fan Beam Result");
// Backproject parallel beam
ParallelBackprojector2D pbp = new ParallelBackprojector2D(imgSzXMM,imgSzYMM,pxSzXMM,pxSzYMM);
Grid2D parallelResult = pbp.backprojectPixelDriven(pBeamSinoRay);
parallelResult.show("Parallel Beam Result");
}
}
/*
* Copyright (C) 2010-2014 Andreas Maier
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/