Show catalog gallery immediately after video upload
Browse files
frame_extraction/src/frame_extraction/app.py
CHANGED
|
@@ -51,11 +51,12 @@ def summarize_catalog(catalog_path: Path) -> Tuple[str, list[dict[str, Any]], li
|
|
| 51 |
return message, index, gallery
|
| 52 |
|
| 53 |
|
| 54 |
-
def build_catalog_from_video(
|
| 55 |
-
if
|
| 56 |
raise gr.Error("Please upload a source video first.")
|
| 57 |
|
| 58 |
ensure_output_dirs()
|
|
|
|
| 59 |
run_id = uuid.uuid4().hex[:8]
|
| 60 |
video_dir = OUTPUT_DIR / "videos"
|
| 61 |
video_path = video_dir / f"{run_id}_{Path(file.name).name}"
|
|
@@ -65,14 +66,17 @@ def build_catalog_from_video(file: gr.FileData) -> tuple[str | None, str, list[d
|
|
| 65 |
cfg = CatalogConfig(video_path=video_path, output_dir=catalog_dir)
|
| 66 |
catalog_path = build_catalog(cfg)
|
| 67 |
message, index, gallery = summarize_catalog(catalog_path)
|
| 68 |
-
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
|
| 71 |
-
def predict_from_arrays(
|
| 72 |
if not catalog_path:
|
| 73 |
raise gr.Error("Catalog not ready yet. Upload a video first.")
|
| 74 |
|
| 75 |
-
if not
|
| 76 |
raise gr.Error("Please upload at least one frame.")
|
| 77 |
|
| 78 |
ensure_output_dirs()
|
|
@@ -80,7 +84,10 @@ def predict_from_arrays(arrays: list[np.ndarray], catalog_path: str | None) -> t
|
|
| 80 |
frames_dir = OUTPUT_DIR / "frames" / run_id
|
| 81 |
frames_dir.mkdir(parents=True, exist_ok=True)
|
| 82 |
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
| 84 |
Image.fromarray(array).save(frames_dir / f"upload_{idx:03d}.png")
|
| 85 |
|
| 86 |
output_path = OUTPUT_DIR / f"matches_{run_id}.json"
|
|
@@ -119,7 +126,11 @@ def build_interface() -> gr.Blocks:
|
|
| 119 |
catalog_json = gr.JSON(label="Character Index", value=initial_index)
|
| 120 |
catalog_gallery = gr.Gallery(label="Catalog Characters", columns=4, value=initial_gallery)
|
| 121 |
|
| 122 |
-
video_upload = gr.
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
frame_upload = gr.UploadButton(
|
| 124 |
label="Upload frames",
|
| 125 |
file_types=["image"],
|
|
@@ -129,16 +140,17 @@ def build_interface() -> gr.Blocks:
|
|
| 129 |
matches_json = gr.JSON(label="Matches")
|
| 130 |
match_gallery = gr.Gallery(label="Matched Characters", columns=3)
|
| 131 |
|
| 132 |
-
|
| 133 |
-
|
| 134 |
-
|
| 135 |
-
|
| 136 |
-
|
| 137 |
-
def on_frames_upload(files: list[gr.FileData], catalog_path: str | None) -> tuple[list[dict[str, Any]], list[list[str]]]:
|
| 138 |
-
arrays = [np.array(Image.open(file.name).convert("RGB")) for file in files]
|
| 139 |
-
return predict_from_arrays(arrays, catalog_path)
|
| 140 |
|
| 141 |
-
frame_upload.upload(
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
return demo
|
| 143 |
|
| 144 |
|
|
|
|
| 51 |
return message, index, gallery
|
| 52 |
|
| 53 |
|
| 54 |
+
def build_catalog_from_video(files: list[gr.FileData]) -> tuple[str | None, str, list[dict[str, Any]], list[list[str]], list[dict[str, Any]], list[list[str]]]:
|
| 55 |
+
if not files:
|
| 56 |
raise gr.Error("Please upload a source video first.")
|
| 57 |
|
| 58 |
ensure_output_dirs()
|
| 59 |
+
file = files[0]
|
| 60 |
run_id = uuid.uuid4().hex[:8]
|
| 61 |
video_dir = OUTPUT_DIR / "videos"
|
| 62 |
video_path = video_dir / f"{run_id}_{Path(file.name).name}"
|
|
|
|
| 66 |
cfg = CatalogConfig(video_path=video_path, output_dir=catalog_dir)
|
| 67 |
catalog_path = build_catalog(cfg)
|
| 68 |
message, index, gallery = summarize_catalog(catalog_path)
|
| 69 |
+
# When a new catalog is generated, clear existing matches display
|
| 70 |
+
empty_matches: list[dict[str, Any]] = []
|
| 71 |
+
empty_gallery: list[list[str]] = []
|
| 72 |
+
return str(catalog_path), message, index, gallery, empty_matches, empty_gallery
|
| 73 |
|
| 74 |
|
| 75 |
+
def predict_from_arrays(files: list[gr.FileData], catalog_path: str | None) -> tuple[list[dict[str, Any]], list[list[str]]]:
|
| 76 |
if not catalog_path:
|
| 77 |
raise gr.Error("Catalog not ready yet. Upload a video first.")
|
| 78 |
|
| 79 |
+
if not files:
|
| 80 |
raise gr.Error("Please upload at least one frame.")
|
| 81 |
|
| 82 |
ensure_output_dirs()
|
|
|
|
| 84 |
frames_dir = OUTPUT_DIR / "frames" / run_id
|
| 85 |
frames_dir.mkdir(parents=True, exist_ok=True)
|
| 86 |
|
| 87 |
+
arrays: list[np.ndarray] = []
|
| 88 |
+
for idx, file in enumerate(files):
|
| 89 |
+
array = np.array(Image.open(file.name).convert("RGB"))
|
| 90 |
+
arrays.append(array)
|
| 91 |
Image.fromarray(array).save(frames_dir / f"upload_{idx:03d}.png")
|
| 92 |
|
| 93 |
output_path = OUTPUT_DIR / f"matches_{run_id}.json"
|
|
|
|
| 126 |
catalog_json = gr.JSON(label="Character Index", value=initial_index)
|
| 127 |
catalog_gallery = gr.Gallery(label="Catalog Characters", columns=4, value=initial_gallery)
|
| 128 |
|
| 129 |
+
video_upload = gr.UploadButton(
|
| 130 |
+
label="Upload source video",
|
| 131 |
+
file_types=["video"],
|
| 132 |
+
file_count="single",
|
| 133 |
+
)
|
| 134 |
frame_upload = gr.UploadButton(
|
| 135 |
label="Upload frames",
|
| 136 |
file_types=["image"],
|
|
|
|
| 140 |
matches_json = gr.JSON(label="Matches")
|
| 141 |
match_gallery = gr.Gallery(label="Matched Characters", columns=3)
|
| 142 |
|
| 143 |
+
video_upload.upload(
|
| 144 |
+
build_catalog_from_video,
|
| 145 |
+
inputs=video_upload,
|
| 146 |
+
outputs=[catalog_state, status_box, catalog_json, catalog_gallery, matches_json, match_gallery],
|
| 147 |
+
)
|
|
|
|
|
|
|
|
|
|
| 148 |
|
| 149 |
+
frame_upload.upload(
|
| 150 |
+
predict_from_arrays,
|
| 151 |
+
inputs=[frame_upload, catalog_state],
|
| 152 |
+
outputs=[matches_json, match_gallery],
|
| 153 |
+
)
|
| 154 |
return demo
|
| 155 |
|
| 156 |
|