Railway Client 사용 가이드
드론 항공 이미지 기반 철도 시설물 자동 검출 파이프라인
서버 상태: sam31server SAM 3.1 → localhost:8000 구동 중
🔴 라멘형(門) 전철주 검출 파이프라인
최우선 기능드론 사선 촬영 이미지에서 門자형 라멘 구조 전철주를 검출한다. SAM3.1로 폴리곤을 추출한 후 소실점(Vanishing Point) 기반 기하학 분석으로 C(기둥)/B(빔)를 분류, 라멘 그룹을 판정한다.
B / C 접두어 — 분류 기준
C
Column (기둥)
소실점 방향으로 향하는 수직·사선 폴리곤.
각도 임계값(
소실점 방향으로 향하는 수직·사선 폴리곤.
각도 임계값(
--c-thresh, 기본 20°) 이내.
B
Beam (빔)
수평으로 뻗은 폴리곤.
소실점 방향에서 크게 벗어난 것.
수평으로 뻗은 폴리곤.
소실점 방향에서 크게 벗어난 것.
라멘 구조 판정: B 1개 + 그 아래 C 2개 이상 → 門자형 라멘으로 분류. 출력 이미지에 B/C 접두어 + 그룹 번호로 표시.
2단계 파이프라인
① detect_all_objects.py
→
JSON annotation
(catenary_pole polygons)
→
(catenary_pole polygons)
② detect_raamen.py
→
B/C 분류
라멘 그룹 판정
라멘 그룹 판정
Step 1 — 전철주 폴리곤 추출
cd D:\MYCLAUDE_PROJECT\railway-client
.venv\Scripts\python.exe tools/detect_all_objects.py `
--input "data/역사구간/1.회덕역/DJI_20260306100900_0034.JPG" `
--categories configs/railway_zone.json `
--tiles all `
--cols 4 --rows 3 --overlap 0.10 --workers 2
출력: output/detect/DJI_20260306100900_0034.json — X-AnyLabeling 호환 annotation
Step 2 — 라멘 구조 분석
.venv\Scripts\python.exe tools/detect_raamen.py `
--image "data/역사구간/1.회덕역/DJI_20260306100900_0034.JPG" `
--label "output/detect/DJI_20260306100900_0034.json" `
--output "output/raamen/DJI_20260306100900_0034_raamen.png"
출력: 이미지 위에 C/B 라벨 + 라멘 그룹 번호 오버레이
detect_raamen.py 파라미터
| 파라미터 | 기본값 | 설명 |
|---|---|---|
--image | 필수 | 원본 이미지 경로 |
--label | 필수 | JSON annotation 파일 (detect_all_objects 출력) |
--output | 자동 생성 | 결과 이미지 저장 경로 |
--class-names | catenary_pole | 분석할 클래스 이름 (쉼표 구분) |
--class-ids | 없음 | 클래스 ID로 필터링 (대안) |
--epsilon | 4.0 | 폴리곤 단순화 강도 (높을수록 단순) |
--c-thresh | 20.0° | C(기둥) 판정 각도 임계값 |
--b-max-diff | 75.0° | B(빔) 최대 각도 편차 |
--margin | 30px | 근접성 그룹핑 거리 |
4단계 내부 처리 흐름
| Phase | 처리 내용 |
|---|---|
| Phase 1 | 폴리곤 단순화(approxPolyDP) + 소실점(Vanishing Point) 계산 |
| Phase 2 | 동적 C/B 분류 — 소실점 기반 기대 각도와 비교 |
| Phase 3 | 근접성 기반 그룹핑 — B 앵커 기준으로 아래 C 탐색 |
| Phase 4 | 라멘 구조 판정 + 가림(occlusion) 예외 처리 |
Everything 탐색 모드 (Discovery Sweep)
새 지역·새 구간을 처음 분석할 때 사용. SAM3.1 텍스트 grounding 방식이므로 완전 무프롬프트는 불가 — 대신 광범위한 Discovery Prompt로 이미지에 존재하는 모든 객체를 일괄 검출하고 라벨 빈도를 집계한다.
용도: 어떤 객체가 이 이미지에 얼마나 나오는지 파악 → 이후
detect_all_objects.py 의 카테고리·conf 튜닝에 활용.
사용법
cd D:\MYCLAUDE_PROJECT\railway-client
# 기본 (8×6 타일)
.venv\Scripts\python.exe tools/sam3_everything_explore.py `
--input "data/역사구간/1.회덕역/DJI_20260306100900_0034.JPG"
# 타일 수 조정 (고해상도 드론 이미지)
.venv\Scripts\python.exe tools/sam3_everything_explore.py `
--input "data/역사구간/..." `
--cols 8 --rows 6 --conf 0.10 --workers 4
# 특정 영역(ROI)만 탐색
.venv\Scripts\python.exe tools/sam3_everything_explore.py `
--input "..." `
--zone 1000 500 3000 2500
# Discovery Prompt에 추가 키워드 삽입
.venv\Scripts\python.exe tools/sam3_everything_explore.py `
--input "..." `
--prompt-extra "signal box, relay cabinet"
파라미터
| 파라미터 | 기본값 | 설명 |
|---|---|---|
--input | 필수 | 이미지 파일 경로 |
--cols | 8 | 가로 타일 분할 수 |
--rows | 6 | 세로 타일 분할 수 |
--overlap | 0.10 | 타일 겹침 비율 |
--conf | 0.10 | 신뢰도 임계값 (탐색 모드라 낮게 설정) |
--workers | 4 | 병렬 처리 스레드 수 |
--nms | 0.40 | NMS IoU 임계값 |
--zone | 없음 | ROI 좌표 (X1 Y1 X2 Y2) — 관심 영역만 처리 |
--prompt-extra | 없음 | Discovery Prompt에 추가할 키워드 |
Discovery Prompt (내장)
다음 키워드 묶음이 자동으로 SAM3.1에 전달된다:
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,
small dark object on ballast, small square metal box on ground,
control box on ballast, gray square lid on gravel,
flat metal cover on ground, bright square object on gravel
--prompt-extra로 추가 키워드를 붙일 수 있다.
출력 해석
output/everything/
└── DJI_20260306100900_0034_everything.jpg ← 모든 segment 오버레이
콘솔 출력 (라벨 빈도 집계):
catenary pole : 47
railway rail : 31
overhead wire : 28
concrete tie : 19
control box on ballast: 8
...
활용: 빈도 상위 라벨 →
railway_zone.json의 프롬프트에 추가하거나 conf 조정. 빈도 0인 카테고리 → 해당 이미지에 없는 객체.
탐색 후 타겟 검출로 전환
sam3_everything_explore
→
라벨 빈도 확인
프롬프트 튜닝
→
프롬프트 튜닝
detect_all_objects
→
detect_raamen (선택)
서버 설정 (sam31server)
시스템 아키텍처
┌─────────────────────────────────┐
│ sam31server │
│ FastAPI app/main.py :8000 │
│ GET /health │
│ POST /v1/predict │
│ Model: SAM 3.1 Multiplex (CUDA)│
└──────────────┬──────────────────┘
│ HTTP localhost:8000
┌──────────────▼──────────────────┐
│ railway-client tools │
│ detect_all_objects.py │ ─┐
│ detect_raamen.py ◀────────┘ │ 라멘 파이프라인
│ sam3_everything_explore.py │
│ sam3_autolabel.py ... │
└─────────────────────────────────┘
요구사항
| 항목 | 버전 |
|---|---|
| Python | 3.12 |
| PyTorch | 2.10.0+cu126 (CUDA 필수) |
| triton-windows | 3.6.0.post25 |
| FastAPI | ≥ 0.115.0 |
| SAM 3.1 모델 | HuggingFace 자동 다운로드 (최초 1회) |
디렉토리 구조
sam31server/
├── sam3/ ← SAM 3.1 모델 라이브러리
├── app/
│ ├── main.py ← FastAPI 진입점
│ ├── api/predict.py ← POST /v1/predict
│ ├── api/health.py ← GET /health
│ ├── models/segment_anything_3.py
│ ├── core/registry.py
│ └── tasks/inference.py
├── configs/
│ ├── server.yaml ← 포트·동시성
│ ├── models.yaml ← enabled: segment_anything_3
│ └── auto_labeling/segment_anything_3.yaml
├── bpe_simple_vocab_16e6.txt.gz
└── start_server.bat
서버 시작
1
sam31server 디렉토리에서 실행
cd D:\MYCLAUDE_PROJECT\sam31server
# 배치파일
start_server.bat
# 또는 직접
.venv\Scripts\python.exe -m app.main
# 또는 uvicorn 직접 (Windows 이벤트루프 이슈 우회)
.venv\Scripts\python.exe -m uvicorn app.main:app --host 0.0.0.0 --port 8000
2
정상 구동 확인
INFO | Loading [segment_anything_3] (Segment Anything 3.1)...
INFO | SAM3 model loaded successfully
INFO | Uvicorn running on http://0.0.0.0:8000
API 엔드포인트
POST /v1/predict
{
"model": "segment_anything_3",
"image": "<base64 JPEG>",
"params": {
"text_prompt": "catenary pole, overhead line pole",
"conf_threshold": 0.25,
"show_masks": true,
"show_boxes": false
}
}
응답:
{
"data": {
"shapes": [
{ "label": "catenary pole", "shape_type": "polygon",
"points": [[x,y], ...], "score": 0.87 }
]
}
}
| params 키 | 설명 |
|---|---|
text_prompt | 텍스트 grounding (쉼표로 다중 객체) |
marks | rectangle / point 시각 프롬프트 |
conf_threshold | 신뢰도 임계값 |
show_masks | polygon 반환 (true 권장) |
show_boxes | bounding box 반환 |
클라이언트 도구 전체 목록
| 스크립트 | 기능 | 출력 | 우선순위 |
|---|---|---|---|
detect_all_objects.py |
타일 분할 + 다중 카테고리 검출 + NMS | PNG + JSON | 핵심 |
detect_raamen.py |
門형 라멘 전철주 B/C 분류 + 그룹 판정 | PNG | 핵심 |
sam3_everything_explore.py |
Discovery Sweep — 전체 객체 탐색 + 빈도 집계 | PNG + 통계 | 탐색 |
sam3_autolabel.py | 전철주 + 레일 zone 기반 자동 라벨링 | JSON | |
sam3_batch_label.py | 폴더 배치 → X-AnyLabeling JSON | JSON | |
yoloworld_sam3_pipeline.py | YOLO-World bbox → SAM3 polygon | JSON+PNG | |
video_sam3_segment.py | 영상 프레임 추출 → 세그멘테이션 | JSON/frame | |
render_everything_by_label.py | 라벨별 색상 렌더링 | PNG | |
render_label_polygons.py | polygon 오버레이 | PNG | |
sam3_segment_everything.py | 이미지 전체 세그멘테이션 | PNG | |
railway_pipeline.py | 전체 파이프라인 통합 | 종합 |
detect_all_objects.py
.venv\Scripts\python.exe tools/detect_all_objects.py `
--input "data/역사구간/..." `
--categories configs/railway_zone.json `
--tiles all `
--cols 4 --rows 3 --overlap 0.10 --workers 2
| 파라미터 | 기본값 | 설명 |
|---|---|---|
--input | 필수 | 이미지 또는 폴더 |
--categories | railway_zone.json | 카테고리 설정 파일 |
--tiles | all | 9-24, 1,5,9, all |
--cols / --rows | 8 / 6 | 타일 분할 수 |
--overlap | 0.10 | 타일 겹침 비율 |
--workers | 4 | 병렬 스레드 |
--conf | 카테고리별 | 전역 신뢰도 오버라이드 |
출력: output/detect/이미지명_detected.png + .json
sam3_autolabel.py
.venv\Scripts\python.exe tools/sam3_autolabel.py `
--input data/역사구간/1.회덕역/ `
--output output/labels/
sam3_batch_label.py
.venv\Scripts\python.exe tools/sam3_batch_label.py `
--input data/역사구간/ `
--prompt "railway catenary pole" `
--output output/batch_labels/ `
--workers 8
yoloworld_sam3_pipeline.py
.venv\Scripts\python.exe tools/yoloworld_sam3_pipeline.py `
--input data/역사구간/ `
--output output/labeled/
video_sam3_segment.py
.venv\Scripts\python.exe tools/video_sam3_segment.py
스크립트 상단에서 영상 경로·프롬프트·프레임 추출 간격 직접 수정.
렌더링 도구
# 라벨별 색상 렌더링
.venv\Scripts\python.exe tools/render_everything_by_label.py `
--input output/labels/image.json --image data/.../image.JPG
# polygon 오버레이
.venv\Scripts\python.exe tools/render_label_polygons.py `
--input output/labels/ --image data/.../
카테고리 설정 — railway_zone.json
경로: configs/railway_zone.json
| 이름 | 한국어 | 색상 | conf | 우선순위 |
|---|---|---|---|---|
control_box | 컨트롤박스 | 노랑 | 0.15 | 2 |
vehicle | 차량 | 흰색 | 0.25 | 2 |
catenary_pole | 전철주 | 마젠타 | 0.25 | 3 |
railway | 철도 레일 | 파랑 | 0.25 | 4 |
fence | 팬스/울타리 | 초록 | 0.50 | 5 |
sleeper | 침목 | 하늘 | 0.20 | 6 |
ballast | 자갈도상 | 남색 | 0.20 | 7 |
bracket | 브라켓/암 | 청색 | 0.20 | 8 |
bridge | 교량/교각 | 주황하늘 | 0.25 | 8 |
building | 건물 | 청보라 | 0.25 | 8 |
retaining_wall | 방음벽/옹벽 | 연두 | 0.25 | 9 |
culvert | 암거/소교량 | 보라 | 0.20 | 9 |
service_road | 유지보수 도로 | 회청 | 0.30 | 10 |
farmland | 농지 | 밝은초록 | 0.25 | 11 |
vegetation | 식생 | 짙은초록 | 0.25 | 12 |
우선순위(priority): 낮을수록 cross-class NMS에서 우선 보존. 우선순위 2 = 최우선(컨트롤박스·차량), 12 = 최하위(식생).
프롬프트 파일
일부 도구는 prompts/ 폴더의 텍스트 파일을 사용:
prompts/
├── pole.txt ← 전철주 검출용 프롬프트
├── rail.txt ← 레일 검출용 프롬프트
├── bracket.txt ← 브라켓 검출용
└── sleeper.txt ← 침목 검출용
빠른 시작 — 단일 이미지 전체 파이프라인
1
SAM3.1 서버 시작 (터미널 A)
cd D:\MYCLAUDE_PROJECT\sam31server
.venv\Scripts\python.exe -m app.main
2
[선택] 탐색 모드로 객체 파악 (터미널 B)
cd D:\MYCLAUDE_PROJECT\railway-client
.venv\Scripts\python.exe tools/sam3_everything_explore.py `
--input "data/역사구간/1.회덕역/.../DJI_20260306100900_0034.JPG" `
--cols 4 --rows 3
3
전철주 검출 + JSON annotation 생성
.venv\Scripts\python.exe tools/detect_all_objects.py `
--input "data/역사구간/1.회덕역/.../DJI_20260306100900_0034.JPG" `
--categories configs/railway_zone.json `
--tiles all --cols 4 --rows 3 --overlap 0.10 --workers 2
4
라멘 구조 분석
.venv\Scripts\python.exe tools/detect_raamen.py `
--image "data/역사구간/1.회덕역/.../DJI_20260306100900_0034.JPG" `
--label "output/detect/DJI_20260306100900_0034.json" `
--output "output/raamen/DJI_20260306100900_0034_raamen.png"
트러블슈팅
| 오류 | 원인 | 해결 |
|---|---|---|
Connection refused :8000 | 서버 미실행 | sam31server에서 서버 시작 |
Torch not compiled with CUDA | CPU 버전 torch | pip install torch==2.10.0+cu126 --index-url .../cu126 |
No module named 'triton' | triton-windows 미설치 | pip install triton-windows==3.6.0.post25 |
No module named 'decord' | decord 미설치 | pip install decord |
| 라멘 검출 없음 | catenary_pole conf 너무 높음 | Step 1에서 --conf 0.10 로 낮춤 |
| C/B 분류 오류 | 소실점 계산 불안정 | --c-thresh 조정 (기본 20°, 높이면 C 기준 완화) |
| Windows 이벤트루프 경고 | Python 3.12 + uvicorn | python -m uvicorn app.main:app --host 0.0.0.0 --port 8000 |
Railway Client Guide · SAM 3.1 + FastAPI · 2026-06