|
4 | 4 | """ |
5 | 5 | import os |
6 | 6 | from glob import glob |
| 7 | +import re |
7 | 8 | import cv2 # pylint: disable=import-error |
8 | 9 | from PIL import Image |
9 | 10 | import numpy as np |
10 | 11 |
|
| 12 | + |
11 | 13 | # Disable no-member for cv2 (OpenCV) for the whole file |
12 | 14 | # pylint: disable=no-member |
13 | 15 |
|
@@ -68,28 +70,67 @@ def images_to_video(image_files, video_path, fps=30): |
68 | 70 | def generate_per_object_videos(output_dir, fps=30): |
69 | 71 | """ |
70 | 72 | Generate per-object videos from mask and overlay images. |
71 | | - Each object will have its own video for masks and overlays. |
| 73 | + Each object (identified by sam_id and core_prompt) will have its own |
| 74 | + video for masks and overlays. |
72 | 75 | """ |
73 | | - mask_pattern = os.path.join(output_dir, "*_obj*_mask.png") |
74 | | - mask_files = sorted(glob(mask_pattern)) |
| 76 | + all_mask_files_pattern = os.path.join(output_dir, "*_mask.png") |
| 77 | + all_mask_files = sorted(glob(all_mask_files_pattern)) |
75 | 78 |
|
76 | | - objects = set() |
77 | | - for f in mask_files: |
78 | | - try: |
79 | | - # Assuming filename format like '000001_obj1_mask.png' |
80 | | - obj_id = os.path.basename(f).split('_')[1] # Extracts 'obj1' |
81 | | - objects.add(obj_id) |
82 | | - except IndexError: |
83 | | - print(f"Warning: Could not parse object ID from filename {f}. Skipping.") |
| 79 | + if not all_mask_files: |
| 80 | + print(f"No mask files found in {output_dir} matching pattern.") |
| 81 | + return |
| 82 | + |
| 83 | + # Store unique combinations of (sam_id_token, core_prompt_slug) |
| 84 | + # sam_id_token is like "obj1", core_prompt_slug is like "dog" or "a_red_bicycle" |
| 85 | + unique_tracked_objects = {} |
| 86 | + |
| 87 | + # Regex to parse filenames like "000001_obj1_dog_mask.png" |
| 88 | + # or "000001_obj1_a_red_bicycle_mask.png" |
| 89 | + # Group 1: (obj\d+) - e.g., "obj1" |
| 90 | + # Group 2: ([^_]+(?:_[^_]+)*) - e.g., "dog" or "a_red_bicycle" |
| 91 | + filename_parser = re.compile(r"^\d+_(obj\d+)_([^_]+(?:_[^_]+)*)_mask\.png$") |
| 92 | + |
| 93 | + for f_path in all_mask_files: |
| 94 | + fname = os.path.basename(f_path) |
| 95 | + match = filename_parser.match(fname) |
| 96 | + if match: |
| 97 | + sam_id_token = match.group(1) # e.g., "obj1" |
| 98 | + core_prompt_slug = match.group(2) # e.g., "dog" or "a_red_bicycle" |
| 99 | + |
| 100 | + # Use a tuple to uniquely identify the tracked object |
| 101 | + object_key = (sam_id_token, core_prompt_slug) |
| 102 | + if object_key not in unique_tracked_objects: |
| 103 | + unique_tracked_objects[object_key] = { |
| 104 | + "sam_id_token": sam_id_token, |
| 105 | + "core_prompt_slug": core_prompt_slug |
| 106 | + } |
| 107 | + else: |
| 108 | + print(f"Warning: Filename {fname} did not match expected pattern.") |
84 | 109 | continue |
85 | 110 |
|
| 111 | + if not unique_tracked_objects: |
| 112 | + print(f"No objects successfully parsed from filenames in {output_dir}.") |
| 113 | + return |
| 114 | + |
| 115 | + for key in sorted(list(unique_tracked_objects.keys())): # Sort for deterministic order |
| 116 | + obj_info = unique_tracked_objects[key] |
| 117 | + sam_id_token = obj_info["sam_id_token"] |
| 118 | + core_prompt_slug = obj_info["core_prompt_slug"] |
| 119 | + |
| 120 | + # Construct glob patterns that include both sam_id_token and core_prompt_slug |
| 121 | + obj_mask_files_pattern = os.path.join( |
| 122 | + output_dir, f"*_{sam_id_token}_{core_prompt_slug}_mask.png") |
| 123 | + obj_overlay_files_pattern = os.path.join( |
| 124 | + output_dir, f"*_{sam_id_token}_{core_prompt_slug}_overlay.png") |
| 125 | + |
| 126 | + obj_mask_files = sorted(glob(obj_mask_files_pattern)) |
| 127 | + obj_overlay_files = sorted(glob(obj_overlay_files_pattern)) |
86 | 128 |
|
87 | | - for obj in sorted(list(objects)): # Convert set to sorted list for deterministic order |
88 | | - obj_mask_files = sorted(glob(os.path.join(output_dir, f"*_{obj}_mask.png"))) |
89 | | - obj_overlay_files = sorted(glob(os.path.join(output_dir, f"*_{obj}_overlay.png"))) |
| 129 | + # Create a descriptive prefix for the video files |
| 130 | + video_file_prefix = f"{sam_id_token}_{core_prompt_slug}" |
90 | 131 |
|
91 | | - mask_video_path = os.path.join(output_dir, f"{obj}_mask_video.mp4") |
92 | | - overlay_video_path = os.path.join(output_dir, f"{obj}_overlay_video.mp4") |
| 132 | + mask_video_path = os.path.join(output_dir, f"{video_file_prefix}_mask_video.mp4") |
| 133 | + overlay_video_path = os.path.join(output_dir, f"{video_file_prefix}_overlay_video.mp4") |
93 | 134 |
|
94 | 135 | images_to_video(obj_mask_files, mask_video_path, fps) |
95 | 136 | images_to_video(obj_overlay_files, overlay_video_path, fps) |
0 commit comments