use of georegression.struct.curve.EllipseRotated_F64 in project BoofCV by lessthanoptimal.
the class DetectCalibrationCircleRegularApp method renderGrid.
@Override
protected void renderGrid(Graphics2D g2, double scale) {
List<Grid> grids = detector.getDetector().getGrider().getGrids().toList();
BasicStroke thin = new BasicStroke(3);
BasicStroke thick = new BasicStroke(5);
for (Grid g : grids) {
double x0 = Double.MAX_VALUE;
double x1 = -Double.MAX_VALUE;
double y0 = Double.MAX_VALUE;
double y1 = -Double.MAX_VALUE;
for (int i = 0; i < g.ellipses.size(); i++) {
EllipseRotated_F64 e = g.ellipses.get(i);
if (e == null)
continue;
x0 = Math.min(e.center.x, x0);
x1 = Math.max(e.center.x, x1);
y0 = Math.min(e.center.y, y0);
y1 = Math.max(e.center.y, y1);
}
x0 *= scale;
y0 *= scale;
x1 *= scale;
y1 *= scale;
g2.setColor(Color.WHITE);
g2.setStroke(thick);
VisualizeShapes.drawRectangle(x0, y0, x1, y1, line, g2);
g2.setColor(Color.ORANGE);
g2.setStroke(thin);
VisualizeShapes.drawRectangle(x0, y0, x1, y1, line, g2);
}
}
use of georegression.struct.curve.EllipseRotated_F64 in project BoofCV by lessthanoptimal.
the class DetectCircleGrid method process.
/**
* Processes the image and finds grids. To retrieve the found grids call {@link #getGrids()}
* @param gray Input image
*/
public void process(T gray) {
if (verbose)
System.out.println("ENTER DetectCircleGrid.process()");
configureContourDetector(gray);
this.binary.reshape(gray.width, gray.height);
inputToBinary.process(gray, binary);
ellipseDetector.process(gray, binary);
List<BinaryEllipseDetector.EllipseInfo> found = ellipseDetector.getFound().toList();
if (verbose)
System.out.println(" Found " + found.size() + " ellpises");
clusters.clear();
clustering.process(found, clusters);
clustersPruned.clear();
clustersPruned.addAll(clusters);
if (verbose)
System.out.println(" Found " + clusters.size() + " clusters");
pruneIncorrectSize(clustersPruned, totalEllipses(numRows, numCols));
if (verbose)
System.out.println(" Remaining clusters after pruning by size " + clustersPruned.size());
List<EllipseRotated_F64> foundEllipses = new ArrayList<>();
for (int i = 0; i < found.size(); i++) {
foundEllipses.add(found.get(i).ellipse);
}
grider.process(foundEllipses, clustersPruned);
FastQueue<Grid> grids = grider.getGrids();
if (verbose)
System.out.println(" Found " + grids.size() + " grids");
pruneIncorrectShape(grids, numRows, numCols);
if (verbose)
System.out.println(" Remaining grids after pruning by shape " + grids.size());
validGrids.clear();
for (int i = 0; i < grids.size(); i++) {
Grid g = grids.get(i);
putGridIntoCanonical(g);
validGrids.add(g);
}
if (verbose)
System.out.println("EXIT DetectCircleGrid.process()");
}
use of georegression.struct.curve.EllipseRotated_F64 in project BoofCV by lessthanoptimal.
the class DetectCircleRegularGrid method isClockWise.
/**
* Uses the cross product to determine if the grid is in clockwise order
*/
private static boolean isClockWise(Grid g) {
EllipseRotated_F64 v00 = g.get(0, 0);
EllipseRotated_F64 v02 = g.get(0, 1);
EllipseRotated_F64 v20 = g.get(1, 0);
double a_x = v02.center.x - v00.center.x;
double a_y = v02.center.y - v00.center.y;
double b_x = v20.center.x - v00.center.x;
double b_y = v20.center.y - v00.center.y;
return a_x * b_y - a_y * b_x < 0;
}
use of georegression.struct.curve.EllipseRotated_F64 in project BoofCV by lessthanoptimal.
the class EllipsesIntoClusters method connect.
/**
* Internal function which connects ellipses together
*/
void connect(List<EllipseInfo> ellipses) {
for (int i = 0; i < ellipses.size(); i++) {
EllipseInfo info1 = ellipses.get(i);
EllipseRotated_F64 e1 = info1.ellipse;
Node node1 = nodes.get(i);
// Only search the maximum of the major axis times two
// add a fudge factor. won't ever be perfect
double maxDistance = e1.a * maxDistanceToMajorAxisRatio;
maxDistance *= maxDistance;
searchResults.reset();
search.findNearest(searchPoints.get(i), maxDistance, Integer.MAX_VALUE, searchResults);
// if this node already has a cluster look it up, otherwise create a new one
List<Node> cluster1;
if (node1.cluster == -1) {
node1.cluster = clusters.size;
cluster1 = clusters.grow();
cluster1.clear();
cluster1.add(node1);
} else {
cluster1 = clusters.get(node1.cluster);
}
double edge1 = info1.averageOutside - info1.averageInside;
// only accept ellipses which have a similar size
for (int j = 0; j < searchResults.size(); j++) {
NnData<Node> d = searchResults.get(j);
EllipseInfo info2 = ellipses.get(d.data.which);
EllipseRotated_F64 e2 = info2.ellipse;
if (e2 == e1)
continue;
// see of they are already connected
if (node1.connections.indexOf(d.data.which) != -1) {
continue;
}
// test the appearance of the ellipses edge
double edge2 = info2.averageOutside - info2.averageInside;
double intensityRatio = Math.abs(edge1 - edge2) / Math.max(edge1, edge2);
if (intensityRatio > edgeIntensitySimilarityTolerance)
continue;
// from the minor axis
if (axisAdjustedDistanceSq(e1, e2) > maxDistance) {
continue;
}
// TODO take in in account how similar their orientation is, but less important when they are circular
// somehow work into aspect ratio test?
// smallest shape divided by largest shape
double ratioA = e1.a > e2.a ? e2.a / e1.a : e1.a / e2.a;
double ratioB = e1.b > e2.b ? e2.b / e1.b : e1.b / e2.b;
if (ratioA < sizeSimilarityTolerance && ratioB < sizeSimilarityTolerance) {
continue;
}
// axis ratio similarity check
double ratioC = (e1.a * e2.b) / (e1.b * e2.a);
if (ratioC > 1)
ratioC = 1.0 / ratioC;
if (ratioC < ratioSimilarityTolerance) {
continue;
}
// Apply rule which combines two features
if (intensityRatio + (1 - ratioC) > (edgeIntensitySimilarityTolerance / 1.5 + (1 - ratioSimilarityTolerance)))
continue;
int indexNode2 = d.data.which;
Node node2 = nodes.get(indexNode2);
// node2 isn't in a cluster already. Add it to this one
if (node2.cluster == -1) {
node2.cluster = node1.cluster;
cluster1.add(node2);
node1.connections.add(indexNode2);
node2.connections.add(i);
} else if (node2.cluster != node1.cluster) {
// Node2 is in a different cluster. Merge the clusters
joinClusters(node1.cluster, node2.cluster);
node1.connections.add(indexNode2);
node2.connections.add(i);
} else {
node1.connections.add(indexNode2);
node2.connections.add(i);
}
}
}
}
use of georegression.struct.curve.EllipseRotated_F64 in project BoofCV by lessthanoptimal.
the class KeyPointsCircleHexagonalGrid method addTangents.
/**
* Computes tangent points to the two ellipses specified by the grid coordinates
*/
private boolean addTangents(Grid grid, int rowA, int colA, int rowB, int colB) {
EllipseRotated_F64 a = grid.get(rowA, colA);
EllipseRotated_F64 b = grid.get(rowB, colB);
if (a == null || b == null) {
return false;
}
if (!tangentFinder.process(a, b, A0, A1, A2, A3, B0, B1, B2, B3)) {
return false;
}
Tangents ta = tangents.get(grid.getIndexOfHexEllipse(rowA, colA));
Tangents tb = tangents.get(grid.getIndexOfHexEllipse(rowB, colB));
// add tangent points from the two lines which do not cross the center line
ta.grow().set(A0);
ta.grow().set(A3);
tb.grow().set(B0);
tb.grow().set(B3);
return true;
}
Aggregations