sam31server 전환, 라멘 파이프라인 정리, 문서 추가
- 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>
This commit is contained in:
@@ -53,7 +53,12 @@ DISCOVERY_PROMPT = (
|
||||
"road, asphalt, pavement, "
|
||||
"slope, embankment, retaining wall, "
|
||||
"noise barrier, sound wall, "
|
||||
"signal, sign board"
|
||||
"signal, sign board, "
|
||||
"small dark object on ballast, small dark object on railway, "
|
||||
"small square metal box on ground, control box on ballast, "
|
||||
"gray square lid on gravel, flat metal cover on ground, "
|
||||
"small bright object on ballast, small white box on ballast, "
|
||||
"small gray box on ground, bright square object on gravel"
|
||||
)
|
||||
|
||||
|
||||
@@ -72,7 +77,7 @@ def sam3_everything(tile_bgr: np.ndarray, conf: float, prompt: str = DISCOVERY_P
|
||||
},
|
||||
}
|
||||
try:
|
||||
r = requests.post(f"{SAM3_SERVER}/v1/predict", json=payload, timeout=120)
|
||||
r = requests.post(f"{SAM3_SERVER}/v1/predict", json=payload, timeout=300)
|
||||
r.raise_for_status()
|
||||
resp = r.json()
|
||||
if not resp.get("success"):
|
||||
@@ -119,14 +124,23 @@ def nms_shapes(shapes: list, iou_thresh: float = 0.4) -> list:
|
||||
|
||||
|
||||
# ── 타일 분할 + 병렬 검출 ─────────────────────────────────────────────────────
|
||||
def detect_everything_tiled(image_bgr, cols, rows, overlap, conf, workers, prompt):
|
||||
def detect_everything_tiled(image_bgr, cols, rows, overlap, conf, workers, prompt,
|
||||
zone=None):
|
||||
"""zone=(x1,y1,x2,y2) 지정 시 겹치는 타일만 처리."""
|
||||
H, W = image_bgr.shape[:2]
|
||||
base_w = W / cols
|
||||
base_h = H / rows
|
||||
pad_x = int(base_w * overlap)
|
||||
pad_y = int(base_h * overlap)
|
||||
|
||||
def overlaps_zone(tx0, ty0, tx1, ty1):
|
||||
if zone is None:
|
||||
return True
|
||||
zx1, zy1, zx2, zy2 = zone
|
||||
return tx0 < zx2 and tx1 > zx1 and ty0 < zy2 and ty1 > zy1
|
||||
|
||||
tiles = []
|
||||
skipped = 0
|
||||
for r in range(rows):
|
||||
for c in range(cols):
|
||||
idx = r * cols + c + 1
|
||||
@@ -134,9 +148,14 @@ def detect_everything_tiled(image_bgr, cols, rows, overlap, conf, workers, promp
|
||||
x1 = min(W, int((c + 1) * base_w) + pad_x)
|
||||
y0 = max(0, int(r * base_h) - pad_y)
|
||||
y1 = min(H, int((r + 1) * base_h) + pad_y)
|
||||
tiles.append((idx, x0, y0, x1, y1))
|
||||
if overlaps_zone(x0, y0, x1, y1):
|
||||
tiles.append((idx, x0, y0, x1, y1))
|
||||
else:
|
||||
skipped += 1
|
||||
|
||||
total = len(tiles)
|
||||
total = len(tiles)
|
||||
if skipped:
|
||||
print(f"zone 필터: {skipped}타일 스킵, {total}타일 처리")
|
||||
done = [0]
|
||||
all_shapes = []
|
||||
|
||||
@@ -227,6 +246,8 @@ def main():
|
||||
ap.add_argument("--workers", type=int, default=4, help="병렬 스레드 수 (기본 4)")
|
||||
ap.add_argument("--nms", type=float, default=0.40, help="NMS IoU 임계값 (기본 0.40)")
|
||||
ap.add_argument("--prompt-extra", default="", help="DISCOVERY_PROMPT 뒤에 추가할 어휘 (콤마 구분)")
|
||||
ap.add_argument("--zone", type=int, nargs=4, metavar=("X1","Y1","X2","Y2"), default=None,
|
||||
help="처리 zone 제한 (이 범위와 겹치는 타일만 처리)")
|
||||
args = ap.parse_args()
|
||||
|
||||
prompt = DISCOVERY_PROMPT + (", " + args.prompt_extra.strip(", ") if args.prompt_extra.strip() else "")
|
||||
@@ -248,10 +269,14 @@ def main():
|
||||
print(f" · {item.strip()}")
|
||||
print()
|
||||
|
||||
zone = tuple(args.zone) if args.zone else None
|
||||
if zone:
|
||||
print(f"zone 제한: x={zone[0]}~{zone[2]} y={zone[1]}~{zone[3]}\n")
|
||||
|
||||
t0 = time.time()
|
||||
shapes = detect_everything_tiled(
|
||||
image_bgr, args.cols, args.rows, args.overlap,
|
||||
args.conf, args.workers, prompt
|
||||
args.conf, args.workers, prompt, zone=zone
|
||||
)
|
||||
print(f"검출 {len(shapes)}개 → NMS(iou={args.nms})...")
|
||||
shapes = nms_shapes(shapes, iou_thresh=args.nms)
|
||||
@@ -279,7 +304,8 @@ def main():
|
||||
)),
|
||||
"segments": [
|
||||
{"label": s.get("label",""), "score": s.get("score",0),
|
||||
"bbox": list(_bbox(s["points"]))}
|
||||
"bbox": list(_bbox(s["points"])),
|
||||
"points": s["points"]}
|
||||
for s in shapes
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user