"""CSI 카메라 소스 (실장비 Pi5, picamera2). Implements SourcePort. picamera2 is a SYSTEM package on Raspberry Pi OS (apt: python3-picamera2 + libcamera), NOT a pip wheel — the venv sees it via --system-site-packages (see deploy/README). COLOR NOTE: configured for "RGB888", which picamera2 delivers as a 3-channel array in **BGR** byte order (documented picamera2 quirk). The downstream pose adapters (MoveNet/Hailo) expect BGR (they do cv2.cvtColor(BGR2RGB)), same as cv2.VideoCapture, so read() returns the array as-is. Validate the channel order on device during bringup (a BGR<->RGB swap yields plausible-but-wrong keypoints). """ class PiCameraSource: def __init__(self, index: int = 0, size=(640, 480), picam2=None): self.index = index if picam2 is None: # pragma: no cover (device-only: needs picamera2 + CSI camera) from picamera2 import Picamera2 # system apt package (python3-picamera2) picam2 = Picamera2(camera_num=index) picam2.configure(picam2.create_video_configuration( main={"size": tuple(size), "format": "RGB888"})) picam2.start() self.picam2 = picam2 def read(self): frame = self.picam2.capture_array() if frame is None: return False, None return True, frame