multimodalart's picture
multimodalart HF Staff
prep stage
1811aab verified
Raw History Blame Contribute Delete
3.62 kB
"""Preview media of rendered clips: RGB | proxy | overlay video and a 6-frame strip.
python -m rtcwm.data.preview OUT_DIR CLIP_DIR [...] [--proxy conditions_coarse]
Writes OUT_DIR/<parent>_<clip>_sbs.mp4, ..._strip.jpg and OUT_DIR/clips.json (one metadata row per clip).
"""
from __future__ import annotations
import argparse
import json
from pathlib import Path
import av
import cv2
import numpy as np
from .clip import FPS, read_meta, read_proxy
PALETTE = np.array([[70, 70, 70], [135, 206, 235], [0, 90, 200], [150, 110, 60], [150, 150, 150], [40, 160, 40],
[200, 120, 80], [230, 200, 0], [230, 60, 60], [255, 0, 255], [0, 220, 220], [255, 255, 255]], np.uint8)
W, H = 448, 256
def proxy_image(clip: Path, i: int, kind: str) -> np.ndarray:
z, s = read_proxy(clip, i, kind)
dn = 1 - np.log(np.clip(z, 0.3, 256) / 0.3) / np.log(256 / 0.3)
dn[z <= 1e-3] = 0
return cv2.resize((0.55 * PALETTE[s] + 0.45 * (dn[..., None] * 255)).astype(np.uint8), (W, H),
interpolation=cv2.INTER_NEAREST)
def label(im, text):
im = im.copy()
cv2.putText(im, text, (8, 24), 0, 0.6, (0, 0, 0), 4)
cv2.putText(im, text, (8, 24), 0, 0.6, (255, 255, 255), 2)
return im
def preview(clip: Path, out: Path, kind: str = "conditions") -> dict:
meta = read_meta(clip)
name = f"{clip.parent.name}_{clip.name}"
with av.open(str(clip / "rgb.mp4")) as c:
frames = [f.to_ndarray(format="rgb24") for f in c.decode(video=0)]
with av.open(str(out / f"{name}_sbs.mp4"), "w") as c:
st = c.add_stream("libx264", rate=FPS)
st.width, st.height, st.pix_fmt = 3 * W, H, "yuv420p"
st.options = {"crf": "26"}
for i, fr in enumerate(frames):
r = cv2.resize(fr, (W, H), interpolation=cv2.INTER_AREA)
p = proxy_image(clip, i, kind)
row = np.concatenate([label(r, f"RGB {i / FPS:.1f}s"), label(p, "proxy: depth + semantic"),
label(cv2.addWeighted(r, 0.5, p, 0.5, 0), "overlay")], 1)
for pk in st.encode(av.VideoFrame.from_ndarray(np.ascontiguousarray(row), format="rgb24")):
c.mux(pk)
for pk in st.encode():
c.mux(pk)
idx = np.linspace(0, len(frames) - 1, 6).astype(int)
strip = np.concatenate([label(cv2.resize(frames[i], (W, H)), f"{i / FPS:.1f}s") for i in idx], 1)
cv2.imwrite(str(out / f"{name}_strip.jpg"), strip[..., ::-1], [cv2.IMWRITE_JPEG_QUALITY, 82])
traj = np.array(meta["hero_traj"])
return dict(name=name, map=meta["map"].replace("_Opt", ""), weather=meta["weather"],
seconds=round(meta["frames"] / FPS, 1), frames=meta["frames"],
hero=round(meta["hero_visible_frac_median"] * 100, 1), fps=round(meta["render_fps"], 1),
end_to_start_m=round(float(np.linalg.norm(traj[-1][:2] - traj[0][:2])), 1),
path_m=round(float(np.linalg.norm(np.diff(traj[:, :2], axis=0), axis=1).sum()), 1))
def main():
ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
ap.add_argument("out", type=Path)
ap.add_argument("clips", nargs="+", type=Path)
ap.add_argument("--proxy", default="conditions", help="conditions (fine) or conditions_coarse")
a = ap.parse_args()
a.out.mkdir(parents=True, exist_ok=True)
rows = []
for clip in a.clips:
rows.append(preview(clip, a.out, a.proxy))
print(rows[-1]["name"], "ok", flush=True)
(a.out / "clips.json").write_text(json.dumps(rows, indent=1))
if __name__ == "__main__":
main()