멀티 카메라 시스템#
멀티 카메라 설정은 검사, 3D 재구성, 동기화된 데이터 취득과 같은 산업용 애플리케이션에서 일반적입니다. 단일 카메라만으로는 필요한 모든 정보를 캡처하기에 충분하지 않을 때 사용됩니다.
일반적인 사용 사례:
- 객체의 다양한 시점 캡처
- 시야(Field of View) 확대
- 처리량(Throughput) 증가
- 여러 객체의 병렬 검사
근본적인 과제#
여러 카메라를 사용하면 다음과 같은 여러 가지 과제가 발생합니다.
- 동기화(타이밍)
- 대역폭 제한(특히 GigE 카메라 사용 시)
- CPU 부하(여러 스트림 처리)
- 장치 식별 및 매핑
디바이스 식별#
각 카메라는 일반적으로 일련번호와 같은 고유 식별자를 가져야 합니다.
매핑 예시:
다음과 같은 인덱스 사용을 피하십시오. devices[0] 카메라 열거 순서가 변경될 수 있기 때문입니다. 자세한 내용은 다음을 참조하십시오. 카메라 열거.
여러 카메라 인스턴스 생성#
from pypylon import pylon
factory = pylon.TlFactory.GetInstance()
device_info_list = factory.EnumerateDevices()
cameras = []
for device_info in device_info_list:
camera = pylon.InstantCamera(factory.CreateDevice(device_info))
camera.Open()
cameras.append(camera)
이렇게 하면 장치당 하나의 카메라 인스턴스가 생성되고 열립니다.
획득 방식#
여러 카메라는 사용할 때는 순차(sequential) 또는 병렬(parallel) 중 하나의 획득 방식을 결정해야 합니다.
순차적 획득#
즉, 이미지 처리가 한 번에 하나의 카메라씩 차례대로 수행됩니다.
이 방식의 주요 특징:
- 구현이 간단함
- 시간 동기화되지 않음
- 전체적인 속도가 느림
병렬 취득#
즉, 여러 카메라의 이미지가 함께 처리됩니다.
이 방식의 주요 특징:
- 카메라가 동시에 획득
- 동기화에 필수적
- 더 높은 CPU 및 대역폭 요구 사항
동기화 방법#
카메라를 동기화하려면 소프트웨어 동기화와 하드웨어 동기화 중 하나를 선택할 수 있습니다. 장단점은 소프트웨어 트리거(triggering) 대 하드웨어 트리거와 유사합니다.
소프트웨어 동기화#
이 방식의 주요 특징:
- 소프트웨어를 통한 카메라 트리거
- 제한된 정밀도
- 운영 체제 스케줄링의 영향 받음
예:
하드웨어 동기화(권장)#
이 방식의 주요 특징:
- 정밀한 타이밍
- 결정론적(deterministic) 동작
- 스테레오 또는 측정 시스템에 필수적
대역폭 고려 사항(GigE)#
여러 대의 GigE 카메라가 동일한 네트워크 대역폭을 공유합니다.
잠재적인 문제:
- 패킷 손실
- 프레임 드롭
- 지연 시간 증가
잠재적인 문제를 완화하기 위해 다음 전략 중 하나를 사용할 수 있습니다.
- 전용 네트워크 인터페이스 카드(NIC) 사용
- 점보 프레임 활성화(MTU 9000)
- ROI 또는 프레임 레이트 줄이기
- 패킷 지연 설정
프로세싱 아키텍처#
단일 스레드#
- 단순함
- 제한된 확장성
멀티 스레드(권장)#
- 확장 가능
- 향상된 CPU 사용률
- 구현 복잡성 증가
예제 패턴#
기본 멀티 카메라 루프(순차 폴링)#
from pypylon import pylon
def process(image):
print(image.shape)
factory = pylon.TlFactory.GetInstance()
device_info_list = factory.EnumerateDevices()
cameras = [pylon.InstantCamera(factory.CreateDevice(device_info)) for device_info in device_info_list]
for camera in cameras:
camera.Open()
camera.StartGrabbing()
while any(camera.IsGrabbing() for camera in cameras):
for camera in cameras:
if camera.IsGrabbing():
with camera.RetrieveResult(1000) as grab_result:
if grab_result.GrabSucceeded():
image = grab_result.Array
# Do processing on image here, e.g. call a function.
process(image)
고급 접근 방식: InstantCameraArray(권장)#
pypylon은 다중 카메라 설정을 위한 전용 추상화를 제공합니다. InstantCameraArray.
이 클래스는 여러 카메라를 관리하고 단일 통합 RetrieveResult() 호출을제공하며, 어떤 카메라가 이미지를 전송했는지에 대한 정보를 포함합니다.
from pypylon import pylon
def process(image):
print(image.shape)
COUNT_OF_IMAGES_TO_GRAB = 100
RETRIEVE_TIMEOUT_MS = 5000
factory = pylon.TlFactory.GetInstance()
device_info_list = factory.EnumerateDevices()
with pylon.InstantCameraArray(len(device_info_list)) as cameras:
for i, camera in enumerate(cameras):
camera.Attach(factory.CreateDevice(device_info_list[i]))
print("Using device:", camera.DeviceInfo.ModelName)
cameras.StartGrabbing()
for i in range(COUNT_OF_IMAGES_TO_GRAB):
if not cameras.IsGrabbing():
break
with cameras.RetrieveResult(
RETRIEVE_TIMEOUT_MS,
pylon.TimeoutHandling_ThrowException
) as grab_result:
if grab_result.GrabSucceeded():
cam_idx = grab_result.CameraContext
print(f"Camera {cam_idx}: {cameras[cam_idx].DeviceInfo.ModelName}")
image = grab_result.Array
# Do processing on image here, e.g. call a function.
process(image)
else:
print("Error:", grab_result.ErrorDescription)
의 중요성 InstantCameraArray 이 중요한 이유
수동 루핑과 비교하여 이 접근 방식은 다음과 같은 이점을 제공합니다.
- 모든 카메라에 대한 단일 취득 루프
- 자동 카메라 컨텍스트 추적(
camera.CameraContext) - 더 간단한 동기화 처리
- 더 효율적인 스레드 사용
개념적으로:
실용적인 설계 가이드라인#
- 항상 시리얼 번호로 카메라를 식별하십시오.
- 하드웨어 동기화를 우선적으로 사용하십시오.
- 가능한 한 대역폭을 줄이십시오(예: ROI 지정 또는 프레임 레이트 낮추기).
- 확장성을 위해 별도의 처리 스레드를 사용하십시오.
- 시스템 부하(CPU, 네트워크)를 모니터링하십시오.
일반적인 문제점#
- 디바이스 인덱스에 의존하는 방식.
- 네트워크 대역폭 초과.
- 동기화 요구 사항 무시.
- 획득 루프에서의 처리 차단.
멘탈 모델#
주요 핵심 사항#
- 다중 카메라 시스템은 신중한 설계가 필요합니다.
- 많은 어플리케이션에서 동기화는 매우 중요합니다.
- 대역폭과 CPU는 초기 단계부터 고려해야 합니다.
- 확장 가능한 아키텍처는 병렬 처리를 사용합니다.