Skip to content

fix(analysis): 화살표 검출이 실촬영에서 항상 0개이던 선별 버그 - #45

Merged
devpark435 merged 1 commit into
devfrom
worktree-idempotent-crunching-beacon
Jul 30, 2026
Merged

devpark435 merged 1 commit into
devfrom
worktree-idempotent-crunching-beacon

Conversation

@devpark435

Copy link
Copy Markdown
Owner

실기기 2회차 (1.3.0+46)

[Arrow] 입력 1080x1920, 검출 0개, 선 실패

원본 해상도를 넘겨도 0개. 로컬에서 실촬영 첫 프레임으로 추적했다.

원인

파이썬으로 같은 알고리즘을 돌리니 화살표 7개가 튜닝 상수 그대로 잡혔다:

항목 실측 임계값
국소배경 대비 어두움 44~64 ≥18
블롭 면적 18~23 ≥12
변 길이 5~6 3~22

좌표도 테스트의 _measured 7점과 1px 이내 일치. 상수는 맞고 Dart 선별 로직이 문제.

필터를 통과한 블롭 20개 = 화살표 7개(변 56) + 잡음 13개(변 818). 전체 크기 중앙값이 8로 잡히고 ±비율 창(0.61.6배 → 4.812.8)이 양쪽을 다 삼켜 무리가 14개가 됐다. 14 > _maxArrows(9) → return const [].

후보 무리를 하나만 시도하고 포기하는 구조가 근본 원인이다.

수정

  1. 후보 열거 — 각 블롭 크기를 씨앗으로 무리를 만들고, 깊이축으로 가장 조밀한 부분집합부터 좁혀가며 셰브론 검증. 통과분을 모아 최선을 고른다
  2. 순도 게이트 — 가로 폭 ≥ 0.15(정규화), 깊이 폭 ≤ 가로 폭의 0.25배
  3. 등간격 게이트 — 규격상 board 5·10·…·35로 5보드 간격이라 화면상 간격도 균일하다. 실측 최대/최소 간격비 1.12, 가장자리 오검출 1개가 끼면 2.65, 뭉친 잡음 무리는 25
  4. 개수를 정확히 7개로 고정 — 구속 계산이 "최대분리 쌍 = board 5·35(둘 다 12ft)"를 가정한다. 끝 화살표가 빠지면 그 쌍이 board 10·30(13ft)이 되어 기준 거리가 조용히 틀어진다. 실측에서 5개 무리가 그대로 "선 성립"으로 통과했다. 못 찾으면 빈 리스트 → 기존 코어 폴백이 정직하다

검증 (실촬영 첫 프레임)

입력 수정 전 수정 후
가로 1920x1080 0개 7개 (실측 좌표 일치, 선 성립)
세로 1080x1920 (앱 방향) 0개 7개 (선 성립)
반대 회전 0개 0개 (중간 단계에선 잡음 5~9개 오검출 → 게이트로 차단)
  • flutter test test/features/analysis — 213 passed
  • flutter analyze lib/features/analysis/ — 신규 이슈 0

추가 테스트

  • 잡음 블롭 혼재 회귀 (실측 좌표·크기 그대로 재현 — 수정 전이면 0개)
  • 바깥 화살표 누락 5개 무리 거부
  • 실촬영 프레임 탐침 (로컬 이미지 없으면 건너뜀)

남은 것

2회차는 궤적이 0포인트로 나왔다(trajectory_points: 0, FSM raw 0). 1회차와 같은 영상·같은 검출 73/210인데 결과가 갈렸다 — 유일한 변수는 레인 확인 화면에서 사용자가 확정한 4코너다. 호모그래피가 FSM 게이트를 통과 못 시킨 것으로 보이며, 확정 코너를 로그에 남겨야 진단 가능하다. 별건으로 처리.

실기기 로그 [Arrow] 입력 1080x1920, 검출 0개. 원본 해상도를 넘겨도
검출이 안 돼 원인을 로컬에서 추적했다.

실촬영 첫 프레임을 파이썬으로 재현하니 화살표 7개가 튜닝 상수 그대로
잡혔다 — 어두움 44~64(임계 18), 면적 18~23, 변 5~6, 좌표는 테스트의
실측값과 1px 이내 일치. 즉 상수는 맞고 Dart 선별 로직이 문제였다.

필터 통과 블롭 20개 = 화살표 7개(변 5~6) + 잡음 13개(변 8~18).
전체 크기 중앙값이 8로 잡히고 ±비율 창(0.6~1.6배)이 양쪽을 다 삼켜
무리가 14개가 되자 개수 초과로 **전부** 버려졌다. 후보 무리를 하나만
시도하고 포기하는 구조가 근본 원인.

[arrow_detector]
- 각 블롭 크기를 씨앗으로 후보 무리를 열거하고, 깊이축으로 가장 조밀한
  부분집합부터 좁혀가며 셰브론 검증. 통과분을 모아 최선을 고른다
- 순도 게이트 2개: 가로 폭 최소 0.15(정규화), 깊이 폭 ≤ 가로 폭 0.25배.
  잡음이 뭉친 좁은 무리와 깊이가 벌어진 무리를 배제
- 등간격 게이트: 규격상 board 5·10·…·35로 5보드 간격이라 화면상 간격도
  균일하다(실측 최대/최소 1.12). 가장자리 오검출이 끼면 2.65, 뭉친 잡음
  무리는 25까지 올라가 걸러진다
- 개수를 7개 **정확히**로 고정. 구속 계산이 "최대분리 쌍 = board 5·35
  (둘 다 12ft)"를 가정하므로 끝 화살표가 빠지면 기준 거리가 조용히
  틀어진다. 실측에서 5개 무리가 그대로 "선 성립"으로 통과했다

검증(실촬영 첫 프레임):
- 가로 1920x1080: 화살표 7개 정확히, 실측 좌표와 일치, 선 성립
- 세로 1080x1920(앱 방향): 화살표 7개, 선 성립
- 반대 회전: 수정 전 잡음 5~9개 오검출 → 이제 0개(안전 폴백)

[테스트]
- 잡음 블롭 혼재 회귀 테스트(실측 좌표/크기 사용)
- 바깥 화살표 누락 5개 무리 거부 테스트
- 실촬영 프레임 탐침(로컬 이미지 없으면 건너뜀)
@devpark435
devpark435 marked this pull request as ready for review July 30, 2026 10:15
@devpark435
devpark435 merged commit 9b363ee into dev Jul 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant