Tutorial Fiducials
- Calib target chess small.png
Calibration Target
In computer vision, a fiducial marker is a known object which can be identified and have its pose estimated. BoofCV provides built in support several different fiducials, which can be easily printed. Applications are provided for automatically creating printable postscript files and a high level interface for detection, identification and pose estimation.
There are two types of fiducials supported in BoofCV, square and calibration targets. Square fiducials encode a pattern inside a black square box. These targets can be uniquely identified and provide a full pose estimate. Calibration targets fiducials are repurposed targets used to calibrate cameras. Calibration fiducials tend to provide very accurate pose estimation when close to the camera, but can have difficulty as they move away. There are two significant disadvantage for calibration targets. 1) They don't provide a unique ID. 2) Most patterns are not fully orientation invariant. You can see the lack of rotation invariance when it suddenly flips 180 degrees.
Fiducial Summary Table
Type | Variant | Speed (FPS) | Unique | Pose | Accuracy |
---|---|---|---|---|---|
Square Binary | Fast | 175 | 4096 | Full | Good |
Robust | 67 | ||||
Square Image | Fast | 170 | ∞ | Full | Good |
Robust | 66 | ||||
Calibration | Chessboard | 69 | 1 | Partial | Best Close |
Speed to detect multiple fiducials in a 640x480 image on a Intel Core i7-2600 3.4 Ghz. Unique max number of unique targets it can identify. Pose indicates if a full 6-DOF estimate is found or subset. Infinity symbol really means "lots".
Quick Start
- Calibrate your camera and save results (Tutorial)
- Technically optional, but highly recommended
- Print binary fiducial, e.g. Binary #0643
- Launch fiducial webcam application
- Point camera at fiducial
Launching Fiducial Application
cd boofcv/applications
gradle applciationsJar
java -cp applications.jar boofcv.app.WebcamTrackFiducial --Resolution=640:480 BINARY
If you calibrated your camera you can do the following and get better results:
java -cp applications.jar boofcv.app.WebcamTrackFiducial --Intrinsic=intrinsic.xml BINARY
To get a list of commands and see how to track other types of fiducials just enter the command with no arguments.
java -cp applications.jar boofcv.app.WebcamTrackFiducial
Printable Fiducials
The following is a printable documents for all the types of fiducials supported in BoofCV. Print these to get started quickly, but creating your own is also easy.
- Square Binary
- Square Image
- Calibration Chessboard
- Calibration Square Grid
Creating your Own Fiducial
For square fiducials, a convenient command-line application is provided which can create printable EPS documents which contain one or more fiducials on them. For calibration targets, prefabricated patterns are provided which can also be printed.
Square Binary
Fiducials can be made using the applications.jar you created earlier. Usual for complete instructions just enter in the classes name with no arguments.
java -cp applications.jar boofcv.app.CreateFiducialSquareBinaryEPS -OutputFile=fiducial.eps -PrintInfo -Units=cm 12 284
That will create a printable fiducial.eps file that encodes the number 284 in a square that's 12 centimeters.
Square Image
A fiducial can be easily created from any image using "applications.jar".
java -cp applications.jar boofcv.app.CreateFiducialSquareImageEPS -OutputFile=fiducial.eps -PrintInfo -Units=cm 12 pentarose.png
This will create a pattern which is 12cm wide and encodes the image contained in 'pentarose.png'. The output will be saved in "fiducial.eps" file.
Not feeling very creative or just want to see some example images? Several patterns are contained in "data/applet/fiducial/image/patterns/".
How Do Square Fiducials Work?
All square fiducials share a common code base. A target contains a black square of constant width and inside there is an image or pattern. The pattern is used to uniquely identify the fiducial and determine its orientation. A full 6-DOF pose is estimated from these fiducials. These targets are inspired by ARToolkit, but the code is not a port and was developed from scratched.
When detecting a square fiducial, the first step is to threshold the image. FactoryFiducial provides "robust" and "fast" techniques and the only difference between them is if they use an adaptive technique or a fixed threshold, respectively. Locally adaptive thresholding is invariant to local changes in lighting. The next step is to find the contour of blobs in the image. Clearly invalid contours are pruned and a polygon fit to the contour. This contour is used to provide the initial estimate of the squares edges. An expectation-maximization algorithm is used to fit lines to the contour and the corners are found by the intersection of the lines. Once the corners are found a homography is computed and then decomposed to return the pose.
Once the pose is known, perspective distortion can be removed and a synthetic image created. Orientation ambiguity is resolved using the fiducials pattern inside the square. For the binary pattern 4 corners are used. For image based fiducials, 4 different possible orientations are considered and the best match used.
Square Binary
The square binary fiducial encodes a 12-bit number, 4096 possible values, using a binary pattern. The number is encoded by breaking up the inner portion into 16 squares in a 4x4 grid. Three of the corners are always white and one black. This is how it resolves an orientation ambiguity.
Square Image
When an image is loaded into this type of fiducial it is first converted into a square image then down sampled into a low resolution image and encoded efficiently . When processing a video feed and a fiducial is detected the pattern is undistorted as usual. Then the hamming distance between the just observed pattern and all the known patterns is found. The pattern with the best score within tolerance is accepted.
Programming
All of these different types of fiducials can be used through a high level interface, *FiducialDetector*. FactoryFiducial is the easiest way to create instances of different fiducial types and it hides much of the complexity. Some detectors require additional information after construction. For example, square image fiducials require images be provided for each target it can detect. A sketch of how to process a single image is shown below.
FiducialDetector<ImageFloat32> detector = FactoryFiducial.pickAFiducial(...);
... additional fiducial specific configuration goes here ...
detector.setIntrinsic(param);
detector.detect(image);
Se3_F64 targetToSensor = new Se3_F64();
for (int i = 0; i < detector.totalFound(); i++){
System.out.println("Target ID = "+detector.getId(i));
System.out.println("Target width = "+detector.getWidth(i));
detector.getFiducialToWorld(i,targetToSensor);
System.out.println("Location:");
}
See the examples below for a more understanding of how to use these different types of fiducials.
Applets:
Examples: