use of georegression.struct.shapes.Polygon2D_F64 in project BoofCV by lessthanoptimal.
the class CommonDetectCalibrationApp method renderShapes.
protected void renderShapes(Graphics2D g2, double scale) {
List<Polygon2D_F64> squares = getFoundPolygons();
for (int i = 0; i < squares.size(); i++) {
Polygon2D_F64 p = squares.get(i);
// if (isInGrids(p)) TODO fix broken method isInGrids
// continue;
g2.setColor(Color.cyan);
g2.setStroke(new BasicStroke(4));
drawPolygon(p, g2, scale);
g2.setColor(Color.blue);
g2.setStroke(new BasicStroke(2));
drawPolygon(p, g2, scale);
drawCornersInside(g2, scale, p);
}
List<EllipseRotated_F64> ellipses = getFoundEllipses();
AffineTransform rotate = new AffineTransform();
for (int i = 0; i < ellipses.size(); i++) {
EllipseRotated_F64 ellipse = ellipses.get(i);
rotate.setToIdentity();
rotate.rotate(ellipse.phi);
double w = scale * ellipse.a * 2;
double h = scale * ellipse.b * 2;
Shape shape = rotate.createTransformedShape(new Ellipse2D.Double(-w / 2, -h / 2, w, h));
shape = AffineTransform.getTranslateInstance(scale * ellipse.center.x, scale * ellipse.center.y).createTransformedShape(shape);
g2.setColor(Color.cyan);
g2.setStroke(new BasicStroke(4));
g2.draw(shape);
g2.setColor(Color.blue);
g2.setStroke(new BasicStroke(2));
g2.draw(shape);
}
}
use of georegression.struct.shapes.Polygon2D_F64 in project BoofCV by lessthanoptimal.
the class BaseDetectFiducialSquare method process.
/**
* Examines the input image to detect fiducials inside of it
*
* @param gray Undistorted input image
*/
public void process(T gray) {
configureContourDetector(gray);
binary.reshape(gray.width, gray.height);
inputToBinary.process(gray, binary);
squareDetector.process(gray, binary);
squareDetector.refineAll();
// These are in undistorted pixels
squareDetector.getPolygons(candidates, candidatesInfo);
found.reset();
if (verbose)
System.out.println("---------- Got Polygons! " + candidates.size());
for (int i = 0; i < candidates.size(); i++) {
// compute the homography from the input image to an undistorted square image
Polygon2D_F64 p = candidates.get(i);
// sanity check before processing
if (!checkSideSize(p)) {
if (verbose)
System.out.println(" rejected side aspect ratio or size");
continue;
}
// REMOVE EVENTUALLY This is a hack around how interpolation is performed
// Using a surface integral instead would remove the need for this. Basically by having it start
// interpolating from the lower extent it samples inside the image more
// A good unit test to see if this hack is no longer needed is to rotate the order of the polygon and
// see if it returns the same undistorted image each time
double best = Double.MAX_VALUE;
for (int j = 0; j < 4; j++) {
double found = p.get(0).normSq();
if (found < best) {
best = found;
interpolationHack.set(p);
}
UtilPolygons2D_F64.shiftDown(p);
}
UtilPolygons2D_F64.convert(interpolationHack, q);
// remember, visual clockwise isn't the same as math clockwise, hence
// counter clockwise visual to the clockwise quad
pairsRemovePerspective.get(0).set(0, 0, q.a.x, q.a.y);
pairsRemovePerspective.get(1).set(square.width, 0, q.b.x, q.b.y);
pairsRemovePerspective.get(2).set(square.width, square.height, q.c.x, q.c.y);
pairsRemovePerspective.get(3).set(0, square.height, q.d.x, q.d.y);
if (!computeHomography.process(pairsRemovePerspective, H)) {
if (verbose)
System.out.println(" rejected initial homography");
continue;
}
// refine homography estimate
if (!refineHomography.fitModel(pairsRemovePerspective, H, H_refined)) {
if (verbose)
System.out.println(" rejected refine homography");
continue;
}
// pass the found homography onto the image transform
ConvertDMatrixStruct.convert(H_refined, H_fixed);
ConvertFloatType.convert(H_fixed, transformHomography.getModel());
// TODO Improve how perspective is removed
// The current method introduces artifacts. If the "square" is larger
// than the detected region and bilinear interpolation is used then pixels outside will// influence the
// value of pixels inside and shift things over. this is all bad
// remove the perspective distortion and process it
removePerspective.apply(gray, square);
DetectPolygonFromContour.Info info = candidatesInfo.get(i);
// see if the black border is actually black
if (minimumBorderBlackFraction > 0) {
double pixelThreshold = (info.edgeInside + info.edgeOutside) / 2;
double foundFraction = computeFractionBoundary((float) pixelThreshold);
if (foundFraction < minimumBorderBlackFraction) {
if (verbose)
System.out.println(" rejected black border fraction " + foundFraction);
continue;
}
}
if (processSquare(square, result, info.edgeInside, info.edgeOutside)) {
prepareForOutput(q, result);
if (verbose)
System.out.println(" accepted!");
} else {
if (verbose)
System.out.println(" rejected process square");
}
}
}
use of georegression.struct.shapes.Polygon2D_F64 in project BoofCV by lessthanoptimal.
the class TextureGrayTrackerObjectRectangleTests method convexFill.
public static void convexFill(Polygon2D_I32 poly, GrayU8 image, double value) {
int minX = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int minY = Integer.MAX_VALUE;
int maxY = Integer.MIN_VALUE;
for (int i = 0; i < poly.size(); i++) {
Point2D_I32 p = poly.vertexes.data[i];
if (p.y < minY) {
minY = p.y;
} else if (p.y > maxY) {
maxY = p.y;
}
if (p.x < minX) {
minX = p.x;
} else if (p.x > maxX) {
maxX = p.x;
}
}
ImageRectangle bounds = new ImageRectangle(minX, minY, maxX, maxY);
BoofMiscOps.boundRectangleInside(image, bounds);
Point2D_F64 p = new Point2D_F64();
Polygon2D_F64 poly64 = new Polygon2D_F64(4);
for (int i = 0; i < 4; i++) poly64.vertexes.data[i].set(poly.vertexes.data[i].x, poly.vertexes.data[i].y);
for (int y = bounds.y0; y < bounds.y1; y++) {
p.y = y;
for (int x = bounds.x0; x < bounds.x1; x++) {
p.x = x;
if (Intersection2D_F64.containConvex(poly64, p)) {
GeneralizedImageOps.set(image, x, y, value);
}
}
}
}
use of georegression.struct.shapes.Polygon2D_F64 in project BoofCV by lessthanoptimal.
the class TestChessboardPolygonHelper method filterPixelPolygon_AllBorder.
@Test
public void filterPixelPolygon_AllBorder() {
ChessboardPolygonHelper alg = new ChessboardPolygonHelper();
Polygon2D_F64 distorted = new Polygon2D_F64(3);
GrowQueue_B touches = new GrowQueue_B();
touches.add(false);
touches.add(false);
touches.add(false);
// nothing is actually touching the border, should be valid
assertTrue(alg.filterPixelPolygon(null, distorted, touches, true));
touches.set(0, true);
touches.set(1, true);
touches.set(2, true);
assertFalse(alg.filterPixelPolygon(null, distorted, touches, true));
}
use of georegression.struct.shapes.Polygon2D_F64 in project BoofCV by lessthanoptimal.
the class TestChessboardPolygonHelper method filterPixelPolygon_border.
@Test
public void filterPixelPolygon_border() {
ChessboardPolygonHelper alg = new ChessboardPolygonHelper();
Polygon2D_F64 distorted = new Polygon2D_F64(2);
GrowQueue_B touches = new GrowQueue_B();
// test initially with all corners inside
touches.add(false);
touches.add(false);
assertFalse(alg.filterPixelPolygon(null, distorted, touches, true));
distorted.vertexes.resize(3);
touches.add(false);
assertTrue(alg.filterPixelPolygon(null, distorted, touches, true));
distorted.vertexes.resize(3);
touches.add(false);
assertTrue(alg.filterPixelPolygon(null, distorted, touches, true));
// these should all fail because there are too many corners inside not touching the border
for (int i = 0; i < 3; i++) {
distorted.vertexes.resize(4 + i + 1);
touches.add(false);
assertFalse(alg.filterPixelPolygon(null, distorted, touches, true));
}
// this should pass because only 1 or 3 corners are inside
for (int i = 0; i < touches.size(); i++) {
touches.set(i, true);
}
for (int i = 0; i < 3; i++) {
touches.set(i, false);
assertTrue(alg.filterPixelPolygon(null, distorted, touches, true));
}
}
Aggregations