/**
*
*/
package fr.unistra.pelican.algorithms.morphology.connected;
import fr.unistra.pelican.Algorithm;
import fr.unistra.pelican.AlgorithmException;
import fr.unistra.pelican.Image;
import fr.unistra.pelican.algorithms.morphology.connected.ReconstructImageFromTree.Data;
import fr.unistra.pelican.algorithms.visualisation.MViewer;
import fr.unistra.pelican.util.connectivityTrees.ComponentNode;
import fr.unistra.pelican.util.connectivityTrees.ComponentTree;
import fr.unistra.pelican.util.connectivityTrees.ComponentTreeUtil;
import fr.unistra.pelican.util.connectivityTrees.attributes.AttributeEnergy;
import fr.unistra.pelican.util.connectivityTrees.attributes.AttributeEnergyPerPixel;
import fr.unistra.pelican.util.connectivityTrees.attributes.AttributeSum;
import fr.unistra.pelican.util.connectivityTrees.attributes.AttributeVolume;
import fr.unistra.pelican.util.connectivityTrees.attributes.UnsupportedDataTypeException;
/**
* Source deblending algorithm. Developed for astronomical images, perhaps other uses exist.
*
* The algorithm filters a component tree to perform sources separation.
*
* A node is an independent source if :
* - its volume is bigger than a given fraction of the volume of its parent
* - at least one other child of its parent fulfill previous condition
*
* @author Benjamin Perret
*
*/
public class VolumeDeblender<T> extends Algorithm {
/**
* The tree to filter
*/
public ComponentTree<T> tree;
/**
* print debug info?
*/
private boolean DEBUG=false;
/**
* threshold
*/
public double fractionThreshold=0.005;
public double energyThreshold=Double.POSITIVE_INFINITY;
/**
*
*/
public VolumeDeblender() {
super.inputs="tree";
super.options="fractionThreshold,energyThreshold";
super.outputs="tree";
}
private double getVolume(ComponentNode<Double> n)
{
return n.getAttributeValue(AttributeVolume.class);
}
private void filter3()
{
ComponentNode<T> root = tree.getRoot();
double volume = root.getAttributeValue(AttributeVolume.class);
double t = fractionThreshold * volume;
//System.out.println("threshold " + t);
tree.resetFlag(0);
// MViewer.exec(ReconstructImageFromTree.exec(tree, Data.Attribute, AttributeEnergyPerPixel.class));
for (ComponentNode<T> n : tree.iterateFromLeafToRoot()) {
if (n != root) {
// if (n.numberOfChildren() < 2)
// tree.deleteNode(n);
// else {
int count = 0;
// System.out.println("Going for " + n.location);
// double volume=n.getAttributeValue(AttributeVolume.class);
// double t=fractionThreshold*volume;
/*volume = n.getAttributeValue(AttributeVolume.class);
t = fractionThreshold * volume;*/
for (ComponentNode<T> child : n.getChildren()) {
double vv = child.getAttributeValue(AttributeVolume.class);
if (child.flag!=1 && vv >= t) {
// System.out.println("-child " + child.location
// + " is ok (v=" + vv);
count++;
}
}
//System.out.println("->count " + count + " on "
// + n.numberOfChildren());
for (ComponentNode<T> child : n.getChildren()) {
double vv = child.getAttributeValue(AttributeVolume.class);
double ee = child.getAttributeValue(AttributeEnergyPerPixel.class);
if ( (count < 2 || vv < t) ) {
//System.out.println("-->delete " + child.location
// + " volume " + vv);
// tree.deleteNode(child);
if(ee < energyThreshold)
child.flag = 1;
else {
//System.out.println("-->saved1 " + child.location + " volume " + vv);
}
} else {
//System.out.println("-->saved2 " + child.location + " volume " + vv +" count " +count );
}
}
}
}
tree.deleteOldNodeWithFlag(1);
}
/* (non-Javadoc)
* @see fr.unistra.pelican.Algorithm#launch()
*/
@Override
public void launch() throws AlgorithmException {
filter3();
}
public static <T> ComponentTree<T> exec(ComponentTree<T> tree)
{
return (ComponentTree<T>)(new VolumeDeblender<T>()).process(tree);
}
public static <T> ComponentTree<T> exec(ComponentTree<T> tree, double fractionThreshold, double energyThreshold)
{
return (ComponentTree<T>)(new VolumeDeblender<T>()).process(tree,fractionThreshold,energyThreshold);
}
/**
* @param args
* @throws UnsupportedDataTypeException
*/
public static void main(String[] args) {
ComponentTree<double []> root = ComponentTreeUtil.getTestCaseVectorial();
try {
System.out.println(root.getRoot());
root.addAttribute(new AttributeSum());
root.addAttribute(new AttributeVolume());
root=VolumeDeblender.exec(root);
Image im0=ReconstructImageFromTree.exec(root,Data.Attribute,AttributeVolume.class);
Image im1=ReconstructImageFromTree.exec(root);
MViewer.exec(root.image,im0,im1);
} catch (UnsupportedDataTypeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}