- sam31server를 SAM3.1 서버로 전환 (x-anylabeling01 대체) - detect_raamen.py: B/C 분류 기반 라멘형 전철주 검출 파이프라인 정비 - sam3_everything_explore.py: Discovery Sweep 탐색 모드 정리 - detect_all_objects.py: 타일 검출 개선 - docs/railway-client-guide.html: 서버·도구·파이프라인 전체 가이드 추가 - tools 추가: detect_control_box, group_ramen_poles, render_everything_by_label, render_label_polygons, debug_vh Closes #1 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
281 lines
10 KiB
Markdown
281 lines
10 KiB
Markdown
# 철도 디지털 트윈 — AI 라벨링 파이프라인 진행 현황
|
||
|
||
> 기준일: 2026-05-22
|
||
> 프로젝트: `d:\MYCLAUDE_PROJECT\x-anylabeling01`
|
||
> 목표: 드론 부감 이미지에서 철도 지장물 자동 탐지 → YOLOv26 학습 데이터 구축 → 디지털 트윈
|
||
|
||
---
|
||
|
||
## 1. 탐지 대상 (지장물 카테고리)
|
||
|
||
| 카테고리 | 한글 | 상태 |
|
||
|---|---|---|
|
||
| raamen (ラーメン) | 라멘형 전철주 | ✅ 완료 |
|
||
| pole | 전철주 일반 | ✅ 완료 |
|
||
| rail | 레일 | ✅ 완료 |
|
||
| sleeper | 침목 | ✅ 완료 |
|
||
| control_box | 컨트롤박스 (소형 금속 박스) | 🔄 진행 중 |
|
||
|
||
---
|
||
|
||
## 2. 완료된 작업
|
||
|
||
### 2-1. 라멘형 전철주 검출 (`tools/detect_raamen.py`)
|
||
|
||
- **방식**: SAM3.1 텍스트 grounding + VP(소실점) 기반 H/V 분류
|
||
- **입력**: 드론 고해상도 이미지 (.JPG), 선택적으로 `--json` (detect_all_objects.py 결과 재사용)
|
||
- **출력**: AnyLabeling JSON (폴리곤 + H/V 라벨)
|
||
- **핵심 알고리즘**:
|
||
- 이미지를 타일 분할 → SAM3.1 병렬 호출
|
||
- VP(소실점) 다중 시드 + 반복 정제로 수직(V) / 수평(H) 분류
|
||
- H-max-diff 필터로 수평 빔과 수직 기둥 구분
|
||
- Cross-NMS로 중복 제거
|
||
- **최근 커밋**: `923c396` (VP 다중 시드 + 반복 정제로 V/H 분류 정확도 향상)
|
||
|
||
### 2-2. 전체 객체 검출 UI (`tools/web_ui.py`)
|
||
|
||
- FastAPI + uvicorn 기반 웹 UI
|
||
- 이미지 선택 → 타일/카테고리 설정 → `detect_all_objects.py` 실행 → 결과 프리뷰
|
||
- **개선 사항** (이번 세션):
|
||
- 마우스 휠 줌 + 드래그 팬 추가
|
||
- `--save-labels` → `--save-json` 수정 (txt 금지, JSON만)
|
||
- `--debug` 플래그 제거 (존재하지 않는 옵션)
|
||
- 프리뷰 해상도 1200 → 2000px
|
||
|
||
### 2-3. 전체 객체 검출 (`tools/detect_all_objects.py`)
|
||
|
||
- SAM3.1 텍스트 grounding, 카테고리별 타일 검출
|
||
- `configs/railway_zone.json` 카테고리 설정 사용
|
||
- **출력 경로 개선**: `output/detect/{이미지명}/tiles{N}_{카테고리}_{번호}.jpg`
|
||
- `--save-json` 옵션으로 AnyLabeling JSON 저장
|
||
|
||
### 2-4. SAM3 Everything 탐색 (`tools/sam3_everything_explore.py`)
|
||
|
||
- 38개 항목 광역 프롬프트로 이미지 전체 탐색
|
||
- 타일 병렬 처리 + NMS
|
||
- JSON 라벨 통계 출력 (text_prompt 후보 발굴용)
|
||
- `--prompt-extra` 옵션으로 추가 어휘 주입 가능
|
||
- **테스트 결과** (DJI_20260306113838_0004.JPG, 8×6 타일):
|
||
- 총 7,111개 세그먼트 검출
|
||
- control_box 관련 라벨 1,740개 매칭
|
||
- **문제**: 정밀도 ~1-2%, false positive 폭증 → SAM3 텍스트 grounding 한계 확인
|
||
|
||
---
|
||
|
||
## 3. 핵심 결정 사항
|
||
|
||
### 3-1. YOLOv26 단독 전환 (2026-05-19)
|
||
|
||
**배경**: SAM3.1 텍스트 grounding으로 control_box 탐지 시도 → 완전 실패
|
||
|
||
| 시도 | 결과 |
|
||
|---|---|
|
||
| 고립 프롬프트 ("railway control box, electrical cabinet...") | 0 → 0 검출 |
|
||
| conf 0.20 → 0.10 낮춤 | 0 → 0 검출 |
|
||
| 16×12 세밀한 타일 그리드 | 0 → 0 검출 |
|
||
| 인접 4개 타일 수동 실험 | 0 → 0 검출 |
|
||
| 38개 광역 프롬프트 | 1,740개 매칭, 정밀도 ~1-2% |
|
||
|
||
**결론**: SAM3.1은 부감 드론 시점 소형 객체 텍스트 grounding에 부적합
|
||
|
||
**전환**: **YOLOv26 학습 데이터셋 구축 → fine-tune → 추론** 경로
|
||
|
||
**준비 완료**:
|
||
- `yolo26n.pt`, `yolo26n-seg.pt` 사전학습 모델 (프로젝트 루트)
|
||
- ultralytics 26.x 설치 완료
|
||
- X-AnyLabeling-Server YOLO endpoint 연동 완료
|
||
|
||
### 3-2. SAM3 활용 방식 변경
|
||
|
||
- **폐기**: SAM3 텍스트 grounding → 단독 검출기
|
||
- **유지**: SAM3 everything 모드 → 후보 bbox 생성기 (인간 라벨링 보조)
|
||
- **신규**: YOLOv26 fine-tune → production 검출기
|
||
|
||
---
|
||
|
||
## 4. 현재 진행 중: control_box 라벨링 파이프라인
|
||
|
||
### 4-1. 전략 (부트스트랩)
|
||
|
||
```
|
||
SAM3 everything → 1,740개 후보 bbox
|
||
↓
|
||
labeling_server.py (인간 투표)
|
||
↓
|
||
MIN_VOTES=3, TRUE_RATIO=0.6 필터
|
||
↓
|
||
YOLO 학습용 txt 라벨
|
||
↓
|
||
YOLOv26 fine-tune (yolo26n.pt)
|
||
↓
|
||
production 검출기
|
||
```
|
||
|
||
### 4-2. 라벨링 서버 (`tools/labeling_server.py`) — v2
|
||
|
||
**실행 명령:**
|
||
```bash
|
||
python tools/labeling_server.py \
|
||
--json "data/역사이미지/slope/DJI_20260306113838_0004_everything.json" \
|
||
--reset
|
||
```
|
||
|
||
**브라우저**: `http://서버IP:7001`
|
||
|
||
**UI 방식** (v2 — 전체 이미지 오버레이):
|
||
- 전체 드론 이미지 표시 (최대 3000px)
|
||
- SAM3 후보 1,740개를 색상 bbox로 오버레이
|
||
- 🟡 노랑: 미투표
|
||
- 🟢 초록: 컨트롤박스 YES
|
||
- 🔴 빨강: 아님 NO
|
||
- ⬜ 회색: 타인 투표 완료
|
||
- 마우스 휠 줌 / 드래그 이동 / F키 맞춤
|
||
- bbox 클릭 → YES/NO 즉시 저장 (SQLite)
|
||
- 호버 → 라벨명 + 점수 툴팁
|
||
|
||
**집계 기준**:
|
||
- `MIN_VOTES = 3` (3인 이상 투표)
|
||
- `TRUE_RATIO = 0.6` (60% 이상 YES)
|
||
|
||
**YOLO 내보내기**: `POST /api/export` → `labels/yolo_export/*.txt`
|
||
|
||
**DB**: `labels/labeling.db` (SQLite, 로컬)
|
||
- `candidates` 테이블: json_idx, label, score, bbox, image_path
|
||
- `votes` 테이블: candidate_id, user, vote, ts (UNIQUE 제약 — 1인 1표)
|
||
|
||
### 4-3. 현재 데이터
|
||
|
||
| 항목 | 값 |
|
||
|---|---|
|
||
| 입력 이미지 | `data/역사이미지/slope/DJI_20260306113838_0004.JPG` |
|
||
| everything JSON | `DJI_20260306113838_0004_everything.json` |
|
||
| 전체 세그먼트 | 7,111개 |
|
||
| control_box 후보 | 1,740개 |
|
||
| 라벨링 진행 | 미시작 (서버 실행 대기) |
|
||
|
||
---
|
||
|
||
## 5. 다음 할 일 (TODO)
|
||
|
||
### 즉시
|
||
- [ ] `labeling_server.py` 배포 → 직원 20명 라벨링 시작
|
||
- [ ] 추가 이미지 `_everything.json` 생성 (현재 1장 → 더 많이 필요)
|
||
|
||
### SAM3 Everything 프롬프트 재설계 (⚠️ 중요)
|
||
- **문제**: 현재 DISCOVERY_PROMPT 38개 항목이 control_box를 제대로 분리 못함
|
||
- **방향**: 더 구체적인 시각적 특징 기반 프롬프트 필요
|
||
- 기존: `"small square box", "compact trackside junction box"` 등 → FP 폭증
|
||
- 새 방향 검토 필요:
|
||
- 크기/형태 명시: `"small gray square metal lid on ground"`, `"square dark gray lid flush with ballast"`
|
||
- 재질/색상 특징: `"weathered gray metal surface"`, `"flat square cover"`
|
||
- 부감 시점 특화: `"top-down view of small electrical enclosure"`
|
||
|
||
### 학습 후
|
||
- [ ] 50-100개 이상 확정 라벨 → `yolo train` 실행
|
||
```bash
|
||
yolo train model=yolo26n.pt data=configs/control_box.yaml epochs=100 imgsz=640
|
||
```
|
||
- [ ] 검출 성능 검증 → 미달 시 데이터 추가 수집
|
||
|
||
---
|
||
|
||
## 6. 설정 파일
|
||
|
||
### `configs/railway_zone.json` (control_box 항목)
|
||
```json
|
||
{
|
||
"name": "control_box",
|
||
"name_kr": "컨트롤박스",
|
||
"prompt": "small square gray metal box beside rail, compact trackside junction box, small near-square electrical enclosure on the ground, small cube-shaped equipment box next to track",
|
||
"conf": 0.15,
|
||
"priority": 2
|
||
}
|
||
```
|
||
|
||
### SAM3 Everything DISCOVERY_PROMPT 현재 상태 (재설계 필요)
|
||
```
|
||
"railroad track, railway rail,
|
||
catenary pole, overhead line pole, electric pole,
|
||
overhead wire, catenary wire, power line cable,
|
||
railway sleeper, concrete tie,
|
||
guardrail, highway barrier, road fence,
|
||
bridge, viaduct, overpass,
|
||
vegetation, tree, bush, grass,
|
||
building, structure, roof, wall,
|
||
vehicle, car, truck,
|
||
road, asphalt, pavement,
|
||
slope, embankment, retaining wall,
|
||
noise barrier, sound wall,
|
||
signal, sign board"
|
||
```
|
||
→ control_box 관련 항목 부재 → everything 탐색에서 누락됨
|
||
|
||
---
|
||
|
||
## 7. 기술 제약 / 주의사항
|
||
|
||
- **CLI 명령어**: bash 한 종류만 사용 (PowerShell 혼용 금지)
|
||
- **라벨 저장**: `--save-json` 옵션만 사용 (txt 금지)
|
||
- **detect_all_objects.py**: `--workers 8` 항상 명시
|
||
- **SAM3 서버**: `python.exe -m app.main` (X-AnyLabeling-Server 디렉토리에서 실행, localhost:8000)
|
||
- **GDINO**: 폐기됨. SAM3.1 텍스트 프롬프트 (`params.text_prompt`) 직접 사용
|
||
- **YOLOv26**: ultralytics 26.x, 모델 파일 `yolo26n.pt` / `yolo26n-seg.pt` (프로젝트 루트)
|
||
|
||
---
|
||
|
||
## 8. 주요 파일 구조
|
||
|
||
```
|
||
x-anylabeling01/
|
||
├── tools/
|
||
│ ├── detect_all_objects.py # 메인 검출 도구 (SAM3 타일 검출)
|
||
│ ├── detect_raamen.py # 라멘형 전철주 전용 검출
|
||
│ ├── web_ui.py # 웹 UI (FastAPI, port:8001)
|
||
│ ├── labeling_server.py # CAPTCHA 라벨링 서버 (port:7001) ← 신규 v2
|
||
│ ├── sam3_everything_explore.py # SAM3 전체 탐색 (프롬프트 발굴용) ← 개선 필요
|
||
│ ├── sam3_segment_everything.py # SAM3 포인트 그리드 세그멘테이션
|
||
│ └── post_merge_poles.py # 전철주 병합 후처리
|
||
├── configs/
|
||
│ └── railway_zone.json # 카테고리별 프롬프트/conf/priority
|
||
├── labels/
|
||
│ ├── labeling.db # 라벨링 투표 SQLite DB
|
||
│ └── yolo_export/ # YOLO txt 내보내기 결과
|
||
├── output/
|
||
│ └── detect/{이미지명}/ # 검출 결과 이미지 (타일/카테고리별)
|
||
├── yolo26n.pt # YOLOv26 nano 사전학습 모델
|
||
└── yolo26n-seg.pt # YOLOv26 nano segmentation 모델
|
||
```
|
||
|
||
---
|
||
|
||
## 9. 다음 세션 시작 프롬프트
|
||
|
||
```
|
||
철도 디지털 트윈 프로젝트 (x-anylabeling01) 이어서 진행합니다.
|
||
|
||
[현재 상태]
|
||
- detect_raamen.py (라멘형 전철주) 검출 완료
|
||
- detect_all_objects.py (다중 카테고리 SAM3 검출) 완료
|
||
- web_ui.py 개선 완료 (줌/팬, --save-json, 폴더 구조)
|
||
- labeling_server.py v2 완료 (전체 이미지 + bbox 오버레이, 클릭 투표)
|
||
|
||
[오늘 할 일: SAM3 Everything 프롬프트 재설계]
|
||
tools/sam3_everything_explore.py의 DISCOVERY_PROMPT를 재설계해야 합니다.
|
||
|
||
현재 문제:
|
||
- 기존 38개 항목 광역 프롬프트로 DJI_20260306113838_0004.JPG 처리 시
|
||
- 7,111개 세그먼트, control_box 관련 1,740개 매칭 → 정밀도 ~1-2%
|
||
- control_box (소형 정사각형 금속 박스, 자갈도상 옆 지면에 놓인 것)가 제대로 분리 안 됨
|
||
|
||
목표:
|
||
- control_box를 효과적으로 탐지할 수 있는 SAM3 텍스트 프롬프트 발굴
|
||
- 혹은 SAM3 everything → 후보 bbox 1,740개에서 더 정밀하게 필터링하는 방법 개선
|
||
- 최종적으로는 YOLOv26 학습 데이터 50-100개 확보
|
||
|
||
[기술 제약]
|
||
- CLI는 bash만 사용 (PowerShell 혼용 금지)
|
||
- 라벨 저장은 --save-json만 (txt 금지)
|
||
- SAM3 서버: python.exe -m app.main (X-AnyLabeling-Server에서, localhost:8000)
|
||
- detect_all_objects.py 실행 시 --workers 8 항상 명시
|
||
```
|