4.18. Capteurs multiples

Quelques OpenMV Cams associent deux capteurs d’image sur la même carte – le plus souvent une caméra couleur aux côtés d’un capteur thermique FLIR® Lepton®, mais le même schéma s’applique aux cartes couleur-plus-événement et à tout futur matériel à double capteur. Chaque capteur possède sa propre matrice de pixels, son propre bus de contrôle, et exécute son propre pipeline à sa propre cadence de trames. L’API CSI les prend en charge en laissant l’application instancier un objet CSI par capteur physique.

4.18.1. Choix du capteur

Le constructeur CSI prend un argument cid qui désigne un capteur spécifique sur la carte. cid=-1 (la valeur par défaut) sélectionne le capteur principal ; les constantes cid nommées sélectionnent un capteur secondaire par identifiant de puce

import csi

csi_rgb     = csi.CSI()                    # primary colour sensor
csi_thermal = csi.CSI(cid=csi.LEPTON)      # FLIR® Lepton®

Chaque instance possède sa propre configuration – format de pixel, taille de trame, réglages d’exposition / gain, pool de tampons d’image – et est réinitialisée, configurée et lue indépendamment de l’autre. Les constantes pour les capteurs secondaires pris en charge (LEPTON, GENX320, et les autres listées dans la référence CSI) nomment la puce que l’application s’attend à trouver sur le port secondaire ; le pilote fait échouer la construction si la puce réelle ne correspond pas.

4.18.2. Capture depuis les deux capteurs

Chaque capteur exécute son pipeline de capture indépendamment de l’autre – le capteur couleur peut fournir trente trames par seconde tandis que le Lepton® en fournit neuf. La manière la plus simple de gérer cet écart est de laisser le capteur le plus rapide piloter la boucle et de lire le capteur le plus lent de façon non bloquante, en prenant ce qui est prêt et en sautant l’itération lorsque rien ne l’est

import csi

csi_rgb     = csi.CSI()
csi_thermal = csi.CSI(cid=csi.LEPTON)

csi_rgb.reset()                        # powers the rail, pulses RESET
csi_rgb.pixformat(csi.RGB565)
csi_rgb.framesize(csi.QVGA)

csi_thermal.reset(hard=False)          # I2C reconfigure only
csi_thermal.pixformat(csi.GRAYSCALE)
csi_thermal.framesize(csi.QQVGA)

while True:
    rgb_img     = csi_rgb.snapshot()                  # blocks for next colour frame
    thermal_img = csi_thermal.snapshot(blocking=False)  # returns None if not ready
    if thermal_img is not None:
        # process aligned colour + thermal pair
        pass
    else:
        # process colour only on this iteration
        pass

Le snapshot() bloquant cadence la boucle ; le non bloquant retourne la trame thermique la plus récente lorsqu’une nouvelle est arrivée depuis l’appel précédent, et None dans le cas contraire. L’application continue de tourner à la cadence de trames du capteur couleur et obtient une trame thermique chaque fois que le Lepton® en produit une.

Le schéma inverse – deux captures bloquantes l’une après l’autre – fonctionne aussi, mais la boucle tourne alors à la cadence du plus lent des deux capteurs, le pipeline du capteur le plus rapide se mettant en pause entre les itérations. Choisissez la cadence que le traitement en aval de l’application souhaite réellement piloter.

4.18.3. Réinitialisation sur des rails d’alimentation partagés

Certaines cartes à double capteur alimentent les deux puces depuis un unique rail d’alimentation ou partagent une ligne de réinitialisation. Sur celles-ci, la première reset() met le rail sous tension et envoie une impulsion sur le signal partagé ; les réinitialisations suivantes sur les autres instances CSI doivent passer hard=False afin de ne reprogrammer que leur propre puce sans entraîner la voisine dans une réinitialisation

csi_rgb.reset()                        # primary -- powers the rail, pulses RESET
csi_thermal.reset(hard=False)          # secondary -- I2C reconfigure only

Un hard=True sur un capteur secondaire dans ce contexte réinitialiserait à nouveau le principal comme effet de bord, annulant toute configuration que l’application aurait déjà appliquée. La page de référence de chaque carte à double capteur indique si les rails sont partagés.

4.18.4. Choix de la source du flux

Les caméras à deux capteurs ont deux instances CSI mais ne disposent malgré tout que d’un seul tampon d’image de flux pour les deux. Un argument du constructeur choisit quel capteur alimente la prévisualisation avec ses trames

csi_rgb     = csi.CSI()                    # primary
csi_thermal = csi.CSI(cid=csi.LEPTON,
                      stream=True)         # preview source

stream=True fait de l’instance nommée la source. Sans argument stream=, le capteur principal (cid=-1, la valeur par défaut) est la source ; les instances construites avec un cid= d’un capteur secondaire restent muettes sur la prévisualisation à moins que stream=True ne soit passé explicitement. Les appels à snapshot() sur le capteur non sélectionné capturent toujours normalement des trames dans les tampons d’image de ce capteur – ils ne mettent simplement pas à jour la prévisualisation.