Multispektralna termowizja (PAG7936)¶
Wariant PAG7936 modułu kamery multispektralnej termowizyjnej łączy 1-megapikselowy kolorowy sensor z migawką typu global shutter z rdzeniem termowizyjnym FLIR Lepton, dzięki czemu OpenMV Cam może równolegle uruchamiać potoki wizji kolorowej oraz termowizji.
Pełną dokumentację techniczną, zdjęcia oraz informacje o zamówieniu znajdziesz na stronie produktu Multispectral Thermal.
Informacja
Obsługiwana wyłącznie na OpenMV N6.
Najważniejsze cechy¶
PAG7936: global shutter 1 MP
Akceptuje rdzenie termowizyjne FLIR Lepton 1.x / 2.x / 3.x
Jednoczesne przetwarzanie termowizji i koloru na jednym module
Widzi w całkowitej ciemności, obsługuje pomiar temperatury
Global shutter radzi sobie z szybkim ruchem bez artefaktów charakterystycznych dla rolling shutter
Użycie¶
Sensor kolorowy oraz FLIR Lepton otrzymują każdy własną instancję csi.CSI. Pierwsze wywołanie domyślnie korzysta z głównego sensora (PAG7936); drugie wiąże się z Leptonem poprzez przekazanie cid= csi.LEPTON. Wykonaj twardy reset sensora kolorowego za pomocą csi.CSI.reset (hard=True), aby podnieść zasilanie szyny, i skonfiguruj Lepton z hard=False, aby jego sterownik jedynie przeprogramował układ bez ponownego przełączania resetu.
csi.CSI.framesize ( csi.QVGA ) dopasowuje wyjście Leptona do kamery kolorowej, tak że każdy snapshot() zwraca ramkę 320x240. Sterownik Leptona wewnętrznie skaluje w górę swoją natywną ramkę 80x60 (1.x/2.x) lub 160x120 (3.x) do żądanego rozmiaru — przy QVGA każdy piksel Leptona pokrywa komórkę 4x4 lub 2x2 na ramce kolorowej.
Dwa bufory robocze pozostają stałe przez całą pętlę ramki — paleta alfa 256x1 przechowywana jako image.Image, dzięki czemu chłodne piksele Leptona stają się przezroczyste, a gorące nieprzezroczyste (kwadratowa rampa tłumi szczegóły tła bez spłaszczania środka zakresu), oraz bufor ramki Leptona wstępnie zaalokowany za pomocą image.Image, tak aby csi.CSI.snapshot (blocking=False, image=...) mógł wypełniać go w miejscu przy każdej iteracji bez ponownej alokacji:
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())
Każda iteracja wykonuje blokujący zrzut obrazu w kolorze oraz nieblokujący zrzut obrazu z Leptona — Lepton działa z częstotliwością 9 Hz, więc blokowanie na nim ograniczyłoby przepustowość potoku kolorowego. Image.draw_image następnie komponuje oba: color_palette= image.PALETTE_IRONBOW mapuje skalę szarości Leptona na ciepłą rampę kolorów w stylu FLIR, alpha_palette= miesza każdy piksel za pomocą kwadratowej mapy alfa, a hint= image.BILINEAR wygładza skalowanie w górę.
Pomiar temperatury¶
Radiometryczne Leptony (Lepton 2.5 / 3.5) raportują skalibrowane dane temperaturowe dla każdego piksela. Włącz tryb pomiarowy poprzez csi.CSI.ioctl z csi.IOCTL_LEPTON_SET_MODE, a następnie ogranicz okno temperaturowe za pomocą csi.IOCTL_LEPTON_SET_RANGE (min_celsius, max_celsius). Sterownik Leptona liniowo mapuje wartość piksela w skali szarości 0 na min_celsius oraz 255 na max_celsius, dzięki czemu każdy piksel staje się odczytem temperatury w skonfigurowanym oknie. Piksele chłodniejsze niż min_celsius nasycają się do 0, a piksele cieplejsze niż max_celsius nasycają się do 255.
csi.IOCTL_LEPTON_SET_MODE przyjmuje dwie flagi. Pierwsza włącza pomiar; druga wybiera zakres temperatury sensora:
Niski zakres —
(True, False)— zakres sensora od-10 °Cdo+140 °C(sceny w skali pomieszczenia). Ogranicz okno do obszaru zainteresowania, np.(20.0, 40.0)do śledzenia ciepła ciała:csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, False) csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 20.0, 40.0)
Wysoki zakres —
(True, True)— typowy zakres sensora od-10 °Cdo~+450 °C(~+400 °Cw temperaturze pokojowej) dla gorących obiektów. Ogranicz np. do(0.0, 400.0)do śledzenia pieców lub gorących elementów:csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, True) csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 0.0, 400.0)
Aby przekonwertować piksel w skali szarości z powrotem na stopnie Celsjusza:
def p_to_temp(p, min_t, max_t):
return (p * (max_t - min_t)) / 255.0 + min_t
Działa to na pojedynczych pikselach lub na zagregowanych statystykach (np. stats.mean() z Image.get_statistics) wewnątrz ROI podczas lokalizowania gorących/chłodnych regionów za pomocą Image.find_blobs.
Wyrównanie przyspieszane przez GPU¶
Image.draw_image akceptuje argument transform= — macierz homografii 3x3 w postaci dwuwymiarowej tablicy ulab.numpy. Na OpenMV N6 GPU wykonuje projekcję per-piksel podczas tego samego rysowania, dzięki czemu ramkę Leptona można ponownie wyrównać względem perspektywy kamery kolorowej bez osobnego przebiegu zniekształcania. Skalibruj macierz dla każdej kamery za pomocą narzędzia 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())
Zwróć uwagę, że ten wariant uruchamia kamerę kolorową w csi.VGA (640x480), a Lepton w csi.QQVGA (160x120) — homografia rzutuje mniejszą ramkę Leptona na większą ramkę kolorową w ramach rysowania, więc współczynnik skalowania w górę jest wbudowany w samą macierz, zamiast być stosowany osobno.