Skip to content

fix: OCR 파서 — 표 처방전 좌표 파싱 복구 + 약봉투 압축형 다중 약 분리 #98

Description

@kangcheolung

📌 Description

OCR 파싱 개선 1단계의 파서 수정. #96(회귀 테스트 기반) 위에서 진행한다.
OcrParser.java 한 파일만 건드리며, 스키마·응답 DTO·보안 설정 변화 없음.

두 서식이 다중 약 추출에 실패한다:

B. 병원 표 처방전 — 좌표 파싱 경로에 못 들어감

parse()isTablePrescription()이 true여야 parseByCoordinates()로 간다. 그런데
isTablePrescription()LABEL_DOSAGE_PATTERN(1회\s*투약량\s*\d 등)이 매치되면 즉시 false를
반환한다. 이 \s*줄바꿈을 삼켜서, 표 헤더 1회투약량\n1일투여횟수의 다음 줄 숫자에
매치된다 → 표 처방전을 "약봉투 라벨"로 오판 → 좌표 파싱이 한 번도 실행된 적 없음.

좌표 경로에 억지로 넣어도, detectColumnIndex()가 헤더 셀의 순서 인덱스로 컬럼을 잡아서
헤더 처방 의약품의 명칭처방의약품의+명칭 두 필드로 쪼개지면 인덱스가 밀려 전 행이 skip된다.

현재 baseline (#96 하네스): table_prescription_synth.json R=0.00 (5약 중 1약).

C. 약봉투 압축형 — 첫 약만 추출

약이름 + 1정씩1회5일분이 N번 반복되는 약봉투. 별표도 1회투약량 N 라벨 텍스트도 없어
isTextSequentialMulti(= LABEL_DOSAGE_PATTERN 2회+)에 안 걸리고 parseByRegex 단일 폴백 →
COMPACT_DOSAGE_PATTERN이 첫 매치만.

🎯 목표

  • 표 처방전이 좌표 파싱 경로로 진입하고, 헤더 셀이 쪼개져도 컬럼을 올바르게 배정한다
  • 압축형 약봉투의 약을 전부 분리 추출한다
  • 두 서식의 합성 fixture를 guard로 승격 (R=1.00)

🛠️ 작업 범위

OcrParser.java 단일 파일.

B-1. 게이트 정규식

LABEL_DOSAGE_PATTERN\s*[ \t]* (같은 줄의 숫자 = 진짜 라벨만 인정).
isTextSequentialMulti, isTablePrescription 둘 다 이 패턴을 공유 → 표 헤더 오인 함께 해소.

B-2. x좌표 앵커 기반 컬럼 배정 (parseByCoordinates)

detectColumnIndex / ColumnIndex(순서 인덱스) 제거하고:

  • 헤더 행에서 키워드가 든 셀마다 (x중심, 컬럼종류)를 앵커로 기록 (0=name 1=dosage 2=times 3=days)
  • 헤더 판정: name 앵커 존재 + 앵커 2개 이상
  • 데이터 행의 각 셀을 x가 가장 가까운 앵커에 배정, 컬럼당 첫 값 채택
  • 헤더 못 찾거나 결과 비면 parseByRegex 폴백 (기존 유지)
  • 미사용이 되는 getCol 정리

B-3. 폴백 조건 완화 (parseByPharmacyReceipt)

allMatch(전부 null)절반 이상 null이면 parseGroupedTrailingNumbers 시도.

C-1. 압축형 게이트 확장 (isTextSequentialMulti)

LABEL_DOSAGE_PATTERN 카운트에 더해, COMPACT_DOSAGE_PATTERN 매치가 2회 이상이어도 true.
parseByTextSequential이 이미 이름 줄로 블록 나누고 tryCompactDosage 시도하므로 로직 재사용.

테스트 (#96 하네스)

  • table_prescription_synth.json — guard 승격
  • drug_bag_compact_synth.json (신규 합성) — 압축형 약봉투, guard
  • 실제 사진 fixture는 팀이 이름 마스킹 후 추후 추가

✅ To-do

  • LABEL_DOSAGE_PATTERN \s*[ \t]*
  • parseByCoordinates x좌표 앵커 방식으로 교체, detectColumnIndex/ColumnIndex/getCol 정리
  • parseByPharmacyReceipt 폴백 조건 완화
  • isTextSequentialMultiCOMPACT_DOSAGE_PATTERN 2회+ 조건 추가
  • 합성 압축형 약봉투 fixture 추가
  • table_prescription_synth.json guard 승격
  • 기존 별표 영수증(guard) 무회귀 확인

📏 완료 조건 (DoD)

  • table_prescription_synth.json: 약 5건, 필드 채움, guard 통과
  • drug_bag_compact_synth.json: 약 N건 전부, guard 통과
  • pharmacy_receipt_starred.json(기존 guard) 결과 변화 없음
  • ./gradlew test --tests "*OcrParser*" 통과

📒 기타

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions