/** * */ package fr.unistra.pelican.algorithms.morphology.connected; import fr.unistra.pelican.Algorithm; import fr.unistra.pelican.AlgorithmException; import fr.unistra.pelican.BooleanImage; import fr.unistra.pelican.DoubleImage; import fr.unistra.pelican.Image; import fr.unistra.pelican.IntegerImage; import fr.unistra.pelican.util.connectivityTrees.ComponentNode; import fr.unistra.pelican.util.connectivityTrees.ComponentTree; import fr.unistra.pelican.util.connectivityTrees.attributes.ComponentAttribute; import fr.unistra.pelican.util.connectivityTrees.attributes.UnsupportedDataTypeException; import fr.unistra.pelican.util.vectorial.ordering.VectorialBasedComponentOrdering; import fr.unistra.pelican.util.vectorial.ordering.VectorialOrdering; /** * Reconstruct an image from a connected component tree * * @author Benjamin Perret * */ public class ReconstructImageFromTree extends Algorithm { /** * Data usable for reconstruction * @author Benjamin Perret * */ public static enum Data{Level,Area,Attribute}; /** * Default data is connected component level */ public Data data=Data.Level; /** * Take data from specified attribute */ public ComponentAttribute attribute; /** * The component tree */ public ComponentTree tree; /** * Constraint result to be smaller than underlying image (ensure anti-extensivity) */ public boolean constraint=false; /** * Class of he attribute used for reconstruction */ public Class<? extends ComponentAttribute> clazz; /** * Result */ public Image output; /** * Dimensions of result */ private int xdim,ydim,zdim; /** * Root of the tree */ private ComponentNode root; /** * Reconstrucut only leaves */ public boolean onlyLeaves=false; public ReconstructImageFromTree(){ super.inputs="tree"; super.options="onlyLeaves,data,clazz"; super.outputs="output"; } /* (non-Javadoc) * @see fr.unistra.pelican.Algorithm#launch() */ @Override public void launch() throws AlgorithmException { xdim=tree.getXdim(); ydim=tree.getYdim(); zdim=tree.getZdim(); root=tree.getRoot(); switch (data) { case Level: try { drawLevel(); } catch (UnsupportedDataTypeException e) { throw new AlgorithmException("Error message was: " +e.getMessage()); } break; case Area: drawArea(); break; case Attribute: if (clazz==null) throw new AlgorithmException("You must specify a class Attribute to use when using Attribute mode!"); try { drawAttr(); } catch (UnsupportedDataTypeException e) { throw new AlgorithmException("Unsupported datatype exception caught! " +e); } break; } } private void drawAttr() throws UnsupportedDataTypeException { Object vv= tree.findNodeAt(0, 0, 0).getAttributeValue(clazz); if(vv instanceof Double) { output=new DoubleImage(xdim,ydim,zdim,1,1); output.fill(Double.NEGATIVE_INFINITY); for(int z=0;z<zdim;z++) for(int y=0;y<ydim;y++) for(int x=0;x<xdim;x++) { ComponentNode n= tree.findNodeAt(x, y, z); if(!onlyLeaves || n.numberOfChildren()==0) { Object v= n.getAttributeValue(clazz); if(v!=null) output.setPixelXYZDouble(x, y, z,(Double)v); else { System.out.println("Attribute does not exist for node: " +tree.findNodeAt(x, y, z) + " for pixel " + "["+x+";"+y+";"+z+"]" + " NOW I WILL CRASH!"); v.toString(); } } } }else if(vv instanceof double[]) { output=new DoubleImage(xdim,ydim,zdim,1,((double[])vv).length); output.fill(Double.NEGATIVE_INFINITY); for(int z=0;z<zdim;z++) for(int y=0;y<ydim;y++) for(int x=0;x<xdim;x++) { ComponentNode n= tree.findNodeAt(x, y, z); if(!onlyLeaves || n.numberOfChildren()==0) { Object v= n.getAttributeValue(clazz); if(v!=null) output.setVectorPixelXYZTDouble(x, y, z,0,(double [])v); else { System.out.println("Attribute does not exist for node: " +tree.findNodeAt(x, y, z) + " for pixel " + "["+x+";"+y+";"+z+"]" + " NOW I WILL CRASH!"); v.toString(); } } } } else if(vv instanceof Integer) { output=new IntegerImage(xdim,ydim,zdim,1,1); //output.fill(Double.NEGATIVE_INFINITY); for(int z=0;z<zdim;z++) for(int y=0;y<ydim;y++) for(int x=0;x<xdim;x++) { ComponentNode n= tree.findNodeAt(x, y, z); if(!onlyLeaves || n.numberOfChildren()==0) { Object v= n.getAttributeValue(clazz); if(v!=null) output.setPixelXYZInt(x, y, z,(Integer)v); else { System.out.println("Attribute does not exist for node: " +tree.findNodeAt(x, y, z) + " for pixel " + "["+x+";"+y+";"+z+"]" + " NOW I WILL CRASH!"); v.toString(); } } } }else if(vv instanceof Boolean) { output=new BooleanImage(xdim,ydim,zdim,1,1); //output.fill(Double.NEGATIVE_INFINITY); for(int z=0;z<zdim;z++) for(int y=0;y<ydim;y++) for(int x=0;x<xdim;x++) { ComponentNode n= tree.findNodeAt(x, y, z); if(!onlyLeaves || n.numberOfChildren()==0) { Object v= n.getAttributeValue(clazz); if(v!=null) output.setPixelXYZBoolean(x, y, z,(Boolean)v); else { System.out.println("Attribute does not exist for node: " +tree.findNodeAt(x, y, z) + " for pixel " + "["+x+";"+y+";"+z+"]" + " NOW I WILL CRASH!"); v.toString(); } } } }else throw new UnsupportedDataTypeException("I don't know how to manage this kind of attribute " + vv + " of type " + vv.getClass()); output.setName(clazz.getSimpleName()); } private void drawLevel() throws UnsupportedDataTypeException { Object v=tree.findNodeAt(0, 0, 0).getLevel(); if(v instanceof Double) { output=new DoubleImage(xdim,ydim,zdim,1,1); output.fill(Double.NEGATIVE_INFINITY); for(int z=0;z<zdim;z++) for(int y=0;y<ydim;y++) for(int x=0;x<xdim;x++) { ComponentNode n= tree.findNodeAt(x, y, z); if(!onlyLeaves || n.numberOfChildren()==0) { double level=(Double)n.getLevel(); if(constraint) level=Math.min(level, tree.image.getPixelXYZDouble(x, y, z)); output.setPixelXYZDouble(x, y, z,level); } } } else if (v instanceof double[]) { output=new DoubleImage(xdim,ydim,zdim,1,((double [])tree.findNodeAt(0, 0, 0).getLevel()).length); output.fill(Double.NEGATIVE_INFINITY); VectorialBasedComponentOrdering comp=(VectorialBasedComponentOrdering )tree.getComparator(); VectorialOrdering comparator=comp.getVectorialOrdering(); for(int z=0;z<zdim;z++) for(int y=0;y<ydim;y++) for(int x=0;x<xdim;x++) { ComponentNode n= tree.findNodeAt(x, y, z); double [] level = (double [])n.getLevel(); if(constraint) level=comparator.min(level, tree.image.getVectorPixelXYZDouble(x, y, z)); if(!onlyLeaves || n.numberOfChildren()==0) output.setVectorPixelXYZTDouble(x, y, z, 0, level); } } else throw new UnsupportedDataTypeException("Data type not supported: " +v.getClass()); output.setName("Reconstruction"); } private void drawArea() { output=new IntegerImage(xdim,ydim,zdim,1,1); output.fill(Integer.MIN_VALUE); for(int z=0;z<zdim;z++) for(int y=0;y<ydim;y++) for(int x=0;x<xdim;x++) { ComponentNode n= tree.findNodeAt(x, y, z); if(!onlyLeaves || n.numberOfChildren()==0) output.setPixelXYZInt(x, y, z,n.getArea()); } output.setName("Area map"); } public static Image exec(ComponentTree tree) { return (Image)(new ReconstructImageFromTree()).process(tree); } public static Image exec(ComponentTree tree, boolean onlyLeaves) { return (Image)(new ReconstructImageFromTree()).process(tree,onlyLeaves); } public static Image exec(ComponentTree tree, Data data) { return (Image)(new ReconstructImageFromTree()).process(tree,null,data); } public static Image exec(ComponentTree tree, Data data,Class<? extends ComponentAttribute> clazz) { return (Image)(new ReconstructImageFromTree()).process(tree,null,data,clazz); } public static Image exec(ComponentTree tree, Data data,Class<? extends ComponentAttribute> clazz, boolean onlyLeaves) { return (Image)(new ReconstructImageFromTree()).process(tree,onlyLeaves,data,clazz); } }