""" Example 6: Multi-Sensor with Async Pipeline Combines multiprocessing (separate CUDA contexts) with async 3-stage pipeline (Capture → Flow → HHD) for maximum throughput. Architecture: Process 1 (Sensor 0): [Capture] → [Flow] → [HHD] → Queue Process 2 (Sensor 1): [Capture] → [Flow] → [HHD] → Queue ↓ Main Process: Display ← ─────────────────────┘ """ import os os.environ["OPENCV_VIDEOIO_MSMF_ENABLE_HW_TRANSFORMS"] = "0" import cv2 import orisys import multiprocessing as mp def main(): configs = [ {'vid_src': './s1.mp4', 'isstitch': True, 'cuda': True, 'cal_path': './config/cal.npy'}, {'vid_src': './s1_copy.mp4', 'isstitch': True, 'cuda': True, 'cal_path': './config/cal.npy'}, ] # Method 1: Using async_context (recommended) with orisys.MultiSensor.async_context(configs) as multi: print("\nAsync multi-sensor started. Press 'q' to quit") for all_data in multi: for data in [d for d in all_data if d]: sid = data['sensor_id'] print(f"Sensor {sid}: FPS={data['fps']:5.1f}, Fn={data['fnormal']:8.2f}") if data['img'] is not None and data['flow'] is not None: arrows = orisys.util.draw_arrows(data['img'].copy(), data['flow'], threshold=5) cv2.imshow(f"Sensor {sid}", arrows) if cv2.waitKey(1) & 0xFF == ord('q'): break cv2.destroyAllWindows() def main_manual(): """Alternative: Manual start with async flag""" configs = [ {'vid_src': './s1.mp4', 'isstitch': True, 'cuda': True, 'cal_path': './config/cal.npy'}, {'vid_src': './s1_copy.mp4', 'isstitch': True, 'cuda': True, 'cal_path': './config/cal.npy'}, ] multi = orisys.MultiSensor(configs) multi.start(use_async=True) # Enable async mode try: while True: for data in [d for d in multi.get_all() if d]: cv2.imshow(f"Sensor {data['sensor_id']}", data['img']) if cv2.waitKey(1) & 0xFF == ord('q'): break finally: multi.stop() cv2.destroyAllWindows() if __name__ == '__main__': mp.freeze_support() main()