fishxinyu/OpenVE-3M-process / build_construct_video.py
fishxinyu's picture
download
raw
6.49 kB
"""
For each selected pair image in OpenVE-3M/selected/, find the corresponding
videos, copy them to construct_video/ with sequential names (001.mp4,
001_orig.mp4, 002.mp4, ...), and write a CSV mapping original names to
renamed ones along with the editing prompt.
"""
import csv
import shutil
from pathlib import Path
BASE_DIR = Path("/home/xinyuy/dataset_processing/OpenVE-3M/OpenVE-3M")
SELECTED_DIR = BASE_DIR / "selected"
VIDEOS_DIR = BASE_DIR / "videos"
CSV_DIR = BASE_DIR / "csv_files"
OUTPUT_DIR = Path("/home/xinyuy/dataset_processing/OpenVE-3M/construct_video")
# Map CSV path prefix → actual subfolder name under VIDEOS_DIR
PREFIX_MAP = {
"local_add": "local_add",
"local_remove": "local_remove",
"global_style": "global_style_new",
"background_change": "background_change",
"local_change": "local_change",
"subject-filtered": "subject-filtered",
}
CSV_FILES = [
CSV_DIR / "local_add.csv",
CSV_DIR / "local_remove.csv",
CSV_DIR / "global_style.csv",
CSV_DIR / "local_add_in_subject.csv",
]
def resolve_video_path(csv_path: str) -> Path | None:
parts = csv_path.strip().split("/", 1)
if len(parts) != 2:
return None
folder_key, filename = parts
actual_folder = PREFIX_MAP.get(folder_key)
if actual_folder is None:
return None
return VIDEOS_DIR / actual_folder / filename
def build_lookup() -> dict[str, dict]:
"""
Build a lookup: video_stem → {edited_path, original_path, prompt}.
Index both the edited and original stems so we can find a row by either ID.
"""
lookup: dict[str, dict] = {}
for csv_file in CSV_FILES:
if not csv_file.exists():
continue
with open(csv_file, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f, delimiter=";")
for row in reader:
edited_csv = row.get("video", "").strip()
original_csv = row.get("original_video", "").strip()
prompt = row.get("prompt", "").strip()
if not edited_csv or not original_csv:
continue
edited_path = resolve_video_path(edited_csv)
original_path = resolve_video_path(original_csv)
if edited_path is None or original_path is None:
continue
entry = {
"edited_path": edited_path,
"original_path": original_path,
"prompt": prompt,
}
# Index by both stems so we can look up by either ID
lookup.setdefault(edited_path.stem, []).append(entry)
lookup.setdefault(original_path.stem, []).append(entry)
return lookup
def find_entry(id_a: str, id_b: str, lookup: dict) -> dict | None:
"""Find the CSV entry where one ID is the edited video and the other is original."""
for entry in lookup.get(id_a, []):
if entry["edited_path"].stem == id_a and entry["original_path"].stem == id_b:
return entry
if entry["edited_path"].stem == id_b and entry["original_path"].stem == id_a:
return entry
for entry in lookup.get(id_b, []):
if entry["edited_path"].stem == id_a and entry["original_path"].stem == id_b:
return entry
if entry["edited_path"].stem == id_b and entry["original_path"].stem == id_a:
return entry
return None
def main():
OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
selected_images = sorted(SELECTED_DIR.glob("*.jpg"))
if not selected_images:
print("No .jpg files found in selected/")
return
print(f"Found {len(selected_images)} selected images. Building CSV lookup...")
lookup = build_lookup()
print("Lookup built.")
results = []
missing = []
idx = 1
for img_path in selected_images:
stem = img_path.stem
parts = stem.split("__", 1)
if len(parts) != 2:
print(f" [WARN] Cannot parse pair IDs from: {img_path.name}")
missing.append({"original_image": img_path.name, "reason": "unparseable name"})
continue
id_a, id_b = parts
entry = find_entry(id_a, id_b, lookup)
if entry is None:
print(f" [WARN] No CSV match for: {img_path.name}")
missing.append({"original_image": img_path.name, "reason": "no CSV match"})
continue
edited_path: Path = entry["edited_path"]
original_path: Path = entry["original_path"]
prompt: str = entry["prompt"]
if not edited_path.exists():
print(f" [WARN] Edited video missing: {edited_path}")
missing.append({"original_image": img_path.name, "reason": f"edited video not found: {edited_path}"})
continue
if not original_path.exists():
print(f" [WARN] Original video missing: {original_path}")
missing.append({"original_image": img_path.name, "reason": f"original video not found: {original_path}"})
continue
tag = f"{idx:03d}"
edited_dest = OUTPUT_DIR / f"{tag}.mp4"
original_dest = OUTPUT_DIR / f"{tag}_orig.mp4"
shutil.copy2(edited_path, edited_dest)
shutil.copy2(original_path, original_dest)
results.append({
"index": tag,
"renamed_edited": edited_dest.name,
"original_edited_name": edited_path.name,
"renamed_original": original_dest.name,
"original_source_name": original_path.name,
"prompt": prompt,
})
print(f" [{tag}] {edited_path.name}{edited_dest.name}")
print(f" {original_path.name}{original_dest.name}")
idx += 1
# Write mapping CSV
out_csv = OUTPUT_DIR / "index.csv"
fieldnames = [
"index",
"renamed_edited",
"original_edited_name",
"renamed_original",
"original_source_name",
"prompt",
]
with open(out_csv, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=fieldnames)
writer.writeheader()
writer.writerows(results)
print(f"\nDone. Copied {len(results)} pairs to {OUTPUT_DIR}")
print(f"Index saved to {out_csv}")
if missing:
print(f"\nSkipped {len(missing)} images:")
for m in missing:
print(f" {m['original_image']}: {m['reason']}")
if __name__ == "__main__":
main()

Xet Storage Details

Size:
6.49 kB
·
Xet hash:
ed344f35cbbcb1ecff8b8788165a6f4f9052b350439e0f164ffb787516616510

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.