File size: 5,845 Bytes
3425a7c
 
 
 
 
 
 
 
 
 
 
 
 
c0c5a11
3425a7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c0c5a11
 
3425a7c
495f293
3425a7c
c0c5a11
3425a7c
 
 
c0c5a11
3425a7c
 
 
 
495f293
3425a7c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
c0c5a11
3425a7c
 
 
c0c5a11
3425a7c
 
 
 
 
 
 
 
 
 
 
c8c0d92
3425a7c
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import os
import re
import shutil
import tempfile
import zipfile

import gradio as gr

def process_zips(camera_zips, regex_pattern, start_frame, end_frame):
    """
    Processes uploaded ZIP files containing frame images from one or more cameras.
    
    Args:
        camera_zips (list): A list of file paths for the uploaded ZIP files (each representing one camera folder).
        regex_pattern (str): A regex pattern with one capturing group that extracts the numeric frame value.
        start_frame (str): The start frame number (as string, will be converted to int).
        end_frame (str): The end frame number (as string, will be converted to int).
    
    Returns:
        str: The path to the output ZIP file containing the sorted frames.
    
    The function:
      1. Extracts each uploaded ZIP into a temporary folder.
      2. Uses the ZIP file name (without extension) as the camera name.
      3. Iterates over every file in the extracted folder, applying the regex to extract the numeric frame.
      4. For files whose numeric value is between start_frame and end_frame (inclusive),
         computes the frame index as: 
             frame_index = extracted_number - start_frame + 1
      5. Copies each matching file into an output folder structure where each frame index gets its own folder.
      6. Compresses the entire output directory into a ZIP file and returns its path.
    """
    try:
        start_frame = int(start_frame)
        end_frame = int(end_frame)
    except ValueError:
        return "Error: Start and End frame numbers must be integers."
    
    if start_frame > end_frame:
        return "Error: Start frame must be less than or equal to End frame."
    
    total_frames = end_frame - start_frame + 1

    # Create a temporary output directory for sorted frames
    output_dir = tempfile.mkdtemp(prefix="sorted_frames_")

    # List to hold (camera_name, folder) tuples
    camera_folders = []
    
    for file_path in camera_zips:
        zip_name = os.path.basename(file_path)
        # Create a temporary directory to extract the ZIP contents
        extract_dir = os.path.join(tempfile.gettempdir(), zip_name + "_extracted")
        os.makedirs(extract_dir, exist_ok=True)
        with zipfile.ZipFile(file_path, "r") as zip_ref:
            zip_ref.extractall(extract_dir)
        
        # If the ZIP extracts to a single subdirectory, use that folder
        subdirs = [os.path.join(extract_dir, d) for d in os.listdir(extract_dir)
                   if os.path.isdir(os.path.join(extract_dir, d))]
        camera_folder = subdirs[0] if len(subdirs) == 1 else extract_dir
        
        # Use the ZIP filename (without extension) as the camera name
        camera_name = os.path.splitext(zip_name)[0]
        camera_folders.append((camera_name, camera_folder))
    
    # Build a mapping for each camera: { frame_index: file_full_path }
    camera_mappings = {}
    for camera_name, folder in camera_folders:
        mapping = {}
        for file_name in os.listdir(folder):
            full_path = os.path.join(folder, file_name)
            if os.path.isfile(full_path):
                try:
                    m = re.search(regex_pattern, file_name)
                except re.error as e:
                    print(f"Regex error on file {file_name}: {e}")
                    continue
                if m:
                    try:
                        num = int(m.group(1))
                    except ValueError:
                        continue
                    if start_frame <= num <= end_frame:
                        frame_index = num - start_frame + 1
                        mapping[frame_index] = full_path
        camera_mappings[camera_name] = mapping
    
    # Create output subfolders for each frame index and copy matching files from each camera
    for frame_index in range(1, total_frames + 1):
        frame_folder = os.path.join(output_dir, f"Frame_{frame_index}")
        os.makedirs(frame_folder, exist_ok=True)
        for camera_name, mapping in camera_mappings.items():
            if frame_index in mapping:
                src_file = mapping[frame_index]
                file_base = os.path.basename(src_file)
                # Rename the file by prefixing it with the camera name
                dst_file = os.path.join(frame_folder, f"{camera_name}_{file_base}")
                try:
                    shutil.copy(src_file, dst_file)
                except Exception as e:
                    print(f"Error copying {src_file} to {dst_file}: {e}")
    
    # Compress the output directory into a ZIP file
    output_zip_base = os.path.join(tempfile.gettempdir(), "sorted_frames")
    shutil.make_archive(base_name=output_zip_base, format="zip", root_dir=output_dir)
    output_zip_path = output_zip_base + ".zip"
    
    return output_zip_path

# Create the Gradio interface using type "filepath"
iface = gr.Interface(
    fn=process_zips,
    inputs=[
        gr.File(label="Camera Folder ZIPs", file_count="multiple", type="filepath"),
        gr.Textbox(label="Regex Pattern (with one capturing group)"),
        gr.Textbox(label="Start Frame Number"),
        gr.Textbox(label="End Frame Number")
    ],
    outputs=gr.File(label="Download Sorted Frames ZIP"),
    title="Frame Sorting Tool",
    description=(
        "Upload one or more ZIP files (each representing a camera folder with frame files), "
        "enter a regex pattern (for example, `_(\\d+)`), and provide the start and end frame numbers. "
        "The tool will group frames by frame index (so that frame 1 from all cameras is together) "
        "and return a downloadable ZIP file with the sorted frames."
        "Mention the Readme for further information on Regex pattern and Start and End Frames format."
    )
)

if __name__ == "__main__":
    iface.launch()