Spaces:
Running on Zero
Running on Zero
File size: 4,151 Bytes
f2ec79c | 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 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | """Hugging Face export for AngleForge image datasets.
Produces a standard ``imagefolder`` layout (``train/<label>/*.jpg``) plus a
``metadata.csv`` and a dataset card, and can push it to the Hub.
"""
from __future__ import annotations
import csv
import json
import shutil
from pathlib import Path
from typing import Dict, List
from .builder import BuildResult
from .config import ANGLE_PRESETS, DatasetConfig
def _dataset_card(config: DatasetConfig, result: BuildResult, repo_id: str) -> str:
labels_table = "\n".join(
f"| `{label}` | {count} |" for label, count in sorted(result.label_counts.items())
)
angles_list = "\n".join(
f"- `{a}` — {ANGLE_PRESETS.get(a, (a, ''))[0]}" for a in config.angles
)
return f"""---
license: cc-by-4.0
pretty_name: {config.dataset_name} multi-angle robotic-arm image dataset
task_categories:
- image-classification
tags:
- image
- robotics
- robotic-arm
- synthetic-data
- multi-view
- qwen-image-edit
- edge-impulse
size_categories:
- n<1K
---
# {config.dataset_name} — Multi-Angle Robotic-Arm Image Dataset
Synthetic multi-viewpoint image dataset generated from real-world photos with
**Qwen Image Edit** ({result.backend_source}). Each source image is re-rendered
from several camera/gripper viewpoints to simulate a robotic arm inspecting an
object from multiple angles.
## Classes
| Label | Images |
|---|---|
{labels_table}
## Viewpoints (angles)
{angles_list}
## Layout
```text
train/<label>/<label>.<id>.jpg
test/<label>/<label>.<id>.jpg
metadata.csv
```
## Loading
```python
from datasets import load_dataset
ds = load_dataset("imagefolder", data_dir="{repo_id.split('/')[-1]}")
# or, once pushed to the Hub:
ds = load_dataset("{repo_id}")
print(ds)
```
## Edge Impulse
Filenames use the `label.<id>.jpg` convention, so they upload directly:
```bash
edge-impulse-uploader --category training train/**/*.jpg
```
## Notes
Synthetic multi-view images are a bootstrap for robotic-arm perception and
inspection models. Validate with real captures from the arm's own camera
before deployment.
"""
def export_hf_dataset(
config: DatasetConfig,
result: BuildResult,
hf_dir: str,
repo_id: str = "your-username/your-dataset",
) -> str:
"""Assemble an imagefolder dataset from a completed build. Returns its path."""
source_dir = Path(result.out_dir)
hf_path = Path(hf_dir).resolve()
if hf_path.exists():
shutil.rmtree(hf_path)
hf_path.mkdir(parents=True, exist_ok=True)
# Copy the imagefolder tree.
src_imagefolder = source_dir / "hf_imagefolder"
rows: List[Dict[str, str]] = []
for split in ("train", "test"):
split_src = src_imagefolder / split
if not split_src.exists():
continue
for label_dir in sorted(p for p in split_src.iterdir() if p.is_dir()):
for img in sorted(label_dir.glob("*.jpg")):
rel = Path(split) / label_dir.name / img.name
dst = hf_path / rel
dst.parent.mkdir(parents=True, exist_ok=True)
shutil.copy2(img, dst)
rows.append({"file_name": str(rel), "label": label_dir.name, "split": split})
with (hf_path / "metadata.csv").open("w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=["file_name", "label", "split"])
writer.writeheader()
writer.writerows(rows)
for name in ("dataset_summary.json",):
src = source_dir / name
if src.exists():
shutil.copy2(src, hf_path / name)
(hf_path / "README.md").write_text(_dataset_card(config, result, repo_id), encoding="utf-8")
return str(hf_path)
def push_to_hub(hf_dir: str, repo_id: str, token: str, private: bool = False) -> str:
"""Upload the HF image dataset folder to the Hub. Returns the dataset URL."""
from huggingface_hub import HfApi
api = HfApi(token=token)
api.create_repo(repo_id=repo_id, repo_type="dataset", exist_ok=True, private=private)
api.upload_folder(folder_path=hf_dir, repo_id=repo_id, repo_type="dataset")
return f"https://huggingface.co/datasets/{repo_id}"
|