Process one scene: inference, optional NPZ / GLB, video render. Args: video_images: Pre-loaded video frames tensor (if from --video_path). None means load from image_folder.
(args, scene_name, image_folder, model, device, video_images=None)
| 909 | |
| 910 | |
| 911 | def process_scene(args, scene_name, image_folder, model, device, video_images=None): |
| 912 | """Process one scene: inference, optional NPZ / GLB, video render. |
| 913 | |
| 914 | Args: |
| 915 | video_images: Pre-loaded video frames tensor (if from --video_path). |
| 916 | None means load from image_folder. |
| 917 | """ |
| 918 | result = { |
| 919 | "scene_name": scene_name, |
| 920 | "image_folder": image_folder, |
| 921 | "success": False, |
| 922 | "error": None, |
| 923 | "duration": 0.0, |
| 924 | } |
| 925 | start_time = time.time() |
| 926 | |
| 927 | video_path = os.path.join(args.output_folder, f"{scene_name}{args.video_suffix}.mp4") |
| 928 | npz_path = os.path.join(args.output_folder, f"{scene_name}.npz") |
| 929 | glb_path = os.path.join(args.output_folder, f"{scene_name}.glb") |
| 930 | result["output_video"] = video_path |
| 931 | result["output_npz"] = npz_path if args.save_predictions else None |
| 932 | result["output_glb"] = glb_path if args.save_glb else None |
| 933 | |
| 934 | try: |
| 935 | print(f"\n{'=' * 60}") |
| 936 | print(f"Processing scene: {scene_name}") |
| 937 | print(f"{'=' * 60}") |
| 938 | |
| 939 | image_paths = None |
| 940 | if video_images is not None: |
| 941 | images = video_images |
| 942 | num_frames = images.shape[0] |
| 943 | print(f" Frames: {num_frames} (loaded from video)") |
| 944 | else: |
| 945 | image_paths = _get_filtered_image_paths(args, image_folder) |
| 946 | if not image_paths: |
| 947 | raise ValueError("No images found after applying filters") |
| 948 | num_frames = len(image_paths) |
| 949 | print(f" Image folder: {image_folder}") |
| 950 | print(f" Frames: {num_frames}") |
| 951 | images = load_images_from_paths( |
| 952 | image_paths, |
| 953 | image_size=args.image_size, |
| 954 | patch_size=args.patch_size, |
| 955 | num_workers=args.num_workers, |
| 956 | ) |
| 957 | # Keep images on CPU; inference_streaming / inference_windowed move |
| 958 | # per-window (or per-frame) slices to the model device just-in-time. |
| 959 | # This avoids OOM on very long sequences (tens of thousands of frames) |
| 960 | # where the full tensor would exceed GPU memory. |
| 961 | if device.type == "cuda": |
| 962 | # Pinned memory makes per-slice .to(cuda, non_blocking=True) fast. |
| 963 | images = images.pin_memory() if not images.is_pinned() else images |
| 964 | |
| 965 | t_infer = time.time() |
| 966 | predictions = run_inference(model, images, args) |
| 967 | t_infer = time.time() - t_infer |
| 968 | print(f"Inference done in {t_infer:.1f}s ({num_frames / max(t_infer, 1e-6):.1f} FPS)") |
no test coverage detected