vision-predictor-action / preprocess.py
multimodalart's picture
multimodalart HF Staff
VPA LIBERO-10 demo
6364f97 verified
Raw History Blame Contribute Delete
1.79 kB
"""Frame preprocessing identical to ``dataset.LiberoHDF5Dataset._to_tensor``.
Verbatim port of the reference transform. LIBERO stores every camera (including the wrist
camera) rotated by 180 degrees; the reference dataset rights them with ``x[:, ::-1, ::-1]``
applied to the ``[n, H, W, C]`` array *before* any other op.
The example PNGs shipped with this Space were exported from the demonstrations with that
rotation already applied, so the app passes ``rotate=False`` for them; set it to ``True`` (the
reference default) for raw, as-stored LIBERO frames.
"""
from __future__ import annotations
from typing import Sequence, Tuple
import numpy as np
import torch
import torch.nn.functional as F
IMAGE_SIZE: Tuple[int, int] = (128, 128)
ROTATE_180: bool = True
def to_tensor(raw: np.ndarray, rotate: bool = ROTATE_180) -> torch.Tensor:
"""``[H, W, C]`` or ``[n, H, W, C]`` -> ``[C, H', W']`` / ``[n, C, H', W']`` float32 in [0, 1]."""
x = np.asarray(raw)
single = x.ndim == 3
if single:
x = x[None]
# the rotate must happen *before* every other op, exactly like the dataset does
if rotate:
x = x[:, ::-1, ::-1]
out = torch.from_numpy(np.ascontiguousarray(x)).permute(0, 3, 1, 2).to(torch.float32)
if x.dtype == np.uint8:
out = out / 255.0
if IMAGE_SIZE is not None and tuple(out.shape[-2:]) != IMAGE_SIZE:
out = F.interpolate(out, size=IMAGE_SIZE, mode="bilinear", align_corners=False, antialias=True)
return out[0] if single else out
def to_views(frames: Sequence[np.ndarray], rotate: bool = ROTATE_180) -> torch.Tensor:
"""One frame per camera -> ``[V, C, H, W]`` in the order given (the checkpoint's ``camera_keys``)."""
return torch.stack([to_tensor(f, rotate=rotate) for f in frames], dim=0)