feat: SAM 3.1 검출 커버리지 튜닝 — 무라벨 16% → 3.6%

2D 검출 단계에서 미검출을 없애는 작업. 지표는 "무라벨 화면%" —
마스크 합집합으로 재서 겹침을 뺀 값이다. 다각형 넓이 단순 합(105%)은
겹침 때문에 미검출을 못 잡아낸다.

원인은 프롬프트가 아니라 통짜 패스였다. wide_v1.txt 의 21개 프롬프트는
8192x5460 을 1x1 로 넣어 대상 하나에 인스턴스가 하나만 살아남았다.
도로는 한쪽 차로만, 논은 한 필지만 잡혔다.

BlockYYX 실측 (사진 8장):
  기준선  무라벨 평균 21.6% (69장 전체로는 16.1%, 최악 52.1%)
  튜닝후  무라벨 평균  3.6% (최대 5.0%)

기여도 (0654 기준):
  통짜 -> 타일 패스     -36.7pp
  conf 0.25 -> 0.10      -5.4pp
  타일 4x3 -> 6x4        -4.6pp
  프롬프트 추가 9개      -0.5pp   <- 거의 기여 없음

비용은 140 -> 548초/장 (3.9배).

sam3_multi_prompt.py: --wide-in-tiles 플래그 추가. 통짜 프롬프트를
타일 패스에서도 돌린다. 겹치는 결과는 NMS 가 지운다.

신규 도구:
  coverage_stats.py     마스크 합집합으로 무라벨% 측정
  prompt_stats.py       카테고리-프롬프트별 검출 집계
  make_merge_monitor.py 모니터 HTML 생성 (수치는 집계 JSON 에서만)

vote_labels.py 에 --rescue-pred 추가 (투표에 졌지만 표가 있고 모델도
동의하는 면을 되돌린다). 3D 작업이 다른 담당으로 넘어가 중단된 상태.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@
This commit is contained in:
minsung
2026-09-01 20:04:45 +09:00
parent 4e5173522d
commit 28bee39196
12 changed files with 1947 additions and 60 deletions
+147
View File
@@ -0,0 +1,147 @@
# 병합 그룹 정의 — 대괄호 안이 병합 후 대표 라벨.
# 같은 그룹에 속한 라벨끼리 외곽선이 --gap px 이내로 인접하면 하나로 합친다.
# 어느 그룹에도 없는 라벨은 건드리지 않는다.
#
# 여기서 나누지 않는 구분이 있다. SAM은 사진만 보므로 미터도 규모도 모른다.
# 아래는 2D가 아니라 3D 메시에서 갈라야 정확하다:
# 낮은수목 / 수목 CSF 지면 위 높이
# 수목 / 숲 [vegetation] 연결성분 면적
# 지형 / 경사면 면 법선 경사각
# 건물 / 빌딩 [building] 연결성분 면적·높이
# 그래서 tree canopy와 dense forest, building과 residential house는
# 일부러 같은 그룹에 둔다 — 2D에서 갈라봐야 중복 마스크만 나온다.
# [building]
building
building rooftop
building facade
residential house
warehouse
factory structure
storage container
blue roof
red roof
green roof
gray roof
dark gray roof
black roof
white roof
silver metal roof
orange roof
brown roof
yellow roof
greenhouse roof
plastic greenhouse
vinyl greenhouse tunnel
# [road]
asphalt road
concrete pavement
parking lot
pedestrian sidewalk
crosswalk
bridge
# 아래는 비활성 — discovery_v1.txt에서 프롬프트를 통째로 껐다.
# 최종 목표가 지면 대 나머지라 차선은 도로면의 일부지 별도 클래스가 아니다.
# 검출량 1위였지만(583개 중 277개) 전부 [road] 안에서 버려지고,
# 논밭 이랑을 yellow center dividing line으로 오인하기까지 했다.
# [road marking]
# road lane marking
# yellow center dividing line
# white solid lane marking
# white dashed lane marking
# white directional arrow marking
# yellow parking stall line
# white parking stall line
# blue handicap parking space
# pink pedestrian safety marking
# green bike lane marking
# [vegetation]
overgrown weeds
shrub
tree canopy
dense forest
green hedge
grass lawn
# [farmland]
crop field
farmland
plowed field
bare soil field
rice paddy
vegetable field
# [ground]
bare ground
dirt field
earth bank
dirt path
# [stored material]
blue plastic drum
orange plastic barrel
yellow plastic container
white industrial tank
metallic storage tank
blue waterproof tarp
green waterproof tarp
black protective sheet
white canvas canopy
# [retaining wall]
retaining wall
concrete retaining wall
gabion wall
# [slope]
grass covered embankment
road embankment slope
cut slope
riprap slope
# [water]
water surface
pond
reservoir
stream
irrigation canal
drainage ditch
# [structure]
utility pole
streetlight pole
road sign
culvert
# [fence]
gray metal fence
green wire fence
red roadside barrier
guardrail
metal guardrail
# [vehicle]
white vehicle
black vehicle
silver vehicle
gray vehicle
red vehicle
blue vehicle
yellow vehicle
orange vehicle
green vehicle
white cargo truck
blue cargo truck
yellow school bus
commercial bus
tractor
farm tractor
excavator
# 아래는 기본 비활성 — 나란히 놓인 콘이 한 덩어리로 융합된다.
# [cone]
# yellow safety cone
# orange traffic cone
+151
View File
@@ -0,0 +1,151 @@
# 병합 그룹 정의 — 대괄호 안이 병합 후 대표 라벨.
# 같은 그룹에 속한 라벨끼리 외곽선이 --gap px 이내로 인접하면 하나로 합친다.
# 어느 그룹에도 없는 라벨은 건드리지 않는다.
#
# 여기서 나누지 않는 구분이 있다. SAM은 사진만 보므로 미터도 규모도 모른다.
# 아래는 2D가 아니라 3D 메시에서 갈라야 정확하다:
# 낮은수목 / 수목 CSF 지면 위 높이
# 수목 / 숲 [vegetation] 연결성분 면적
# 지형 / 경사면 면 법선 경사각
# 건물 / 빌딩 [building] 연결성분 면적·높이
# 그래서 tree canopy와 dense forest, building과 residential house는
# 일부러 같은 그룹에 둔다 — 2D에서 갈라봐야 중복 마스크만 나온다.
# [building]
building
building rooftop
building facade
residential house
warehouse
factory structure
storage container
blue roof
red roof
green roof
gray roof
dark gray roof
black roof
white roof
silver metal roof
orange roof
brown roof
yellow roof
greenhouse roof
plastic greenhouse
vinyl greenhouse tunnel
# [road]
gravel shoulder
asphalt road
concrete pavement
parking lot
pedestrian sidewalk
crosswalk
bridge
# 아래는 비활성 — discovery_v1.txt에서 프롬프트를 통째로 껐다.
# 최종 목표가 지면 대 나머지라 차선은 도로면의 일부지 별도 클래스가 아니다.
# 검출량 1위였지만(583개 중 277개) 전부 [road] 안에서 버려지고,
# 논밭 이랑을 yellow center dividing line으로 오인하기까지 했다.
# [road marking]
# road lane marking
# yellow center dividing line
# white solid lane marking
# white dashed lane marking
# white directional arrow marking
# yellow parking stall line
# white parking stall line
# blue handicap parking space
# pink pedestrian safety marking
# green bike lane marking
# [vegetation]
yellow grass field
overgrown weeds
shrub
tree canopy
dense forest
green hedge
grass lawn
# [farmland]
ripening rice field
harvested field
crop field
farmland
plowed field
bare soil field
rice paddy
vegetable field
# [ground]
bare ground
dirt field
earth bank
dirt path
# [stored material]
blue plastic drum
orange plastic barrel
yellow plastic container
white industrial tank
metallic storage tank
blue waterproof tarp
green waterproof tarp
black protective sheet
white canvas canopy
# [retaining wall]
retaining wall
concrete retaining wall
gabion wall
# [slope]
grass covered embankment
road embankment slope
cut slope
riprap slope
# [water]
water surface
pond
reservoir
stream
irrigation canal
drainage ditch
# [structure]
utility pole
streetlight pole
road sign
culvert
# [fence]
gray metal fence
green wire fence
red roadside barrier
guardrail
metal guardrail
# [vehicle]
white vehicle
black vehicle
silver vehicle
gray vehicle
red vehicle
blue vehicle
yellow vehicle
orange vehicle
green vehicle
white cargo truck
blue cargo truck
yellow school bus
commercial bus
tractor
farm tractor
excavator
# 아래는 기본 비활성 — 나란히 놓인 콘이 한 덩어리로 융합된다.
# [cone]
# yellow safety cone
# orange traffic cone
+111
View File
@@ -0,0 +1,111 @@
{
"title": "SAM 3.1 후처리 — 검출 커버리지 · 집합 병합",
"note": "1단계는 미검출을 없애는 것이다. 지표는 '무라벨 화면%' — 마스크 합집합으로 재서 겹침을 뺀 값. 목표 5% 이하, 8장 평균 3.6% 로 달성. 2단계는 집합으로 묶고 외곽선이 gap px 이내로 인접한 폴리곤을 합치는 것.",
"params": {
"gap_px": 2,
"epsilon_px": 1.5,
"기준 런": "output/sam3/tune_t64 (확정 설정 8장) / 기준선은 output/sam3/YYX_run 69장",
"프롬프트 파일": "prompts/discovery_v4.txt (94개). 기준선은 discovery_v1.txt (85개)",
"집합 정의": "configs/merge_groups_v4.txt (12집합). 기준선은 merge_groups.txt",
"타일": "6×4 = 24개, overlap 10%, 타일 크기 1365×1365. 기준선은 4×3 (2048×1820)",
"검출 설정": "conf 0.10 · NMS iou 0.40 · 같은 라벨 병합 gap 8px · --wide-in-tiles. 기준선 conf 0.25, 통짜 분리",
"공정 보기 사진": "확정 설정 8장 (기준선 무라벨 3.5~52.1% 분포에서 고름)",
"확정 후보 설정": "prompts/discovery_v4.txt (94개) · configs/merge_groups_v4.txt · --wide-in-tiles · --cols 6 --rows 4 · --conf 0.10 · NMS 0.40 · --merge (gap 8px) · 병합 gap 2px"
},
"steps": [
{
"id": "M1",
"name": "프롬프트별 검출 집계",
"state": "done",
"detail": "tools/prompt_stats.py. YYX_run 실측: 폴리곤 13,580 · 라벨 77종."
},
{
"id": "M1b",
"name": "공정 보기(검출 → 병합) 뷰어 연결",
"state": "done",
"detail": "tools/make_viewer.py 로 같은 사진 3장을 단계별로 굽고 모니터에 붙였다. docs/pilot/theater/."
},
{
"id": "M1c",
"name": "무라벨 지표 확립",
"state": "done",
"detail": "tools/coverage_stats.py. YYX_run 69장 실측: 무라벨 평균 16.1% · 중앙 15.0% · 최악 52.1%(0654). 덮음 95% 이상은 2장뿐."
},
{
"id": "M1d",
"name": "통짜 패스 원인 규명",
"state": "done",
"detail": "wide_v1.txt 의 21개(asphalt road, crop field, farmland, tree canopy 등)는 8192×5460 을 1×1 로 넣어 대상당 인스턴스가 1개만 살아남았다. 0006 에서 asphalt road 가 서쪽 차로만 덮음(1개, score 0.910)."
},
{
"id": "M1e",
"name": "--wide-in-tiles 시험",
"state": "done",
"detail": "통짜 프롬프트를 타일 패스에도 돌린다. 0654 무라벨 52.1→15.4%, 0006 19.4→12.2%. 비용 140→231초/장 (+65%)."
},
{
"id": "M1f",
"name": "경계 띠 프롬프트 추가 (v3)",
"state": "done",
"detail": "잔여 무라벨이 논밭 둑·도로 법면·밭 가장자리 잡초였다. overgrown weeds / shrub / grass covered embankment / earth bank / dirt path 5개 추가. 효과 작음 — 0654 15.4→14.9%, 0006 12.2→11.9%."
},
{
"id": "M1g",
"name": "conf 스윕",
"state": "done",
"detail": "conf 0.10 으로 한 번 뽑고 점수 문턱을 오프라인으로 쓸었다. 0006: 0.25에서 9.3% → 0.10에서 5.8%. 0654: 13.1% → 9.5%. conf 0.03 은 마스크 폭증으로 37분에 1장도 못 끝내 중단."
},
{
"id": "M1h",
"name": "v4 프롬프트 (익은 논·갓길)",
"state": "done",
"detail": "ripening rice field / yellow grass field / harvested field / gravel shoulder 추가. 효과 없음 — 0006 5.8→5.7%, 0654 9.5→9.6%. 프롬프트 추가는 포화."
},
{
"id": "M1i",
"name": "타일 4×3 → 6×4 (목표 달성)",
"state": "done",
"detail": "conf 0.10 · v4 프롬프트 · --wide-in-tiles 와 함께. 4장 실측 무라벨: 0654 5.0% (기준선 52.1) · 0484 3.0% (38.7) · 0079 4.4% (27.1) · 0006 5.0% (19.4). 평균 34.3% → 4.35%. 비용 466~616초/장, 평균 523초 = 기준선 140초의 3.7배. 69장 재검출 시 약 10시간."
},
{
"id": "M1j",
"name": "확정 설정 8장 검증",
"state": "done",
"detail": "8장 실측 무라벨(conf 0.10): 0654 5.0 · 0006 5.0 · 0653 4.7 · 0079 4.4 · 0484 3.0 · 0274 2.9 · 0321 2.5 · 0475 1.5 → 평균 3.6%. 같은 8장 기준선은 평균 21.8%. 소요 466~662초/장(평균 548초). 중간에 PC 다운으로 2장 유실, 재개함."
},
{
"id": "M2",
"name": "집합 정의 조정",
"state": "todo",
"detail": "튜닝 검출 결과(라벨 79종)를 보고 집합을 다시 짠다. 1차는 Claude, 이후 사용자."
},
{
"id": "M3",
"name": "gap 값 조정",
"state": "todo",
"detail": "외곽선 인접 판정 1~3 px. 파일럿 기준 2 px 로 시작."
}
],
"issues": [
{
"state": "closed",
"text": "통짜(1×1) 패스는 대상 하나에 인스턴스가 하나만 남는다 — 도로 한쪽 차로, 논 한 필지만 잡힘. --wide-in-tiles 로 해결(측정치는 M1e)."
},
{
"state": "open",
"text": "orange traffic cone / yellow safety cone 은 어느 집합에도 없어 검출 52 폴리곤이 버려진다. [cone] 그룹이 주석 처리돼 있음 — 나란히 놓인 콘이 한 덩어리로 융합된다는 이유."
},
{
"state": "open",
"text": "검출 0 인 프롬프트 8개 (plowed field, rice paddy, vinyl greenhouse tunnel, gabion wall, road embankment slope, riprap slope, water surface, reservoir) — 유지할지 뺄지 미정."
},
{
"state": "rejected",
"text": "프롬프트 색 특정성 A/B (car/sedan/suv/van/pickup truck) — 폴리곤 +26% 인데 마스크 면적은 +0.002~0.068%p 뿐, 신규 마스크의 90~99%가 기존과 겹침."
},
{
"state": "rejected",
"text": "정사영상으로 차량 검증 — 경사 사진(2025-08-05)과 정사영상(250922)이 다른 비행이라 주차 차량 위치가 다르다."
}
]
}