Skip to content

Commit

Permalink
Merge branch 'master' into macro
Browse files Browse the repository at this point in the history
  • Loading branch information
uschmidt83 committed Apr 7, 2020
2 parents f290dc6 + 7f0cffe commit dd20147
Show file tree
Hide file tree
Showing 9 changed files with 204 additions and 127 deletions.
22 changes: 16 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
<parent>
<groupId>org.scijava</groupId>
<artifactId>pom-scijava</artifactId>
<version>27.0.1</version>
<version>28.0.0</version>
<relativePath />
</parent>

<groupId>de.csbdresden</groupId>
<artifactId>StarDist_</artifactId>
<version>0.1.0</version>
<version>0.2.0</version>

<name>StarDist</name>
<description>StarDist - Object Detection with Star-convex Shapes</description>
Expand Down Expand Up @@ -69,6 +69,16 @@
<url>https://github.com/frauzufall</url>
<roles><role>reviewer</role></roles>
</contributor>
<contributor>
<name>Olivier Burri</name>
<url>https://github.com/lacan</url>
<roles><role>developer</role></roles>
</contributor>
<contributor>
<name>Romain Guiet</name>
<url>https://github.com/romainGuiet</url>
<roles><role>developer</role></roles>
</contributor>
</contributors>

<mailingLists>
Expand All @@ -79,14 +89,14 @@
</mailingLists>

<scm>
<connection>scm:git:git://github.com/uschmidt83/stardist-imagej</connection>
<developerConnection>scm:git:git://github.com/uschmidt83/stardist-imagej</developerConnection>
<connection>scm:git:git://github.com/mpicbg-csbd/stardist-imagej</connection>
<developerConnection>scm:git:git://github.com/mpicbg-csbd/stardist-imagej</developerConnection>
<tag>HEAD</tag>
<url>https://github.com/uschmidt83/stardist-imagej</url>
<url>https://github.com/mpicbg-csbd/stardist-imagej</url>
</scm>
<issueManagement>
<system>GitHub Issues</system>
<url>https://github.com/uschmidt83/stardist-imagej/issues</url>
<url>https://github.com/mpicbg-csbd/stardist-imagej/issues</url>
</issueManagement>
<ciManagement>
<system>None</system>
Expand Down
52 changes: 35 additions & 17 deletions src/main/java/de/csbdresden/stardist/Candidates.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
import de.lighti.clipper.Path;
import de.lighti.clipper.Paths;
import de.lighti.clipper.Point.LongPoint;
import ij.gui.PointRoi;
import ij.gui.PolygonRoi;
import ij.gui.Roi;
import net.imglib2.RandomAccess;
import net.imglib2.RandomAccessibleInterval;
import net.imglib2.type.numeric.real.FloatType;
Expand All @@ -29,6 +32,9 @@ public class Candidates {
private final boolean[] suppressed;
private final boolean verbose;
private final LogService log;

// scale all coordinates by this value and divide later to get subpixel resolution
private static final long S = 100;

public Candidates(RandomAccessibleInterval<FloatType> prob, RandomAccessibleInterval<FloatType> dist) {
this(prob, dist, 0.4);
Expand Down Expand Up @@ -65,8 +71,8 @@ public Candidates(RandomAccessibleInterval<FloatType> prob, RandomAccessibleInte
for (int k = 0; k < nrays; k++) {
s.setPosition(k, 2);
FloatType d = s.get();
long x = Math.round(i + d.getRealDouble() * Math.cos(phis[k]));
long y = Math.round(j + d.getRealDouble() * Math.sin(phis[k]));
long x = Math.round(S * (i + d.getRealDouble() * Math.cos(phis[k])));
long y = Math.round(S * (j + d.getRealDouble() * Math.sin(phis[k])));
xmin = Math.min(xmin,x);
ymin = Math.min(ymin,y);
xmax = Math.max(xmax,x);
Expand All @@ -75,7 +81,7 @@ public Candidates(RandomAccessibleInterval<FloatType> prob, RandomAccessibleInte
}
polygons.add(poly);
bboxes.add(new Box2D(xmin,xmax,ymin,ymax));
origins.add(new Point2D(i,j));
origins.add(new Point2D(S*i,S*j));
scores.add(score);
areas.add(poly.area());
}
Expand Down Expand Up @@ -165,24 +171,36 @@ public List<Integer> getSorted() {
return score_indices;
}

public Point2D getOrigin(int i) {
return origins.get(i);
}
// public Point2D getOrigin(int i) {
// return origins.get(i);
// }

public Path getPolygon(int i) {
return polygons.get(i);
}
// public Path getPolygon(int i) {
// return polygons.get(i);
// }

public Box2D getBbox(int i) {
return bboxes.get(i);
}
// public Box2D getBbox(int i) {
// return bboxes.get(i);
// }

public float getScore(int i) {
return scores.get(i);
}
// public float getScore(int i) {
// return scores.get(i);
// }

public double getArea(int i) {
return areas.get(i);
// public double getArea(int i) {
// return areas.get(i);
// }

public PolygonRoi getPolygonRoi(int i) {
return Utils.toPolygonRoi(polygons.get(i), S);
}

public PointRoi getOriginRoi(int i) {
return Utils.toPointRoi(origins.get(i), S);
}

public Roi getBboxRoi(int i) {
return Utils.toBoxRoi(bboxes.get(i), S);
}


Expand Down
5 changes: 5 additions & 0 deletions src/main/java/de/csbdresden/stardist/Opt.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ public class Opt {

static final String NUM_TILES = "Number of Tiles";
static final String EXCLUDE_BNDRY = "Boundary Exclusion";
static final String ROI_POSITION = "ROI Position";
static final String ROI_POSITION_AUTO = "Automatic";
static final String ROI_POSITION_STACK = "Stack";
static final String ROI_POSITION_HYPERSTACK = "Hyperstack";
static final String VERBOSE = "Verbose";
static final String CSBDEEP_PROGRESS_WINDOW = "Show CNN Progress";
static final String SHOW_PROB_DIST = "Show CNN Output";
Expand All @@ -48,6 +52,7 @@ public class Opt {
DEFAULTS.put(OUTPUT_TYPE, OUTPUT_BOTH);
DEFAULTS.put(NUM_TILES, 1);
DEFAULTS.put(EXCLUDE_BNDRY, 2);
DEFAULTS.put(ROI_POSITION, ROI_POSITION_AUTO);
DEFAULTS.put(VERBOSE, false);
DEFAULTS.put(CSBDEEP_PROGRESS_WINDOW, false);
DEFAULTS.put(SHOW_PROB_DIST, false);
Expand Down
62 changes: 38 additions & 24 deletions src/main/java/de/csbdresden/stardist/StarDist2D.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import static de.csbdresden.stardist.StarDist2DModel.MODELS;
import static de.csbdresden.stardist.StarDist2DModel.MODEL_DSB2018_HEAVY_AUGMENTATION;
import static de.csbdresden.stardist.StarDist2DModel.MODEL_DSB2018_PAPER;
import static de.csbdresden.stardist.StarDist2DModel.MODEL_HE_HEAVY_AUGMENTATION;

import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -54,7 +55,7 @@ public class StarDist2D extends StarDist2DBase implements Command {
private final String msgTitle = "<html>" +
"<table><tr valign='top'><td>" +
"<h2>Object Detection with Star-convex Shapes</h2>" +
"<a href='https://github.com/mpicbg-csbd/stardist'>https://github.com/mpicbg-csbd/stardist</a>" +
"<a href='https://imagej.net/StarDist'>https://imagej.net/StarDist</a>" +
"<br/><br/><small>Please cite our paper if StarDist was helpful for your research. Thanks!</small>" +
"</td><td>&nbsp;&nbsp;<img src='"+getResource("images/logo.png")+"' width='100' height='100'></img><td>" +
"</tr></table>" +
Expand All @@ -70,6 +71,7 @@ public class StarDist2D extends StarDist2DBase implements Command {

@Parameter(label=Opt.MODEL,
choices={MODEL_DSB2018_HEAVY_AUGMENTATION,
MODEL_HE_HEAVY_AUGMENTATION,
MODEL_DSB2018_PAPER,
Opt.MODEL_FILE,
Opt.MODEL_URL}, style=ChoiceWidget.LIST_BOX_STYLE)
Expand All @@ -83,7 +85,7 @@ public class StarDist2D extends StarDist2DBase implements Command {

@Parameter(label=Opt.PERCENTILE_HIGH, stepSize="0.1", min="0", max="100", style=NumberWidget.SLIDER_STYLE, callback="percentileTopChanged")
private double percentileTop = (double) Opt.getDefault(Opt.PERCENTILE_HIGH);

@Parameter(label=Opt.PROB_IMAGE, type=ItemIO.OUTPUT)
private Dataset prob;

Expand Down Expand Up @@ -123,16 +125,20 @@ public class StarDist2D extends StarDist2DBase implements Command {

@Parameter(label=Opt.EXCLUDE_BNDRY, min="0", stepSize="1")
private int excludeBoundary = (int) Opt.getDefault(Opt.EXCLUDE_BNDRY);

@Parameter(label=Opt.ROI_POSITION, choices={Opt.ROI_POSITION_AUTO, Opt.ROI_POSITION_STACK, Opt.ROI_POSITION_HYPERSTACK}, style=ChoiceWidget.RADIO_BUTTON_HORIZONTAL_STYLE)
private String roiPosition = (String) Opt.getDefault(Opt.ROI_POSITION);
private String roiPositionActive = null;

@Parameter(label=Opt.VERBOSE)
private boolean verbose = (boolean) Opt.getDefault(Opt.VERBOSE);

@Parameter(label=Opt.CSBDEEP_PROGRESS_WINDOW)
private boolean showCsbdeepProgress = (boolean) Opt.getDefault(Opt.CSBDEEP_PROGRESS_WINDOW);

@Parameter(label=Opt.SHOW_PROB_DIST)
private boolean showProbAndDist = (boolean) Opt.getDefault(Opt.SHOW_PROB_DIST);

// TODO: values for block multiple and overlap

@Parameter(label=Opt.SET_THRESHOLDS, callback="setThresholds")
Expand All @@ -153,6 +159,7 @@ private void restoreDefaults() {
outputType = (String) Opt.getDefault(Opt.OUTPUT_TYPE);
nTiles = (int) Opt.getDefault(Opt.NUM_TILES);
excludeBoundary = (int) Opt.getDefault(Opt.EXCLUDE_BNDRY);
roiPosition = (String) Opt.getDefault(Opt.ROI_POSITION);
verbose = (boolean) Opt.getDefault(Opt.VERBOSE);
showCsbdeepProgress = (boolean) Opt.getDefault(Opt.CSBDEEP_PROGRESS_WINDOW);
showProbAndDist = (boolean) Opt.getDefault(Opt.SHOW_PROB_DIST);
Expand All @@ -165,7 +172,7 @@ private void percentileBottomChanged() {
private void percentileTopChanged() {
percentileBottom = Math.min(percentileBottom, percentileTop);
}

private void setThresholds() {
switch (modelChoice) {
case Opt.MODEL_FILE:
Expand Down Expand Up @@ -203,7 +210,12 @@ private void checkForCSBDeep() {
public void run() {
checkForCSBDeep();
if (!checkInputs()) return;


if (roiPosition.equals(Opt.ROI_POSITION_AUTO))
roiPositionActive = input.numDimensions() > 3 ? Opt.ROI_POSITION_HYPERSTACK : Opt.ROI_POSITION_STACK;
else
roiPositionActive = roiPosition;

File tmpModelFile = null;
try {
final HashMap<String, Object> paramsCNN = new HashMap<>();
Expand Down Expand Up @@ -238,13 +250,14 @@ public void run() {
paramsCNN.put("blockMultiple", pretrainedModel.sizeDivBy);
paramsCNN.put("overlap", pretrainedModel.tileOverlap);
}

final HashMap<String, Object> paramsNMS = new HashMap<>();
paramsNMS.put("probThresh", probThresh);
paramsNMS.put("nmsThresh", nmsThresh);
paramsNMS.put("excludeBoundary", excludeBoundary);
paramsNMS.put("verbose", verbose);

paramsNMS.put("roiPosition", roiPositionActive);
paramsNMS.put("verbose", verbose);

final LinkedHashSet<AxisType> inputAxes = Utils.orderedAxesSet(input);
final boolean isTimelapse = inputAxes.contains(Axes.TIME);

Expand Down Expand Up @@ -276,11 +289,12 @@ public void run() {

final Future<CommandModule> futureNMS = command.run(StarDist2DNMS.class, false, paramsNMS);
final Candidates polygons = (Candidates) futureNMS.get().getOutput("polygons");
export(outputType, polygons, 1+t);
export(outputType, polygons, 1+t, numFrames, roiPositionActive);

status.showProgress(1+t, (int)numFrames);
}
label = labelImageToDataset(outputType);
label = labelImageToDataset(outputType);
// if (roiManager != null) OverlayCommands.listRois(roiManager.getRoisAsArray());

} else {
// note: the code below supports timelapse data too. differences to above:
Expand All @@ -289,7 +303,7 @@ public void run() {
// - allows showing prob and dist easily
final Future<CommandModule> futureCNN = command.run(de.csbdresden.csbdeep.commands.GenericNetwork.class, false, paramsCNN);
final Dataset prediction = (Dataset) futureCNN.get().getOutput("output");

final Pair<Dataset, Dataset> probAndDist = splitPrediction(prediction);
final Dataset probDS = probAndDist.getA();
final Dataset distDS = probAndDist.getB();
Expand Down Expand Up @@ -318,7 +332,7 @@ public void run() {
}
}
}

// this function is very cumbersome... is there a better way to do this?
private Pair<Dataset, Dataset> splitPrediction(final Dataset prediction) {
final RandomAccessibleInterval<FloatType> predictionRAI = (RandomAccessibleInterval<FloatType>) prediction.getImgPlus();
Expand All @@ -331,7 +345,7 @@ private Pair<Dataset, Dataset> splitPrediction(final Dataset prediction) {
final long[] predSize = predAxes.stream().mapToLong(axis -> {
return axis == Axes.CHANNEL ? prediction.dimension(axis)-1 : prediction.dimension(axis);
}).toArray();

final RandomAccessibleInterval<FloatType> probRAI = Views.hyperSlice(predictionRAI, predChannelDim, 0);
final RandomAccessibleInterval<FloatType> distRAI = Views.offsetInterval(predictionRAI, predStart, predSize);

Expand All @@ -349,23 +363,23 @@ private boolean checkInputs() {
(input.numDimensions() == 3 && axes.containsAll(Arrays.asList(Axes.X, Axes.Y, Axes.CHANNEL))) ||
(input.numDimensions() == 4 && axes.containsAll(Arrays.asList(Axes.X, Axes.Y, Axes.CHANNEL, Axes.TIME))) ))
return showError("Input must be a 2D image or timelapse (with or without channels).");
if (!( modelChoice.equals(Opt.MODEL_FILE) || modelChoice.equals(Opt.MODEL_URL) || MODELS.containsKey(modelChoice) ))

if (!( modelChoice.equals(Opt.MODEL_FILE) || modelChoice.equals(Opt.MODEL_URL) || MODELS.containsKey(modelChoice) ))
return showError(String.format("Unsupported Model \"%s\".", modelChoice));

return true;
}


@Override
protected void exportPolygons(Candidates polygons) {}


@Override
protected ImagePlus createLabelImage() {
return IJ.createImage("Labeling", "16-bit black", (int)input.getWidth(), (int)input.getHeight(), 1, 1, (int)input.getFrames());
return IJ.createImage(Opt.LABEL_IMAGE, "16-bit black", (int)input.getWidth(), (int)input.getHeight(), 1, 1, (int)input.getFrames());
}


public static void main(final String... args) throws Exception {
final ImageJ ij = new ImageJ();
Expand Down
Loading

0 comments on commit dd20147

Please sign in to comment.