Skip to content

Commit

Permalink
Merge pull request #25 from xraynaud/master
Browse files Browse the repository at this point in the history
Master
  • Loading branch information
Thorsten Wagner authored Mar 4, 2017
2 parents bcc137b + 8122eef commit df0d3b8
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 32 deletions.
86 changes: 74 additions & 12 deletions src/main/java/de/biomedical_imaging/ij/steger/LineDetector.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,23 +70,23 @@ public class LineDetector {
* @return An arraylist with line objects
*/
public Lines detectLines(ImageProcessor ip, double sigma,
double upperThresh, double lowerThresh, boolean isDarkLine,
double upperThresh, double lowerThresh, double minLength, double maxLength, boolean isDarkLine,
boolean doCorrectPosition, boolean doEstimateWidth,
boolean doExtendLine) {
return detectLines(ip, sigma, upperThresh, lowerThresh, isDarkLine,
return detectLines(ip, sigma, upperThresh, lowerThresh, minLength, maxLength,isDarkLine,
doCorrectPosition, doEstimateWidth, doExtendLine, OverlapOption.NONE);
}

public Lines detectLines(ImageProcessor ip, double sigma,
double upperThresh, double lowerThresh, boolean isDarkLine,
double upperThresh, double lowerThresh, double minLength, double maxLength, boolean isDarkLine,
boolean doCorrectPosition, boolean doEstimateWidth,
boolean doExtendLine, OverlapOption overlapOption) {
this.isDarkLine = isDarkLine;
this.doCorrectPosition = doCorrectPosition;
this.doEstimateWidth = doEstimateWidth;
this.doExtendLine = doExtendLine;
junctions = new Junctions(ip.getSliceNumber());
lines = get_lines(sigma, upperThresh, lowerThresh, ip.getHeight(),
lines = get_lines(sigma, upperThresh, lowerThresh, minLength, maxLength, ip.getHeight(),
ip.getWidth(), ip, junctions, overlapOption);
return lines;
}
Expand Down Expand Up @@ -496,7 +496,8 @@ private double[] minDistance(Line l, float x, float y){
double[] ret = {min,index};
return ret;
}
private void deleteContour(Lines contours, Junctions junctions, Line c) {

/* private void deleteContour(Lines contours, Junctions junctions, Line c) {
ArrayList<Junction> remove = new ArrayList<Junction>();
for (Junction junction : junctions) {
Expand All @@ -512,20 +513,52 @@ private void deleteContour(Lines contours, Junctions junctions, Line c) {
}
contours.remove(c);
} */

//To be removed once the problem with junctions.cont1 & .cont2 is solved.
private void deleteJunctions(Lines contours, Junctions junctions, Line c) {
deleteJunctions(contours, junctions, c, OverlapOption.NONE);
}
private void deleteJunctions(Lines contours, Junctions junctions, Line c, OverlapOption overlapOption) {

ArrayList<Junction> remove = new ArrayList<Junction>();
for (Junction junction : junctions) {
// This if() should be removed once cont1 and 2 contain the same info whatever OverlapOption
if (overlapOption == OverlapOption.SLOPE) {
if (junction.cont1 == c.getID() || junction.cont2 == c.getID()) {
log("Removing junction between line IDs"+ junction.cont1+ " and "+junction.cont2);
remove.add(junction);
}
} else {
if (contours.get((int) junction.cont1).getID() == c.getID()
|| contours.get((int) junction.cont2).getID() == c.getID()) {
log("Removing junction between line idx "+ junction.cont1+ " and "+junction.cont2);
remove.add(junction);
}
}
}
for (Junction junction : remove) {
junctions.remove(junction);
}
}

private void fixContours(Lines contours, Junctions junctions) {

ArrayList<Line> remove = new ArrayList<Line>();
// Contours with only a single position cant be valid.
for (Line contour : contours) {
if (contour.num == 1) {
deleteContour(contours,junctions,contour);
continue;
deleteJunctions(contours,junctions,contour);
remove.add(contour);
}
//If the results are corrupted, this informationen has to be reconstructed in fixJunctions
contour.setContourClass(LinesUtil.contour_class.cont_no_junc);
}

for (Line c : remove) {
contours.remove(c);
}

// For some reason the first and the last element are the same. Delete
// it!

Expand All @@ -535,21 +568,45 @@ private void fixContours(Lines contours, Junctions junctions) {
}
}
}

private Lines get_lines(double sigma, double high, double low, int rows,

private void pruneContours(Lines contours, Junctions junctions, double minLength, double maxLength, OverlapOption overlapOption) {
ArrayList<Line> remove = new ArrayList<Line>();

log("Pruning lines:");
for (Line c : contours) {
if ((c.estimateLength() < minLength) || (maxLength > 0 && c.estimateLength() > maxLength)) {
log("Removing line "+c.getID()+ " of length "+c.estimateLength());
deleteJunctions(contours, junctions, c,overlapOption);
remove.add(c);
} else {
log("Keeping line "+c.getID()+ " of length "+c.estimateLength());
}
}
for (Line c : remove) {

contours.remove(c);
}
}



private Lines get_lines(double sigma, double high, double low, double minLength, double maxLength, int rows,
int cols, ImageProcessor in_img, Junctions resultJunction, OverlapOption overlapOption) {
FloatProcessor image;
Lines contours = new Lines(in_img.getSliceNumber());
int num_cont = 0;
opts = new Options(-1.0, -1.0, -1.0, isDarkLine ? LinesUtil.MODE_DARK
: LinesUtil.MODE_LIGHT, doCorrectPosition, doEstimateWidth,
: LinesUtil.MODE_LIGHT, -1.0, -1.0, doCorrectPosition, doEstimateWidth,
doExtendLine, false, false, false, overlapOption);

opts.sigma = sigma;
opts.high = high;
opts.low = low;
check_sigma(opts.sigma, cols, rows);

opts.minLength = minLength;
opts.maxLength = maxLength;

OverlapResolver resolver = null;

switch (overlapOption) {
Expand Down Expand Up @@ -591,7 +648,7 @@ private Lines get_lines(double sigma, double high, double low, int rows,
junctions = resultJunction;

/*
* RECONSRUCTION OF CONTOUR CLASS
* RECONSTRUCTION OF CONTOUR CLASS
*/
//Reset contour class
for(int i = 0; i < contours.size(); i++){
Expand All @@ -615,8 +672,13 @@ private Lines get_lines(double sigma, double high, double low, int rows,
j.getLine2().setContourClass(reconstructContourClass(j.getLine2(),j.getLine2().getStartOrdEndPosition(x, y)));
}


if (resolver != null) contours = resolver.resolve(contours, junctions, bechatty);

if (minLength != 0 || maxLength != 0) {
pruneContours(contours, junctions, minLength, maxLength,overlapOption);
}


return contours;

}
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/de/biomedical_imaging/ij/steger/Lines.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
package de.biomedical_imaging.ij.steger;

import java.util.ArrayList;
import java.util.Iterator;

public class Lines extends ArrayList<Line> {

Expand Down Expand Up @@ -52,6 +53,4 @@ public int getIndexByID(int id){
}
return -1;
}


}
88 changes: 71 additions & 17 deletions src/main/java/de/biomedical_imaging/ij/steger/Lines_.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
import java.awt.Color;
import java.awt.Font;
import java.awt.TextField;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.CompositeImage;
import ij.Prefs;
import ij.gui.DialogListener;
import ij.gui.GenericDialog;
Expand All @@ -48,6 +50,7 @@
import ij.plugin.filter.PlugInFilterRunner;
import ij.plugin.frame.RoiManager;
import ij.process.FloatPolygon;
import ij.process.LUT;
import ij.process.ImageProcessor;


Expand All @@ -70,6 +73,12 @@ public class Lines_ implements ExtendedPlugInFilter, DialogListener {
final static double upperThreshDefault = 7.99;
double upperThresh = upperThreshDefault;

final static double minLengthDefault = 0;
double minLength = minLengthDefault;

final static double maxLengthDefault = 0;
double maxLength = maxLengthDefault;

final static boolean isDarkLineDefault = false;
boolean isDarkLine = isDarkLineDefault;

Expand All @@ -91,7 +100,7 @@ public class Lines_ implements ExtendedPlugInFilter, DialogListener {
final static boolean addToRoiManagerDefault = true;
boolean addToRoiManager = addToRoiManagerDefault;

final static boolean makeBinaryDefault = true;
final static boolean makeBinaryDefault = false;
boolean makeBinary = makeBinaryDefault;

OverlapOption overlapOption = OverlapOption.NONE;
Expand Down Expand Up @@ -222,6 +231,8 @@ public int showDialog(ImagePlus imp, String command, PlugInFilterRunner pfr) {
gd.addNumericField("Sigma", sigma, 2);
gd.addNumericField("Lower_Threshold", lowerThresh, 2);
gd.addNumericField("Upper_Threshold", upperThresh, 2);
gd.addNumericField("Minimum_Line_Length", minLength, 2);
gd.addNumericField("Maximum Line Length", maxLength, 2);
gd.addCheckbox("Darkline", isDarkLine);
gd.addCheckbox("Correct_position", doCorrectPosition);
gd.addCheckbox("Estimate_width", doEstimateWidth);
Expand Down Expand Up @@ -257,6 +268,8 @@ public int showDialog(ImagePlus imp, String command, PlugInFilterRunner pfr) {
sigma = gd.getNextNumber();
lowerThresh = gd.getNextNumber();
upperThresh = gd.getNextNumber();
minLength = gd.getNextNumber();
maxLength = gd.getNextNumber();
isDarkLine = gd.getNextBoolean();
doCorrectPosition = gd.getNextBoolean();
doEstimateWidth = gd.getNextBoolean();
Expand Down Expand Up @@ -288,6 +301,8 @@ private void readSettings(){
sigma = Prefs.get("RidgeDetection.sigma",sigmaDefault);
lowerThresh = Prefs.get("RidgeDetection.lowerThresh", lowerThreshDefault);
upperThresh = Prefs.get("RidgeDetection.upperThresh", upperThreshDefault);
minLength = Prefs.get("RidgeDetection.minLength", minLengthDefault);
maxLength = Prefs.get("RidgeDetection.maxLength", maxLengthDefault);
isDarkLine = Prefs.get("RidgeDetection.isDarkLine", isDarkLineDefault);
doCorrectPosition = Prefs.get("RidgeDetection.doCorrectPosition", doCorrectPositionDefault);
doEstimateWidth = Prefs.get("RidgeDetection.doEstimateWidth", doEstimateWidthDefault);
Expand All @@ -310,6 +325,8 @@ private void saveSettings(){
Prefs.set("RidgeDetection.sigma", sigma);
Prefs.set("RidgeDetection.lowerThresh", lowerThresh);
Prefs.set("RidgeDetection.upperThresh", upperThresh);
Prefs.set("RidgeDetection.minLength", minLength);
Prefs.set("RidgeDetection.maxLength", maxLength);
Prefs.set("RidgeDetection.isDarkLine", isDarkLine);
Prefs.set("RidgeDetection.doCorrectPosition", doCorrectPosition);
Prefs.set("RidgeDetection.doEstimateWidth", doEstimateWidth);
Expand Down Expand Up @@ -429,28 +446,64 @@ private void createResultsTable(boolean showJunctions) {
}

public void makeBinary() {
ImagePlus binary = NewImage.createByteImage(imp.getTitle()+" Detected segments",imp.getWidth(), imp.getHeight(),imp.getStackSize(),NewImage.FILL_WHITE);
ImagePlus binary = IJ.createHyperStack(imp.getTitle()+" Detected segments",imp.getWidth(), imp.getHeight(),imp.getNChannels(), imp.getStackSize()/imp.getNChannels(),1,8);
binary.copyScale(imp);

ImageProcessor binaryProcessor = binary.getProcessor();
binaryProcessor.invertLut();
if (imp.getCompositeMode()>0) {
((CompositeImage)binary).setLuts(imp.getLuts());
}

ImageStack is = binary.getImageStack();
ImageProcessor ip = binary.getProcessor();

for (Lines contours : result) {
for (Line c : contours) {

float[] x = c.getXCoordinates();
float[] y = c.getYCoordinates();
int prev_x =0;
int prev_y =0;

int[] x_poly_r = new int[x.length];
int[] y_poly_r = new int[x.length];

Polygon LineSurface = new Polygon();

ip = is.getProcessor(c.getFrame());

ip.setLineWidth(1);
ip.setColor(255);

for(int j = 0; j < x.length; j++){
int new_x = (int) Math.floor(x[j]);
int new_y = (int) Math.floor(y[j]);
is.getProcessor(c.getFrame()).putPixel(new_x,new_y,0);
// this draws the identified line
if (j >0) {
if (Math.abs(new_x - prev_x) >1 || Math.abs(new_y - prev_y) >1) {
is.getProcessor(c.getFrame()).putPixel(new_x - 1*Integer.signum(new_x - prev_x),new_y - 1*Integer.signum(new_y - prev_y),0);
}
ip.drawLine((int) Math.round(x[j-1]), (int) Math.round(y[j-1]),(int) Math.round(x[j]), (int) Math.round(y[j]));
}

// If Estimate Width is ticked, we also draw the line surface in the binary
if (doEstimateWidth) {

double nx = Math.sin(c.angle[j]);
double ny = Math.cos(c.angle[j]);

//left point coordinates are directly added to the polygon. right coordinates are saved to be added at the end of the coordinates list
LineSurface.addPoint((int) Math.round(x[j] - c.width_l[j] * nx),(int) Math.round(y[j] - c.width_l[j] * ny));

x_poly_r[j] = (int) Math.round(x[j] + c.width_r[j] * nx);
y_poly_r[j] = (int) Math.round(y[j] + c.width_r[j] * ny);
}

prev_x = new_x;
prev_y = new_y;
}

if (doEstimateWidth) {
// loop to add the right coordinates to the end of the polygon, reversed
for (int j = 0; j < x.length; j++) {
if (j < x.length) {
LineSurface.addPoint(x_poly_r[x.length-1-j],y_poly_r[x.length-1-j]);
}
}
//draw surfaces.
ip.fillPolygon(LineSurface);
}
}
}
binary.show();
Expand Down Expand Up @@ -606,6 +659,7 @@ public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) {
lineWidth = lwCand;
lwChanged = true;
}

double conCand = gd.getNextNumber();
diff = Math.abs(conCand-contrastHigh);
if ( diff > 0.0001) {
Expand All @@ -619,15 +673,13 @@ public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) {
contrastLow = conCand;
contLowChanged = true;
}


boolean darklineCand = gd.getNextBoolean();
if(darklineCand != isDarkLine){
isDarkLine = darklineCand;
darklineChanged = true;
}


doCorrectPosition = gd.getNextBoolean();
doEstimateWidth = gd.getNextBoolean();
doExtendLine = gd.getNextBoolean();
Expand Down Expand Up @@ -684,6 +736,8 @@ public boolean dialogItemChanged(GenericDialog gd, AWTEvent e) {
return false;
}

minLength = gd.getNextNumber();
maxLength = gd.getNextNumber();

isPreview = gd.isPreviewActive();

Expand All @@ -704,7 +758,7 @@ public void run(ImageProcessor ip) {
LineDetector detect = new LineDetector();
detect.bechatty = verbose;

result.add(detect.detectLines(ip, sigma, upperThresh, lowerThresh, isDarkLine, doCorrectPosition, doEstimateWidth, doExtendLine, overlapOption));
result.add(detect.detectLines(ip, sigma, upperThresh, lowerThresh, minLength,maxLength, isDarkLine, doCorrectPosition, doEstimateWidth, doExtendLine, overlapOption));
usedOptions = detect.getUsedParamters();
resultJunction.add(detect.getJunctions());

Expand Down
Loading

0 comments on commit df0d3b8

Please sign in to comment.