DetectorAprilTag¶
- class DetectorAprilTag(*args, **kwargs)¶
Bases:
DetectorBase
Base class for AprilTag detector. This class is a wrapper over AprilTag . There is no need to download and install AprilTag from source code or existing pre-built packages since the source code is embedded in ViSP. Reference papers are AprilTag: A robust and flexible visual fiducial system ( [36] ), AprilTag 2: Efficient and robust fiducial detection ( [46] ) and Flexible Layouts for Fiducial Tags (Under Review) ( [22] ).
The detect() function allows to detect multiple tags in an image. Once detected, for each tag it is possible to retrieve the location of the corners using getPolygon() , the encoded message using getMessage() , the bounding box using getBBox() and the center of gravity using getCog() .
If camera parameters and the size of the tag are provided, you can also estimate the 3D pose of the tag in terms of position and orientation wrt the camera considering 2 cases:
If tag sizes differ, use rather getPose()
The following sample code shows how to use this class to detect the location of 36h11 AprilTag patterns in an image.
#include <visp3/detection/vpDetectorAprilTag.h> #include <visp3/io/vpImageIo.h> #ifdef ENABLE_VISP_NAMESPACE using namespace VISP_NAMESPACE_NAME; #endif int main() { #ifdef VISP_HAVE_APRILTAG vpImage<unsigned char> I; vpImageIo::read(I, "image-tag36h11.pgm"); vpDetectorAprilTag detector(vpDetectorAprilTag::TAG_36h11); bool status = detector.detect(I); if (status) { for(size_t i=0; i < detector.getNbObjects(); ++i) { std::cout << "Tag code " << i << ":" << std::endl; std::vector<vpImagePoint> p = detector.getPolygon(i); for(size_t j=0; j < p.size(); ++j) std::cout << " Point " << j << ": " << p[j] << std::endl; std::cout << " Message: \"" << detector.getMessage(i) << "\"" << std::endl; } } #endif }
The previous example may produce results like:
Tag code 0: Point 0: 124.008, 442.226 Point 1: 194.614, 441.237 Point 2: 184.833, 540.386 Point 3: 111.948, 533.634 Message: "36h11 id: 0" Tag code 1: Point 0: 245.327, 438.801 Point 1: 338.116, 437.221 Point 2: 339.341, 553.539 Point 3: 238.954, 543.855 Message: "36h11 id: 1"
<unparsed image <doxmlparser.compound.docImageType object at 0x7f6df13a02b0>>There is the function setZAlignedWithCameraAxis() that allows to choose which tag frame has to be considered.
This other example shows how to estimate the 3D pose of 36h11 AprilTag patterns considering that all the tags have the same size (in our example 0.053 m). Here we consider the default case, when z-camera and z-tag axis are not aligned.
#include <visp3/detection/vpDetectorAprilTag.h> #include <visp3/io/vpImageIo.h> #ifdef ENABLE_VISP_NAMESPACE using namespace VISP_NAMESPACE_NAME; #endif int main() { #ifdef VISP_HAVE_APRILTAG vpImage<unsigned char> I; vpImageIo::read(I, "image-tag36h11.pgm"); vpDetectorAprilTag detector(vpDetectorAprilTag::TAG_36h11); detector.setZAlignedWithCameraAxis(false); // Default configuration std::vector<vpHomogeneousMatrix> cMo; vpCameraParameters cam; cam.initPersProjWithoutDistortion(615.1674805, 615.1675415, 312.1889954, 243.4373779); double tagSize = 0.053; bool status = detector.detect(I, tagSize, cam, cMo); if (status) { for(size_t i=0; i < detector.getNbObjects(); ++i) { std::cout << "Tag number " << i << ":" << std::endl; std::cout << " Message: \"" << detector.getMessage(i) << "\"" << std::endl; std::cout << " Pose: " << vpPoseVector(cMo[i]).t() << std::endl; std::size_t tag_id_pos = detector.getMessage(i).find("id: "); if (tag_id_pos != std::string::npos) { std::string tag_id = detector.getMessage(i).substr(tag_id_pos + 4); std::cout << " Tag Id: " << tag_id << std::endl; } } } #endif }
The previous example may produce results like:
Tag number 0: Message: "36h11 id: 0" Pose: 0.1015061088 -0.05239057228 0.3549037285 1.991474322 2.04143538 -0.9412360063 Tag Id: 0 Tag number 1: Message: "36h11 id: 1" Pose: 0.08951250829 0.02243780207 0.306540622 1.998073197 2.061488008 -0.8699567948 Tag Id: 1
In this other example we estimate the 3D pose of 36h11 AprilTag patterns considering that tag 36h11 with id 0 (in that case the tag message is “36h11 id: 0”) has a size of 0.040 m, while all the others have a size of 0.053m.
#include <visp3/detection/vpDetectorAprilTag.h> #include <visp3/io/vpImageIo.h> #ifdef ENABLE_VISP_NAMESPACE using namespace VISP_NAMESPACE_NAME; #endif int main() { #ifdef VISP_HAVE_APRILTAG vpImage<unsigned char> I; vpImageIo::read(I, "image-tag36h11.pgm"); vpDetectorAprilTag detector(vpDetectorAprilTag::TAG_36h11); vpHomogeneousMatrix cMo; vpCameraParameters cam; cam.initPersProjWithoutDistortion(615.1674805, 615.1675415, 312.1889954, 243.4373779); double tagSize_id_0 = 0.04; double tagSize_id_others = 0.053; bool status = detector.detect(I); if (status) { for(size_t i=0; i < detector.getNbObjects(); ++i) { std::cout << "Tag code " << i << ":" << std::endl; std::cout << " Message: \"" << detector.getMessage(i) << "\"" << std::endl; if (detector.getMessage(i) == std::string("36h11 id: 0")) { if (! detector.getPose(i, tagSize_id_0, cam, cMo)) { std::cout << "Unable to get tag index " << i << " pose!" << std::endl; } } else { if (! detector.getPose(i, tagSize_id_others, cam, cMo)) { std::cout << "Unable to get tag index " << i << " pose!" << std::endl; } } std::cout << " Pose: " << vpPoseVector(cMo).t() << std::endl; } } #endif }
With respect to the previous example, this example may now produce a different pose for tag with id 0:
Tag code 0: Message: "36h11 id: 0" Pose: 0.07660838403 -0.03954005455 0.2678518706 1.991474322 2.04143538 -0.9412360063 Tag code 1: Message: "36h11 id: 1" Pose: 0.08951250829 0.02243780207 0.306540622 1.998073197 2.061488008 -0.8699567948
Other examples are also provided in tutorial-apriltag-detector.cpp and tutorial-apriltag-detector-live.cpp
Overloaded function.
__init__(self: visp._visp.detection.DetectorAprilTag, tagFamily: visp._visp.detection.DetectorAprilTag.AprilTagFamily = TAG_36h11, poseEstimationMethod: visp._visp.detection.DetectorAprilTag.PoseEstimationMethod = HOMOGRAPHY_VIRTUAL_VS) -> None
__init__(self: visp._visp.detection.DetectorAprilTag, o: visp._visp.detection.DetectorAprilTag) -> None
Methods
Overloaded function.
Detect AprilTag tags in the image.
Overloaded function.
Overloaded function.
Return the pose estimation method.
Return the corners coordinates for the detected tags.
Return the decoded Apriltag id for each detection.
Return a vector that contains for each tag id the corresponding tag 3D corners coordinates in the tag frame.
- return:
When true, z-axis are aligned, false otherwise
Set the number of threads for April Tag detection (default is 1).
From the AprilTag code:detection of quads can be done on a lower-resolution image, improving speed at a cost of pose accuracy and a slight decrease in detection rate.
From the AprilTag code:What Gaussian blur should be applied to the segmented image (used for quad detection?) Parameter is the standard deviation in pixels.
From the AprilTag code:When non-zero, the edges of the each quad are adjusted to "snap
Allow to enable the display of overlay tag information in the windows ( vpDisplay ) associated to the input image.
Modify the resulting tag pose returned by getPose() or detect(const vpImage<unsigned char> &, double, const vpCameraParameters &, std::vector<vpHomogeneousMatrix> &, std::vector<vpHomogeneousMatrix> *, std::vector<double> *, std::vector<double> *) in order to get a pose where z-axis is aligned when the camera plane is parallel to the tag.
Inherited Methods
Return the center of gravity location of the ith object.
Overloaded function.
Return the bounding box of the ith object.
Return the number of objects that are detected.
Overloaded function.
Set detector timeout in milli-seconds.
Operators
__doc__
Overloaded function.
__module__
Attributes
BEST_RESIDUAL_VIRTUAL_VS
DEMENTHON_VIRTUAL_VS
HOMOGRAPHY
HOMOGRAPHY_ORTHOGONAL_ITERATION
HOMOGRAPHY_VIRTUAL_VS
LAGRANGE_VIRTUAL_VS
TAG_16h5
TAG_25h7
TAG_25h9
TAG_36ARTOOLKIT
TAG_36h10
TAG_36h11
TAG_CIRCLE21h7
TAG_CIRCLE49h12
TAG_CUSTOM48h12
TAG_STANDARD41h12
TAG_STANDARD52h13
__annotations__
- class AprilTagFamily(self, value: int)¶
Bases:
pybind11_object
Values:
HOMOGRAPHY: Pose from homography
HOMOGRAPHY_VIRTUAL_VS: Non linear virtual visual servoing approach initialized by the homography approach
DEMENTHON_VIRTUAL_VS: Non linear virtual visual servoing approach initialized by the Dementhon approach
LAGRANGE_VIRTUAL_VS: Non linear virtual visual servoing approach initialized by the Lagrange approach
BEST_RESIDUAL_VIRTUAL_VS: Non linear virtual visual servoing approach initialized by the approach that gives the lowest residual
HOMOGRAPHY_ORTHOGONAL_ITERATION: Pose from homography followed by a refinement by Orthogonal Iteration
- class PoseEstimationMethod(self, value: int)¶
Bases:
pybind11_object
Values:
HOMOGRAPHY: Pose from homography
HOMOGRAPHY_VIRTUAL_VS: Non linear virtual visual servoing approach initialized by the homography approach
DEMENTHON_VIRTUAL_VS: Non linear virtual visual servoing approach initialized by the Dementhon approach
LAGRANGE_VIRTUAL_VS: Non linear virtual visual servoing approach initialized by the Lagrange approach
BEST_RESIDUAL_VIRTUAL_VS: Non linear virtual visual servoing approach initialized by the approach that gives the lowest residual
HOMOGRAPHY_ORTHOGONAL_ITERATION: Pose from homography followed by a refinement by Orthogonal Iteration
- __init__(*args, **kwargs)¶
Overloaded function.
__init__(self: visp._visp.detection.DetectorAprilTag, tagFamily: visp._visp.detection.DetectorAprilTag.AprilTagFamily = TAG_36h11, poseEstimationMethod: visp._visp.detection.DetectorAprilTag.PoseEstimationMethod = HOMOGRAPHY_VIRTUAL_VS) -> None
__init__(self: visp._visp.detection.DetectorAprilTag, o: visp._visp.detection.DetectorAprilTag) -> None
- detect(self, I: visp._visp.core.ImageGray) bool ¶
Detect AprilTag tags in the image. Return true if at least one tag is detected, false otherwise.
- Parameters:
- I: visp._visp.core.ImageGray¶
Input image.
- Returns:
true if at least one tag is detected.
- displayFrames(*args, **kwargs)¶
Overloaded function.
displayFrames(self: visp._visp.detection.DetectorAprilTag, I: visp._visp.core.ImageGray, cMo_vec: list[visp._visp.core.HomogeneousMatrix], cam: visp._visp.core.CameraParameters, size: float, color: visp._visp.core.Color, thickness: int = 1) -> None
Display the tag frames on a grayscale image.
- Parameters:
- I
The image.
- cMo_vec
The vector of computed tag poses.
- cam
Camera intrinsic parameters.
- size
Size of the frame.
- color
The desired color, if none the X-axis is red, the Y-axis green and the Z-axis blue.
- thickness
The thickness of the lines.
displayFrames(self: visp._visp.detection.DetectorAprilTag, I: visp._visp.core.ImageRGBa, cMo_vec: list[visp._visp.core.HomogeneousMatrix], cam: visp._visp.core.CameraParameters, size: float, color: visp._visp.core.Color, thickness: int = 1) -> None
Display the tag frames on a vpRGBa image.
- Parameters:
- I
The image.
- cMo_vec
The vector of computed tag poses.
- cam
Camera intrinsic parameters.
- size
Size of the frame.
- color
The desired color, if none the X-axis is red, the Y-axis green and the Z-axis blue.
- thickness
The thickness of the lines.
- displayTags(*args, **kwargs)¶
Overloaded function.
displayTags(self: visp._visp.detection.DetectorAprilTag, I: visp._visp.core.ImageGray, tagsCorners: list[list[visp._visp.core.ImagePoint]], color: visp._visp.core.Color = vpColor::none, thickness: int = 1) -> None
Display the tag contours on a grayscale image.
- Parameters:
- I
The image.
- tagsCorners
The vector of tag contours.
- color
The desired color, if none RGBY colors are used.
- thickness
The thickness of the lines.
displayTags(self: visp._visp.detection.DetectorAprilTag, I: visp._visp.core.ImageRGBa, tagsCorners: list[list[visp._visp.core.ImagePoint]], color: visp._visp.core.Color = vpColor::none, thickness: int = 1) -> None
Display the tag contours on a vpRGBa image.
- Parameters:
- I
The image.
- tagsCorners
The vector of tag contours.
- color
The desired color, if none RGBY colors are used.
- thickness
The thickness of the lines.
- getBBox(self, i: int) visp._visp.core.Rect ¶
Return the bounding box of the ith object.
- getCog(self, i: int) visp._visp.core.ImagePoint ¶
Return the center of gravity location of the ith object.
- getMessage(*args, **kwargs)¶
Overloaded function.
getMessage(self: visp._visp.detection.DetectorBase) -> list[str]
Returns the contained message of the ith object if there is one.
getMessage(self: visp._visp.detection.DetectorBase, i: int) -> str
Returns the contained message of the ith object if there is one.
- getPolygon(*args, **kwargs)¶
Overloaded function.
getPolygon(self: visp._visp.detection.DetectorBase) -> list[list[visp._visp.core.ImagePoint]]
Returns object container box as a vector of points.
getPolygon(self: visp._visp.detection.DetectorBase, i: int) -> list[visp._visp.core.ImagePoint]
Returns ith object container box as a vector of points.
- getPoseEstimationMethod(self) visp._visp.detection.DetectorAprilTag.PoseEstimationMethod ¶
Return the pose estimation method.
- getTagsCorners(self) list[list[visp._visp.core.ImagePoint]] ¶
Return the corners coordinates for the detected tags.
Note
See getTagsId() , getTagsPoints3D()
- getTagsId(self) list[int] ¶
Return the decoded Apriltag id for each detection.
Note
See getTagsCorners() , getTagsPoints3D()
- getTagsPoints3D(self, tagsId: list[int], tagsSize: dict[int, float]) list[list[visp._visp.core.Point]] ¶
Return a vector that contains for each tag id the corresponding tag 3D corners coordinates in the tag frame.
Note
See getTagsCorners() , getTagsId()
- Parameters:
A vector containing the id of each tag that is detected. It’s size corresponds to the number of tags that are detected. This vector is returned by getTagsId() .
a map that contains as first element a tag id and as second elements its 3D size in meter. When first element of this map is -1, the second element corresponds to the default tag size.
std::map<int, double> tagsSize; tagsSize[-1] = 0.05; // Default tag size in meter, used when detected tag id is not in this map tagsSize[10] = 0.1; // All tags with id 10 are 0.1 meter large tagsSize[20] = 0.2; // All tags with id 20 are 0.2 meter large
- setAprilTagFamily(self, tagFamily: visp._visp.detection.DetectorAprilTag.AprilTagFamily) None ¶
- setAprilTagNbThreads(self, nThreads: int) None ¶
Set the number of threads for April Tag detection (default is 1).
- setAprilTagPoseEstimationMethod(self, poseEstimationMethod: visp._visp.detection.DetectorAprilTag.PoseEstimationMethod) None ¶
- setAprilTagQuadDecimate(self, quadDecimate: float) None ¶
From the AprilTag code:detection of quads can be done on a lower-resolution image, improving speed at a cost of pose accuracy and a slight decrease in detection rate. Decoding the binary payload is still done at full resolution. Default is 1.0, increase this value to reduce the computation time.
- setAprilTagQuadSigma(self, quadSigma: float) None ¶
From the AprilTag code:What Gaussian blur should be applied to the segmented image (used for quad detection?) Parameter is the standard deviation in pixels. Very noisy images benefit from non-zero values (e.g. 0.8). Default is 0.0.
- setAprilTagRefineEdges(self, refineEdges: bool) None ¶
- From the AprilTag code:When non-zero, the edges of the each quad are adjusted to “snap
to” strong gradients nearby. This is useful when decimation is employed, as it can increase the quality of the initial quad estimate substantially. Generally recommended to be on (1). Very computationally inexpensive. Option is ignored if quad_decimate = 1.
Default is 1.
- setDisplayTag(self: visp._visp.detection.DetectorAprilTag, display: bool, color: visp._visp.core.Color = vpColor::none, thickness: int = 2) None ¶
Allow to enable the display of overlay tag information in the windows ( vpDisplay ) associated to the input image.
- setTimeout(self, timeout_ms: int) None ¶
Set detector timeout in milli-seconds. When set to 0, there is no timeout.
- setZAlignedWithCameraAxis(self, zAlignedWithCameraFrame: bool) None ¶
Modify the resulting tag pose returned by getPose() or detect(const vpImage<unsigned char> &, double, const vpCameraParameters &, std::vector<vpHomogeneousMatrix> &, std::vector<vpHomogeneousMatrix> *, std::vector<double> *, std::vector<double> *) in order to get a pose where z-axis is aligned when the camera plane is parallel to the tag.
<unparsed image <doxmlparser.compound.docImageType object at 0x7f6df1337820>>