use of georegression.struct.point.Point2D_F64 in project BoofCV by lessthanoptimal.
the class AdjustPolygonForThresholdBias method process.
/**
* Processes and adjusts the polygon
*
* @param polygon The polygon that is to be adjusted. Modified.
* @param clockwise Is the polygon in a lockwise orientation?
*/
public void process(Polygon2D_F64 polygon, boolean clockwise) {
int N = polygon.size();
segments.resize(N);
// Apply the adjustment independently to each side
for (int i = N - 1, j = 0; j < N; i = j, j++) {
int ii, jj;
if (clockwise) {
ii = i;
jj = j;
} else {
ii = j;
jj = i;
}
Point2D_F64 a = polygon.get(ii), b = polygon.get(jj);
double dx = b.x - a.x;
double dy = b.y - a.y;
double l = Math.sqrt(dx * dx + dy * dy);
// only needs to be shifted in two directions
if (dx < 0)
dx = 0;
if (dy > 0)
dy = 0;
LineSegment2D_F64 s = segments.get(ii);
s.a.x = a.x - dy / l;
s.a.y = a.y + dx / l;
s.b.x = b.x - dy / l;
s.b.y = b.y + dx / l;
}
// Find the intersection between the adjusted lines to convert it back into polygon format
for (int i = N - 1, j = 0; j < N; i = j, j++) {
int ii, jj;
if (clockwise) {
ii = i;
jj = j;
} else {
ii = j;
jj = i;
}
UtilLine2D_F64.convert(segments.get(ii), ga);
UtilLine2D_F64.convert(segments.get(jj), gb);
if (null != Intersection2D_F64.intersection(ga, gb, intersection)) {
// very acute angles can cause a large delta. This is conservative and prevents that
if (intersection.distance2(polygon.get(jj)) < 20) {
polygon.get(jj).set(intersection);
}
}
}
}
use of georegression.struct.point.Point2D_F64 in project BoofCV by lessthanoptimal.
the class RefinePolygonToGrayLine method checkShapeTooSmall.
/**
* Looks at the distance between each vertex. If that distance is so small the edge can't be measured the
* return true.
* @param input polygon
* @return true if too small or false if not
*/
private boolean checkShapeTooSmall(Polygon2D_F64 input) {
// must be longer than the border plus some small fudge factor
double minLength = cornerOffset * 2 + 2;
for (int i = 0; i < input.size(); i++) {
int j = (i + 1) % input.size();
Point2D_F64 a = input.get(i);
Point2D_F64 b = input.get(j);
if (a.distance2(b) < minLength * minLength)
return true;
}
return false;
}
use of georegression.struct.point.Point2D_F64 in project BoofCV by lessthanoptimal.
the class ShapeFittingOps method fitEllipse_F64.
/**
* Computes the best fit ellipse based on minimizing Euclidean distance. An estimate is initially provided
* using algebraic algorithm which is then refined using non-linear optimization. The amount of non-linear
* optimization can be controlled using 'iterations' parameter. Will work with partial and complete contours
* of objects.
*
* <p>NOTE: To improve speed, make calls directly to classes in Georegression. Look at the code for details.</p>
*
* @param points (Input) Set of unordered points. Not modified.
* @param iterations Number of iterations used to refine the fit. If set to zero then an algebraic solution
* is returned.
* @param computeError If true it will compute the average Euclidean distance error
* @param outputStorage (Output/Optional) Storage for the ellipse. Can be null.
* @return Found ellipse.
*/
public static FitData<EllipseRotated_F64> fitEllipse_F64(List<Point2D_F64> points, int iterations, boolean computeError, FitData<EllipseRotated_F64> outputStorage) {
if (outputStorage == null) {
outputStorage = new FitData<>(new EllipseRotated_F64());
}
// Compute the optimal algebraic error
FitEllipseAlgebraic_F64 algebraic = new FitEllipseAlgebraic_F64();
if (!algebraic.process(points)) {
// could be a line or some other weird case. Create a crude estimate instead
FitData<Circle2D_F64> circleData = averageCircle_F64(points, null, null);
Circle2D_F64 circle = circleData.shape;
outputStorage.shape.set(circle.center.x, circle.center.y, circle.radius, circle.radius, 0);
} else {
UtilEllipse_F64.convert(algebraic.getEllipse(), outputStorage.shape);
}
// Improve the solution from algebraic into Euclidean
if (iterations > 0) {
RefineEllipseEuclideanLeastSquares_F64 leastSquares = new RefineEllipseEuclideanLeastSquares_F64();
leastSquares.setMaxIterations(iterations);
leastSquares.refine(outputStorage.shape, points);
outputStorage.shape.set(leastSquares.getFound());
}
// compute the average Euclidean error if the user requests it
if (computeError) {
ClosestPointEllipseAngle_F64 closestPoint = new ClosestPointEllipseAngle_F64(1e-8, 100);
closestPoint.setEllipse(outputStorage.shape);
double total = 0;
for (Point2D_F64 p : points) {
closestPoint.process(p);
total += p.distance(closestPoint.getClosest());
}
outputStorage.error = total / points.size();
} else {
outputStorage.error = 0;
}
return outputStorage;
}
use of georegression.struct.point.Point2D_F64 in project BoofCV by lessthanoptimal.
the class EdgeIntensityPolygon method computeEdge.
/**
* Checks to see if its a valid polygon or a false positive by looking at edge intensity
*
* @param polygon The polygon being tested
* @param ccw True if the polygon is counter clockwise
* @return true if it could compute the edge intensity, otherwise false
*/
public boolean computeEdge(Polygon2D_F64 polygon, boolean ccw) {
averageInside = 0;
averageOutside = 0;
double tangentSign = ccw ? 1 : -1;
int totalSides = 0;
for (int i = polygon.size() - 1, j = 0; j < polygon.size(); i = j, j++) {
Point2D_F64 a = polygon.get(i);
Point2D_F64 b = polygon.get(j);
double dx = b.x - a.x;
double dy = b.y - a.y;
double t = Math.sqrt(dx * dx + dy * dy);
dx /= t;
dy /= t;
// see if the side is too small
if (t < 3 * cornerOffset) {
offsetA.set(a);
offsetB.set(b);
} else {
offsetA.x = a.x + cornerOffset * dx;
offsetA.y = a.y + cornerOffset * dy;
offsetB.x = b.x - cornerOffset * dx;
offsetB.y = b.y - cornerOffset * dy;
}
double tanX = -dy * tangentDistance * tangentSign;
double tanY = dx * tangentDistance * tangentSign;
scorer.computeAverageDerivative(offsetA, offsetB, tanX, tanY);
if (scorer.getSamplesInside() > 0) {
totalSides++;
averageInside += scorer.getAverageUp() / tangentDistance;
averageOutside += scorer.getAverageDown() / tangentDistance;
}
}
if (totalSides > 0) {
averageInside /= totalSides;
averageOutside /= totalSides;
} else {
averageInside = averageOutside = 0;
return false;
}
return true;
}
use of georegression.struct.point.Point2D_F64 in project BoofCV by lessthanoptimal.
the class TestNarrowToWidePtoP_F64 method rotateCamera.
/**
* Rotate the camera and see if the point moves in the expected way
*/
@Test
public void rotateCamera() {
NarrowToWidePtoP_F64 alg = createAlg();
Point2D_F64 found = new Point2D_F64();
DMatrixRMaj R = ConvertRotation3D_F64.eulerToMatrix(EulerType.YXZ, 0.1, 0, 0, null);
alg.setRotationWideToNarrow(R);
alg.compute(250, 250, found);
assertTrue(480 < found.x - 5);
R = ConvertRotation3D_F64.eulerToMatrix(EulerType.YXZ, -0.1, 0, 0, null);
alg.setRotationWideToNarrow(R);
alg.compute(250, 250, found);
assertTrue(480 > found.x + 5);
R = ConvertRotation3D_F64.eulerToMatrix(EulerType.YXZ, 0, -0.1, 0, null);
alg.setRotationWideToNarrow(R);
alg.compute(250, 250, found);
assertTrue(480 < found.y - 5);
R = ConvertRotation3D_F64.eulerToMatrix(EulerType.YXZ, 0, 0.1, 0, null);
alg.setRotationWideToNarrow(R);
alg.compute(250, 250, found);
assertTrue(480 > found.y + 5);
}
Aggregations