Spaces:
Sleeping
Sleeping
| # -*- coding: utf-8 -*- | |
| """ | |
| data.py | |
| ์ด๋ฏธ ํฌ๋กญ๋ ์ฌ๋ผ์ด์ค(cropped/ + labels.jsonl)์์ ๋ฐฐํฐ๋ฆฌ๋ฅผ ์ฝ์ด์จ๋ค. | |
| ์ด ํ์ ๋ฐ์ดํฐ๋ ์๋ณธ์ด ์๋๋ผ '๋ด ์ ์ฒ๋ฆฌ ์ถ๋ ฅ'์ด๋ค: | |
| data/cropped/<battery_key>/<slice>.jpg (๋ฐฐํฐ๋ฆฌ outline+์ฌ์ ๋ก ํฌ๋กญ๋ ํ์ ์ฌ๋ผ์ด์ค) | |
| data/labels.jsonl (์ฌ๋ผ์ด์ค๋ณ: set/path/battery_key/type(cell|module)/swelling_flag/boxes(ํฌ๋กญ์ขํ GT)) | |
| โ ์ด๋ฏธ ํฌ๋กญ๋ผ ์์ผ๋ฏ๋ก ์ถ๋ก ์ outline ํฌ๋กญ ์์ด 'ํฌ๋กญ ์ด๋ฏธ์ง ๊ทธ๋๋ก' ํ์ผ๋ง/letterbox ํ๋ค. | |
| ๋ฃจํธ ์ง์ (์ฐ์ ์์): GLUE_DATA_ROOT > /workspace/battery-ct-security/data > d:/CT DATA | |
| """ | |
| import json | |
| import os | |
| from collections import defaultdict | |
| from pathlib import Path | |
| from PIL import Image | |
| # ๋ฐฐํฐ๋ฆฌ๋น ์ฌ๋ผ์ด์ค ์ํ(๋ฐ๋ชจ ์๋; ์ถ๋น ๊ท ๋ฑ ์ํ). 0 ์ด๋ฉด ์ ๋. env GLUE_MAX_SLICES. | |
| MAX_SLICES = int(os.environ.get("GLUE_MAX_SLICES", "0")) | |
| _ROOT = None | |
| _INDEX = None # {battery_key: {"type": str, "slices": [(name, rel_path)]}} | |
| def _candidates(): | |
| env = os.environ.get("GLUE_DATA_ROOT") | |
| if env: | |
| yield Path(env) | |
| yield Path("/workspace/battery-ct-security/data") | |
| yield Path("d:/CT DATA") | |
| def data_root(): | |
| global _ROOT | |
| if _ROOT is not None: | |
| return _ROOT | |
| for c in _candidates(): | |
| if c and (c / "labels.jsonl").exists(): | |
| _ROOT = c | |
| return _ROOT | |
| raise FileNotFoundError( | |
| "labels.jsonl ์ ๋ชป ์ฐพ์. GLUE_DATA_ROOT ๋ก data ํด๋๋ฅผ ์ง์ ํ์ธ์.") | |
| def _build_index(): | |
| global _INDEX | |
| if _INDEX is not None: | |
| return _INDEX | |
| root = data_root() | |
| idx = defaultdict(lambda: {"type": None, "slices": []}) | |
| with open(root / "labels.jsonl", encoding="utf-8") as f: | |
| for line in f: | |
| r = json.loads(line) | |
| bk = r["battery_key"] | |
| idx[bk]["type"] = r.get("type") | |
| idx[bk]["slices"].append((Path(r["path"]).stem, r["path"])) | |
| for bk in idx: | |
| idx[bk]["slices"].sort(key=lambda s: s[0]) | |
| _INDEX = idx | |
| return idx | |
| def list_batteries(): | |
| return sorted(_build_index().keys()) | |
| def cell_type_of(bid): | |
| t = _build_index().get(bid, {}).get("type") | |
| return t if t in ("cell", "module") else ("cell" if "cell" in bid else "module") | |
| def _subsample(records, k): | |
| if k <= 0 or len(records) <= k: | |
| return records | |
| return [records[round(t * (len(records) - 1) / (k - 1))] for t in range(k)] | |
| def load_battery(bid): | |
| """๋ฐฐํฐ๋ฆฌ ํ๋ โ (slices, cell_type). | |
| slices = [{"idx", "name", "img_path"(ํฌ๋กญ ์ด๋ฏธ์ง ์ ๋๊ฒฝ๋ก)}] (์ด๋ฏธ ํฌ๋กญ๋จ โ outline ๋ถํ์).""" | |
| idx = _build_index() | |
| if bid not in idx: | |
| raise KeyError(f"๋ฐฐํฐ๋ฆฌ ์์: {bid}") | |
| root = data_root() | |
| recs = _subsample(idx[bid]["slices"], MAX_SLICES) | |
| slices = [{"idx": i, "name": name, "img_path": str(root / "cropped" / rel)} | |
| for i, (name, rel) in enumerate(recs)] | |
| return slices, cell_type_of(bid) | |
| def open_slice(sl): | |
| """ํฌ๋กญ ์ฌ๋ผ์ด์ค โ ํ์ ์ด๋ฏธ์ง(PIL 'L'). (์ด๋ฏธ ํฌ๋กญ๋ ์ด๋ฏธ์ง ๊ทธ๋๋ก).""" | |
| return Image.open(sl["img_path"]).convert("L") | |