Example Fiducial Random Dots
From BoofCV
Jump to navigationJump to searchUchiya 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:
- Will be added soon
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
ConfigUchiyaMarker config = new ConfigUchiyaMarker();
config.markerLength = defs.markerWidth;
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.loadImage(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();
Se3_F64 targetToSensor = new Se3_F64();
Polygon2D_F64 bounds = new Polygon2D_F64();
Point2D_F64 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);
}
}