| |
| """ |
| 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 |
| """ |
| |
| center_crop = transforms.CenterCrop(224) |
|
|
| cropped_frames = [] |
| for frame in frames: |
| |
| pil_frame = Image.fromarray(frame.astype(np.uint8)) |
|
|
| |
| cropped_pil = center_crop(pil_frame) |
|
|
| |
| 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"]: |
| 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 |
|
|
| |
| 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 |
|
|
| |
| quality_label = map_quality_label(original_quality_label) |
|
|
| |
| video_files = list(quality_dir.glob("*.mp4")) + list(quality_dir.glob("*.gif")) |
|
|
| |
| |
|
|
| for video_file in video_files: |
| |
| |
| |
| |
| |
|
|
| |
| original_frames = load_video_frames(video_file) |
| cropped_frames = apply_center_crop_to_frames(original_frames) |
|
|
| nl_name = anns.get(task_name) |
|
|
| |
| trajectory = { |
| "frames": cropped_frames, |
| "task": nl_name, |
| "quality_label": 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 |
|
|