import math, jsondef pixel_to_gps(px, py, center_gps, gsd_m, img_shape, heading=0): """픽셀 좌표 → GPS 변환""" h, w = img_shape dx = (px - w/2) * gsd_m dy = (h/2 - py) * gsd_m rad = math.radians(heading) east = dx * math.cos(rad) - dy * math.sin(rad) north = dx * math.sin(rad) + dy * math.cos(rad) lat, lon = center_gps return lat + north/111320, lon + east/(111320 * math.cos(math.radians(lat)))# GeoJSON LineString으로 저장feature = { "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[lon, lat] for lat, lon in gps_points]}, "properties": {"source_image": "drone_001.jpg", "confidence": 0.92}}
비행 고도
GSD
선로 폭(1435mm) 표현
30m
~0.8 cm/px
~179 픽셀
50m
~1.4 cm/px
~102 픽셀
100m
~2.7 cm/px
~53 픽셀
150m
~4.1 cm/px
~35 픽셀
PostGIS 테이블 설계
CREATE TABLE railway_centerlines ( id SERIAL PRIMARY KEY, geom GEOMETRY(LineString, 4326), source_image VARCHAR(255), confidence FLOAT, drone_altitude FLOAT, gsd FLOAT, extracted_at TIMESTAMP DEFAULT NOW(), verified BOOLEAN DEFAULT FALSE);CREATE INDEX idx_centerlines_geom ON railway_centerlines USING GIST (geom);
파이프라인 B: SAM+YOLO 반복 학습
데이터가 주기적으로 들어올 때, 사이클마다 정확도를 높여가는 파이프라인이다. SAM은 학습하지 않으므로 YOLO를 통해서만 데이터 축적 효과를 얻을 수 있다.
SAM은 왜 학습하지 않는가?
SAM은 Meta가 11억 개 마스크 + 1,100만 장 이미지로 이미 학습을 완료한 추론 전용(inference-only) 모델이다. 10만 장을 처리해도 모델 자체는 변하지 않는다.
배치
처리량
SAM 모델 상태
결과 정확도
1차 (1,000장)
1,000장
sam3_large.pt (변화 없음)
85%
5차 (5,000장)
누적 5,000장
sam3_large.pt (변화 없음)
85% (동일)
10차 (10,000장)
누적 10,000장
sam3_large.pt (변화 없음)
85% (동일)
반복 학습 아키텍처
flowchart TD
subgraph "1차 사이클"
A[드론 이미지 배치 1] --> B[SAM 3 자동 라벨링]
B --> C[사람 검수]
C --> D[YOLO-Seg 학습 v1]
end
subgraph "2차+ 사이클"
E[드론 이미지 배치 N] --> F[YOLO vN 추론]
F --> G{신뢰도?}
G -->|높음| H[자동 확정]
G -->|낮음| I[SAM 보정 + 사람 검수]
H --> J[학습 데이터 추가]
I --> J
J --> K[YOLO 재학습 vN+1]
end
D --> F
def active_learning_select(model, images, threshold=0.6): """신뢰도 낮은 이미지만 선별""" auto_pass, need_review, rejected = [], [], [] for img in images: results = model(str(img), verbose=False) if results[0].boxes is None: rejected.append(img); continue min_conf = results[0].boxes.conf.min().item() if min_conf >= 0.7: auto_pass.append(img) elif min_conf >= 0.4: need_review.append(img) else: rejected.append(img) return auto_pass, need_review, rejected
신뢰도
처리
비율
≥ 0.7
자동 확정
80~90%
0.4~0.7
사람 검수
10~20%
< 0.4
제거 또는 SAM 재처리
~5%
재학습 트리거
트리거
기준
mAP 하락
기존 대비 3%+ 하락
신뢰도 하락
배치 평균 confidence 10%+ 하락
데이터 분포 변화
새 환경 (계절/날씨/시간대)
누적 데이터량
이전 학습 대비 30%+ 증가
품질 검증 체계
SAM이든 YOLO든, 자동 결과를 100% 사람이 검수하지 않는다. 자동 필터링 + 샘플 검수 조합으로 처리한다.
flowchart TD
A[모델 출력<br/>마스크 + 신뢰도] --> B{자동 필터링}
B -->|통과| C[자동 사용<br/>80~90%]
B -->|의심| D[사람 확인<br/>10~20%]
B -->|실패| E[제거 ~5%]
C --> F[중심선 추출 → DB]
D -->|OK| F
D -->|수정| G[마스크 보정] --> F
자동 검증 규칙
검증 항목
기준
의미
신뢰도
≥ 0.7 통과 / 0.4~0.7 검토 / < 0.4 제거
모델 자체 확신도
최소 면적
전체 이미지의 1% 이상
너무 작으면 선로 아님
최대 면적
전체 이미지의 50% 미만
너무 크면 배경 포함
종횡비
3:1 이상 길쭉
선로는 길고 좁은 형태
중심선 곡률
급격한 꺾임 없음
선로 곡선은 완만함
중심선 길이
이미지 대각선의 10% 이상
너무 짧으면 의미 없음
고해상도 이미지 — SAHI 타일링
드론 4K~8K 이미지는 SAM 기본 처리 크기(1024px)보다 크다. SAHI로 타일 분할 후 처리한다.