use of net.imglib2.RealPoint in project imagej-ops by imagej.
the class DefaultDetectJunctions method filterJunctions.
private void filterJunctions(List<RealPoint> list) {
// filter out all vaguely similar junction points.
for (int i = 0; i < list.size() - 1; i++) {
ArrayList<RealPoint> similars = new ArrayList<>();
similars.add(list.get(i));
list.remove(i);
for (int j = 0; j < list.size(); j++) {
if (areClose(list.get(j), similars)) {
similars.add(list.get(j));
list.remove(j);
j--;
}
}
if (list.size() > 0)
list.add(i, averagePoints(similars));
else
list.add(averagePoints(similars));
}
}
use of net.imglib2.RealPoint in project imagej-ops by imagej.
the class DefaultDetectRidges method getNextPoint.
/**
* Recursively determines the next line point and adds it to the running list
* of line points.
*
* @param gradientRA - the {@link RandomAccess} of the gradient image.
* @param pRA - the {@link RandomAccess} of the eigenvector image.
* @param nRA - the {@link RandomAccess} of the subpixel line location image.
* @param points - the {@link ArrayList} containing the line points.
* @param octant - integer denoting the octant of the last gradient vector,
* oriented with 1 being 0 degrees and increasing in the
* counterclockwise direction.
* @param lastnx - the x component of the gradient vector of the last line
* point.
* @param lastny - the y component of the gradient vector of the last line
* point.
* @param lastpx - the x component of the subpixel line location of the last
* line point.
* @param lastpy - the y component of the subpixel line location of the last
* line point.
*/
private void getNextPoint(RandomAccess<DoubleType> gradientRA, RandomAccess<DoubleType> pRA, RandomAccess<DoubleType> nRA, List<RealPoint> points, int octant, double lastnx, double lastny, double lastpx, double lastpy) {
Point currentPos = new Point(gradientRA);
// variables for the best line point of the three.
Point salientPoint = new Point(gradientRA);
double salientnx = 0;
double salientny = 0;
double salientpx = 0;
double salientpy = 0;
double bestSalience = Double.MAX_VALUE;
boolean lastPointInLine = true;
// check the three possible points that could continue the line, starting at
// the octant after the given octant and rotating clockwise around the
// current pixel.
double lastAngle = RidgeDetectionUtils.getAngle(lastnx, lastny);
for (int i = 1; i < 4; i++) {
int[] modifier = RidgeDetectionUtils.getOctantCoords(octant + i);
gradientRA.move(modifier[0], 0);
gradientRA.move(modifier[1], 1);
// there.
if (gradientRA.get().get() > lowerThreshold) /*&& isMaxRA.get().get() > 0*/
{
long[] vectorArr = { gradientRA.getLongPosition(0), gradientRA.getLongPosition(1), 0 };
nRA.setPosition(vectorArr);
double nx = nRA.get().get();
nRA.fwd(2);
double ny = nRA.get().get();
pRA.setPosition(vectorArr);
double px = pRA.get().get();
pRA.fwd(2);
double py = pRA.get().get();
double currentAngle = RidgeDetectionUtils.getAngle(nx, ny);
double subpixelDiff = Math.sqrt(Math.pow(px - lastpx, 2) + Math.pow(py - lastpy, 2));
double angleDiff = Math.abs(currentAngle - lastAngle);
lastPointInLine = false;
// numbers relative to other potential line points.
if (subpixelDiff + angleDiff < bestSalience) {
// record the values of the new most salient pixel
salientPoint = new Point(gradientRA);
salientnx = nx;
salientny = ny;
salientpx = px;
salientpy = py;
bestSalience = subpixelDiff + angleDiff;
}
// set the values to zero so that they are not added to another line.
gradientRA.get().set(0);
}
// reset our randomAccess for the next check
gradientRA.setPosition(currentPos);
}
// set the current pixel to 0 in the first slice of eigenRA!
gradientRA.get().setReal(0);
// find the next line point as long as there is one to find
if (!lastPointInLine) {
// take the most salient point
gradientRA.setPosition(salientPoint);
points.add(RidgeDetectionUtils.get2DRealPoint(gradientRA.getDoublePosition(0) + salientpx, gradientRA.getDoublePosition(1) + salientpy));
// the gradient vector itself refers to the greatest change in intensity,
// and for a pixel on a line this vector will be perpendicular to the
// direction of the line. But this vector can point to either the left or
// the right of the line from the perspective of the detector, and there
// is no guarantee that the vectors at line point will point off the same
// side of the line. So if they point off different sides, set the current
// vector by 180 degrees for the purposes of this detector. We set the
// threshold for angle fixing just above 90 degrees since any lower would
// prevent ridges curving.
double potentialGradient = RidgeDetectionUtils.getAngle(salientnx, salientny);
// even though they are close enough to satisfy.
if (lastAngle < angleThreshold)
lastAngle += 360;
if (potentialGradient < angleThreshold)
potentialGradient += 360;
if (Math.abs(potentialGradient - lastAngle) > angleThreshold) {
salientnx = -salientnx;
salientny = -salientny;
}
// perform the operation again on the new end of the line being formed.
getNextPoint(gradientRA, pRA, nRA, points, RidgeDetectionUtils.getOctant(salientnx, salientny), salientnx, salientny, salientpx, salientpy);
}
}
use of net.imglib2.RealPoint 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;
}
use of net.imglib2.RealPoint in project imagej-ops by imagej.
the class DefaultContour method calculate.
@Override
public Polygon2D calculate(final RandomAccessibleInterval<B> input) {
List<RealPoint> p = new ArrayList<>();
final B var = Util.getTypeFromInterval(input).createVariable();
final RandomAccess<B> raInput = Views.extendValue(input, var).randomAccess();
final Cursor<B> cInput = Views.flatIterable(input).cursor();
final ClockwiseMooreNeighborhoodIterator<B> cNeigh = new ClockwiseMooreNeighborhoodIterator<>(raInput);
double[] position = new double[2];
double[] startPos = new double[2];
// find first true pixel
while (cInput.hasNext()) {
// we are looking for a true pixel
if (cInput.next().get()) {
raInput.setPosition(cInput);
raInput.localize(startPos);
// add to polygon
p.add(new RealPoint(startPos[0], startPos[1]));
// backtrack:
raInput.move(-1, 0);
cNeigh.reset();
while (cNeigh.hasNext()) {
if (cNeigh.next().get()) {
boolean specialBacktrack = false;
raInput.localize(position);
if (startPos[0] == position[0] && startPos[1] == position[1]) {
// startPoint was found.
if (useJacobs) {
// Jacobs stopping criteria
final int index = cNeigh.getIndex();
if (index == 1 || index == 0) {
// Jonathans refinement to
// non-terminating jacobs criteria
specialBacktrack = true;
} else if (index == 2 || index == 3) {
// way.
break;
}
// else criteria not fulfilled, continue.
} else {
break;
}
}
// add found point to polygon
p.add(new RealPoint(position[0], position[1]));
if (specialBacktrack) {
cNeigh.backtrackSpecial();
} else {
cNeigh.backtrack();
}
}
}
// we only need to extract one contour.
break;
}
}
return new DefaultWritablePolygon2D(p);
}
use of net.imglib2.RealPoint in project imagej-ops by imagej.
the class DefaultConvexHull2D method calculate.
@Override
public Polygon2D calculate(final Polygon2D input) {
// create a copy of points because se will get resorted, etc.
List<? extends RealLocalizable> RealPoints = new ArrayList<>(GeomUtils.vertices(input));
// Sort RealPoints of P by x-coordinate (in case of a tie, sort by
// y-coordinate).
Collections.sort(RealPoints, new Comparator<RealLocalizable>() {
@Override
public int compare(final RealLocalizable o1, final RealLocalizable o2) {
final Double o1x = new Double(o1.getDoublePosition(0));
final Double o2x = new Double(o2.getDoublePosition(0));
final int result = o1x.compareTo(o2x);
if (result == 0) {
return new Double(o1.getDoublePosition(1)).compareTo(new Double(o2.getDoublePosition(1)));
}
return result;
}
});
// Initialize U and L as empty lists.
// lists will hold vertices of upper and lower hulls
// respectively.
final List<RealLocalizable> U = new ArrayList<>();
final List<RealLocalizable> L = new ArrayList<>();
// build lower hull
for (final RealLocalizable p : RealPoints) {
// turn: remove last RealPoint from L
while (L.size() >= 2 && ccw(L.get(L.size() - 2), L.get(L.size() - 1), p) <= 0) {
L.remove(L.size() - 1);
}
L.add(p);
}
// build upper hull
Collections.reverse(RealPoints);
for (final RealLocalizable p : RealPoints) {
// turn: remove last RealPoint from U
while (U.size() >= 2 && ccw(U.get(U.size() - 2), U.get(U.size() - 1), p) <= 0) {
U.remove(U.size() - 1);
}
U.add(p);
}
// Remove last RealPoint of each list (it's same as first
// RealPoint
// of or list).
L.remove(L.size() - 1);
U.remove(U.size() - 1);
// concatenate L and U
L.addAll(U);
return new DefaultWritablePolygon2D(L);
}
Aggregations