Commit f5df793f authored by Daniel Felipe  GONZALEZ OBANDO's avatar Daniel Felipe GONZALEZ OBANDO
Browse files

enabled volume constraint in Plugin GUI

parent 4be794ba
bin bin
pluginfile-active-contours*.jar pluginfile-active-contours*.jar
/ActiveContours.jar
...@@ -80,1797 +80,1610 @@ import plugins.kernel.roi.roi3d.ROI3DStack; ...@@ -80,1797 +80,1610 @@ import plugins.kernel.roi.roi3d.ROI3DStack;
import plugins.nchenouard.spot.Detection; import plugins.nchenouard.spot.Detection;
import vtk.vtkObjectBase; import vtk.vtkObjectBase;
public class ActiveContours extends EzPlug implements EzStoppable, Block public class ActiveContours extends EzPlug implements EzStoppable, Block {
{ public static final String CONTOUR_BASE_NAME = "Contour #";
public static final String CONTOUR_BASE_NAME = "Contour #"; public static final String CONTOUR_ID = "contourId";
public static final String CONTOUR_ID = "contourId";
private class LocalRegionStatisticsComputer implements Callable<Object> {
private class LocalRegionStatisticsComputer implements Callable<Object> final ActiveContour contour;
{ final boolean maskBased;
final ActiveContour contour;
final boolean maskBased; public LocalRegionStatisticsComputer(ActiveContour contour, boolean maskBased) {
this.contour = contour;
public LocalRegionStatisticsComputer(ActiveContour contour, boolean maskBased) this.maskBased = maskBased;
{ }
this.contour = contour;
this.maskBased = maskBased; @Override
} public Object call() {
try {
@Override double cin = contour.computeAverageIntensity(contour instanceof Mesh3D ? regionData : regionDataSummed,
public Object call() maskBased ? contourMask_buffer : null);
{ region_cin.put(trackGroup.getValue().getTrackSegmentWithDetection(contour), cin);
try } catch (TopologyException topo) {
{ System.err.println("Removing a contour. Reason: " + topo.getMessage());
double cin = contour.computeAverageIntensity(contour instanceof Mesh3D ? regionData : regionDataSummed, allContoursAtTimeT.remove(contour);
maskBased ? contourMask_buffer : null); evolvingContoursAtTimeT.remove(contour);
region_cin.put(trackGroup.getValue().getTrackSegmentWithDetection(contour), cin); }
} return null;
catch (TopologyException topo) }
{ }
System.err.println("Removing a contour. Reason: " + topo.getMessage());
allContoursAtTimeT.remove(contour); private class LocalBackgroundStatisticsComputer implements Callable<Object> {
evolvingContoursAtTimeT.remove(contour); final ActiveContour contour;
}
return null; public LocalBackgroundStatisticsComputer(ActiveContour contour) {
} this.contour = contour;
} }
private class LocalBackgroundStatisticsComputer implements Callable<Object> @Override
{ public Object call() {
final ActiveContour contour; TrackSegment segment = trackGroup.getValue().getTrackSegmentWithDetection(contour);
public LocalBackgroundStatisticsComputer(ActiveContour contour) double cout = contour.computeBackgroundIntensity(regionData, contourMask_buffer);
{
this.contour = contour; region_cout.put(segment, cout);
}
return null;
@Override }
public Object call() }
{
TrackSegment segment = trackGroup.getValue().getTrackSegmentWithDetection(contour); private class ContourInitializer implements Callable<Object> {
final ROI roi;
double cout = contour.computeBackgroundIntensity(regionData, contourMask_buffer); final int z;
final int t;
region_cout.put(segment, cout); final Tuple3d pixelSize;
final int convWinSize;
return null; final List<TrackSegment> activeTracks;
} final List<TrackSegment> endedTracks;
}
public ContourInitializer(ROI roi, int z, int t, Tuple3d pixelSize, int convWinSize,
private class ContourInitializer implements Callable<Object> List<TrackSegment> activeTracks, List<TrackSegment> justEndedTracks) {
{ super();
final ROI roi;
final int z; this.roi = roi;
final int t; this.z = z;
final Tuple3d pixelSize; this.t = t;
final int convWinSize; this.pixelSize = pixelSize;
final List<TrackSegment> activeTracks; this.convWinSize = convWinSize;
final List<TrackSegment> endedTracks; this.activeTracks = activeTracks;
this.endedTracks = justEndedTracks;
public ContourInitializer(ROI roi, int z, int t, Tuple3d pixelSize, int convWinSize, }
List<TrackSegment> activeTracks, List<TrackSegment> justEndedTracks)
{ // test if the object is colliding an existing contour or if we need to discard
super(); // it for other reason
private boolean colliding() {
this.roi = roi; // // image bounds
this.z = z; // final Rectangle imageBounds = inputData.getBounds2D();
this.t = t; // // minus one (to detect object on border)
this.pixelSize = pixelSize; // imageBounds.x++;
this.convWinSize = convWinSize; // imageBounds.y++;
this.activeTracks = activeTracks; // imageBounds.width -= 2;
this.endedTracks = justEndedTracks; // imageBounds.height -= 2;
}
// test if object is intersecting with current active contours
// test if the object is colliding an existing contour or if we need to discard it for other reason for (TrackSegment segment : activeTracks) {
private boolean colliding() // get contour for this active track
{ final ActiveContour contour = (ActiveContour) segment.getLastDetection();
// // image bounds // get ROI from contour
// final Rectangle imageBounds = inputData.getBounds2D(); final ROI contourROI = contour.toROI(ROIType.POLYGON, null);
// // minus one (to detect object on border)
// imageBounds.x++; // object is intersecting contour ? --> discard
// imageBounds.y++; if (roi.intersects(contourROI))
// imageBounds.width -= 2; return true;
// imageBounds.height -= 2; }
// test if object is intersecting with current active contours return false;
for (TrackSegment segment : activeTracks) }
{
// get contour for this active track @Override
final ActiveContour contour = (ActiveContour) segment.getLastDetection(); public Object call() {
// get ROI from contour // object colliding active contours ? --> discard it
final ROI contourROI = contour.toROI(ROIType.POLYGON, null); if (colliding())
return null;
// object is intersecting contour ? --> discard
if (roi.intersects(contourROI)) // get contour for the new object
return true; final ActiveContour contour = getContourOf(roi, z, t, pixelSize, convWinSize);
} // error creating contour
if (contour == null)
return false; return null;
}
// does it overlap with a track that terminates in the previous frame?
@Override for (TrackSegment track : endedTracks) {
public Object call() final ActiveContour previousContour = (ActiveContour) track.getLastDetection();
{ // get ROI from contour
// object colliding active contours ? --> discard it final ROI previousContourROI = previousContour.toROI(ROIType.POLYGON, null);
if (colliding())
return null; // object is intersecting previous contour ?
if (roi.intersects(previousContourROI)) {
// get contour for the new object System.out.println(
final ActiveContour contour = getContourOf(roi, z, t, pixelSize, convWinSize); "Found link at time " + t + ", position (" + contour.getX() + ";" + contour.getY() + ")");
// error creating contour // add contour to the track
if (contour == null) track.addDetection(contour);
return null; // done (no new track)
return null;
// does it overlap with a track that terminates in the previous frame? }
for (TrackSegment track : endedTracks) }
{
final ActiveContour previousContour = (ActiveContour) track.getLastDetection(); // need to create a new track
// get ROI from contour final TrackSegment result = new TrackSegment();
final ROI previousContourROI = previousContour.toROI(ROIType.POLYGON, null); // add contour to it
result.addDetection(contour);
// object is intersecting previous contour ?
if (roi.intersects(previousContourROI)) // and return the new created track
{ return result;
System.out.println( }
"Found link at time " + t + ", position (" + contour.getX() + ";" + contour.getY() + ")"); }
// add contour to the track
track.addDetection(contour); private class ContourDuplicator implements Callable<Object> {
// done (no new track) final TrackSegment segment;
return null; final int t;
} final int convWinSize;
}
public ContourDuplicator(TrackSegment segment, int t, int convWinSize) {
// need to create a new track super();
final TrackSegment result = new TrackSegment();
// add contour to it this.segment = segment;
result.addDetection(contour); this.t = t;
this.convWinSize = convWinSize;
// and return the new created track }
return result;
} @Override
} public Object call() {
Detection detection;
private class ContourDuplicator implements Callable<Object>
{ detection = segment.getDetectionAtTime(t);
final TrackSegment segment; // already have detection for that time point (shouldn't be the case) ? --> exit
final int t; if (detection != null)
final int convWinSize; return detection;
public ContourDuplicator(TrackSegment segment, int t, int convWinSize) detection = segment.getDetectionAtTime(t - 1);
{ // no detection for previous time point ? nothing to do
super(); if (detection == null)
return null;
this.segment = segment;
this.t = t; final ActiveContour previousContour = (ActiveContour) detection;
this.convWinSize = convWinSize; final ActiveContour currentContour = previousContour.clone();
}
currentContour.convergence.setSize(convWinSize);
@Override currentContour.setT(t);
public Object call()
{ segment.addDetection(currentContour);
Detection detection;
detection = segment.getDetectionAtTime(t);
// already have detection for that time point (shouldn't be the case) ? --> exit
if (detection != null)
return detection;
detection = segment.getDetectionAtTime(t - 1);
// no detection for previous time point ? nothing to do
if (detection == null)
return null;
final ActiveContour previousContour = (ActiveContour) detection;
final ActiveContour currentContour = previousContour.clone();
currentContour.convergence.setSize(convWinSize);
currentContour.setT(t);
segment.addDetection(currentContour);
return currentContour;
}
}
private final double EPSILON = 0.0000001;
private final EzVarBoolean showAdvancedOptions = new EzVarBoolean("Show advanced options", false);
public final EzVarSequence input = new EzVarSequence("Input"); return currentContour;
private Sequence inputData; }
}
public final EzVarDouble regul_weight = new EzVarDouble("Contour smoothness", 0.05, 0, 1.0, 0.01); private final double EPSILON = 0.0000001;
public final EzGroup edge = new EzGroup("Find bright/dark edges"); private final EzVarBoolean showAdvancedOptions = new EzVarBoolean("Show advanced options", false);
public final EzVarDimensionPicker edge_c = new EzVarDimensionPicker("Find edges in channel", DimensionId.C, input);
public final EzVarDouble edge_weight = new EzVarDouble("Edge weight", 0, -1, 1, 0.1);
public final EzGroup region = new EzGroup("Find homogeneous intensity areas"); public final EzVarSequence input = new EzVarSequence("Input");
public final EzVarDimensionPicker region_c = new EzVarDimensionPicker("Find regions in channel", DimensionId.C, private Sequence inputData;
input);
public final EzVarDouble region_weight = new EzVarDouble("Region weight", 1.0, 0.0, 1.0, 0.1);
public final EzVarDouble region_sensitivity = new EzVarDouble("Region sensitivity", 1.0, 0.2, 5.0, 0.1);
public final EzVarBoolean region_localise = new EzVarBoolean("Variable background", false);
public final EzVarDouble balloon_weight = new EzVarDouble("Contour inflation", 0, -0.5, 0.5, 0.001);
public final EzVarDouble axis_weight = new EzVarDouble("Axis constraint", 0, 0.0, 1, 0.1);
public final EzVarBoolean coupling_flag = new EzVarBoolean("Multi-contour coupling", true);
public final EzGroup evolution = new EzGroup("Evolution parameters");
public final EzVarSequence evolution_bounds = new EzVarSequence("Bound field to ROI of");
public final EzVarDouble contour_resolution = new EzVarDouble("Contour sampling", 2, 0.1, 10000.0, 0.1);
public final EzVarDouble contour_timeStep = new EzVarDouble("Evolution time step", 0.1, 0.1, 10, 0.01);
public final EzVarInteger convergence_winSize = new EzVarInteger("Convergence window size", 50, 10, 10000, 10);
public final EzVarEnum<Operation> convergence_operation = new EzVarEnum<SlidingWindow.Operation>(
"Convergence operation", Operation.values(), Operation.VAR_COEFF);
public final EzVarDouble convergence_criterion = new EzVarDouble("Convergence criterion", 0.001, 0, 1, 0.0001);
public final EzVarInteger convergence_nbIter = new EzVarInteger("Max. iterations", 100000, 100, 100000, 1000);
public enum ExportROI
{
NO, ON_INPUT, ON_NEW_IMAGE, AS_LABELS
}
public enum ROIType
{
AREA(ROI2DArea.class), POLYGON(ROI2DPolygon.class);
final Class<? extends ROI> clazz; public final EzVarDouble regul_weight = new EzVarDouble("Contour smoothness", 0.05, 0, 1.0, 0.01);
private ROIType(Class<? extends ROI> clazz) public final EzGroup edge = new EzGroup("Find bright/dark edges");
{ public final EzVarDimensionPicker edge_c = new EzVarDimensionPicker("Find edges in channel", DimensionId.C, input);
this.clazz = clazz; public final EzVarDouble edge_weight = new EzVarDouble("Edge weight", 0, -1, 1, 0.1);
}
}
public final EzVarEnum<ExportROI> output_rois = new EzVarEnum<ExportROI>("Export ROI", ExportROI.values(), public final EzGroup region = new EzGroup("Find homogeneous intensity areas");
ExportROI.NO); public final EzVarDimensionPicker region_c = new EzVarDimensionPicker("Find regions in channel", DimensionId.C,
public final EzVarEnum<ROIType> output_roiType = new EzVarEnum<ROIType>("Type of ROI", ROIType.values(), input);
ROIType.AREA); public final EzVarDouble region_weight = new EzVarDouble("Region weight", 1.0, 0.0, 1.0, 0.1);
private VarSequence output_labels = new VarSequence("Labels", null); public final EzVarDouble region_sensitivity = new EzVarDouble("Region sensitivity", 1.0, 0.2, 5.0, 0.1);
public final EzVarBoolean region_localise = new EzVarBoolean("Variable background", false);
public final EzVarBoolean tracking = new EzVarBoolean("Track objects over time", false);
public final EzVarDouble balloon_weight = new EzVarDouble("Contour inflation", 0, -0.5, 0.5, 0.001);
public final EzVarDouble division_sensitivity = new EzVarDouble("Division sensitivity", 0, 0, 2, 0.1);
public final EzVarDouble axis_weight = new EzVarDouble("Axis constraint", 0, 0.0, 1, 0.1);
public final EzVarBoolean tracking_newObjects = new EzVarBoolean("Watch entering objects", false);
public final EzVarBoolean coupling_flag = new EzVarBoolean("Multi-contour coupling", true);
private final HashMap<TrackSegment, Double> volumes = new HashMap<TrackSegment, Double>();
public final EzVarBoolean volume_constraint = new EzVarBoolean("Volume constraint", false); public final EzGroup evolution = new EzGroup("Evolution parameters");
public final EzVarDouble volume_weight = new EzVarDouble("Volume weight", 0.01, 0,1, 0.01); public final EzVarSequence evolution_bounds = new EzVarSequence("Bound field to ROI of");
public final EzVarDouble contour_resolution = new EzVarDouble("Contour sampling", 2, 0.1, 10000.0, 0.1);
public final EzButton showTrackManager; public final EzVarDouble contour_timeStep = new EzVarDouble("Evolution time step", 0.1, 0.1, 10, 0.01);
public final EzVarInteger convergence_winSize = new EzVarInteger("Convergence window size", 50, 10, 10000, 10);
private Sequence edgeData; public final EzVarEnum<Operation> convergence_operation = new EzVarEnum<SlidingWindow.Operation>(
private Sequence regionData; "Convergence operation", Operation.values(), Operation.VAR_COEFF);
private Sequence regionDataSummed; public final EzVarDouble convergence_criterion = new EzVarDouble("Convergence criterion", 0.001, 0, 1, 0.0001);
public final EzVarInteger convergence_nbIter = new EzVarInteger("Max. iterations", 100000, 100, 100000, 1000);
private BooleanMask3D contourMask_buffer;
public enum ExportROI {
HashMap<TrackSegment, Double> region_cin = new HashMap<TrackSegment, Double>(0); NO, ON_INPUT, ON_NEW_IMAGE, AS_LABELS
HashMap<TrackSegment, Double> region_cout = new HashMap<TrackSegment, Double>(0); }
public final VarROIArray roiInput = new VarROIArray("input ROI"); public enum ROIType {
public final VarROIArray roiOutput = new VarROIArray("Regions of interest"); AREA(ROI2DArea.class), POLYGON(ROI2DPolygon.class);
private boolean globalStop; final Class<? extends ROI> clazz;
Var<TrackGroup> trackGroup = new Var<TrackGroup>("Tracks", TrackGroup.class); private ROIType(Class<? extends ROI> clazz) {
this.clazz = clazz;
/** }
* All contours present on the current time point }
*/
private final HashSet<ActiveContour> allContoursAtTimeT = new HashSet<ActiveContour>(); public final EzVarEnum<ExportROI> output_rois = new EzVarEnum<ExportROI>("Export ROI", ExportROI.values(),
ExportROI.NO);
/** public final EzVarEnum<ROIType> output_roiType = new EzVarEnum<ROIType>("Type of ROI", ROIType.values(),
* Set of contours that have not yet converged on the current time point ROIType.AREA);
*/ private VarSequence output_labels = new VarSequence("Labels", null);
private final HashSet<ActiveContour> evolvingContoursAtTimeT = new HashSet<ActiveContour>();
public final EzVarBoolean tracking = new EzVarBoolean("Track objects over time", false);
private ActiveContoursOverlay overlay;
public final EzVarDouble division_sensitivity = new EzVarDouble("Division sensitivity", 0, 0, 2, 0.1);
private Processor multiThreadService = new Processor(SystemUtil.getNumberOfCPUs());
public final EzVarBoolean tracking_newObjects = new EzVarBoolean("Watch entering objects", false);
private long lastVtkGCTime = 0L;
private final HashMap<TrackSegment, Double> volumes = new HashMap<TrackSegment, Double>();
public ActiveContours() public final EzVarBoolean volume_constraint = new EzVarBoolean("Volume constraint", false);
{ public final EzVarDouble volume_weight = new EzVarDouble("Volume weight", 0.01, 0, 1, 0.001);
super();
public final EzButton showTrackManager;
multiThreadService.setThreadName("Active Contours");
private Sequence edgeData;
showTrackManager = new EzButton("Send to track manager", new ActionListener() private Sequence regionData;
{ private Sequence regionDataSummed;
@Override
public void actionPerformed(ActionEvent e) private BooleanMask3D contourMask_buffer;
{
ThreadUtil.invokeLater(new Runnable() HashMap<TrackSegment, Double> region_cin = new HashMap<TrackSegment, Double>(0);
{ HashMap<TrackSegment, Double> region_cout = new HashMap<TrackSegment, Double>(0);
@Override
public void run() public final VarROIArray roiInput = new VarROIArray("input ROI");
{ public final VarROIArray roiOutput = new VarROIArray("Regions of interest");
if (trackGroup.getValue() == null)
return; private boolean globalStop;
if (trackGroup.getValue().getTrackSegmentList().isEmpty())
return; Var<TrackGroup> trackGroup = new Var<TrackGroup>("Tracks", TrackGroup.class);
Icy.getMainInterface().getSwimmingPool().add(new SwimmingObject(trackGroup.getValue())); /**
TrackManager tm = new TrackManager(); * All contours present on the current time point
tm.reOrganize(); */
tm.setDisplaySequence(inputData); private final HashSet<ActiveContour> allContoursAtTimeT = new HashSet<ActiveContour>();
}
}); /**
} * Set of contours that have not yet converged on the current time point
}); */
} private final HashSet<ActiveContour> evolvingContoursAtTimeT = new HashSet<ActiveContour>();
public TrackGroup getTrackGroup() private ActiveContoursOverlay overlay;
{
return trackGroup.getValue(); private Processor multiThreadService = new Processor(SystemUtil.getNumberOfCPUs());
}
private long lastVtkGCTime = 0L;
@Override
public void initialize() public ActiveContours() {
{ super();
addEzComponent(showAdvancedOptions);
addEzComponent(input); multiThreadService.setThreadName("Active Contours");
// edge showTrackManager = new EzButton("Send to track manager", new ActionListener() {
edge.setToolTipText("Sets the contour(s) to follow image intensity gradients"); @Override
edge_weight.setToolTipText( public void actionPerformed(ActionEvent e) {
"Negative (resp. positive) weight pushes contours toward decreasing (resp. increasing) intensities"); ThreadUtil.invokeLater(new Runnable() {