멀티스펙트럼 서멀(PAG7936)¶
멀티스펙트럼 서멀 카메라 모듈의 PAG7936 변형은 1MP 글로벌 셔터 컬러 센서와 FLIR Lepton 서멀 코어를 결합하여, OpenMV Cam이 컬러 비전과 서멀 파이프라인을 나란히 실행할 수 있도록 합니다.
전체 데이터시트, 사진, 주문 정보는 멀티스펙트럼 서멀 제품 페이지를 참조하세요.
참고
OpenMV N6에서만 지원됩니다.
주요 특징¶
PAG7936: 1MP 글로벌 셔터
FLIR Lepton 1.x / 2.x / 3.x 서멀 코어 지원
하나의 모듈에서 서멀 + 컬러 동시 처리
완전한 어둠 속에서도 인식 가능하며 온도 측정 지원
글로벌 셔터는 롤링 셔터 아티팩트 없이 빠른 움직임을 처리합니다
사용법¶
컬러 센서와 FLIR Lepton은 각각 자체 csi.CSI 인스턴스를 가집니다. 첫 번째 호출은 기본적으로 기본 센서(PAG7936)를 사용하고, 두 번째 호출은 cid= csi.LEPTON을 전달하여 Lepton에 바인딩됩니다. csi.CSI.reset (hard=True)로 컬러 센서를 하드 리셋하여 전원 레일을 켜고, Lepton은 hard=False로 구성하여 드라이버가 리셋을 다시 토글하지 않고 칩만 재프로그래밍하도록 합니다.
csi.CSI.framesize ( csi.QVGA )는 Lepton 출력을 컬러 카메라에 맞추므로, 각 snapshot()은 320x240 프레임을 반환합니다. Lepton 드라이버는 내부적으로 80x60(1.x/2.x) 또는 160x120(3.x) 네이티브 프레임을 요청된 크기로 업스케일합니다. QVGA에서는 각 Lepton 픽셀이 컬러 프레임의 4x4 또는 2x2 셀을 덮습니다.
두 개의 스크래치 버퍼는 프레임 루프 전반에 걸쳐 일정하게 유지됩니다. 하나는 image.Image로 저장된 256x1 알파 팔레트로, 차가운 Lepton 픽셀은 투명하게, 뜨거운 픽셀은 불투명하게 만듭니다(2차 램프는 중간 영역을 뭉개지 않으면서 배경 디테일을 억제합니다). 다른 하나는 image.Image로 미리 할당된 Lepton 프레임 버퍼로, csi.CSI.snapshot (blocking=False, image=...)이 재할당 없이 매 반복마다 제자리에서 채울 수 있도록 합니다:
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())
각 반복은 블로킹 컬러 스냅샷과 논블로킹 Lepton 스냅샷을 취합니다. Lepton은 9Hz로 동작하므로 여기서 블로킹하면 컬러 파이프라인이 느려집니다. 그런 다음 Image.draw_image가 두 개를 합성합니다. color_palette= image.PALETTE_IRONBOW는 Lepton의 그레이스케일을 FLIR 스타일의 따뜻한 색상 램프로 매핑하고, alpha_palette=는 2차 알파 맵을 사용하여 각 픽셀을 블렌딩하며, hint= image.BILINEAR는 업스케일을 매끄럽게 합니다.
온도 측정¶
라디오메트릭 Lepton(Lepton 2.5 / 3.5)은 보정된 픽셀별 온도 데이터를 보고합니다. csi.IOCTL_LEPTON_SET_MODE와 함께 csi.CSI.ioctl을 통해 측정 모드를 활성화한 다음, csi.IOCTL_LEPTON_SET_RANGE (min_celsius, max_celsius)로 온도 범위를 제한하세요. Lepton 드라이버는 그레이스케일 픽셀 값 0을 min_celsius에, 255를 max_celsius에 선형으로 매핑하므로, 각 픽셀은 구성된 범위 내의 온도 조회값이 됩니다. min_celsius보다 차가운 픽셀은 0으로, max_celsius보다 뜨거운 픽셀은 255로 포화됩니다.
csi.IOCTL_LEPTON_SET_MODE는 두 개의 플래그를 받습니다. 첫 번째는 측정을 켜고, 두 번째는 센서의 온도 범위를 선택합니다:
저범위 —
(True, False)— 센서 범위-10 °C에서+140 °C까지(실내 규모 장면). 관심 영역에 맞게 범위를 제한하세요. 예: 체온 추적의 경우(20.0, 40.0)csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, False) csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 20.0, 40.0)
고범위 —
(True, True)— 뜨거운 물체를 위한 센서 범위는 일반적으로-10 °C에서~+450 °C까지(상온에서~+400 °C)입니다. 예: 용광로나 발열체 추적의 경우(0.0, 400.0)으로 제한하세요:csi1.ioctl(csi.IOCTL_LEPTON_SET_MODE, True, True) csi1.ioctl(csi.IOCTL_LEPTON_SET_RANGE, 0.0, 400.0)
그레이스케일 픽셀을 다시 섭씨로 변환하려면:
def p_to_temp(p, min_t, max_t):
return (p * (max_t - min_t)) / 255.0 + min_t
이는 개별 픽셀에서, 또는 Image.find_blobs로 뜨겁거나 차가운 영역을 찾을 때 ROI 내부의 집계 통계(예: Image.get_statistics의 stats.mean())에서도 작동합니다.
GPU 가속 정렬¶
Image.draw_image는 transform= 인자를 받습니다. 이는 2차원 ulab.numpy 배열로 된 3x3 호모그래피 행렬입니다. OpenMV N6에서는 GPU가 같은 그리기 작업 중에 픽셀별 투영을 실행하므로, 별도의 워프 패스 없이 Lepton 프레임을 컬러 카메라의 원근에 맞춰 재정렬할 수 있습니다. 서멀 오버레이 보정 도구로 카메라별 행렬을 보정하세요:
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())
이 변형은 컬러 카메라를 csi.VGA(640x480)에서, Lepton을 csi.QQVGA(160x120)에서 실행한다는 점에 유의하세요. 호모그래피가 그리기 과정의 일부로 더 작은 Lepton 프레임을 더 큰 컬러 프레임에 투영하므로, 업스케일 배율은 별도로 적용되지 않고 행렬 자체에 내장됩니다.