use of net.imglib2.roi.geom.real.WritablePolyline in project imagej-ops by imagej.
the class DefaultDetectJunctions method calculate.
@Override
public List<RealPoint> calculate(List<? extends WritablePolyline> input) {
// output that allows for both split polyline inputs and a
// realPointCollection for our junctions.
List<RealPoint> output = new ArrayList<>();
for (int first = 0; first < input.size() - 1; first++) {
WritablePolyline firstLine = input.get(first);
for (int second = first + 1; second < input.size(); second++) {
WritablePolyline secondLine = input.get(second);
// interval containing both plines
Interval intersect = Intervals.intersect(slightlyEnlarge(firstLine, 2), slightlyEnlarge(secondLine, 2));
// each other.
if (Intervals.isEmpty(intersect))
continue;
// create an arraylist to contain all of the junctions for these two
// lines (so that we can filter the junctions before putting them in
// output).
ArrayList<RealPoint> currentPairJunctions = new ArrayList<>();
for (int p = 0; p < firstLine.numVertices() - 1; p++) {
for (int q = 0; q < secondLine.numVertices() - 1; q++) {
RealLocalizableRealPositionable p1 = firstLine.vertex(p);
RealLocalizableRealPositionable p2 = firstLine.vertex(p + 1);
RealLocalizableRealPositionable q1 = secondLine.vertex(q);
RealLocalizableRealPositionable q2 = secondLine.vertex(q + 1);
// special cases if both lines are vertical
boolean pVertical = Math.round(p1.getDoublePosition(0)) == Math.round(p2.getDoublePosition(0));
boolean qVertical = Math.round(q1.getDoublePosition(0)) == Math.round(q2.getDoublePosition(0));
// intersection point between the lines created by line segments p
// and q.
double[] intersectionPoint = new double[2];
// since they are parallel and cannot be the same.
if (pVertical && qVertical) {
parallelRoutine(p1, p2, q1, q2, currentPairJunctions, true);
continue;
} else if (pVertical) {
double mq = (q2.getDoublePosition(1) - q1.getDoublePosition(1)) / (q2.getDoublePosition(0) - q1.getDoublePosition(0));
double bq = (q1.getDoublePosition(1) - mq * q1.getDoublePosition(0));
double x = p1.getDoublePosition(0);
double y = mq * x + bq;
intersectionPoint[0] = x;
intersectionPoint[1] = y;
} else if (qVertical) {
double mp = (p2.getDoublePosition(1) - p1.getDoublePosition(1)) / (p2.getDoublePosition(0) - p1.getDoublePosition(0));
double bp = (p1.getDoublePosition(1) - mp * p1.getDoublePosition(0));
double x = q1.getDoublePosition(0);
double y = mp * x + bp;
intersectionPoint[0] = x;
intersectionPoint[1] = y;
} else {
double mp = (p2.getDoublePosition(1) - p1.getDoublePosition(1)) / (p2.getDoublePosition(0) - p1.getDoublePosition(0));
double mq = (q2.getDoublePosition(1) - q1.getDoublePosition(1)) / (q2.getDoublePosition(0) - q1.getDoublePosition(0));
if (mp == mq) {
parallelRoutine(p1, p2, q1, q2, currentPairJunctions, false);
continue;
}
double bp = (p2.getDoublePosition(1) - mp * p2.getDoublePosition(0));
double bq = (q2.getDoublePosition(1) - mq * q2.getDoublePosition(0));
// point of intersection of lines created by line segments p and
// q.
double x = (bq - bp) / (mp - mq);
double y = mp * x + bp;
intersectionPoint[0] = x;
intersectionPoint[1] = y;
}
// find the distance from the intersection point to both line
// segments, and the length of the line segments.
double distp1 = getDistance(intersectionPoint, p1);
double distp2 = getDistance(intersectionPoint, p2);
double distq1 = getDistance(intersectionPoint, q1);
double distq2 = getDistance(intersectionPoint, q2);
// max distance from line segment to intersection point
double maxDist = Math.max(Math.min(distp1, distp2), Math.min(distq1, distq2));
// these lines are close enough to form a junction
if (maxDist <= threshold)
currentPairJunctions.add(new RealPoint(intersectionPoint));
}
}
// filter out the current pair's junctions by removing duplicates and
// then averaging all remaining nearby junctions
filterJunctions(currentPairJunctions);
// add the filtered junctions to the output list.
for (RealPoint point : currentPairJunctions) output.add(point);
}
}
// filter the junctions -- for each set of junctions that seem vaguely
// similar, pick out the best one-
filterJunctions(output);
return output;
}
use of net.imglib2.roi.geom.real.WritablePolyline in project imagej-ops by imagej.
the class DefaultDetectRidges method calculate.
@Override
public List<? extends WritablePolyline> calculate(RandomAccessibleInterval<T> input) {
double sigma = (width / (2 * Math.sqrt(3)));
// generate the metadata images
RidgeDetectionMetadata ridgeDetectionMetadata = new RidgeDetectionMetadata(input, sigma, lowerThreshold, higherThreshold);
// retrieve the metadata images
Img<DoubleType> p_values = ridgeDetectionMetadata.getPValues();
Img<DoubleType> n_values = ridgeDetectionMetadata.getNValues();
Img<DoubleType> gradients = ridgeDetectionMetadata.getGradients();
// create RandomAccesses for the metadata images
OutOfBoundsConstantValueFactory<DoubleType, RandomAccessibleInterval<DoubleType>> oscvf = new OutOfBoundsConstantValueFactory<>(new DoubleType(0));
RandomAccess<DoubleType> pRA = oscvf.create(p_values);
RandomAccess<DoubleType> nRA = oscvf.create(n_values);
RandomAccess<DoubleType> gradientRA = oscvf.create(gradients);
// create the output polyline list.
List<DefaultWritablePolyline> lines = new ArrayList<>();
// start at the point of greatest maximum absolute value
gradientRA.setPosition(RidgeDetectionUtils.getMaxCoords(gradients, true));
// loop through the maximum values of the image
while (Math.abs(gradientRA.get().get()) > higherThreshold) {
// create the List of points that will be used to make the polyline
List<RealPoint> points = new ArrayList<>();
// get all of the necessary metadata from the image.
long[] eigenvectorPos = { gradientRA.getLongPosition(0), gradientRA.getLongPosition(1), 0 };
// obtain the n-values
nRA.setPosition(eigenvectorPos);
double eigenx = nRA.get().getRealDouble();
nRA.fwd(2);
double eigeny = nRA.get().getRealDouble();
// obtain the p-values
pRA.setPosition(eigenvectorPos);
double px = pRA.get().getRealDouble();
pRA.fwd(2);
double py = pRA.get().getRealDouble();
// start the list by adding the current point, which is the most line-like
// point on the polyline
points.add(RidgeDetectionUtils.get2DRealPoint(gradientRA.getDoublePosition(0) + px, gradientRA.getDoublePosition(1) + py));
// go in the direction to the left of the perpendicular value
getNextPoint(gradientRA, pRA, nRA, points, RidgeDetectionUtils.getOctant(eigenx, eigeny), eigenx, eigeny, px, py);
// flip the array list around so that we get one cohesive line
gradientRA.setPosition(new long[] { eigenvectorPos[0], eigenvectorPos[1] });
Collections.reverse(points);
// go in the opposite direction as before.
eigenx = -eigenx;
eigeny = -eigeny;
getNextPoint(gradientRA, pRA, nRA, points, RidgeDetectionUtils.getOctant(eigenx, eigeny), eigenx, eigeny, px, py);
// set the value to 0 so that it is not reused.
gradientRA.get().setReal(0);
// list has fewer vertices than the parameter, then we do not report it.
if (points.size() > ridgeLengthMin) {
DefaultWritablePolyline pline = new DefaultWritablePolyline(points);
lines.add(pline);
}
// find the next max absolute value
gradientRA.setPosition(RidgeDetectionUtils.getMaxCoords(gradients, true));
}
return lines;
}
Aggregations