멀티스펙트럴 이벤트 카메라¶
멀티스펙트럴 이벤트 카메라 모듈은 GENX320 이벤트 센서와 1 MP PAG7936 글로벌 셔터 컬러 센서를 단일 모듈에 결합합니다 — 고속 객체 추적, LED 추적, 유체 흐름 및 기타 동적 장면을 위한 동기화된 이벤트 + 컬러 파이프라인입니다.
전체 데이터시트, 사진 및 주문 정보는 멀티스펙트럴 이벤트 카메라 제품 페이지 를 참조하세요.
참고
OpenMV N6에서만 지원됩니다.
주요 특징¶
320x320 이벤트 센서, >140 dB 다이내믹 레인지, 375 Hz+ 히스토그램
PAG7936 컬러: 1280x800 @ 120 FPS, 640x400 @ 240 FPS
공유 노출 트리거를 사용한 동기화된 이벤트 타임스탬프
자동 노출 없이 5 lux 미만에서도 인식
이벤트 스트리밍 시 ~3 mW부터 시작하는 전력
고속 추적, LED 추적, 유체/입자 흐름을 대상으로 함
사용법¶
컬러 센서와 GENX320 이벤트 센서는 각각 자체 csi.CSI 인스턴스를 가집니다. 첫 번째 호출은 기본적으로 기본 센서(PAG7936)로 지정되며, 두 번째 호출은 cid= csi.GENX320 을 전달하여 GENX320에 바인딩됩니다. csi.CSI.reset (hard=True) 로 컬러 센서를 하드 리셋하여 전원 레일을 켜고, GENX320은 hard=False 로 구성하여 드라이버가 리셋을 다시 토글하지 않고 칩만 재프로그래밍하도록 합니다.
GENX320은 히스토그램 모드에서 320x320을 출력하고, PAG7936은 csi.QVGA 에서 320x200을 출력합니다. 아래의 기본 오버레이는 GENX320 프레임의 하단 120행을 잘라냅니다. 맞춰진 오버레이나 더 큰 PAG7936 프레임 크기를 위해서는 (아래의) 호모그래피 변환을 사용하세요.
두 개의 스크래치 버퍼는 프레임 루프 전체에서 일정하게 유지됩니다 — 하나는 image.Image 로 저장된 256x1 알파 팔레트로, 중간 회색 기준선(128)의 히스토그램 픽셀은 투명하게 만들고 ON-이벤트 하이라이트와 OFF-이벤트 그림자 모두는 불투명하게 만듭니다. 다른 하나는 image.Image 로 사전 할당된 GENX320 프레임 버퍼로, csi.CSI.snapshot (blocking=False, image=...) 이 매 반복마다 재할당 없이 제자리에서 채울 수 있게 합니다:
import time
import csi
import image
import math
# V-shaped alpha: pixels far from the baseline 128 become opaque.
alpha_pal = image.Image(256, 1, image.GRAYSCALE)
for i in range(256):
alpha_pal[i] = int(math.pow(abs(i - 128) / 128.0, 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.GENX320)
csi1.reset(hard=False) # no hardware reset - just configure GENX320
csi1.pixformat(csi.GRAYSCALE)
csi1.framesize((320, 320))
csi1.brightness(128) # histogram baseline (default)
csi1.contrast(64) # per-event step
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_EVT_LIGHT,
alpha_palette=alpha_pal,
hint=image.BILINEAR)
print(clock.fps())
각 반복은 블로킹 컬러 스냅샷과 논블로킹 GENX320 스냅샷을 가져옵니다. 그런 다음 Image.draw_image 가 둘을 합성합니다: color_palette= image.PALETTE_EVT_LIGHT (또는 어두운 배경의 경우 image.PALETTE_EVT_DARK)은 GENX320의 그레이스케일 히스토그램을 컬러 램프로 매핑하고, alpha_palette= 는 V자 형태의 알파 맵을 사용하여 각 픽셀을 블렌딩하므로 장면의 조용한 영역은 컬러 이미지로 비쳐 보이며, hint= image.BILINEAR 은 컬러 센서가 GENX320보다 높은 해상도로 실행될 때 업스케일을 부드럽게 만듭니다.
GENX320의 바이어스 프리셋, AFK 필터, 핫 픽셀 보정, STC 필터 ioctl은 모두 이 듀얼 카메라 설정에서 동일한 방식으로 작동합니다 — csi.CSI.reset 이후 csi1 에서 호출하세요. 자세한 내용은 아래 섹션을 참조하세요.
GPU 가속 정렬¶
Image.draw_image 는 transform= 인수를 받습니다 — 2차원 ulab.numpy 배열 형태의 3x3 호모그래피 행렬입니다. OpenMV N6에서는 GPU가 동일한 그리기 작업 중에 픽셀별 투영을 실행하므로, 별도의 워프 패스 없이 GENX320 프레임을 컬러 카메라의 관점에 맞춰 재정렬할 수 있습니다 — 두 센서의 광학 특성이나 시야가 약간 다르거나 컬러 카메라가 더 높은 해상도로 실행될 때 유용합니다. 카메라별로 GenX320 오버레이 보정 도구 로 행렬을 보정하세요. 이 도구는 깜박이는 체커보드를 표시하여 물리적 움직임 없이도 이벤트 센서가 코너 이벤트를 생성하도록 합니다:
import time
import csi
import image
from ulab import numpy as np
import math
# Calibration matrix from the GenX320 Overlay Calibration tool.
m = np.array([
[2.000000, 0.000000, 0.000000],
[0.000000, 2.000000, 80.000000],
[0.000000, 0.000000, 1.000000],
])
alpha_pal = image.Image(256, 1, image.GRAYSCALE)
for i in range(256):
alpha_pal[i] = int(math.pow(abs(i - 128) / 128.0, 2) * 255)
# Setup the color camera sensor.
csi0 = csi.CSI()
csi0.reset(hard=True)
csi0.pixformat(csi.RGB565)
csi0.framesize(csi.VGA)
csi1 = csi.CSI(cid=csi.GENX320)
csi1.reset(hard=False)
csi1.pixformat(csi.GRAYSCALE)
csi1.framesize((320, 320))
csi1.brightness(128)
csi1.contrast(64)
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_EVT_LIGHT,
alpha_palette=alpha_pal,
hint=image.BILINEAR,
transform=m)
print(clock.fps())
이 변형은 컬러 카메라를 csi.VGA (640x480)에서, GENX320을 기본 해상도인 320x320에서 실행합니다 — 호모그래피가 그리기의 일부로 더 작은 GENX320 프레임을 더 큰 컬러 프레임에 투영하므로, 업스케일 계수는 별도로 적용되는 대신 행렬 자체에 포함됩니다.
이벤트 카메라 세부 정보¶
GENX320은 이벤트 기반 비전 센서입니다 — 고정된 프레임 클럭으로 전체 320x320 배열을 읽어내는 대신, 각 픽셀이 밝기 변화를 감지하는 순간 비동기 “이벤트”를 보고합니다. 모든 이벤트는 X/Y 좌표, ON/OFF 극성(밝음→어두움 또는 어두움→밝음), 마이크로초 타임스탬프를 담고 있습니다. 바로 여기에서 센서의 마이크로초 단위 시간 정밀도, 모션 블러 없음, 매우 높은 다이내믹 레인지, 활동량에 비례하는 전력 소비가 나옵니다. 정적인 장면은 데이터를 생성하지 않습니다.
OpenMV 펌웨어는 cid= csi.GENX320 과 함께 csi.CSI 를 통해 GENX320을 노출합니다. 두 가지 동작 모드를 사용할 수 있습니다:
히스토그램 모드 (기본값) — 이벤트가 칩에서 픽셀별 빈에 누적되어 구성 가능한 속도(~20-350 FPS)로 320x320 그레이스케일 프레임으로 보고됩니다. 센서가 일반 카메라처럼 동작하므로 모든 표준 이미지 처리 루틴(
Image.find_blobs, 팔레트 등)이 직접 작동합니다.이벤트 모드 — 사전 비닝된 프레임보다 시간적 세부 정보가 필요한 응용을 위해 원시 이벤트가 전체 마이크로초 타임스탬프와 함께 numpy
ndarray로 스트리밍됩니다.
히스토그램 모드¶
히스토그램 모드에서 GENX320은 각 픽셀이 해당 위치의 최근 이벤트 활동을 인코딩하는 그레이스케일 프레임을 출력합니다. 밝기 기준선보다 위에 있는 픽셀은 ON 이벤트(밝기 상승)이고, 아래에 있는 픽셀은 OFF 이벤트(밝기 하강)입니다. 기본 기준선 밝기는 128이고 이벤트당 대비 단계는 16입니다 — 이벤트를 두드러지게 하려면 대비를 높이세요:
import csi
import time
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize((320, 320))
csi0.brightness(128) # baseline (default 128)
csi0.contrast(16) # per-event step
csi0.framerate(50) # 20-350 FPS
clock = time.clock()
while True:
clock.tick()
img = csi0.snapshot()
print(clock.fps())
csi.CSI.brightness, csi.CSI.contrast, csi.CSI.framerate 는 히스토그램 출력을 형성하는 세 가지 조절 항목입니다.
컬러화된 출력¶
밝은 배경의 경우 csi.CSI.color_palette 를 image.PALETTE_EVT_LIGHT 로, 어두운 배경의 경우 image.PALETTE_EVT_DARK 로 설정하세요 — 드라이버는 팔레트를 직접 사용하여 RGB565 프레임을 출력합니다:
csi0.color_palette(image.PALETTE_EVT_LIGHT)
핫 픽셀 보정¶
이벤트 센서는 가짜로 발화하는 “핫 픽셀”을 누적합니다. 정적인 장면에 대해 csi.IOCTL_GENX320_CALIBRATE 를 실행하여 이들을 비활성화하세요. 드라이버는 320x320 픽셀별 히트 카운트를 구축하고 평균과 표준편차를 계산한 뒤, 카운트가 mean + sigma * stddev 보다 큰 픽셀을 비활성화합니다 — 그러면 비활성화된 픽셀은 센서 수준에서 이벤트 방출을 멈춥니다.
보정을 제어하는 두 가지 매개변수:
event_count— 통계를 계산하기 전에 집계할 이벤트 수입니다. 루프는 누적 이벤트 합계가 이 예산을 넘을 때까지 프레임을 캡처합니다. 카운트가 높을수록 더 신뢰할 수 있는 추정치를 얻지만 보정 시간이 길어집니다.10000이 합리적인 시작점입니다.sigma— 표준편차에 대한 임계값 배수입니다. 값이 낮을수록 더 공격적이고(더 많은 픽셀이 비활성화됨), 높을수록 더 보수적입니다.0.5가 좋은 기본값입니다.
실제로는 정상인 픽셀에 움직임에 의한 이벤트가 카운트되지 않도록, 먼저 센서를 정적인 장면을 향하게 하세요:
csi0.snapshot(time=5000) # let the user steady the camera
disabled = csi0.ioctl(csi.IOCTL_GENX320_CALIBRATE, 10000, 0.5)
print(f"disabled {disabled} hot pixels")
안티 플리커(AFK) 필터¶
주기적인 광원(형광등, LED 구동 디스플레이)은 엄청난 양의 중복 이벤트를 생성합니다. AFK 필터는 픽셀이 특정 대역 내의 주파수로 토글되는 이벤트를 거부합니다 — 대역 가장자리를 헤르츠 단위로 지정하여 csi.IOCTL_GENX320_SET_AFK 를 통해 활성화하세요:
csi0.ioctl(csi.IOCTL_GENX320_SET_AFK, 1, 130, 160) # 130-160 Hz
csi0.ioctl(csi.IOCTL_GENX320_SET_AFK, 0) # disable
바이어스 프리셋¶
GenX320의 각 픽셀은 여러 구성 가능한 바이어스를 가진 아날로그 프런트엔드를 실행합니다. 이들은 함께 감도, 노이즈, 픽셀 대역폭, 이벤트 속도를 좌우합니다 — 올바른 조합은 장면에 따라 다릅니다. 개별 바이어스는 다음과 같습니다:
DIFF_ON — 양의 비교기 대비 임계값입니다. 픽셀의 로그 조도가 이만큼 상승하면 ON 이벤트를 방출합니다. 낮을수록 = 밝은 전환에 더 민감합니다.
DIFF_OFF — 음의 비교기 대비 임계값입니다(OFF 이벤트에 대한 대칭 대응 항목). 낮을수록 = 어두운 전환에 더 민감합니다.
FO — 픽셀의 저역 통과 차단 주파수입니다. 높을수록 = 더 넓은 픽셀 대역폭(더 빠른 응답, 더 낮은 지연 시간)이지만 배경 노이즈 활동이 더 많아집니다.
HPF — 고역 통과 차단 주파수입니다. 높을수록 = 느린 밝기 변화에 대한 거부가 더 강해집니다. 빠른 전환만 비교기에 도달합니다. 주변 광 드리프트를 무시하는 데 유용합니다.
REFR — 불응 기간입니다. 픽셀이 발화한 후, 다시 발화할 수 있기 전까지 이 시간 동안 리셋 상태를 유지합니다. 높을수록 = 더 긴 데드 타임으로, 픽셀별 이벤트 속도를 제한하는 데 유용합니다.
csi.CSI.reset 이후 드라이버는 csi.GENX320_BIASES_DEFAULT 가 아니라 csi.GENX320_BIASES_LOW_NOISE 를 적용합니다 — 데이터시트 기본값은 훨씬 더 높은 배경 이벤트 속도를 방출하므로, 스트림을 조용하게 유지하기 위해 LOW_NOISE 가 시작점으로 사용됩니다. 응용에 더 높은 감도나 대역폭이 필요할 때는 다른 프리셋으로 csi.IOCTL_GENX320_SET_BIASES 를 호출하세요.
csi.IOCTL_GENX320_SET_BIASES 는 다섯 가지 프리셋 중 하나를 적용합니다:
csi.GENX320_BIASES_DEFAULT— GenX320 데이터시트 기본값입니다. 일반적인 장면을 위한 균형 잡힌 감도, 노이즈, 대역폭입니다.csi.GENX320_BIASES_LOW_LIGHT— 더 높은 감도를 위해 두 대비 임계값이 모두 완화되고, 노이즈를 낮추기 위해 FO가 내려가며, 느린 밝기 변화도 여전히 등록되도록 HPF가 0으로 설정됩니다 — 저조도 장면은 자체적으로 이벤트를 거의 생성하지 않으므로 가능한 한 많은 이벤트가 통과하도록 하고자 합니다.csi.GENX320_BIASES_ACTIVE_MARKER— 고대비 깜박이는 LED 추적에 맞춰 조정되었습니다. 날카로운 전환만 트리거하도록 대비 임계값이 높아지고, 픽셀 대역폭을 최대화하고 느린 주변 광 드리프트를 거부하기 위해 FO와 HPF가 높게 설정되며, 모든 깜박임 에지가 연속으로 캡처되도록 REFR이 0으로 낮춰집니다. 그 결과: 거의 전부 LED 에지로 이루어진, 추적하기 쉬운 스트림입니다.csi.GENX320_BIASES_LOW_NOISE— 드라이버 기본값입니다.DEFAULT대비 두 대비 임계값이 모두 높아지고(감도 낮음) FO가 내려갑니다(느린 픽셀 = 조용한 픽셀). 그렇지 않으면 거짓 이벤트가 지배하게 될 정적이거나 느린 장면에 가장 적합합니다.csi.GENX320_BIASES_HIGH_SPEED— 각 픽셀이 더 빠르게 응답할 수 있도록 FO가 높아지고, 느린 밝기 드리프트를 거부하기 위해 HPF가 높아지며, 단일 고속 이동 에지가 읽기 처리를 넘치게 하지 않도록 REFR이 높아집니다 — 더 긴 데드 타임이 격렬한 움직임에서도 이벤트 양을 제한된 범위로 유지합니다.
csi.IOCTL_GENX320_SET_BIAS 에 csi.GENX320_BIAS_DIFF_ON, csi.GENX320_BIAS_DIFF_OFF, csi.GENX320_BIAS_FO, csi.GENX320_BIAS_HPF, csi.GENX320_BIAS_REFR 중 하나와 DAC 값을 더해 개별 바이어스를 재정의하세요. 각 바이어스는 독립적으로 설정됩니다 — 프리셋을 시작점으로 선택한 다음, 장면에 필요한 바이어스를 조정하세요:
csi0.ioctl(csi.IOCTL_GENX320_SET_BIASES, csi.GENX320_BIASES_LOW_LIGHT)
csi0.ioctl(csi.IOCTL_GENX320_SET_BIAS, csi.GENX320_BIAS_HPF, 20)
추적¶
히스토그램 모드 출력은 단지 그레이스케일 이미지이므로 일반 블롭 추적이 직접 작동합니다. 액티브 마커 LED를 추적하려면 액티브 마커 바이어스 프리셋을 로드하고 히스토그램의 밝은 쪽 끝에서 블롭을 찾으세요:
import csi
import time
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.pixformat(csi.GRAYSCALE)
csi0.framesize((320, 320))
csi0.brightness(128)
csi0.contrast(16)
csi0.framerate(200)
csi0.ioctl(csi.IOCTL_GENX320_SET_BIASES, csi.GENX320_BIASES_ACTIVE_MARKER)
clock = time.clock()
while True:
clock.tick()
img = csi0.snapshot()
for blob in img.find_blobs([(120, 140)], invert=True,
pixels_threshold=2, area_threshold=4,
merge=True):
img.draw_detection(blob)
print(clock.fps())
이벤트 모드¶
이벤트 모드는 칩 내 히스토그램을 우회하여 원시 이벤트를 numpy ndarray 로 스트리밍합니다. 각 이벤트는 여섯 개의 uint16 열로 이루어진 행입니다:
[0]이벤트 유형 — 아래 참조[1]초 타임스탬프[2]밀리초 타임스탬프[3]마이크로초 타임스탬프[4]X 좌표, 0-319[5]Y 좌표, 0-319
드라이버는 [0] 열에 여섯 가지 이벤트 유형을 방출합니다:
csi.PIX_OFF_EVENT— 픽셀이 밝기 감소를 감지함(DIFF_OFF비교기 임계값이 교차됨). X/Y는 발화한 픽셀을 가리킵니다.csi.PIX_ON_EVENT— 픽셀이 밝기 증가를 감지함(DIFF_ON임계값이 교차됨). X/Y는 픽셀을 가리킵니다.csi.EXT_TRIGGER_FALLING— 센서의 외부 트리거 핀이 하강 에지를 감지함. X/Y는 사용되지 않습니다.csi.EXT_TRIGGER_RISING— 센서의 외부 트리거 핀이 상승 에지를 감지함. X/Y는 사용되지 않습니다.csi.RST_TRIGGER_FALLING— 픽셀 리셋 트리거, 하강 에지. X/Y는 사용되지 않습니다. 현재 펌웨어에서는 생성되지 않습니다.csi.RST_TRIGGER_RISING— 픽셀 리셋 트리거, 상승 에지. X/Y는 사용되지 않습니다. 현재 펌웨어에서는 생성되지 않습니다.
GENX320의 외부 트리거 입력은 카메라의 프레임 동기화 라인에 연결되어 있으며, 이 라인은 프로세서와 핀 헤더 양쪽의 P10 에도 연결됩니다 — P10을 구동하여 동기화 에지를 이벤트 스트림에 주입하고, 픽셀 데이터와 함께 EXT_TRIGGER_RISING / EXT_TRIGGER_FALLING 이벤트로 가져오세요.
대부분의 응용은 PIX_OFF_EVENT 와 PIX_ON_EVENT 에만 관심이 있습니다. 트리거 유형은 이벤트를 외부 타이밍 신호와 상관시킬 수 있게 해줍니다.
EVT_res 가 1024에서 65536 사이의 2의 거듭제곱인 (EVT_res, 6) 형태로 이벤트 버퍼를 할당한 다음, csi.GENX320_MODE_EVENT 와 버퍼 크기를 사용하여 csi.IOCTL_GENX320_SET_MODE 를 통해 이벤트 모드로 진입하세요. csi.IOCTL_GENX320_READ_EVENTS 로 이벤트를 읽으면 버퍼가 용량까지 채워지고 유효한 행의 수가 반환됩니다.
Image.draw_event_histogram 은 이벤트를 그레이스케일 이미지로 래스터화합니다 — 각 ON 이벤트마다 빈에 contrast 를 더하고, 각 OFF 이벤트마다 뺍니다. clear=True 는 먼저 이미지를 brightness 로 재설정하고, clear=False 는 여러 호출에 걸쳐 누적합니다:
import csi
import image
import time
from ulab import numpy as np
img = image.Image(320, 320, image.GRAYSCALE)
events = np.zeros((2048, 6), dtype=np.uint16)
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()
while True:
clock.tick()
n = csi0.ioctl(csi.IOCTL_GENX320_READ_EVENTS, events)
img.draw_event_histogram(events[:n], clear=True, brightness=128, contrast=64)
img.flush()
print(n, clock.fps())
히스토그램 모드의 바이어스 프리셋, AFK 필터, 핫 픽셀 보정 ioctl은 모두 이벤트 모드에서 동일한 방식으로 작동합니다 — csi.IOCTL_GENX320_SET_MODE 이후에 호출하세요.
극성으로 필터링하기¶
ON 이벤트(더 밝은 상태로의 움직임)만 또는 OFF 이벤트만 유지하려면 ulab으로 이벤트 배열을 슬라이스하세요:
TARGET = csi.PIX_ON_EVENT # or csi.PIX_OFF_EVENT
events_slice = events[:n]
indices = np.nonzero(events_slice[:, 0] == TARGET)[0]
if len(indices):
target_events = np.take(events_slice, indices, axis=0)
img.draw_event_histogram(target_events, clear=True,
brightness=128, contrast=64)
장노출 누적¶
clear=False 로 설정하여 여러 프레임에 걸쳐 동일한 이미지에 이벤트를 계속 쌓으세요 — 그 결과는 모션 트레일 시각화입니다. 주기적으로 재설정하여 새 노출을 시작하세요:
EXPOSURE_FRAMES = 30
i = 0
while True:
n = csi0.ioctl(csi.IOCTL_GENX320_READ_EVENTS, events)
clear = (i % EXPOSURE_FRAMES) == 0
img.draw_event_histogram(events[:n], clear=clear, brightness=128, contrast=64)
img.flush()
i += 1
고속 처리¶
이벤트 처리를 위해 CPU를 확보하려면 시각화를 생략하세요. N번째 반복마다만 통계를 출력하세요 — 매 반복마다 print 줄을 내보내는 것이 높은 이벤트 속도에서 병목이 됩니다:
csi0 = csi.CSI(cid=csi.GENX320)
csi0.reset()
csi0.ioctl(csi.IOCTL_GENX320_SET_MODE, csi.GENX320_MODE_EVENT, events.shape[0])
clock = time.clock()
i = 0
while True:
clock.tick()
n = csi0.ioctl(csi.IOCTL_GENX320_READ_EVENTS, events)
i += 1
if not i % 10:
print(f"{n} events {clock.fps()} fps")
시공간 대비(STC) 필터¶
실제 움직이는 대비 에지는 짧은 시간 창 내에 동일한 픽셀에서 노이즈가 많은 이벤트 버스트 를 트리거하는 경향이 있습니다 — 픽셀 불일치와 아날로그 노이즈는 응용에 유용하지 않은 추가 이벤트를 진짜 전환 주변에 생성합니다. STC 필터는 버스트당 하나(또는 몇 개)의 이벤트만 유지하고 나머지는 버리는 칩 내 후처리입니다.
이 필터는 csi.IOCTL_GENX320_SET_STC 와 GENX320_STC_* 상수를 통해 선택되는 세 가지 전략을 구현합니다. 각 모드는 버스트에서 어떤 이벤트를 전달하는지에 따라 정의됩니다:
모드 |
유지 |
폐기 |
|---|---|---|
모든 이벤트 |
없음 |
|
버스트의 두 번째 이벤트 |
첫 번째 + 이후 이벤트 |
|
버스트의 첫 번째 이벤트 |
후속 이벤트 |
|
첫 번째 + 후속 에지 |
중복 노이즈만 |
자세히:
csi.GENX320_STC_DISABLE— 필터 꺼짐, 모든 이벤트가 통과합니다(기본값).csi.GENX320_STC_ONLY— 버스트의 두 번째 이벤트를 유지합니다. 매개변수:stc_threshold(ms). 픽셀의 새 이벤트가 이전 이벤트로부터stc_threshold이내에 도착하면 버스트의 “두 번째”로 간주되어 전달됩니다 — 첫 번째 이벤트와 동일 버스트의 모든 후속 이벤트는 필터링됩니다. 맨 처음 히트보다 노이즈로 확인된 전환을 원할 때 가장 적합합니다.csi.GENX320_STC_TRAIL_ONLY— 버스트의 첫 번째 이벤트를 유지합니다. 매개변수:trail_threshold(ms). 픽셀이 발화한 후,trail_threshold가 경과할 때까지 동일 픽셀의 후속 이벤트는 폐기됩니다. 선행 에지의 정확한 타이밍을 보존합니다 — 버스트 확인보다 극성 전환 순간이 더 중요할 때 유용합니다.csi.GENX320_STC_TRAIL— 둘을 결합합니다. 매개변수:stc_threshold와trail_threshold(둘 다 ms). Trail 모드처럼 선행 에지를 유지하고 STC 모드처럼 후속 에지도 유지하므로, 버스트의 여러 이벤트가 여전히 통과합니다 — 단일 모드 필터보다 이벤트 처리량이 높지만 가장 풍부한 신호를 제공합니다.
두 임계값은 대략 13:1 비율 이내에 머물러야 합니다 — 센서는 하나가 다른 하나의 약 13배를 초과하는 구성을 거부합니다:
csi0.ioctl(csi.IOCTL_GENX320_SET_STC, csi.GENX320_STC_TRAIL, 1, 2)
csi0.ioctl(csi.IOCTL_GENX320_SET_STC, csi.GENX320_STC_DISABLE)
버퍼 깊이¶
이벤트 속도가 급증하면 기본 트리플 버퍼 파이프라인은 최신 프레임을 선호하고 오래된 프레임을 폐기합니다. 대신 이벤트를 큐에 넣으려면 csi.CSI.framebuffers 를 통해 FIFO 깊이를 높이세요 — 호스트가 뒤처질 때 약간 오래된 데이터를 처리하는 비용이 듭니다:
csi0.framebuffers(10) # FIFO depth, > 3 enables queueing
데스크톱 스트리밍 및 시각화¶
호스트 PC에서의 실시간 GUI 시각화를 위해, openmv-projects 저장소의 GenX320 이벤트 스트리밍 도구 는 카메라를 DearPyGui 프런트엔드와 결합합니다. PC GUI는 두 가지 시각화를 나란히 실행합니다: 이벤트 누적 캔버스(Image.draw_event_histogram 과 같은 개념이지만 선택 가능한 팔레트와 슬라이딩 윈도우 대 자동 지우기 모드를 가짐)와 IIR 대역 통과 필터로 구동되는 픽셀별 주파수 맵입니다 — 이벤트 스트림에서 직접 주기적 신호(회전 팬, 깜박이는 LED 등)를 찾아내는 데 유용합니다.
두 개의 온캠 스트리밍 스크립트를 제공합니다:
처리 모드 (
genx320_event_mode_streaming_on_cam.py) — 카메라가csi.IOCTL_GENX320_READ_EVENTS로 이벤트를 디코딩하고 각 행을 12바이트로 USB를 통해 스트리밍합니다([0]유형,[1]초,[2]ms,[3]us,[4]x,[5]y). 와이어 포맷이 온캠 ndarray 포맷과 일치하므로 PC에서 소비하기 쉽습니다.원시 모드 (
genx320_raw_event_mode_streaming_on_cam.py) — 카메라가csi.IOCTL_GENX320_READ_EVENTS_RAW를 통해 칩의 기본 32비트 패킹된 이벤트 워드를 스트리밍합니다. 이는 처리 모드의 12바이트 대비 이벤트당 4바이트로(USB를 통해 약 3배 적은 데이터), 링크가 병목일 때 달성 가능한 이벤트 속도가 ~3배 높아집니다. PC는 벡터화된 numpy를 사용하여 패킹된 워드를 동일한 6열 이벤트 레이아웃으로 다시 디코딩하므로, 다운스트림 시각화 코드는 동일합니다.
GenX320이 생성할 수 있는 속도에서는 USB 처리량이 제약 조건이 되기 때문에 GUI에서는 원시 모드가 기본값입니다. 온캠 스크립트에 처리 로직을 연결해야 하는 경우 처리 모드로 전환하세요.