Multispektral termisk (PAG7936)

PAG7936-varianten av Multispectral Thermal Camera Module kombinerar en 1 MP global-shutter-färgsensor med en FLIR Lepton termisk kärna, så att OpenMV Cam kan köra färgseende- och termiska pipelines sida vid sida.

Multispektral termisk (PAG7936)

För fullständigt datablad, foton och beställning, se produktsidan för Multispectral Thermal.

Anteckning

Stöds endast på OpenMV N6.

Höjdpunkter

  • PAG7936: 1 MP global shutter

  • Accepterar FLIR Lepton 1.x / 2.x / 3.x termiska kärnor

  • Samtidig termisk- och färgbehandling på en enda modul

  • Ser i fullständigt mörker, stöder temperaturmätning

  • Global shutter hanterar snabb rörelse utan rolling-shutter-artefakter

Användning

Färgsensorn och FLIR Lepton får var sin egen csi.CSI-instans. Det första anropet använder som standard den primära sensorn (PAG7936); det andra binder till Lepton genom att skicka cid= csi.LEPTON. Gör en hård återställning av färgsensorn med csi.CSI.reset (hard=True) för att få upp spänningen, och konfigurera Lepton med hard=False så att dess drivrutin endast omprogrammerar chipet utan att växla återställningen på nytt.

csi.CSI.framesize ( csi.QVGA ) anpassar Lepton-utmatningen till färgkameran, så att varje snapshot() returnerar en 320x240-bildruta. Lepton-drivrutinen skalar internt upp sin ursprungliga bildruta på 80x60 (1.x/2.x) eller 160x120 (3.x) till den begärda storleken — vid QVGA täcker varje Lepton-pixel en cell på 4x4 eller 2x2 i färgbildrutan.

Två arbetsbuffertar förblir konstanta genom bildrutans loop — en 256x1 alfa-palett lagrad som en image.Image så att svala Lepton-pixlar blir transparenta och heta pixlar blir ogenomskinliga (den kvadratiska rampen dämpar bakgrundsdetaljer utan att klämma ihop mellanområdet), och en Lepton-bildbuffert som förallokeras med image.Image så att csi.CSI.snapshot (blocking=False, image=...) kan fylla den på plats vid varje iteration utan omallokering:

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())

Varje iteration tar en blockerande färgstillbild och en icke-blockerande Lepton-stillbild — Lepton körs vid 9 Hz, så att blockera på den skulle strypa färgpipelinen. Image.draw_image sammanfogar sedan de två: color_palette= image.PALETTE_IRONBOW mappar Leptons gråskala till en varm färgramp i FLIR-stil, alpha_palette= blandar varje pixel med hjälp av den kvadratiska alfakartan, och hint= image.BILINEAR jämnar ut uppskalningen.

Temperaturmätning

Radiometriska Lepton-enheter (Lepton 2.5 / 3.5) rapporterar kalibrerade temperaturdata per pixel. Aktivera mätläge via csi.CSI.ioctl med csi.IOCTL_LEPTON_SET_MODE, och begränsa sedan temperaturfönstret med csi.IOCTL_LEPTON_SET_RANGE (min_celsius, max_celsius). Lepton-drivrutinen mappar linjärt gråskalepixelvärdet 0 till min_celsius och 255 till max_celsius, så att varje pixel blir en temperaturuppslagning inom det konfigurerade fönstret. Pixlar som är kallare än min_celsius mättas vid 0, pixlar som är varmare än max_celsius mättas vid 255.

csi.IOCTL_LEPTON_SET_MODE tar två flaggor. Den första aktiverar mätning; den andra väljer sensorns temperaturområde:

  • Lågt område(True, False) — sensorspann -10 °C till +140 °C (rumsskaliga scener). Begränsa fönstret till intresseområdet, t.ex. (20.0, 40.0) för kroppsvärmespårning:

    csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, False)
    csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 20.0, 40.0)
    
  • Högt område(True, True) — sensorspann -10 °C till typiskt ~+450 °C (~+400 °C vid rumstemperatur) för heta objekt. Begränsa till t.ex. (0.0, 400.0) för spårning av ugn eller heta element:

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

För att konvertera en gråskalepixel tillbaka till Celsius:

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

Detta fungerar på enskilda pixlar eller på aggregerad statistik (t.ex. stats.mean() från Image.get_statistics) inom ett ROI när heta/svala regioner lokaliseras med Image.find_blobs.

GPU-accelererad inriktning

Image.draw_image accepterar ett transform=-argument — en 3x3 homografimatris som en 2D ulab.numpy-array. På OpenMV N6 kör GPU:n projektionen per pixel under samma rityta, så att Lepton-bildrutan kan omriktas mot färgkamerans perspektiv utan en separat förvrängningspassning. Kalibrera matrisen per kamera med verktyget 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())

Observera att denna variant kör färgkameran vid csi.VGA (640x480) och Lepton vid csi.QQVGA (160x120) — homografin projicerar den mindre Lepton-bildrutan in i den större färgbildrutan som en del av ritningen, så uppskalningsfaktorn är inbakad i själva matrisen i stället för att tillämpas separat.