Suivi de balise AprilTag
Tutoriel vidéo 11 - Suivi AprilTag : https://singtown.com/learn/49590/
Tutoriel vidéo 21 - Une voiture chassant d'autres objets : https://singtown.com/learn/50041/
Introduction à AprilTag
Ressources : https://april.eecs.umich.edu/software/apriltag.html
AprilTag est un système de référence visuelle qui peut être utilisé pour de nombreuses tâches, notamment la RA, la robotique et l'étalonnage de caméra. Cette balise peut être imprimée directement avec une imprimante, et le programme de détection AprilTag peut calculer la position 3D précise, l'orientation, et l'id par rapport à la caméra. Pour OpenMV, c'est particulièrement utile ! Cela ressemble à ceci :

En termes simples, il suffit d'attacher cette balise à la cible pour identifier la position 3D et l'id de cette balise sur OpenMV.
Types d'AprilTag
Les types d'AprilTag sont appelés familles, et il existe les types suivants :
TAG16H5 → 0 à 29\ TAG25H7 → 0 à 241\ TAG25H9 → 0 à 34\ TAG36H10 → 0 à 2319\ TAG36H11 → 0 à 586\ ARTOOLKIT → 0 à 511\ C'est-à-dire qu'il existe 30 familles pour TAG16H5, chacune avec un id correspondant, de 0 à 29.
Alors quelles sont les différences entre les différentes familles ?
Par exemple, la zone effective de TAG16H5 est de 4 x 4 blocs, elle peut donc être vue de plus loin que TAG36H11 (car celle-ci a 6 x 6 blocs). Cependant, le taux d'erreur de TAG16H5 est bien plus élevé que celui de TAG36H11, car TAG36H11 possède plus d'informations de vérification, donc en l'absence d'autre raison, il est recommandé d'utiliser TAG36H11.
Fabriquer une AprilTag
C'est très simple. Vous pouvez la télécharger sur Internet ou la générer directement depuis l'IDE OpenMV. Sélectionnez la famille dans Outils - Vision par ordinateur - Générateur AprilTag. TAG36H11 est recommandé.

Ensuite, renseignez le nombre que vous devez générer, par exemple, si vous avez besoin de 10, cela génère des images avec les id 0~9.

Ensuite, sélectionnez le dossier où l'image sera enregistrée, et c'est tout.

Ensuite, l'image sera générée dans le dossier.

Enfin, imprimez l'image avec une imprimante (bien sûr, vous pouvez aussi utiliser directement un écran, mais cela peut refléter la lumière).
Programme
# Exemple AprilTags
#
# Cet exemple montre la puissance de l'OpenMV Cam pour détecter les April Tags
# sur l'OpenMV Cam M7. Les versions M4 ne peuvent pas détecter les April Tags.
import csi, image, time, math
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QQVGA) # nous manquons de mémoire si la résolution est beaucoup plus grande...
csi0.snapshot(frames=30)
csi0.auto_gain(False) # doit être désactivé pour éviter la saturation de l'image...
csi0.auto_whitebal(False) # doit être désactivé pour éviter la saturation de l'image...
clock = time.clock()
while(True):
clock.tick()
img = csi0.snapshot()
for tag in img.find_apriltags(): # utilise TAG36H11 par défaut sans "families".
img.draw_rectangle(tag.rect, color = (255, 0, 0))
img.draw_cross((tag.cx, tag.cy), color = (0, 255, 0))
degress = 180 * tag.rotation / math.pi
print(tag.id,degress)

Comme vous pouvez le voir, vous pouvez identifier l'id 0, l'angle de
rotation, et la position\

Positionnement 3D
Ce qu'il y a de plus incroyable avec AprilTag, c'est la fonction de positionnement 3D, qui permet de connaître la position spatiale de la balise, avec un total de 6 degrés de liberté, trois positions, et trois angles.
# Exemple AprilTags
#
# Cet exemple montre la puissance de l'OpenMV Cam pour détecter les April Tags
# sur l'OpenMV Cam M7. Les versions M4 ne peuvent pas détecter les April Tags.
import csi, image, time, math
csi0 = csi.CSI()
csi0.reset()
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QQVGA) # nous manquons de mémoire si la résolution est beaucoup plus grande...
csi0.snapshot(frames=30)
csi0.auto_gain(False) # doit être désactivé pour éviter la saturation de l'image...
csi0.auto_whitebal(False) # doit être désactivé pour éviter la saturation de l'image...
clock = time.clock()
# Remarque ! Contrairement à find_qrcodes, find_apriltags n'a pas besoin d'une correction logicielle de la distorsion pour fonctionner.
# Remarque, l'unité de la posture en sortie est le radian, elle peut être convertie en degrés, mais l'unité de la position dépend de votre échelle, elle doit être convertie proportionnellement
# f_x est la distance focale en pixels selon x. Pour un OpenMV standard, elle devrait être égale à 2.8/3.984*656, cette valeur est la distance focale en millimètres divisée par la longueur du capteur photosensible dans la direction x, multipliée par le nombre de pixels du capteur dans la direction x (OV7725)
# f_y est la distance focale en pixels selon y. Pour un OpenMV standard, elle devrait être égale à 2.8/2.952*488, cette valeur est la distance focale en millimètres divisée par la longueur du capteur photosensible dans la direction y, multipliée par le nombre de pixels du capteur dans la direction y (OV7725)
# c_x est la position centrale x de l'image
# c_y est la position centrale y de l'image
f_x = (2.8 / 3.984) * 160 # valeur par défaut
f_y = (2.8 / 2.952) * 120 # valeur par défaut
c_x = 160 * 0.5 # valeur par défaut (image.w * 0.5)
c_y = 120 * 0.5 # valeur par défaut (image.h * 0.5)
def degrees(radians):
return (180 * radians) / math.pi
while(True):
clock.tick()
img = csi0.snapshot()
for tag in img.find_apriltags(fx=f_x, fy=f_y, cx=c_x, cy=c_y): # TAG36H11 par défaut
img.draw_rectangle(tag.rect, color = (255, 0, 0))
img.draw_cross((tag.cx, tag.cy), color = (0, 255, 0))
print_args = (tag.x_translation, tag.y_translation, tag.z_translation, \
degrees(tag.x_rotation), degrees(tag.y_rotation), degrees(tag.z_rotation))
# l'unité de la position est inconnue, l'unité de la rotation est le degré
print("Tx: %f, Ty %f, Tz %f, Rx %f, Ry %f, Rz %f" % print_args)
print(clock.fps())

Le port série affiche 6 variables, Tx, Ty, Tz sont les 3 grandeurs de position dans l'espace, et Rx, Ry, Rz sont les trois grandeurs de rotation.
Pour aller plus loin :
- Depuis l'application Singtown Lab : Comment localiser/mesurer une distance en reconnaissance Apriltag ? Quelle est l'unité de sortie de tx ty tz ? Comment obtenir la distance réelle ? https://forum.singtown.com/topic/52