Thermique multispectral (PAG7936)¶
La variante PAG7936 du module de caméra thermique multispectrale associe un capteur couleur 1 MP à obturateur global à un cœur thermique FLIR Lepton, de sorte que l’OpenMV Cam peut exécuter en parallèle des pipelines de vision couleur et des pipelines thermiques.
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 N6.
Points forts¶
PAG7936 : obturateur global 1 MP
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
L’obturateur global gère les mouvements rapides sans artefacts d’obturateur déroulant
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 (le PAG7936) ; 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.
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 corporellecsi1.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 °Ctypique (~+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 chaudcsi1.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.
Alignement accéléré par GPU¶
Image.draw_image accepte un argument transform= — une matrice d’homographie 3x3 sous forme de tableau ulab.numpy 2-D. Sur l’OpenMV N6, le GPU exécute la projection par pixel pendant le même tracé, de sorte que la trame du Lepton peut être réalignée sur la perspective de la caméra couleur sans passe de déformation distincte. Calibrez la matrice par caméra avec l”outil thermal-overlay-calibration
import time
import csi
import image
from ulab import numpy as np
import math
# Calibration matrix from the thermal-overlay-calibration tool.
m = np.array([
[3.704807, 0.257018, 37.260564],
[0.052147, 3.609977, -7.831831],
[0.000294, 0.000552, 1.000000],
])
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.VGA)
csi1 = csi.CSI(cid=csi.LEPTON)
csi1.reset(hard=False) # no hardware reset - just configure lepton
csi1.pixformat(csi.GRAYSCALE)
csi1.framesize(csi.QQVGA)
# 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,
transform=m)
print(clock.fps())
Notez que cette variante fait fonctionner la caméra couleur en csi.VGA (640x480) et le Lepton en csi.QQVGA (160x120) — l’homographie projette la plus petite trame du Lepton dans la plus grande trame couleur dans le cadre du tracé, de sorte que le facteur de suréchantillonnage est intégré à la matrice elle-même plutôt qu’appliqué séparément.