/*
* Copyright (C) 2010-2014 - Mathias Unberath & Eric Goppert
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/
package edu.stanford.rsl.conrad.data.numeric;
import java.util.ArrayList;
import edu.stanford.rsl.conrad.utils.ImageUtil;
import ij.IJ;
import ij.ImageJ;
import ij.ImagePlus;
import ij.plugin.filter.GaussianBlur;
import ij.process.ImageProcessor;
public class BurtPyramid{
private ArrayList<Grid2D[]> precomp = null;
private boolean PRECOMPUTED = false;
private ImagePlus level0 = null;
private int nOctaves = 0;
private int lvlPerOctave = 1;
//===============================================================
// Methods
//===============================================================
public static void main(String[] args){
Grid2D g = ImageUtil.wrapImageProcessor(IJ.openImage("D:\\Data\\Lena.tif").getProcessor());
BurtPyramid pyramid = new BurtPyramid(g,3);
Grid2D firstLevel = pyramid.getAtOctaveAndLevel(1, 2);
new ImageJ();
g.show("Original Image");
firstLevel.show("Pyramid Image");
}
/**
* Constructor for precomputation of Pyramid levels.
* @param nOctaves
* @param lvlPerOctave
* @param img
*/
public BurtPyramid(int nOctaves, int lvlPerOctave, Grid2D img){
init(nOctaves, lvlPerOctave, img);
precompute();
}
/**
* Precomputes the octaves and levels of the requested Burt pyramid and stores the grids in the respective
* class member. This causes overhead, as it is called in the constructor directly.
*/
private void precompute(){
this.precomp = new ArrayList<Grid2D[]>();
for(int i = 0; i <= nOctaves; i++){
Grid2D[] grids = new Grid2D[lvlPerOctave];
for(int j = 1; j <= lvlPerOctave; j++){
grids[j-1] = getAtOctaveAndLevel(i, j);
}
precomp.add(grids);
}
this.PRECOMPUTED = true;
}
/**
* Constructor that does not pre-compute the octaves and levels.
* @param img
* @param lvlPerOctave Default is 1
*/
public BurtPyramid(Grid2D img, int lvlPerOctave){
init(0, lvlPerOctave, img);
}
public BurtPyramid(ImagePlus img, int lvlPerOctave){
init(0, lvlPerOctave, img);
}
/**
* Constructor that does not pre-compute the octaves and levels.
* @param img
*/
public BurtPyramid(Grid2D img){
init(0, 1, img);
}
/**
* Initializes class members.
* @param nOctaves
* @param lvlPerOctave
* @param img
*/
private void init(int nOctaves, int lvlPerOctave, Grid2D img){
this.nOctaves = nOctaves;
this.lvlPerOctave = lvlPerOctave;
this.level0 = ImageUtil.wrapGrid(img, "");
}
/**
* Initializes class members.
* @param nOctaves
* @param lvlPerOctave
* @param img
*/
private void init(int nOctaves, int lvlPerOctave, ImagePlus img){
this.nOctaves = nOctaves;
this.lvlPerOctave = lvlPerOctave;
this.level0 = img;
}
/**
* Calculates (or references if precomputed) the requested Grid at the specified octave.
* @param oct
* @return
*/
public Grid2D getAtOctave(int oct){
return getAtOctaveAndLevel(oct, 1);
}
/**
* Calculates (or references if precomputed) the requested Grid at the specified octave and level.
* @param oct
* @param lvl
* @return
*/
public Grid2D getAtOctaveAndLevel(int oct, int lvl){
assert(lvl != 0 && lvl <= lvlPerOctave) : new IllegalArgumentException("Level requested not valid.");
if(PRECOMPUTED){
assert(oct < nOctaves) : new IllegalArgumentException("Octave requested not valid.");
return precomp.get(oct)[lvl-1];
}
ImageProcessor blurred = level0.getProcessor().duplicate().convertToFloat();
GaussianBlur gs = new GaussianBlur();
if(oct != 0){
double sigmaOct = Math.pow(2,oct);
gs.blurGaussian(blurred, sigmaOct, sigmaOct, 0.0002);
}
int widthOct = (int)(level0.getWidth()/(oct+1.0));
int heightOct = (int)(level0.getHeight()/(oct+1.0));
blurred = blurred.resize(widthOct, heightOct);
//TODO level einbauen
double sigmaLvl = (lvl-1.0)/lvlPerOctave;
if(sigmaLvl != 0){
gs.blurGaussian(blurred, sigmaLvl, sigmaLvl, 0.0002);
}
return ImageUtil.wrapImageProcessor(blurred);
}
public ArrayList<Grid2D[]> getPrecomputedPyramid(){
return this.precomp;
}
}