Difference between revisions of "Example Fiducial Random Dots"
From BoofCV
Jump to navigationJump to searchm |
m |
||
(One intermediate revision by the same user not shown) | |||
Line 7: | Line 7: | ||
Uchiya Markers are composed of random dots and work by computing a hashing function based on the relative orientation of neighboring dots. One advantage to these markers is that they are resistant to conclusion. Many of the dots can be covered and the ID and pose of the marker can still be recovered! Square based markers become unrecognizable if the black square is blocked or damaged. BoofCV also provides tools for generating random marker PDF documents that can be printed. | Uchiya Markers are composed of random dots and work by computing a hashing function based on the relative orientation of neighboring dots. One advantage to these markers is that they are resistant to conclusion. Many of the dots can be covered and the ID and pose of the marker can still be recovered! Square based markers become unrecognizable if the black square is blocked or damaged. BoofCV also provides tools for generating random marker PDF documents that can be printed. | ||
Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v0. | Example File: [https://github.com/lessthanoptimal/BoofCV/blob/v0.40/examples/src/main/java/boofcv/examples/fiducial/ExampleFiducialRandomDots.java ExampleFiducialRandomDots.java] | ||
Concepts: | Concepts: | ||
Line 41: | Line 41: | ||
// The only parameter that you have to set is markerLength. It's used to compute bounding | // The only parameter that you have to set is markerLength. It's used to compute bounding | ||
// boxes and similar. If you don't know what the width is just set it to 1.0 | // boxes and similar. If you don't know what the width is just set it to 1.0 | ||
var config = new ConfigUchiyaMarker(); | |||
config.markerWidth = defs.markerWidth; | config.markerWidth = defs.markerWidth; | ||
config.markerHeight = defs.markerHeight; | config.markerHeight = defs.markerHeight; | ||
Line 59: | Line 59: | ||
// It's now ready to start processing images. Let's load an image | // It's now ready to start processing images. Let's load an image | ||
BufferedImage image = UtilImageIO. | BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("fiducial/random_dots/image02.jpg")); | ||
GrayU8 gray = ConvertBufferedImage.convertFrom(image, false, ImageType.SB_U8); | GrayU8 gray = ConvertBufferedImage.convertFrom(image, false, ImageType.SB_U8); | ||
Line 66: | Line 66: | ||
// Time to visualize the results | // Time to visualize the results | ||
Graphics2D g2 = image.createGraphics(); | Graphics2D g2 = image.createGraphics(); | ||
var targetToSensor = new Se3_F64(); | |||
var bounds = new Polygon2D_F64(); | |||
var center = new Point2D_F64(); | |||
for (int i = 0; i < detector.totalFound(); i++) { | for (int i = 0; i < detector.totalFound(); i++) { | ||
detector.getBounds(i, bounds); | detector.getBounds(i, bounds); |
Latest revision as of 14:44, 17 January 2022
Uchiya Markers are composed of random dots and work by computing a hashing function based on the relative orientation of neighboring dots. One advantage to these markers is that they are resistant to conclusion. Many of the dots can be covered and the ID and pose of the marker can still be recovered! Square based markers become unrecognizable if the black square is blocked or damaged. BoofCV also provides tools for generating random marker PDF documents that can be printed.
Example File: ExampleFiducialRandomDots.java
Concepts:
- Fiducial Markers
- Dots
- Pose Estimation
Relevant Videos:
Related Tutorials/Example Code:
Example Code
/**
* Random dot markers are exactly what their name implies. Each marker is a set of random dots that the tracker
* learns to identify using hash codes computed from geometric invariants which describe the relationships between
* the dots. These markers are based off of Uchiya Markers.
*
* @author Peter Abeles
*/
public class ExampleFiducialRandomDots {
public static void main( String[] args ) {
// The definitions file specifies where dots are on each marker and other bits of meta data
RandomDotDefinition defs = FiducialIO.loadRandomDotYaml(
UtilIO.fileExample("fiducial/random_dots/descriptions.yaml"));
// The only parameter that you have to set is markerLength. It's used to compute bounding
// boxes and similar. If you don't know what the width is just set it to 1.0
var config = new ConfigUchiyaMarker();
config.markerWidth = defs.markerWidth;
config.markerHeight = defs.markerHeight;
Uchiya_to_FiducialDetector<GrayU8> detector = FactoryFiducial.randomDots(config, GrayU8.class);
// Load / learn all the markers. This can take a few seconds if there are a lot of markers
for (List<Point2D_F64> marker : defs.markers) {
detector.addMarker(marker);
}
// If you want 3D pose information then the camera need sto be calibrated. If you don't provide
// this information then just things like the bounding box will be returned
CameraPinholeBrown intrinsic = CalibrationIO.load(
UtilIO.fileExample("fiducial/random_dots/intrinsic.yaml"));
detector.setLensDistortion(LensDistortionFactory.narrow(intrinsic), intrinsic.width, intrinsic.height);
// It's now ready to start processing images. Let's load an image
BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("fiducial/random_dots/image02.jpg"));
GrayU8 gray = ConvertBufferedImage.convertFrom(image, false, ImageType.SB_U8);
detector.detect(gray);
// Time to visualize the results
Graphics2D g2 = image.createGraphics();
var targetToSensor = new Se3_F64();
var bounds = new Polygon2D_F64();
var center = new Point2D_F64();
for (int i = 0; i < detector.totalFound(); i++) {
detector.getBounds(i, bounds);
detector.getCenter(i, center);
g2.setColor(new Color(50, 50, 255));
g2.setStroke(new BasicStroke(10));
VisualizeShapes.drawPolygon(bounds, true, 1.0, g2);
VisualizeFiducial.drawLabel(center, "" + detector.getId(i), g2);
System.out.println("Target ID = " + detector.getId(i));
if (detector.is3D()) {
detector.getFiducialToCamera(i, targetToSensor);
VisualizeFiducial.drawCube(targetToSensor, intrinsic, detector.getWidth(i), 3, g2);
}
}
ShowImages.showWindow(image, "Random Dot Markers", true);
}
}