PPE_detector / scripts /download_data.py
WalterYeYint's picture
Sync from GitHub @ c09d55f
d4a30e5 verified
Raw
History Blame Contribute Delete
3.32 kB
"""Fetch the PPE dataset into work/ so train/val/test resolve for Ultralytics.
The dataset is NOT committed to git (it's ~5k images). This script reconstructs
it locally / in Colab / in CI. From repo root:
uv run --with gdown python scripts/download_data.py
DATA_URL="https://drive.google.com/uc?id=<FILE_ID>" uv run --with gdown python scripts/download_data.py
`--with gdown` installs gdown just for this run without touching the project deps.
Source options (set DATA_URL or --url):
* A Google Drive ZIP (recommended) — a single file, no download caps. Zip your
`data/` folder once, share it, and pass its `https://drive.google.com/uc?id=...` URL.
* A Google Drive FOLDER — works only if it has <50 files (gdown's folder limit),
so not suitable for the full image set. Kept as a fallback for small mirrors.
* Roboflow — the original source; `pip install roboflow` then use the versioned
download snippet from your Roboflow project for the most reproducible pull.
Expected final layout (what work/data.yaml points at):
work/train/ work/valid/ work/test/
"""
from __future__ import annotations
import argparse
import os
import sys
import zipfile
from pathlib import Path
# Documented Drive *folder* mirror (see README). Prefer a zip via DATA_URL.
DEFAULT_URL = "https://drive.google.com/drive/folders/1Vhf9QP4WG9yF11EeFUtmFKDU7sKut69f"
DEST = Path("work")
def _require_gdown():
try:
import gdown # noqa: PLC0415
except ImportError:
sys.exit(
"gdown is not installed. Re-run with uv's ephemeral install:\n"
" uv run --with gdown python scripts/download_data.py"
)
return gdown
def _extract_and_flatten(zip_path: Path) -> None:
with zipfile.ZipFile(zip_path) as zf:
zf.extractall(DEST)
# If the zip wrapped everything in a single top dir, surface train/valid/test.
for split in ("train", "valid", "test"):
if (DEST / split).exists():
continue
matches = list(DEST.glob(f"*/{split}"))
if matches:
matches[0].rename(DEST / split)
def main() -> None:
p = argparse.ArgumentParser(description=__doc__)
p.add_argument("--url", default=os.environ.get("DATA_URL", DEFAULT_URL))
args = p.parse_args()
gdown = _require_gdown()
DEST.mkdir(exist_ok=True)
if "/folders/" in args.url:
print("⚠️ Downloading a Drive FOLDER — gdown caps this at 50 files, so the")
print(" full image set will be truncated. Prefer a zip via DATA_URL.\n")
gdown.download_folder(args.url, output=str(DEST), quiet=False, use_cookies=False)
else:
zip_path = DEST / "dataset.zip"
gdown.download(args.url, str(zip_path), quiet=False, fuzzy=True)
print(f"Extracting {zip_path}{DEST}/ ...")
_extract_and_flatten(zip_path)
zip_path.unlink(missing_ok=True)
missing = [s for s in ("train", "valid", "test") if not (DEST / s).exists()]
if missing:
print(f"\n⚠️ Done, but these splits are missing under work/: {missing}")
print(" Check the archive layout — work/data.yaml expects work/train, work/valid, work/test.")
else:
print("\n✅ Dataset ready: work/train, work/valid, work/test")
if __name__ == "__main__":
main()