Shuyang-Yu-808
Add Robometer code + Robometer-4B weights
319eb16
Raw
History Blame Contribute Delete
5.86 kB
#!/usr/bin/env python3
"""
Metaworld dataset loader for the generic dataset converter for Robometer model training.
This module contains logic for loading metaworld data organized by task and quality.
uv run python dataset_upload/generate_hf_dataset.py \
--config_path=dataset_upload/configs/data_gen_configs/metaworld.yaml
"""
import collections
from pathlib import Path
import h5py
import numpy as np
from PIL import Image
from torchvision import transforms
from tqdm import tqdm
from dataset_upload.video_helpers import load_video_frames
from dataset_upload.dataset_loaders.mw_task_annotations import TRAIN_GT_ANN, EVAL_GT_ANN
def apply_center_crop_to_frames(frames: np.ndarray) -> np.ndarray:
"""Apply center crop (224, 224) to video frames using torchvision transforms.
Args:
frames: numpy array of shape (T, H, W, 3) in RGB order
Returns:
numpy array of shape (T, 224, 224, 3) with center cropped frames
"""
# Define the center crop transform
center_crop = transforms.CenterCrop(224)
cropped_frames = []
for frame in frames:
# Convert numpy array to PIL Image
pil_frame = Image.fromarray(frame.astype(np.uint8))
# Apply center crop
cropped_pil = center_crop(pil_frame)
# Convert back to numpy array
cropped_frame = np.array(cropped_pil)
cropped_frames.append(cropped_frame)
return np.array(cropped_frames)
def map_quality_label(original_label: str) -> str:
"""Map original quality labels to standardized Robometer labels."""
label_mapping = {"GT": "successful", "success": "successful", "all_fail": "failure", "close_succ": "suboptimal"}
return label_mapping.get(original_label, original_label)
def load_metaworld_dataset(base_path: str, dataset_name: str) -> dict[str, list[dict]]:
"""Load metaworld dataset and organize by task.
Args:
base_path: Path to the metaworld dataset directory
Returns:
Dictionary mapping task names to lists of trajectory dictionaries
"""
print(f"Loading metaworld dataset from: {base_path}")
task_data = collections.defaultdict(list)
base_path = Path(base_path)
if not base_path.exists():
raise FileNotFoundError(f"Metaworld dataset path not found: {base_path}")
if "train" in dataset_name:
tasks = TRAIN_GT_ANN.keys()
anns = TRAIN_GT_ANN
elif "eval" in dataset_name:
tasks = EVAL_GT_ANN.keys()
anns = EVAL_GT_ANN
print("number of tasks: ", len(tasks))
scucessful_trajs_file = "downloaded_data/metaworld_video.h5"
with h5py.File(scucessful_trajs_file, "r") as f:
print("Available tasks: ", f.keys())
print("number of tasks: ", len(f.keys()))
task_names = list(f.keys())
for task_name in tqdm(task_names, desc="Loading successful trajectories"):
if task_name not in tasks:
continue
for traj_name in ["0", "1", "10", "11", "12"]: # not sure why we use these, but we use these 5
traj = f[task_name][traj_name]
frames = np.array(traj)
cropped_frames = apply_center_crop_to_frames(frames)
trajectory = {
"frames": cropped_frames,
"task": anns.get(task_name),
"quality_label": "successful",
"is_robot": True,
"partial_success": 0,
}
task_data[task_name].append(trajectory)
if "eval" in dataset_name:
task_dirs = [d for d in base_path.iterdir() if d.is_dir() and not d.name.startswith(".")]
for task_dir in tqdm(task_dirs, desc="Processing tasks"):
task_name = task_dir.name
if task_name in [".DS_Store"]:
continue
# Find all quality label directories within this task
quality_dirs = [d for d in task_dir.iterdir() if d.is_dir() and not d.name.startswith(".")]
for quality_dir in quality_dirs:
original_quality_label = quality_dir.name
# Map quality label to standardized format
quality_label = map_quality_label(original_quality_label)
# Find all video files in this quality directory
video_files = list(quality_dir.glob("*.mp4")) + list(quality_dir.glob("*.gif"))
# if len(video_files) != 2:
# import ipdb; ipdb.set_trace()
for video_file in video_files:
# # Extract index from filename (e.g., "1.mp4" -> 1)
# try:
# int(video_file.stem)
# except ValueError:
# print(f"Warning: Could not parse index from filename: {video_file.name}")
# Load frames and apply center crop
original_frames = load_video_frames(video_file)
cropped_frames = apply_center_crop_to_frames(original_frames)
nl_name = anns.get(task_name)
# Create trajectory entry
trajectory = {
"frames": cropped_frames,
"task": nl_name, # Natural language task
"quality_label": quality_label, # Mapped quality label
"is_robot": True,
"partial_success": 0,
}
task_data[task_name].append(trajectory)
for task_name, trajectories in task_data.items():
print(f"Task {task_name}: {len(trajectories)} trajectories")
total_trajectories = sum(len(trajectories) for trajectories in task_data.values())
print(f"\nLoaded {total_trajectories} trajectories from {len(task_data)} tasks")
return task_data