| |
| """ |
| 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 |
|
|
| |
| MAX_SLICES = int(os.environ.get("GLUE_MAX_SLICES", "0")) |
|
|
| _ROOT = None |
| _INDEX = None |
|
|
|
|
| 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") |
|
|