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)
② 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-namescatenary_pole분석할 클래스 이름 (쉼표 구분)
--class-ids없음클래스 ID로 필터링 (대안)
--epsilon4.0폴리곤 단순화 강도 (높을수록 단순)
--c-thresh20.0°C(기둥) 판정 각도 임계값
--b-max-diff75.0°B(빔) 최대 각도 편차
--margin30px근접성 그룹핑 거리

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필수이미지 파일 경로
--cols8가로 타일 분할 수
--rows6세로 타일 분할 수
--overlap0.10타일 겹침 비율
--conf0.10신뢰도 임계값 (탐색 모드라 낮게 설정)
--workers4병렬 처리 스레드 수
--nms0.40NMS 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  ...         │
└─────────────────────────────────┘

요구사항

항목버전
Python3.12
PyTorch2.10.0+cu126 (CUDA 필수)
triton-windows3.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 (쉼표로 다중 객체)
marksrectangle / point 시각 프롬프트
conf_threshold신뢰도 임계값
show_maskspolygon 반환 (true 권장)
show_boxesbounding 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 JSONJSON
yoloworld_sam3_pipeline.pyYOLO-World bbox → SAM3 polygonJSON+PNG
video_sam3_segment.py영상 프레임 추출 → 세그멘테이션JSON/frame
render_everything_by_label.py라벨별 색상 렌더링PNG
render_label_polygons.pypolygon 오버레이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필수이미지 또는 폴더
--categoriesrailway_zone.json카테고리 설정 파일
--tilesall9-24, 1,5,9, all
--cols / --rows8 / 6타일 분할 수
--overlap0.10타일 겹침 비율
--workers4병렬 스레드
--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.152
vehicle차량흰색0.252
catenary_pole전철주마젠타0.253
railway철도 레일파랑0.254
fence팬스/울타리초록0.505
sleeper침목하늘0.206
ballast자갈도상남색0.207
bracket브라켓/암청색0.208
bridge교량/교각주황하늘0.258
building건물청보라0.258
retaining_wall방음벽/옹벽연두0.259
culvert암거/소교량보라0.209
service_road유지보수 도로회청0.3010
farmland농지밝은초록0.2511
vegetation식생짙은초록0.2512
우선순위(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 CUDACPU 버전 torchpip 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 + uvicornpython -m uvicorn app.main:app --host 0.0.0.0 --port 8000

Railway Client Guide · SAM 3.1 + FastAPI · 2026-06