UCF-Net / scripts /materialize_config.py
csYiZhou's picture
Restore UCF-Net inference demo
872778f verified
Raw History Blame Contribute Delete
5.97 kB
#!/usr/bin/env python3
"""Write a portable runtime detector config for UCF-Net."""
import argparse
import os
from pathlib import Path
import yaml
LEGACY_DATASET_PATHS = {
"train.json": "splits/train.json",
"val.json": "splits/val.json",
"test.json": "splits/test.json",
"test_in_domain.json": "splits/test_in_domain.json",
"test_cross_domain.json": "splits/test_cross_domain.json",
"train_scale_10k.json": "splits/scale/train_10k.json",
"train_scale_1m.json": "splits/scale/train_1m.json",
"train_scale_2m.json": "splits/scale/train_2m.json",
}
def portable_path(path, base_dir):
path = Path(path).expanduser()
if not path.is_absolute():
return str(path)
try:
return str(path.relative_to(base_dir))
except ValueError:
return str(Path(os.path.relpath(path, base_dir)))
def portable_under(root, path, base_dir):
path = Path(path).expanduser()
if path.is_absolute():
return portable_path(path, base_dir)
path = str(path)
if path.startswith("../pretrained/"):
path = path[len("../pretrained/"):]
elif path.startswith("pretrained/"):
path = path[len("pretrained/"):]
return portable_path(root / path, base_dir)
def relative_to_dataset_root(path, data_root, default):
"""Keep split subdirectories when re-rooting detector config paths."""
def normalize(candidate):
value = candidate.as_posix()
return Path(LEGACY_DATASET_PATHS.get(value, value))
value = str(path or default).replace("\\", "/")
marker = "UCF-Net-dataset/"
if marker in value:
return normalize(Path(value.split(marker, 1)[1]))
candidate = Path(value).expanduser()
if candidate.is_absolute():
try:
return normalize(candidate.resolve().relative_to(data_root.resolve()))
except ValueError:
return normalize(Path(candidate.name))
if not value.startswith("../"):
return normalize(candidate)
return normalize(Path(candidate.name))
def main():
parser = argparse.ArgumentParser()
parser.add_argument(
"--template",
default="DeepfakeBench/training/config/detector/ucfnet.yaml",
help="Detector YAML to copy and rewrite.",
)
parser.add_argument("--output", default=".runtime/configs/ucfnet.yaml")
parser.add_argument("--repo-root", default=".")
parser.add_argument("--data-root", default="UCF-Net-dataset")
parser.add_argument("--pretrained-root", default="pretrained")
parser.add_argument("--log-dir", default="runs/train/ucfnet")
parser.add_argument("--clip-model", default=None)
parser.add_argument(
"--dino-weights",
default=None,
)
parser.add_argument("--train-batch-size", type=int, default=None)
parser.add_argument("--test-batch-size", type=int, default=None)
parser.add_argument("--workers", type=int, default=None)
parser.add_argument("--max-train-iters", type=int, default=None)
args = parser.parse_args()
repo_root = Path(args.repo_root).expanduser().resolve()
runtime_base = repo_root / "DeepfakeBench"
data_root = Path(args.data_root).expanduser()
if not data_root.is_absolute():
data_root = repo_root / data_root
pretrained_root = Path(args.pretrained_root).expanduser()
if not pretrained_root.is_absolute():
pretrained_root = repo_root / pretrained_root
template = Path(args.template).expanduser()
if not template.is_absolute():
template = repo_root / template
with open(template, "r") as f:
config = yaml.safe_load(f)
log_dir = Path(args.log_dir).expanduser()
if not log_dir.is_absolute():
log_dir = repo_root / log_dir
config["log_dir"] = portable_path(log_dir, runtime_base)
config["dataset_json_folder"] = portable_path(
repo_root / "DeepfakeBench" / "dataset_json" / "ffpp",
runtime_base,
)
image_json = dict(config.get("image_data_json") or {})
# Respect split subdirectories already set in the template and re-root them
# under data_root so runtime configs remain portable.
train_path = relative_to_dataset_root(
image_json.get("train"), data_root, "splits/train.json"
)
val_path = relative_to_dataset_root(
image_json.get("val"), data_root, "splits/val.json"
)
image_json.update(
{
"enabled": True,
"root": portable_path(data_root, runtime_base),
"train": portable_path(data_root / train_path, runtime_base),
"val": portable_path(data_root / val_path, runtime_base),
"label_map": {"real": 0, "fake": 1},
}
)
config["image_data_json"] = image_json
clip_cfg = dict(config.get("clip") or {})
clip_model = args.clip_model or clip_cfg.get("model_path", "clip-vit-large-patch14-local")
clip_cfg["model_path"] = portable_under(pretrained_root, clip_model, runtime_base)
config["clip"] = clip_cfg
dino_cfg = dict(config.get("dino") or {})
dino_weights = args.dino_weights or dino_cfg.get(
"weights",
"dinov2_vitl14_reg4_pretrain.pth",
)
dino_cfg["weights"] = portable_under(pretrained_root, dino_weights, runtime_base)
config["dino"] = dino_cfg
if args.train_batch_size is not None:
config["train_batchSize"] = args.train_batch_size
if args.test_batch_size is not None:
config["test_batchSize"] = args.test_batch_size
if args.workers is not None:
config["workers"] = args.workers
if args.max_train_iters is not None:
config["max_train_iters"] = args.max_train_iters
config["nEpochs"] = 1
output = Path(args.output).expanduser()
if not output.is_absolute():
output = repo_root / output
output.parent.mkdir(parents=True, exist_ok=True)
with open(output, "w") as f:
yaml.safe_dump(config, f, sort_keys=False)
print(output)
if __name__ == "__main__":
main()