Spaces:
Runtime error
Runtime error
Update app.py from anycoder
Browse files
app.py
CHANGED
|
@@ -1,167 +1,121 @@
|
|
| 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 |
-
> **Adjusting UI and Logic**
|
| 119 |
-
>
|
| 120 |
-
> I've now incorporated the changes into `src/sam3d_body/gradio_ui/sam3d_body_ui.py`, updating the file input to accept multiple uploads. I've adjusted the code to load and handle images and video files. The main task will be testing to ensure that the multiple uploads are processed correctly, and that the Rerun streaming occurs as designed, showing frames smoothly.
|
| 121 |
-
>
|
| 122 |
-
>
|
| 123 |
-
> **Adjusting the Main UI**
|
| 124 |
-
>
|
| 125 |
-
> I've now incorporated the changes into `src/sam3d_body/gradio_ui/sam3d_body_ui.py`, updating the file input to support multiple uploads and revising the example inputs, including the addition of `cv2`. I am making sure that the application now smoothly handles multiple images and videos. The main task is verifying the Rerun streaming and its dynamic behavior.
|
| 126 |
-
>
|
| 127 |
-
>
|
| 128 |
-
> **Refactoring for File Handling**
|
| 129 |
-
>
|
| 130 |
-
> I'm now changing the function signature for `sam3d_prediction_fn`, making it accept a list of file paths. I'm focusing on creating an effective processing loop that distinguishes between images and videos and also uses a frame index for the Rerun timeline. I've chosen `cv2` for frame extraction. I'm taking the steps necessary to make my function more versatile.
|
| 131 |
-
>
|
| 132 |
-
>
|
| 133 |
-
> **Finalizing Code and Testing**
|
| 134 |
-
>
|
| 135 |
-
> I've implemented the changes in `src/sam3d_body/gradio_ui/sam3d_body_ui.py`, updating the UI and processing logic to accommodate multiple file uploads and stream the Rerun output. The focus now is on thorough testing to ensure proper handling of various image and video formats, continuous timeline indexing, and correct GLB export, using `cv2` within the revised functions.
|
| 136 |
-
>
|
| 137 |
-
>
|
| 138 |
-
> **Adjusting for Testing**
|
| 139 |
-
>
|
| 140 |
-
> I'm now adapting the code to accommodate the changes, after which I'll focus on testing. I'm focusing on ensuring the Rerun timeline remains continuous across multiple file uploads and that videos are handled correctly with `cv2`. The core thing is getting to testing now.
|
| 141 |
-
>
|
| 142 |
-
>
|
| 143 |
-
> **Finalizing the Integration**
|
| 144 |
-
>
|
| 145 |
-
> I'm now delivering the completed code for `src/sam3d_body/gradio_ui/sam3d_body_ui.py`, fully updated to handle multiple file uploads and stream the Rerun output. The changes now allow for the correct processing of a user's image and video uploads, with the `cv2` library and the Rerun stream working in tandem.
|
| 146 |
-
>
|
| 147 |
-
>
|
| 148 |
-
> **Finalizing the Adaptation**
|
| 149 |
-
>
|
| 150 |
-
> I'm now delivering the completed code for `src/sam3d_body/gradio_ui/sam3d_body_ui.py`, fully updated to handle multiple file uploads and stream the Rerun output. The changes now allow for the correct processing of a user's image and video uploads, with the `cv2` library and the Rerun stream working in tandem, ready for final tests.
|
| 151 |
-
>
|
| 152 |
-
>
|
| 153 |
-
> **Modifying the UI Elements**
|
| 154 |
-
>
|
| 155 |
-
> I'm now restructuring `src/sam3d_body/gradio_ui/sam3d_body_ui.py` to change the input component and related examples to support multiple files, using `gr.File(file_count="multiple", label="Input Images/Videos")`. I'm also preparing for the required tests.
|
| 156 |
-
>
|
| 157 |
-
>
|
| 158 |
-
> **Adapting for Gradio Updates**
|
| 159 |
-
>
|
| 160 |
-
> I'm now fully integrating the file upload functionality and Rerun streaming. This encompasses modifying the UI components and processing steps to accommodate `gr.File` for uploading and iterating through multiple files. The emphasis is on seamless operation and correct behavior when the user uploads multiple media, and ensuring updates show smoothly in the Gradio interface.
|
| 161 |
-
>
|
| 162 |
-
>
|
| 163 |
-
> **Integrating New Uploads**
|
| 164 |
-
>
|
| 165 |
-
> I'm now changing the input to `gr.File(file_count="multiple")` in `src/sam3d_body/gradio_ui/sam3d_body_ui.py` to allow multi-file uploads. The `sam3d_prediction_fn` function signature is also updated to accommodate a list of file paths to process. I am also adjusting the UI examples for file input.
|
| 166 |
-
>
|
| 167 |
-
>
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import cv2
|
| 3 |
+
import os
|
| 4 |
+
import time
|
| 5 |
+
from utils import is_video, process_frame_mock
|
| 6 |
|
| 7 |
+
def sam3d_prediction_fn(file_paths, progress=gr.Progress()):
|
| 8 |
+
"""
|
| 9 |
+
Processes a list of file paths (images or videos).
|
| 10 |
+
Simulates the SAM3D/Rerun logic by iterating through files
|
| 11 |
+
and yielding results for a streaming UI.
|
| 12 |
+
"""
|
| 13 |
+
if not file_paths:
|
| 14 |
+
return [], "No files uploaded."
|
| 15 |
+
|
| 16 |
+
processed_results = []
|
| 17 |
+
total_files = len(file_paths)
|
| 18 |
+
status_log = ""
|
| 19 |
+
|
| 20 |
+
# Global frame counter simulation (as mentioned in your thought trace)
|
| 21 |
+
global_frame_idx = 0
|
| 22 |
+
|
| 23 |
+
for i, file_path in enumerate(file_paths):
|
| 24 |
+
file_name = os.path.basename(file_path)
|
| 25 |
+
status_msg = f"Processing file {i+1}/{total_files}: {file_name}..."
|
| 26 |
+
status_log += status_msg + "\n"
|
| 27 |
+
|
| 28 |
+
# Yield status update immediately
|
| 29 |
+
yield processed_results, status_log
|
| 30 |
+
|
| 31 |
+
# Determine if file is video or image
|
| 32 |
+
if is_video(file_path):
|
| 33 |
+
cap = cv2.VideoCapture(file_path)
|
| 34 |
+
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
| 35 |
+
|
| 36 |
+
# Process video frames (simulating frame-by-frame logic)
|
| 37 |
+
# We'll just process a few frames to keep the demo quick
|
| 38 |
+
max_frames_to_preview = 5
|
| 39 |
+
current_frame = 0
|
| 40 |
+
|
| 41 |
+
while cap.isOpened() and current_frame < max_frames_to_preview:
|
| 42 |
+
ret, frame = cap.read()
|
| 43 |
+
if not ret:
|
| 44 |
+
break
|
| 45 |
+
|
| 46 |
+
# Simulate SAM3D processing on the frame
|
| 47 |
+
processed_frame = process_frame_mock(frame, f"Video Frame {global_frame_idx}")
|
| 48 |
+
processed_results.append((processed_frame, f"{file_name} - Frame {current_frame}"))
|
| 49 |
+
|
| 50 |
+
global_frame_idx += 1
|
| 51 |
+
current_frame += 1
|
| 52 |
+
|
| 53 |
+
# Stream updates every frame
|
| 54 |
+
yield processed_results, status_log
|
| 55 |
+
time.sleep(0.1) # Simulate processing time
|
| 56 |
+
|
| 57 |
+
cap.release()
|
| 58 |
+
status_log += f"Finished video: {file_name}\n"
|
| 59 |
+
|
| 60 |
+
else:
|
| 61 |
+
# Process single image
|
| 62 |
+
image = cv2.imread(file_path)
|
| 63 |
+
if image is not None:
|
| 64 |
+
processed_image = process_frame_mock(image, f"Image {global_frame_idx}")
|
| 65 |
+
processed_results.append((processed_image, file_name))
|
| 66 |
+
global_frame_idx += 1
|
| 67 |
+
|
| 68 |
+
# Stream update
|
| 69 |
+
yield processed_results, status_log
|
| 70 |
+
time.sleep(0.5) # Simulate processing time
|
| 71 |
+
|
| 72 |
+
status_log += f"Finished image: {file_name}\n"
|
| 73 |
+
|
| 74 |
+
status_log += "All processing complete."
|
| 75 |
+
yield processed_results, status_log
|
| 76 |
+
|
| 77 |
+
# --- Gradio 6 Application Structure ---
|
| 78 |
+
|
| 79 |
+
with gr.Blocks() as demo:
|
| 80 |
+
# Header with required link
|
| 81 |
+
gr.Markdown("# SAM3D Multi-File Processor")
|
| 82 |
+
gr.Markdown("[Built with anycoder](https://huggingface.co/spaces/akhaliq/anycoder)")
|
| 83 |
+
|
| 84 |
+
with gr.Row():
|
| 85 |
+
with gr.Column(scale=1):
|
| 86 |
+
# UPDATED: Using gr.File with file_count="multiple" as requested
|
| 87 |
+
input_files = gr.File(
|
| 88 |
+
file_count="multiple",
|
| 89 |
+
label="Input Images/Videos",
|
| 90 |
+
file_types=["image", "video"]
|
| 91 |
+
)
|
| 92 |
+
process_btn = gr.Button("Start Processing", variant="primary")
|
| 93 |
+
|
| 94 |
+
# Log output to see the sequential processing logic
|
| 95 |
+
log_output = gr.Textbox(label="Processing Log", lines=10, interactive=False)
|
| 96 |
+
|
| 97 |
+
with gr.Column(scale=2):
|
| 98 |
+
# Gallery to display the streaming results
|
| 99 |
+
output_gallery = gr.Gallery(
|
| 100 |
+
label="Processed Stream",
|
| 101 |
+
columns=3,
|
| 102 |
+
height=600,
|
| 103 |
+
object_fit="contain"
|
| 104 |
+
)
|
| 105 |
+
|
| 106 |
+
# Event Listener
|
| 107 |
+
process_btn.click(
|
| 108 |
+
fn=sam3d_prediction_fn,
|
| 109 |
+
inputs=[input_files],
|
| 110 |
+
outputs=[output_gallery, log_output],
|
| 111 |
+
api_visibility="public"
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
# Launch with Gradio 6 parameters
|
| 115 |
+
if __name__ == "__main__":
|
| 116 |
+
demo.launch(
|
| 117 |
+
theme=gr.themes.Soft(),
|
| 118 |
+
footer_links=[
|
| 119 |
+
{"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"}
|
| 120 |
+
]
|
| 121 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|