Thermique multispectral (OV5640)

La variante OV5640 du module de caméra thermique multispectrale associe un capteur couleur 5 MP à obturateur déroulant à un cœur thermique FLIR Lepton, de sorte que l’OpenMV Cam peut exécuter en parallèle des pipelines de vision couleur haute résolution et des pipelines thermiques.

Thermique multispectral (OV5640)

Pour la fiche technique complète, les photos et les commandes, consultez la page produit Multispectral Thermal.

Note

Pris en charge uniquement sur l’OpenMV Cam RT1062.

Points forts

  • OV5640 : obturateur déroulant 5 MP pour une couleur de plus haute résolution

  • Accepte les cœurs thermiques FLIR Lepton 1.x / 2.x / 3.x

  • Traitement simultané thermique + couleur sur un seul module

  • Voit dans l’obscurité totale, prend en charge la mesure de température

  • Autofocus et ouverture F2.0 sur le capteur couleur

Utilisation

Le capteur couleur et le FLIR Lepton disposent chacun de leur propre instance csi.CSI. Le premier appel utilise par défaut le capteur principal (l’OV5640) ; le second se lie au Lepton en passant cid= csi.LEPTON. Effectuez une réinitialisation matérielle du capteur couleur avec csi.CSI.reset (hard=True) pour mettre le rail sous tension, et configurez le Lepton avec hard=False afin que son pilote reprogramme uniquement la puce sans réactiver la réinitialisation.

csi.CSI.framesize ( csi.QVGA ) fait correspondre la sortie du Lepton à la caméra couleur, de sorte que chaque snapshot() renvoie une trame 320x240. Le pilote du Lepton suréchantillonne en interne sa trame native 80x60 (1.x/2.x) ou 160x120 (3.x) à la taille demandée — en QVGA, chaque pixel du Lepton couvre une cellule 4x4 ou 2x2 sur la trame couleur.

Deux tampons de travail restent constants tout au long de la boucle de trames — une palette alpha 256x1 stockée sous forme d”image.Image afin que les pixels froids du Lepton deviennent transparents et les pixels chauds opaques (la rampe quadratique atténue les détails de l’arrière-plan sans écraser la plage médiane), et un tampon d’image du Lepton préalloué avec image.Image afin que csi.CSI.snapshot (blocking=False, image=...) puisse le remplir sur place à chaque itération sans réallocation

import time
import csi
import image
import math

alpha_pal = image.Image(256, 1, image.GRAYSCALE)
for i in range(256):
    alpha_pal[i] = int(math.pow((i / 255), 2) * 255)

# Setup the color camera sensor.
csi0 = csi.CSI()
csi0.reset(hard=True)  # force hardware reset.
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.QVGA)

csi1 = csi.CSI(cid=csi.LEPTON)
csi1.reset(hard=False)  # no hardware reset - just configure lepton
csi1.pixformat(csi.GRAYSCALE)
csi1.framesize(csi.QVGA)

# Optional temperature range controls for the LEPTON.
# csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, False)
# csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 20.0, 40.0)

clock = time.clock()

img1 = image.Image(csi1.width(), csi1.height(), csi1.pixformat())

while True:
    clock.tick()
    img0 = csi0.snapshot()
    csi1.snapshot(blocking=False, image=img1)
    img0.draw_image(img1, 0, 0, color_palette=image.PALETTE_IRONBOW,
                    alpha_palette=alpha_pal,
                    hint=image.BILINEAR)
    print(clock.fps())

Chaque itération effectue une capture couleur bloquante et une capture Lepton non bloquante — le Lepton fonctionne à 9 Hz, donc un blocage sur celui-ci ralentirait le pipeline couleur. Image.draw_image compose ensuite les deux : color_palette= image.PALETTE_IRONBOW mappe les niveaux de gris du Lepton sur une rampe de couleurs chaudes de style FLIR, alpha_palette= mélange chaque pixel à l’aide de la carte alpha quadratique, et hint= image.BILINEAR lisse le suréchantillonnage.

L’OV5640 dispose d’un objectif à autofocus à actionneur à bobine mobile. Déclenchez un seul passage d’autofocus sur la caméra couleur via csi.CSI.ioctl avec csi.IOCTL_TRIGGER_AUTO_FOCUS — le capteur balaie une fois le moteur de mise au point et se fixe sur ce qui se trouve devant lui

csi0.ioctl(csi.IOCTL_TRIGGER_AUTO_FOCUS)

Réémettez l’ioctl chaque fois que la scène change — l’autofocus est ponctuel, pas continu.

Mesure de température

Les Leptons radiométriques (Lepton 2.5 / 3.5) fournissent des données de température calibrées par pixel. Activez le mode mesure via csi.CSI.ioctl avec csi.IOCTL_LEPTON_SET_MODE, puis limitez la fenêtre de température avec csi.IOCTL_LEPTON_SET_RANGE (min_celsius, max_celsius). Le pilote du Lepton mappe linéairement la valeur de pixel en niveaux de gris 0 à min_celsius et 255 à max_celsius, de sorte que chaque pixel devient une recherche de température dans la fenêtre configurée. Les pixels plus froids que min_celsius saturent à 0, les pixels plus chauds que max_celsius saturent à 255.

csi.IOCTL_LEPTON_SET_MODE prend deux indicateurs. Le premier active la mesure ; le second sélectionne la plage de température du capteur :

  • Plage basse(True, False) — étendue du capteur de -10 °C à +140 °C (scènes à l’échelle d’une pièce). Limitez la fenêtre à la zone d’intérêt, p. ex. (20.0, 40.0) pour le suivi de la chaleur corporelle

    csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, False)
    csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 20.0, 40.0)
    
  • Plage haute(True, True) — étendue du capteur de -10 °C à ~+450 °C typique (~+400 °C à température ambiante) pour les objets chauds. Limitez par exemple à (0.0, 400.0) pour le suivi d’un four ou d’un élément chaud

    csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, True)
    csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 0.0, 400.0)
    

Pour reconvertir un pixel en niveaux de gris en degrés Celsius

def p_to_temp(p, min_t, max_t):
    return (p * (max_t - min_t)) / 255.0 + min_t

Cela fonctionne sur des pixels individuels ou sur des statistiques agrégées (p. ex. stats.mean() issu de Image.get_statistics) à l’intérieur d’une ROI lors de la localisation de régions chaudes/froides avec Image.find_blobs.