Example Fiducial Square Hamming
From BoofCV
Jump to navigationJump to searchDemonstration how to detect square fiducials which match targets based on hamming distance, e.g. ArUco and AprilTags.
Example Code:
Concepts:
- Fiducials
- Pose estimation
Relevant Examples/Tutorials:
- Tutorial Fiducials
- Example Fiducial Square Image
- Example Fiducial Square Binary
- Example Fiducial Calibration Target
Videos
Example Code
/**
* Hamming fiducials are an entire family of markers/tags which work by identifying unique ID's by minimizing
* the hamming distance. This family includes ArUco, ArUco 3, AprilTag, and others. Several prebuilt dictionaries
* are included with BoofCV and you can specify your own easily. Hamming tags have error correction capabilities
* can are resiliant to noise. How resilient depends on the dictionary. In general the fewer unique IDs available
* the better it is at error correction. The recommended dictionary is ARUCO_MIP_25h7.
*
* See:
* Aruco https://www.uco.es/investiga/grupos/ava/node/26
* AprilTag https://april.eecs.umich.edu/software/apriltag
*
* @author Peter Abeles
*/
public class ExampleFiducialHamming {
public static void main( String[] args ) {
String directory = UtilIO.pathExample("fiducial/square_hamming/aruco_25h7");
// load the lens distortion parameters and the input image
CameraPinholeBrown param = CalibrationIO.load(new File(directory, "intrinsic.yaml"));
LensDistortionNarrowFOV lensDistortion = new LensDistortionBrown(param);
// You need to create a different configuration for each dictionary type
ConfigHammingMarker configMarker = ConfigHammingMarker.loadDictionary(HammingDictionary.ARUCO_MIP_25h7);
FiducialDetector<GrayF32> detector = FactoryFiducial.squareHamming(configMarker, /*detector*/null, GrayF32.class);
// Provide it lens parameters so that a 3D pose estimate is possible
detector.setLensDistortion(lensDistortion, param.width, param.height);
// Load and process all example images
ListDisplayPanel gui = new ListDisplayPanel();
for (int imageID = 1; imageID <= 3; imageID++) {
String name = String.format("image%02d.jpg", imageID);
System.out.println("processing: " + name);
// Load the image
BufferedImage buffered = UtilImageIO.loadImage(new File(directory, name).getPath());
// Convert to a BoofCV format
GrayF32 input = ConvertBufferedImage.convertFrom(buffered, (GrayF32)null);
// Run the detector
detector.detect(input);
// Render a 3D compute on top of all detections
Graphics2D g2 = buffered.createGraphics();
Se3_F64 targetToSensor = new Se3_F64();
Point2D_F64 locationPixel = new Point2D_F64();
Polygon2D_F64 bounds = new Polygon2D_F64();
for (int i = 0; i < detector.totalFound(); i++) {
detector.getCenter(i, locationPixel);
detector.getBounds(i, bounds);
g2.setColor(new Color(50, 50, 255));
g2.setStroke(new BasicStroke(10));
VisualizeShapes.drawPolygon(bounds, true, 1.0, g2);
if (detector.hasID())
System.out.println("Target ID = " + detector.getId(i));
if (detector.hasMessage())
System.out.println("Message = " + detector.getMessage(i));
System.out.println("2D Image Location = " + locationPixel);
if (detector.is3D()) {
detector.getFiducialToCamera(i, targetToSensor);
System.out.println("3D Location:");
System.out.println(targetToSensor);
VisualizeFiducial.drawCube(targetToSensor, param, detector.getWidth(i), 3, g2);
VisualizeFiducial.drawLabelCenter(targetToSensor, param, "" + detector.getId(i), g2);
} else {
VisualizeFiducial.drawLabel(locationPixel, "" + detector.getId(i), g2);
}
}
gui.addImage(buffered, name, ScaleOptions.ALL);
}
ShowImages.showWindow(gui, "Example Fiducial Hamming", true);
}
}