Spaces:
Running on Zero
Running on Zero
File size: 1,787 Bytes
6364f97 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | """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)
|