#! /usr/bin/env python3 import argparse import sys import logging import cv2 import pyvirtualcam import subprocess import numpy as np logger = logging.getLogger(__name__) def main() -> int: # Handle program arguments ap = argparse.ArgumentParser( prog="leap-view", description="View the camera feeds from a Leap Motion controller", ) ap.add_argument("device", help="Path to the video device") ap.add_argument( "-r", "--resolution", help="Resolution of the camera", choices=["640x120", "640x240", "640x480", "752x120", "752x240", "752x480"], default="640x480", ) ap.add_argument( "-v", "--verbose", help="Enable verbose logging", action="store_true" ) args = ap.parse_args() # Configure logging logging.basicConfig( level=logging.DEBUG if args.verbose else logging.INFO, format="%(levelname)s: %(message)s", ) # Open the video device cap = cv2.VideoCapture(args.device) if not cap.isOpened(): logger.error("Failed to open video device") return 1 # Set the resolution width, height = map(int, args.resolution.split("x")) cap.set(cv2.CAP_PROP_FRAME_WIDTH, width) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, height) cap.set(cv2.CAP_PROP_CONVERT_RGB, 0) # Call v4l2loopback to create two virtual cameras subprocess.run( [ "sudo", "modprobe", "v4l2loopback", "video_nr=31,32", 'card_label="Leap Motion Left","Leap Motion Right"', ], check=True, ) # Create left and right virtual cameras virtual_cam_left = pyvirtualcam.Camera( width=width, height=height, fps=30, fmt=pyvirtualcam.PixelFormat.GRAY, device="/dev/video31", ) virtual_cam_right = pyvirtualcam.Camera( width=width, height=height, fps=30, fmt=pyvirtualcam.PixelFormat.GRAY, device="/dev/video32", ) # Read frames try: while True: ret, frame = cap.read() if not ret: logger.error("Failed to read frame") break # Reshape the frame frame = np.reshape(frame, (height, width * 2)) # Split into left and right frames (every other byte) left_frame = frame[:, 0::2] right_frame = frame[:, 1::2] # Write the frames to the virtual cameras virtual_cam_left.send(left_frame) virtual_cam_right.send(right_frame) except KeyboardInterrupt: pass finally: cap.release() virtual_cam_left.close() virtual_cam_right.close() return 0 if __name__ == "__main__": sys.exit(main())