kordoc 4.21.21 → 4.21.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +6 -4
  2. package/dist/{-ZYF6HX4M.js → -FLEBKE6V.js} +25 -25
  3. package/dist/{chunk-QHNVH4TC.js → chunk-2S37CQUJ.js} +21 -21
  4. package/dist/{chunk-YM3K3LCD.js → chunk-4F6OVO2A.js} +122 -46
  5. package/dist/chunk-4F6OVO2A.js.map +1 -0
  6. package/dist/{chunk-ZZIQWSGC.js → chunk-75J4Y5ZQ.js} +2 -2
  7. package/dist/{chunk-7YAJCXCD.js → chunk-7MTKOSAF.js} +2 -2
  8. package/dist/{chunk-KBV4WFZ6.js → chunk-C3RR6Z3M.js} +4 -4
  9. package/dist/{chunk-KBV4WFZ6.js.map → chunk-C3RR6Z3M.js.map} +1 -1
  10. package/dist/{chunk-TRO4CQHJ.js → chunk-CA742RMF.js} +4 -4
  11. package/dist/{chunk-CY4QM2KQ.js → chunk-DACTHSPR.js} +2 -2
  12. package/dist/{chunk-DTZIZ5PP.cjs → chunk-EGYLKSA4.cjs} +13 -13
  13. package/dist/{chunk-DTZIZ5PP.cjs.map → chunk-EGYLKSA4.cjs.map} +1 -1
  14. package/dist/{chunk-T7PN5D4D.cjs → chunk-EVPP2BSO.cjs} +6 -6
  15. package/dist/{chunk-T7PN5D4D.cjs.map → chunk-EVPP2BSO.cjs.map} +1 -1
  16. package/dist/{chunk-TMUUDMDH.cjs → chunk-GELBKBGQ.cjs} +23 -23
  17. package/dist/{chunk-TMUUDMDH.cjs.map → chunk-GELBKBGQ.cjs.map} +1 -1
  18. package/dist/{chunk-FBJVDBMO.js → chunk-GNIOEZDG.js} +2 -2
  19. package/dist/{chunk-RBRHO7WL.js → chunk-GPIMKPEI.js} +2 -2
  20. package/dist/{chunk-MCUX2Y2C.cjs → chunk-GUU7OHIH.cjs} +2 -2
  21. package/dist/{chunk-MCUX2Y2C.cjs.map → chunk-GUU7OHIH.cjs.map} +1 -1
  22. package/dist/{chunk-5HTFWUJE.js → chunk-J25WF6DP.js} +2 -2
  23. package/dist/{chunk-HWIW3WK2.js → chunk-JA4ZWCYL.js} +3 -3
  24. package/dist/{chunk-2ZGP7A5T.js → chunk-JLG7KK4M.js} +2 -2
  25. package/dist/{chunk-3TCF5HPP.js → chunk-JUA7IACQ.js} +2 -2
  26. package/dist/{chunk-YQZOPT3A.js → chunk-L4NFUEWJ.js} +5 -5
  27. package/dist/{chunk-YQZOPT3A.js.map → chunk-L4NFUEWJ.js.map} +1 -1
  28. package/dist/{chunk-T3DTTK23.js → chunk-QRIGJUOQ.js} +26 -25
  29. package/dist/chunk-QRIGJUOQ.js.map +1 -0
  30. package/dist/{chunk-J5PBI3ZC.js → chunk-RDV2RHVH.js} +3 -3
  31. package/dist/{chunk-YHPJTLCA.js → chunk-RKWJMA2B.js} +2 -2
  32. package/dist/{chunk-FZMGF6XU.js → chunk-TAU45SJK.js} +2 -2
  33. package/dist/{chunk-BG6LUCQL.js → chunk-U6D7LUCR.js} +2 -2
  34. package/dist/{chunk-BC54LBST.js → chunk-UKLNKY7Q.js} +3 -3
  35. package/dist/{chunk-H2MS4VG3.cjs → chunk-VA43X5N4.cjs} +3 -3
  36. package/dist/{chunk-H2MS4VG3.cjs.map → chunk-VA43X5N4.cjs.map} +1 -1
  37. package/dist/{chunk-7FCNOKOR.js → chunk-VKVDMH7X.js} +2 -1
  38. package/dist/{chunk-KTLHADU4.js → chunk-XEUBMLAS.js} +2 -2
  39. package/dist/{chunk-57VNFMMS.cjs → chunk-Y7XHHV55.cjs} +28 -27
  40. package/dist/chunk-Y7XHHV55.cjs.map +1 -0
  41. package/dist/{chunk-PTF4NCFM.js → chunk-YA6UGARL.js} +2 -2
  42. package/dist/{chunk-WGMYVRSA.js → chunk-ZE77KLKN.js} +2 -2
  43. package/dist/chunks-PR2GRNLX.js +10 -0
  44. package/dist/cli.js +34 -34
  45. package/dist/{formula-P7M7IH2L.js → formula-2MTBKZKO.js} +4 -4
  46. package/dist/{formula-A3I5VAP7.cjs → formula-CY2HF27M.cjs} +9 -9
  47. package/dist/{formula-A3I5VAP7.cjs.map → formula-CY2HF27M.cjs.map} +1 -1
  48. package/dist/{formula-6XNIXZ5L.js → formula-LGLSIYDI.js} +3 -3
  49. package/dist/{image-ocr-ITNY454I.js → image-ocr-BKRQVMW6.js} +9 -9
  50. package/dist/{image-ocr-UJRSQ2T3.cjs → image-ocr-HJM5IJKU.cjs} +15 -15
  51. package/dist/{image-ocr-UJRSQ2T3.cjs.map → image-ocr-HJM5IJKU.cjs.map} +1 -1
  52. package/dist/{image-ocr-3C6W3KZO.js → image-ocr-HP65O2CC.js} +6 -6
  53. package/dist/index.cjs +653 -577
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.js +83 -7
  56. package/dist/index.js.map +1 -1
  57. package/dist/mcp.js +28 -28
  58. package/dist/{model-bundle-LAWQH75O.js → model-bundle-M7YMF4L4.js} +5 -5
  59. package/dist/{models-6QTD2CFM.js → models-AMPRHBYB.js} +5 -5
  60. package/dist/{parse-worker-v2-FEPJG3ER.js → parse-worker-v2-NMYEMVYX.js} +14 -14
  61. package/dist/{parser-VKWUMUML.cjs → parser-J6M4WG3I.cjs} +136 -136
  62. package/dist/{parser-VKWUMUML.cjs.map → parser-J6M4WG3I.cjs.map} +1 -1
  63. package/dist/{parser-56I364YM.js → parser-LX5MOE6Q.js} +8 -8
  64. package/dist/{parser-KFCY3NIN.js → parser-M45SFXWF.js} +22 -22
  65. package/dist/pdf-ocr-4YVV5PT4.cjs +19 -0
  66. package/dist/{pdf-ocr-OKAHNEJA.cjs.map → pdf-ocr-4YVV5PT4.cjs.map} +1 -1
  67. package/dist/pdf-ocr-D73YYQJ5.js +18 -0
  68. package/dist/pdf-ocr-SLWZO4D2.js +22 -0
  69. package/dist/{profile-io-OCITHUQF.js → profile-io-CUMSC3TD.js} +3 -3
  70. package/dist/{rasterize-SFCG4YOI.js → rasterize-W6NY4ADH.js} +3 -3
  71. package/dist/{redact-doc-5SMPXIGG.js → redact-doc-7HVCZT3C.js} +25 -25
  72. package/dist/{render-FGPG5A2N.js → render-FPMJX4CU.js} +9 -9
  73. package/dist/seal-YTRVR373.js +10 -0
  74. package/dist/{setup-JQVYZO7I.js → setup-UKIYOUT6.js} +3 -3
  75. package/dist/visual-DG5EVBZD.js +20 -0
  76. package/dist/{watch-C77BUSP7.js → watch-YHKMAVJ6.js} +16 -16
  77. package/package.json +1 -1
  78. package/dist/chunk-57VNFMMS.cjs.map +0 -1
  79. package/dist/chunk-T3DTTK23.js.map +0 -1
  80. package/dist/chunk-YM3K3LCD.js.map +0 -1
  81. package/dist/chunks-MDMJRCJ7.js +0 -10
  82. package/dist/pdf-ocr-MME37BL4.js +0 -18
  83. package/dist/pdf-ocr-OKAHNEJA.cjs +0 -19
  84. package/dist/pdf-ocr-ZZ6AJL6Z.js +0 -22
  85. package/dist/seal-GA7NZDTG.js +0 -10
  86. package/dist/visual-YMG644YW.js +0 -20
  87. /package/dist/{-ZYF6HX4M.js.map → -FLEBKE6V.js.map} +0 -0
  88. /package/dist/{chunk-QHNVH4TC.js.map → chunk-2S37CQUJ.js.map} +0 -0
  89. /package/dist/{chunk-ZZIQWSGC.js.map → chunk-75J4Y5ZQ.js.map} +0 -0
  90. /package/dist/{chunk-7YAJCXCD.js.map → chunk-7MTKOSAF.js.map} +0 -0
  91. /package/dist/{chunk-TRO4CQHJ.js.map → chunk-CA742RMF.js.map} +0 -0
  92. /package/dist/{chunk-CY4QM2KQ.js.map → chunk-DACTHSPR.js.map} +0 -0
  93. /package/dist/{chunk-FBJVDBMO.js.map → chunk-GNIOEZDG.js.map} +0 -0
  94. /package/dist/{chunk-RBRHO7WL.js.map → chunk-GPIMKPEI.js.map} +0 -0
  95. /package/dist/{chunk-5HTFWUJE.js.map → chunk-J25WF6DP.js.map} +0 -0
  96. /package/dist/{chunk-HWIW3WK2.js.map → chunk-JA4ZWCYL.js.map} +0 -0
  97. /package/dist/{chunk-2ZGP7A5T.js.map → chunk-JLG7KK4M.js.map} +0 -0
  98. /package/dist/{chunk-3TCF5HPP.js.map → chunk-JUA7IACQ.js.map} +0 -0
  99. /package/dist/{chunk-J5PBI3ZC.js.map → chunk-RDV2RHVH.js.map} +0 -0
  100. /package/dist/{chunk-YHPJTLCA.js.map → chunk-RKWJMA2B.js.map} +0 -0
  101. /package/dist/{chunk-FZMGF6XU.js.map → chunk-TAU45SJK.js.map} +0 -0
  102. /package/dist/{chunk-BG6LUCQL.js.map → chunk-U6D7LUCR.js.map} +0 -0
  103. /package/dist/{chunk-BC54LBST.js.map → chunk-UKLNKY7Q.js.map} +0 -0
  104. /package/dist/{chunk-7FCNOKOR.js.map → chunk-VKVDMH7X.js.map} +0 -0
  105. /package/dist/{chunk-KTLHADU4.js.map → chunk-XEUBMLAS.js.map} +0 -0
  106. /package/dist/{chunk-PTF4NCFM.js.map → chunk-YA6UGARL.js.map} +0 -0
  107. /package/dist/{chunk-WGMYVRSA.js.map → chunk-ZE77KLKN.js.map} +0 -0
  108. /package/dist/{chunks-MDMJRCJ7.js.map → chunks-PR2GRNLX.js.map} +0 -0
  109. /package/dist/{formula-P7M7IH2L.js.map → formula-2MTBKZKO.js.map} +0 -0
  110. /package/dist/{formula-6XNIXZ5L.js.map → formula-LGLSIYDI.js.map} +0 -0
  111. /package/dist/{image-ocr-ITNY454I.js.map → image-ocr-BKRQVMW6.js.map} +0 -0
  112. /package/dist/{image-ocr-3C6W3KZO.js.map → image-ocr-HP65O2CC.js.map} +0 -0
  113. /package/dist/{model-bundle-LAWQH75O.js.map → model-bundle-M7YMF4L4.js.map} +0 -0
  114. /package/dist/{models-6QTD2CFM.js.map → models-AMPRHBYB.js.map} +0 -0
  115. /package/dist/{parse-worker-v2-FEPJG3ER.js.map → parse-worker-v2-NMYEMVYX.js.map} +0 -0
  116. /package/dist/{parser-56I364YM.js.map → parser-LX5MOE6Q.js.map} +0 -0
  117. /package/dist/{parser-KFCY3NIN.js.map → parser-M45SFXWF.js.map} +0 -0
  118. /package/dist/{pdf-ocr-MME37BL4.js.map → pdf-ocr-D73YYQJ5.js.map} +0 -0
  119. /package/dist/{pdf-ocr-ZZ6AJL6Z.js.map → pdf-ocr-SLWZO4D2.js.map} +0 -0
  120. /package/dist/{profile-io-OCITHUQF.js.map → profile-io-CUMSC3TD.js.map} +0 -0
  121. /package/dist/{rasterize-SFCG4YOI.js.map → rasterize-W6NY4ADH.js.map} +0 -0
  122. /package/dist/{redact-doc-5SMPXIGG.js.map → redact-doc-7HVCZT3C.js.map} +0 -0
  123. /package/dist/{render-FGPG5A2N.js.map → render-FPMJX4CU.js.map} +0 -0
  124. /package/dist/{seal-GA7NZDTG.js.map → seal-YTRVR373.js.map} +0 -0
  125. /package/dist/{setup-JQVYZO7I.js.map → setup-UKIYOUT6.js.map} +0 -0
  126. /package/dist/{visual-YMG644YW.js.map → visual-DG5EVBZD.js.map} +0 -0
  127. /package/dist/{watch-C77BUSP7.js.map → watch-YHKMAVJ6.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["/Users/mong-e/workspace/kordoc/dist/chunk-DTZIZ5PP.cjs","../src/ocr/ruling-lines.ts","../src/ocr/engine.ts","../src/ocr/line-split.ts","../src/ocr/glyph-restore.ts","../src/ocr/postprocess.ts","../src/ocr/crop.ts","../src/ocr/deskew.ts","../src/ocr/pdf-ocr.ts"],"names":["median","gaps","c","n","mx","stars","ring","prev","join"],"mappings":"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","file":"/Users/mong-e/workspace/kordoc/dist/chunk-DTZIZ5PP.cjs","sourcesContent":[null,"/**\n * 래스터 괘선 감지 — 스캔/이미지 페이지의 픽셀에서 표 괘선(수평/수직 선)을\n * 찾아 선 기반 표 파이프라인(line-detector → table-grid)에 공급한다.\n *\n * PDF 그래픽 ops 가 없는 OCR 경로는 종전에 클러스터 감지기만 탔는데,\n * 병합 라벨 셀 + 다중줄 서술형 서식(정부 제출 서식류)은 라인 클러스터로\n * 행 경계를 잡을 수 없다. 괘선은 이미지에 실존하므로 이진화 + 런렝스로\n * 직접 감지한다 — ML 없음, 축 정렬 전제(스캔 스큐 보정은 스코프 밖).\n *\n * 오탐 방어 3겹 (실측: 우수사례 제출 서식 스캔 — 진짜 괘선은 길고 얇음):\n * - 최소 길이 20pt: 글리프 획(가로 ≤한 글자폭·세로 ≤글자높이)은 걸러짐\n * - 두께 상한 2.5pt: 굵은 제목 획(6~13px)·텍스트 줄 밴드·채운 색상바 탈락\n * - 양측 잉크 포위 제외: 색상바(붙임 박스 등) 안 흰 글자 틈새 슬리버 탈락\n *\n * 텍스트층 경로가 선으로 받는 것 중 잉크 런렝스로 안 보이는 두 가지도 선으로 낸다 — 점선 괘선(DOT_*),\n * 채움 사각형의 변(FILL_*). 둘 다 표 괘선에 맞물린 것만.\n */\n\nimport type { LineSegment } from \"../pdf/line-types.js\"\n\n/**\n * 잉크 판정 휘도 상한 — 셀 배경 음영(회색 ~220)은 통과, 실선(진회~검정·남색)만 잉크. 0.12mm 가는 괘선이 픽셀 경계에\n * 걸려 두 픽셀로 번지면 픽셀마다 192~207 이라 190 에선 놓쳤다(ice-geomjeong 시험일정표 \"구분│일자\" 세로선, ktdb 목록표)\n */\nconst INK_LUMA_MAX = 205\n/** 최소 선 길이 (pt) — 최소 셀 변(≈7mm)과 대형 글리프 획(≤1em) 사이 */\nconst MIN_LINE_LENGTH_PT = 20\n/** 선 두께 상한 (pt) — 진짜 괘선(0.12~0.7mm ≈ 0.3~2pt)과 굵은 글리프 획(2pt+) 분리 */\nconst MAX_LINE_WIDTH_PT = 2.5\n/** 런 내 허용 끊김 (px) — 스캔 노이즈/JPEG 아티팩트 */\nconst GAP_TOL_PX = 2\n/** 밴드 병합 시 요구하는 x(또는 y) 범위 겹침 비율 (짧은 쪽 기준) */\nconst BAND_OVERLAP_RATIO = 0.5\n/** 밴드 양측(±2px)이 이 비율 이상 잉크면 채운 영역 내부 슬리버로 판정 */\nconst SURROUND_INK_RATIO = 0.35\n/**\n * 점선·파선 괘선. 텍스트층 경로(line-extract.ts)는 대시 패턴을 보지 않고 경로 기하만 읽어 점선 괘선도\n * 실선으로 받는데, 래스터에선 점 사이 간격(216dpi 에서 2~4px)이 GAP_TOL_PX 를 넘어 선이 조각난다 —\n * 점선으로 행을 가른 표가 OCR 경로에서만 한 행으로 뭉쳤다(changwon-plan2026 p5 정원표 22행 → 2행,\n * ice-geomjeong-plan p3 세로 점선 표 → 열 없는 한 칸). 점 사이 간격 상한 1.3pt 안에서 짧은 점(대시 4pt 이하)이\n * 8개+ 이어지면 점선 후보. 목차 리더 점(\"······\")도 같은 모양이라 주기로 가른다 — 코퍼스 실측 괘선 점선 주기\n * 0.8~2.0pt(점 ≈ 간격), 리더 2.5~3.3pt(간격 ≈ 점 × 2). 대시가 간격보다 확연히 긴(1.5배+) 파선은 주기 무관.\n * 마지막으로 수직 방향 괘선(실선·점선)과 닿는 것만 남긴다 — 리더는 글자 사이에 떠 있고 괘선은 표·상자 테두리에 물린다.\n */\nconst DOT_MAX_GAP_PT = 1.3\nconst DOT_MAX_DASH_PT = 4\nconst DOT_MAX_PERIOD_PT = 2.2\nconst DOT_MIN_COUNT = 8\n/** 점선 후보가 수직 괘선에 닿았다고 보는 거리 (pt) */\nconst DOT_TOUCH_PT = 1.5\n/**\n * 채움 경계. 텍스트층 경로는 순수 채움 경로(머리 행 음영·색 칸의 사각형)의 변도 선으로 받는다(line-extract.ts\n * flushPath → classifyAndAdd). 잉크 감지(휘도 ≤ 190)는 연한 채움과 흰 바탕의 경계를 못 봐, 머리 행에만 좌우 변이\n * 있는 개방 변 표 두 개를 가상 테두리가 한 격자로 용접했고(ice-election-cases p5 8×3·10×3 → 19×5, seoul-archives p3,\n * ice-geomjeong p3), 흰 틈으로 칸을 가른 색 머리 행이 한 칸으로 뭉쳤다(cbe-record-guide). 쪽 바탕(휘도 최빈값)보다\n * FILL_DELTA 이상 어두운 곳이 안쪽으로 FILL_MIN_DEPTH_PT 이상 이어지는 바깥 경계 픽셀 런을 선으로 낸다 — 괘선(≤ 2.5pt)과\n * 글자 획은 그보다 얇다. 바탕을 흰색으로 못박으면 크림색 바탕 쪽 전체가 채움이 되어 본문이 통째로 표가 됐다\n * (pen-cyberbridge p2 바탕 휘도 242). 경계 안쪽 휘도가 고르지 않은 것(사진·그림·배경 도안)은 채움이 아니다.\n */\nconst FILL_DELTA = 10\n/** 채움 경계 최소 길이 (pt) — 색 머리 행 높이(15~18pt)의 칸 틈도 잡게 괘선(20pt)보다 짧게. 글자 획은 두께 조건이 막는다 */\nconst FILL_MIN_LENGTH_PT = 10\nconst FILL_MIN_DEPTH_PT = 4\nconst FILL_FLAT_TOL = 12\nconst FILL_FLAT_RATIO = 0.8\n\n/** 픽셀 공간(top-left origin) 선분 — 두께는 밴드 픽셀 수 */\nexport interface PxSegment {\n x1: number; y1: number\n x2: number; y2: number\n thicknessPx: number\n}\n\nexport interface RulingLines {\n /** Newly recovered faint column rules, used to split OCR boxes before recognition. */\n cellDividers?: PxSegment[]\n horizontals: PxSegment[]\n verticals: PxSegment[]\n}\n\n/**\n * RGBA 래스터에서 수평/수직 괘선 감지.\n * @param scale 렌더 스케일 (px/pt) — 길이·두께 임계를 pt 기준으로 환산\n */\nexport function detectRulingLines(\n rgba: Uint8Array,\n width: number,\n height: number,\n scale: number,\n): RulingLines {\n const minLenPx = Math.round(MIN_LINE_LENGTH_PT * scale)\n const maxThickPx = Math.max(1, Math.floor(MAX_LINE_WIDTH_PT * scale))\n\n // 잉크 마스크 1회 구축 — 수평/수직 두 패스가 공유\n const ink = new Uint8Array(width * height)\n // 휘도는 채움 경계(fillEdges)도 쓴다 — 한 번만 계산\n const luma = new Uint8Array(width * height)\n for (let p = 0, i = 0; p < ink.length; p++, i += 4) {\n // ITU-R BT.601 휘도 근사 (정수 시프트)\n const l = (rgba[i] * 77 + rgba[i + 1] * 150 + rgba[i + 2] * 29) >> 8\n luma[p] = l\n if (l <= INK_LUMA_MAX && rgba[i + 3] >= 128) ink[p] = 1\n }\n\n const solid: RunReader = (m, base, step, span) => solidRuns(m, base, step, span, minLenPx)\n const dot = {\n maxGap: Math.max(2, Math.round(DOT_MAX_GAP_PT * scale)),\n maxDash: Math.max(2, Math.round(DOT_MAX_DASH_PT * scale)),\n maxPeriod: DOT_MAX_PERIOD_PT * scale,\n }\n const dotted: RunReader = (m, base, step, span) => dottedRuns(m, base, step, span, minLenPx, dot.maxGap, dot.maxDash, dot.maxPeriod)\n const horizontals = detectBands(ink, width, height, maxThickPx, false, solid)\n const verticals = detectBands(ink, width, height, maxThickPx, true, solid)\n const dotH = detectBands(ink, width, height, maxThickPx, false, dotted)\n const dotV = detectBands(ink, width, height, maxThickPx, true, dotted)\n const tol = Math.max(2, Math.round(DOT_TOUCH_PT * scale))\n const allH = [...horizontals, ...dotH], allV = [...verticals, ...dotV]\n // 가로 a 가 세로 선(p.x1 = p.x2)과 만나거나 끝이 닿는지 (세로 a 는 축을 바꿔 같은 판정)\n const touchesV = (a: PxSegment) => allV.some(p => p.x1 >= a.x1 - tol && p.x1 <= a.x2 + tol && a.y1 >= p.y1 - tol && a.y1 <= p.y2 + tol)\n const touchesH = (a: PxSegment) => allH.some(p => p.y1 >= a.y1 - tol && p.y1 <= a.y2 + tol && a.x1 >= p.x1 - tol && a.x1 <= p.x2 + tol)\n horizontals.push(...dotH.filter(touchesV))\n verticals.push(...dotV.filter(touchesH))\n // 채움 경계는 표 괘선에 맞물린 것만 쓴다 — 머리 행 음영의 윗변·아랫변은 표 가로 괘선(세로 괘선과 만나는 것)과 폭(양 끝)이\n // 같고, 좌우 변은 그 가로선 끝점에, 칸 사이 흰 틈은 바로 위아래 본문 세로 괘선과 같은 x 에 선다. 칸 안에 놓인 단색\n // 로고·그림의 변은 어느 쪽도 아니다(kmcc-press 참여 기업 표: 로고 칸이 행·열을 쪼갰다 — 로고 밑줄은 잉크 선으로 잡히지만\n // 세로 괘선과 만나지 않는다)\n const inkV = [...verticals]\n const ruleH = horizontals.filter(p => inkV.some(v => v.x1 >= p.x1 - tol && v.x1 <= p.x2 + tol && p.y1 >= v.y1 - tol && p.y1 <= v.y2 + tol))\n const fill = fillEdges(luma, width, height, scale)\n const fillH = fill.horizontals.filter(a => ruleH.some(p => Math.abs(p.x1 - a.x1) <= tol && Math.abs(p.x2 - a.x2) <= tol))\n horizontals.push(...fillH)\n const edgeH = [...ruleH, ...fillH]\n verticals.push(...fill.verticals.filter(a =>\n inkV.some(p => Math.abs(p.x1 - a.x1) <= tol && p.y1 <= a.y2 + tol && p.y2 >= a.y1 - tol) ||\n edgeH.some(p => (Math.abs(p.x1 - a.x1) <= tol || Math.abs(p.x2 - a.x1) <= tol) && p.y1 >= a.y1 - tol && p.y1 <= a.y2 + tol)))\n // Faint internal rules are evidence only when enclosed by an existing dark\n // frame and repeated across both axes. Do not brighten the whole page's grid.\n const cellDividers: PxSegment[] = []\n const frames: Array<{ x1: number; x2: number; y1: number; y2: number }> = []\n for (let i = 0; i < horizontals.length && frames.length < 32; i++) {\n const a = horizontals[i]\n for (let j = i + 1; j < horizontals.length && frames.length < 32; j++) {\n const b = horizontals[j]\n if (Math.abs(a.x1 - b.x1) > tol || Math.abs(a.x2 - b.x2) > tol) continue\n const y1 = Math.min(a.y1, b.y1), y2 = Math.max(a.y1, b.y1)\n if (a.x2 - a.x1 < minLenPx * 3 || y2 - y1 < minLenPx * 2) continue\n if (![a.x1, a.x2].every(x => verticals.some(v => Math.abs(v.x1 - x) <= tol && v.y1 <= y1 + tol && v.y2 >= y2 - tol))) continue\n frames.push({ x1: a.x1, x2: a.x2, y1, y2 })\n }\n }\n if (frames.length) {\n const faint = new Uint8Array(ink.length)\n for (let p = 0; p < faint.length; p++) if (luma[p] <= 240 && rgba[p * 4 + 3] >= 128) faint[p] = 1\n const hs = detectBands(faint, width, height, maxThickPx, false, solid)\n const vs = detectBands(faint, width, height, maxThickPx, true, solid)\n for (const f of frames) {\n const innerH = hs.filter(h => h.y1 > f.y1 + tol && h.y1 < f.y2 - tol && Math.abs(h.x1 - f.x1) <= tol && Math.abs(h.x2 - f.x2) <= tol)\n const innerV = vs.filter(v => v.x1 > f.x1 + tol && v.x1 < f.x2 - tol && Math.abs(v.y1 - f.y1) <= tol && Math.abs(v.y2 - f.y2) <= tol)\n if (innerH.length < 3 || innerV.length < 1) continue\n for (const h of innerH) if (!horizontals.some(p => Math.abs(p.y1 - h.y1) <= tol && p.x1 <= h.x1 + tol && p.x2 >= h.x2 - tol)) horizontals.push(h)\n for (const v of innerV) if (!verticals.some(p => Math.abs(p.x1 - v.x1) <= tol && p.y1 <= v.y1 + tol && p.y2 >= v.y2 - tol)) { verticals.push(v); cellDividers.push(v) }\n }\n }\n return { horizontals, verticals, ...(cellDividers.length ? { cellDividers } : {}) }\n}\n\n/**\n * 채움 영역의 바깥 경계 선 (FILL_* 주석). 채움 경계는 칸 크기 단위라 해상도가 필요 없어 k×k(≈1pt) 블록으로 줄여 본다 —\n * 블록 휘도는 가장 밝은 픽셀(칸 사이 1~3px 흰 틈이 채움에 묻히지 않게). 방향마다 안쪽 연속 채움 길이를 한 번 누적해\n * 경계 마스크를 만들고, 찾은 선은 원래 픽셀 좌표로 되돌린다\n */\nfunction fillEdges(pageLuma: Uint8Array, width: number, height: number, scale: number): RulingLines {\n const k = Math.max(1, Math.round(scale))\n const w = Math.floor(width / k), h = Math.floor(height / k), n = w * h\n const luma = new Uint8Array(n)\n const hist = new Uint32Array(256)\n for (let y = 0; y < h; y++) {\n for (let x = 0; x < w; x++) {\n let mx = 0\n for (let by = 0; by < k; by++) {\n let i = (y * k + by) * width + x * k\n for (let bx = 0; bx < k; bx++, i++) if (pageLuma[i] > mx) mx = pageLuma[i]\n }\n luma[y * w + x] = mx\n hist[mx]++\n }\n }\n let bg = 255\n for (let v = 0; v < 256; v++) if (hist[v] > hist[bg]) bg = v\n const tint = new Uint8Array(n)\n for (let p = 0; p < n; p++) if (luma[p] < bg - FILL_DELTA) tint[p] = 1\n const depth = Math.max(2, Math.round(FILL_MIN_DEPTH_PT * scale / k))\n const minLen = Math.round(FILL_MIN_LENGTH_PT * scale / k)\n const solid: RunReader = (m, base, step, span) => solidRuns(m, base, step, span, minLen)\n const run = new Uint16Array(n)\n const mask = new Uint8Array(n)\n const out: RulingLines = { horizontals: [], verticals: [] }\n // dx,dy = 채움 안쪽 방향. 위 변(0,1)·아래 변(0,-1)·왼 변(1,0)·오른 변(-1,0)\n for (const [dx, dy] of [[0, 1], [0, -1], [1, 0], [-1, 0]] as const) {\n // run[p] = p 에서 안쪽 방향으로 이어지는 채움 길이 (안쪽 끝부터 거꾸로 누적)\n const step = dy * w + dx\n const ys = dy > 0 ? [h - 1, -1, -1] : [0, h, 1]\n const xs = dx > 0 ? [w - 1, -1, -1] : [0, w, 1]\n for (let y = ys[0]; y !== ys[1]; y += ys[2]) {\n for (let x = xs[0]; x !== xs[1]; x += xs[2]) {\n const p = y * w + x\n const nx = x + dx, ny = y + dy\n run[p] = tint[p] ? (nx >= 0 && nx < w && ny >= 0 && ny < h ? Math.min(65535, run[p + step] + 1) : 1) : 0\n }\n }\n mask.fill(0)\n for (let y = 0; y < h; y++) {\n for (let x = 0; x < w; x++) {\n const p = y * w + x\n if (run[p] < depth) continue\n const ox = x - dx, oy = y - dy // 바깥 이웃\n if (ox < 0 || oy < 0 || ox >= w || oy >= h || !tint[p - step]) mask[p] = 1\n }\n }\n const vertical = dx !== 0\n const flat = (s: PxSegment) => {\n // 경계 안쪽 depth/2 지점의 휘도가 고른지 — 사진·도안 탈락\n const d = depth >> 1\n const vals: number[] = []\n if (vertical) {\n const x = Math.round(s.x1) + dx * d\n for (let y = Math.round(s.y1); y <= s.y2; y++) if (x >= 0 && x < w) vals.push(luma[y * w + x])\n } else {\n const y = Math.round(s.y1) + dy * d\n for (let x = Math.round(s.x1); x <= s.x2; x++) if (y >= 0 && y < h) vals.push(luma[y * w + x])\n }\n if (!vals.length) return false\n const med = [...vals].sort((a, b) => a - b)[vals.length >> 1]\n return vals.filter(v => Math.abs(v - med) <= FILL_FLAT_TOL).length >= vals.length * FILL_FLAT_RATIO\n }\n for (const s of detectBands(mask, w, h, 1, vertical, solid)) {\n if (!flat(s)) continue\n const c = (v: number) => v * k + (k - 1) / 2\n ;(vertical ? out.verticals : out.horizontals).push({ x1: c(s.x1), y1: c(s.y1), x2: c(s.x2), y2: c(s.y2), thicknessPx: 1 })\n }\n }\n return out\n}\n\n/**\n * 스캔라인 하나의 런 판독 — 마스크의 base + pos·step 픽셀(pos = 0..span-1). 가로 스캔은 step 1, 세로 스캔은 step = 쪽 폭.\n * 픽셀마다 접근 함수를 부르던 종전 모양은 괘선 감지 시간의 40% 가 그 호출이었다(쪽당 4패스 × 450만 픽셀)\n */\ntype RunReader = (mask: Uint8Array, base: number, step: number, span: number) => Array<{ lo: number; hi: number }>\n\n/** 스캔라인 하나의 실선 런 (GAP_TOL_PX 이하 끊김 허용, 최소 길이 이상) */\nfunction solidRuns(mask: Uint8Array, base: number, step: number, span: number, minLenPx: number): Array<{ lo: number; hi: number }> {\n const runs: Array<{ lo: number; hi: number }> = []\n let runStart = -1\n let gap = 0\n for (let pos = 0; pos <= span; pos++) {\n const on = pos < span && mask[base + pos * step] === 1\n if (on) {\n if (runStart < 0) runStart = pos\n gap = 0\n } else if (runStart >= 0) {\n if (++gap > GAP_TOL_PX || pos >= span) {\n const hi = pos - gap\n if (hi - runStart + 1 >= minLenPx) runs.push({ lo: runStart, hi })\n runStart = -1\n gap = 0\n }\n }\n }\n return runs\n}\n\n/** 스캔라인 하나의 점선 런 — 짧은 잉크 조각(≤ maxDash)이 간격 ≤ maxGap 으로 DOT_MIN_COUNT 개+ 이어진 사슬 (DOT_* 주석) */\nfunction dottedRuns(\n mask: Uint8Array,\n base: number,\n step: number,\n span: number,\n minLenPx: number,\n maxGap: number,\n maxDash: number,\n maxPeriod: number,\n): Array<{ lo: number; hi: number }> {\n const runs: Array<{ lo: number; hi: number }> = []\n // 사슬 조각의 [lo, hi] — 사슬이 끊길 때만 통계를 본다 (대부분 스캔라인은 사슬이 없다)\n const chain: number[] = []\n const median = (xs: number[]) => xs.sort((a, b) => a - b)[xs.length >> 1]\n const flush = () => {\n const cnt = chain.length >> 1\n if (cnt >= DOT_MIN_COUNT && chain[chain.length - 1] - chain[0] + 1 >= minLenPx) {\n const periods: number[] = [], dashes: number[] = [], gaps: number[] = []\n for (let k = 0; k < cnt; k++) {\n dashes.push(chain[2 * k + 1] - chain[2 * k] + 1)\n if (k) { periods.push(chain[2 * k] - chain[2 * k - 2]); gaps.push(chain[2 * k] - chain[2 * k - 1] - 1) }\n }\n if (median(periods) <= maxPeriod || median(dashes) >= 1.5 * median(gaps)) runs.push({ lo: chain[0], hi: chain[chain.length - 1] })\n }\n chain.length = 0\n }\n let s = -1\n for (let pos = 0; pos <= span; pos++) {\n const on = pos < span && mask[base + pos * step] === 1\n if (on) { if (s < 0) s = pos; continue }\n if (s < 0) continue\n const lo = s, hi = pos - 1\n s = -1\n if (hi - lo + 1 > maxDash) { flush(); continue }\n if (chain.length && lo - chain[chain.length - 1] - 1 > maxGap) flush()\n chain.push(lo, hi)\n }\n flush()\n return runs\n}\n\n/** 열린 밴드 — 인접 스캔라인의 런을 누적 */\ninterface Band {\n lo: number // 런 진행축 시작 (h: x1, v: y1)\n hi: number // 런 진행축 끝\n first: number // 직교축 시작 스캔라인 (h: yTop, v: xLeft)\n last: number // 직교축 마지막 스캔라인\n}\n\n/**\n * 스캔라인 런렝스 → 인접 라인 밴드 병합 → 두께 필터 → 선분 방출.\n * transpose=false 면 수평선(행 스캔), true 면 수직선(열 스캔).\n */\nfunction detectBands(\n ink: Uint8Array,\n width: number,\n height: number,\n maxThickPx: number,\n transpose: boolean,\n readRuns: RunReader,\n): PxSegment[] {\n const lines = transpose ? width : height // 스캔라인 개수 (직교축)\n const span = transpose ? height : width // 런 진행축 길이\n const step = transpose ? width : 1\n const baseOf = (line: number) => (transpose ? line : line * width)\n\n const out: PxSegment[] = []\n let open: Band[] = []\n\n /** 밴드 양측(±2px 스캔라인)의 잉크 비율 — 채운 색상바 안 흰 글자 틈새 슬리버 판별 */\n const surroundInkRatio = (b: Band, side: number): number => {\n if (side < 0 || side >= lines) return 0\n let dark = 0, total = 0\n const base = baseOf(side)\n for (let pos = b.lo; pos <= b.hi; pos += 3) {\n total++\n if (ink[base + pos * step] === 1) dark++\n }\n return total > 0 ? dark / total : 0\n }\n\n const emit = (b: Band) => {\n const thick = b.last - b.first + 1\n if (thick > maxThickPx) return // 색상바·텍스트 밴드\n if (\n surroundInkRatio(b, b.first - 2) >= SURROUND_INK_RATIO &&\n surroundInkRatio(b, b.last + 2) >= SURROUND_INK_RATIO\n ) return // 채운 영역 내부 슬리버\n const center = (b.first + b.last) / 2\n out.push(\n transpose\n ? { x1: center, y1: b.lo, x2: center, y2: b.hi, thicknessPx: thick }\n : { x1: b.lo, y1: center, x2: b.hi, y2: center, thicknessPx: thick },\n )\n }\n\n for (let line = 0; line < lines; line++) {\n // 1) 이 스캔라인의 런 (실선 또는 점선 사슬)\n const runs = readRuns(ink, baseOf(line), step, span)\n\n // 2) 열린 밴드와 병합 — 직전 스캔라인까지 이어졌고 범위가 겹치면 확장\n const next: Band[] = []\n const used = new Set<number>()\n for (const band of open) {\n if (band.last !== line - 1) { emit(band); continue } // 연속 끊김 → 확정\n let merged = false\n for (let r = 0; r < runs.length; r++) {\n if (used.has(r)) continue\n const run = runs[r]\n const overlap = Math.min(band.hi, run.hi) - Math.max(band.lo, run.lo) + 1\n const shorter = Math.min(band.hi - band.lo, run.hi - run.lo) + 1\n if (overlap >= shorter * BAND_OVERLAP_RATIO) {\n band.lo = Math.min(band.lo, run.lo)\n band.hi = Math.max(band.hi, run.hi)\n band.last = line\n next.push(band)\n used.add(r)\n merged = true\n break\n }\n }\n if (!merged) emit(band)\n }\n for (let r = 0; r < runs.length; r++) {\n if (!used.has(r)) next.push({ lo: runs[r].lo, hi: runs[r].hi, first: line, last: line })\n }\n open = next\n }\n for (const band of open) emit(band)\n return out\n}\n\n/**\n * 픽셀 선분 → PDF pt LineSegment (bottom-up, classifyAndAdd 규약:\n * 수평선 y1==y2·x1<x2, 수직선 x1==x2·y1<y2).\n */\nexport function rulingToPdfLines(\n ruling: RulingLines,\n scale: number,\n pdfHeight: number,\n): { horizontals: LineSegment[]; verticals: LineSegment[] } {\n const horizontals: LineSegment[] = ruling.horizontals.map(s => {\n const y = pdfHeight - (s.y1 + s.y2) / 2 / scale\n return {\n x1: Math.min(s.x1, s.x2) / scale,\n y1: y,\n x2: Math.max(s.x1, s.x2) / scale,\n y2: y,\n lineWidth: s.thicknessPx / scale,\n }\n })\n const verticals: LineSegment[] = ruling.verticals.map(s => {\n const x = (s.x1 + s.x2) / 2 / scale\n const yA = pdfHeight - Math.max(s.y1, s.y2) / scale\n const yB = pdfHeight - Math.min(s.y1, s.y2) / scale\n return { x1: x, y1: yA, x2: x, y2: yB, lineWidth: s.thicknessPx / scale }\n })\n return { horizontals, verticals }\n}\n","/**\n * 내장 텍스트 OCR 엔진 — PP-OCRv5 korean (det DBNet + rec SVTR/CTC) ONNX 추론.\n *\n * 파이프라인: 페이지 RGBA → det(선 검출) → 박스 픽셀 분석(대비·행 밴드) → 라인 crop\n * → rec 배치(CTC 인식) → 표기 후처리 → OcrItem[]\n * (좌표는 입력 픽셀 기준 top-left origin — 호출자가 PDF 좌표계로 변환).\n *\n * 전·후처리는 공식 inference.yml 스펙 그대로:\n * - det: BGR, 긴 변 960 리사이즈(32 배수), mean/std [0.485,0.456,0.406]/[0.229,0.224,0.225],\n * DBPostProcess thresh 0.3 / box_thresh 0.6 / unclip_ratio 1.5\n * - rec: BGR, 높이 48 고정 비율 리사이즈 + 우측 zero-pad(최소 폭 320), (x/255-0.5)/0.5,\n * CTC 디코드 (blank=0, 1..N=사전, N+1=공백), text_score 0.5.\n * 배치(recBatch>1)는 공식처럼 폭 비율로 정렬해 묶고 배치 최대 폭까지 zero-pad — 기본은 1\n * DB 후처리의 contour+minAreaRect 는 축정렬 connected-component bbox 로 근사\n * (공문서 스캔은 수평 텍스트가 지배적).\n *\n * 공식 파이프라인 밖의 보강 (근거는 bench/ocr-accuracy.mjs 코퍼스 실측, 각 모듈 주석):\n * - 키 큰 박스(세로로 쌓인 글자)는 행 밴드로 갈라 밴드마다 인식 (line-split.ts)\n * - 잉크 대비가 낮은 박스(배경 도안)는 인식하지 않음 — 환각 방지\n * - 사전 밖 공문서 기호(○ △)·둥근 따옴표·천 단위 숫자 공백 복원, 점류 조각 폐기 (postprocess.ts)\n * - 결과 좌표는 det 박스(unclip 여백) 대신 박스 안 잉크 외곽 — 텍스트층 아이템과 같은 기하\n *\n * 의존성(onnxruntime-node, sharp)은 optional — 미설치 시 create()가 명확한 에러.\n * 모델 미다운로드 시에도 즉시 실패 — 호출자가 ensureOcrModels() 먼저.\n */\n\nimport type { InferenceSession } from \"onnxruntime-node\"\nimport { readFile } from \"fs/promises\"\nimport { join } from \"path\"\nimport { OPTIONAL_DEP_INSTALL_HINT } from \"../utils.js\"\nimport {\n OCR_DET_MODEL,\n OCR_REC_MODEL,\n OCR_REC_DICT,\n getOcrModelsDir,\n parseCharacterDict,\n} from \"./models.js\"\nimport { edgeTrim, leadingBullet, tallInkCount, grayCrop, inkBounds, inkStats, leaderRuns, leadingTriangle, splitRowBands } from \"./line-split.js\"\nimport { restoreGlyphs } from \"./glyph-restore.js\"\nimport { isDotFragment, joinLeaderItems, restoreBulletItems, restoreSymbols } from \"./postprocess.js\"\nimport { bandBoxes, splitBoxAtCellRules, lineCrop, type Box, REC_HEIGHT } from \"./crop.js\"\nimport { disableOrtTelemetry } from \"./runtime-env.js\"\n\n/** OCR 인식 결과 한 줄 — 좌표는 입력 이미지 픽셀 (top-left origin, y down) */\nexport interface OcrItem {\n text: string\n x: number\n y: number\n w: number\n h: number\n /** CTC 평균 신뢰도 0~1 */\n confidence: number\n}\n\nexport interface OcrPageStats {\n droppedLowConf: number\n truncatedBoxes?: number\n}\n\n/**\n * 엔진 튜닝 — 기본값이 제품 동작. 벤치·실험만 덮어쓴다 (공개 API 아님).\n */\nexport interface OcrTuning {\n /** det 입력 긴 변 (공식 resize_long). 1920 보존 실험은 recall Δ median +0.04pp에\n * 속도 -25%로 기각 (2026-08-02) */\n detLongSide: number\n detThresh: number\n detBoxThresh: number\n detUnclip: number\n /** 인식 신뢰도 하한 (공식 drop_score) */\n textScore: number\n /** rec 배치 크기. 공식 rec_batch_num 은 6 이지만 onnxruntime CPU 에선 배치(최대 폭까지\n * zero-pad)가 오히려 느리다 — 코퍼스 16쪽 교대 실측 1: 0.57 · 4: 0.93 · 8: 0.87 s/page,\n * 정확도 차는 박스 내 CER 0.08pp (2026-09-23). 기본 1 */\n recBatch: number\n /** 키 큰 박스 행 밴드 분할 */\n splitTall: boolean\n /** 한 줄 박스에 걸린 이웃 줄 끝자락·상자 테두리를 지운 crop 도 인식 (line-split edgeTrim). 그림 영역만 읽을 때는 끈다 —\n * 쪽 배율·두 배 재인식 중 평균 신뢰도로 한쪽을 통째로 고르는데 지운 판이 한쪽 신뢰도만 올려 선택이 뒤집혔다(ODL 073) */\n trimEdges: boolean\n /** 이 대비(전경/배경 평균 휘도 차) 미만 박스는 글자가 아님 — 0 이면 끔 */\n minInkContrast: number\n /** 기호·따옴표 복원 + 점류 조각 폐기 */\n postprocess: boolean\n /** 결과 좌표를 det 박스(unclip 여백 포함) 대신 박스 안 잉크 외곽으로 */\n tightBoxes: boolean\n /** 목차 리더 점 무리를 빼고 앞뒤를 따로 인식 (line-split.ts leaderRuns) */\n splitLeaders: boolean\n}\n\nexport const DEFAULT_OCR_TUNING: Readonly<OcrTuning> = Object.freeze({\n detLongSide: 960,\n detThresh: 0.3,\n detBoxThresh: 0.6,\n detUnclip: 1.5,\n textScore: 0.5,\n recBatch: 1,\n splitTall: true,\n trimEdges: true,\n minInkContrast: 35,\n postprocess: true,\n tightBoxes: true,\n splitLeaders: true,\n})\n\nconst DET_MIN_SIZE = 3\nconst DET_MAX_BOXES = 3000\nconst REC_MIN_WIDTH = 320\n/** 배치 텐서 폭 합 상한 — 긴 줄 여러 개를 한 텐서로 묶어 메모리가 튀지 않게 */\nconst REC_BATCH_MAX_PIXELS = 48 * 16000\n/** 키 큰 박스 판정 (공식 파이프라인의 세로 판정 h/w ≥ 1.5 와 같은 문턱) */\nconst TALL_RATIO = 1.5\n/** 밴드로 갈라지지 않는 키 큰 박스 중 이 비율 이상은 90° 회전 글자 후보 */\nconst ROTATE_RATIO = 3\n/** 이웃 줄 끝자락을 지운 crop 이 원본 crop 을 이기려면 넘어야 할 신뢰도 차 (recognizePage 주석) */\nconst KEEP_MARGIN = 0.06\n/** 리더로 볼 최소 점 수 — 말줄임표 \"…\"(3점)보다 많이. 목차 쪽번호 박스가 무는 점은 코퍼스 실측 4~9개가 대부분 */\nconst LEADER_MIN_DOTS = 4\n/** 리더 앞 조각 crop 을 리더 안쪽으로 더 무는 폭 (박스 높이 배수, recognizePage 주석) */\nconst LEADER_CONTEXT = 0.5\n/** 박스 잉크 비율 하한 (engine recognizePage 주석) */\nconst MIN_INK_RATIO = 0.01\n\n// det: BGR 채널 순서에 yml 기재 순서 그대로 적용 (mean[0]→B)\nconst DET_MEAN = [0.485, 0.456, 0.406]\nconst DET_STD = [0.229, 0.224, 0.225]\n\ntype SharpFactory = (\n input: Uint8Array | Buffer,\n options?: { raw?: { width: number; height: number; channels: number } },\n) => SharpChain\ninterface SharpChain {\n resize(w: number, h: number, opts?: { fit?: string }): SharpChain\n removeAlpha(): SharpChain\n raw(): { toBuffer(): Promise<Buffer> }\n}\n\n/** 인식 대상 한 줄 — rot 는 crop 회전(90=반시계, 270=시계). join: 리더로 가른 박스 번호, dotsBefore: 앞에 리더가 있었는지,\n * trimDots: crop 이 뒤 리더 점을 물었는지(결과 끝 점을 지운다) */\n/** keep: 인식 crop 에서 남길 박스 로컬 구간 — 밖(이웃 줄 끝자락·상자 테두리)은 배경으로 칠한다 (edgeTrim) */\ninterface LineJob { box: Box; rot: 0 | 90 | 270; group: number; join?: number; dotsBefore?: boolean; trimDots?: boolean; keep?: { x0: number; x1: number; y0: number; y1: number; bg: number } }\n\nexport class OcrEngine {\n private det: InferenceSession\n private rec: InferenceSession\n private dict: string[]\n private ort: typeof import(\"onnxruntime-node\")\n private sharp: SharpFactory\n\n private constructor(parts: {\n det: InferenceSession\n rec: InferenceSession\n dict: string[]\n ort: typeof import(\"onnxruntime-node\")\n sharp: SharpFactory\n }) {\n this.det = parts.det\n this.rec = parts.rec\n this.dict = parts.dict\n this.ort = parts.ort\n this.sharp = parts.sharp\n }\n\n static async create(): Promise<OcrEngine> {\n disableOrtTelemetry()\n const [ortMod, sharpModRaw] = await Promise.all([\n tryImport<typeof import(\"onnxruntime-node\")>(\"onnxruntime-node\", () => import(\"onnxruntime-node\")),\n tryImport<{ default?: SharpFactory } & SharpFactory>(\n \"sharp\",\n () => import(\"sharp\") as unknown as Promise<{ default?: SharpFactory } & SharpFactory>,\n ),\n ])\n const sharpAny = sharpModRaw as { default?: SharpFactory } | SharpFactory\n const sharpMod: SharpFactory =\n typeof sharpAny === \"function\" ? sharpAny : (sharpAny.default ?? (sharpAny as unknown as SharpFactory))\n\n const dir = getOcrModelsDir()\n const sessionOpts: import(\"onnxruntime-node\").InferenceSession.SessionOptions = {\n graphOptimizationLevel: \"all\",\n executionProviders: [\"cpu\"],\n logSeverityLevel: 3, // paddle2onnx 변환 잔여물 W 로그 폭주 억제\n }\n const [det, rec, dictYml] = await Promise.all([\n ortMod.InferenceSession.create(join(dir, OCR_DET_MODEL.filename), sessionOpts),\n ortMod.InferenceSession.create(join(dir, OCR_REC_MODEL.filename), sessionOpts),\n readFile(join(dir, OCR_REC_DICT.filename), \"utf-8\"),\n ])\n const dict = parseCharacterDict(dictYml)\n if (dict.length === 0) throw new Error(\"OCR 사전 파싱 실패 — 모델 캐시를 삭제 후 재다운로드하세요\")\n\n return new OcrEngine({ det, rec, dict, ort: ortMod, sharp: sharpMod })\n }\n\n /** onnxruntime-node 1.14+ InferenceSession.release() — 구버전은 무시 */\n async destroy(): Promise<void> {\n for (const s of [this.det, this.rec]) {\n const rel = (s as unknown as { release?: () => Promise<void> }).release\n if (typeof rel === \"function\") {\n try { await rel.call(s) } catch { /* ignore */ }\n }\n }\n }\n\n /**\n * 페이지 RGBA 픽셀 → 텍스트 라인 인식.\n * 반환 좌표는 입력 픽셀 기준. 라인은 위→아래, 좌→우 정렬.\n * @param stats 저신뢰(conf<0.5) 폐기 라인 카운트 출력 — 종전엔 무음 폐기라 관측 불가\n */\n async recognizePage(\n rgba: Uint8Array,\n width: number,\n height: number,\n stats?: OcrPageStats,\n tuning: Readonly<OcrTuning> = DEFAULT_OCR_TUNING,\n cellRules: Array<{ x1: number; y1: number; y2: number; thicknessPx: number }> = [],\n ): Promise<OcrItem[]> {\n if (width < DET_MIN_SIZE || height < DET_MIN_SIZE) return []\n const detected = await this.detect(rgba, width, height, tuning, stats)\n const boxes = cellRules.length ? detected.flatMap(b => splitBoxAtCellRules(b, cellRules)) : detected\n\n // 박스 픽셀 분석 → 인식 작업(라인) 목록. group = 한 결과로 합칠 후보 묶음(회전 후보)\n const jobs: LineJob[] = []\n /** 리더로 가른 검출 박스 — 조각 인식 결과를 모아 한 아이템으로 합친다 */\n const joins: Array<{ box: Box; parts: Array<{ x: number; text: string; dotsBefore: boolean; confidence: number }>; trailDots: boolean }> = []\n let group = 0\n for (const b of boxes) {\n const gray = grayCrop(rgba, width, b)\n const ink = inkStats(gray)\n if (tuning.minInkContrast > 0 && ink.contrast < tuning.minInkContrast) continue\n // 잉크가 박스의 1% 미만이면 가는 선·티끌이다 — 연한 배경 도안 띠를 가로지르는 파란 세로선이 대비 검사를\n // 통과시키고 인식기가 도안을 \"D D D … O\" 로 읽었다(ice-election-cases 표지, 잉크 0.4%). 가장 가는 글자(\"-\")도\n // 여백 포함 박스의 1.5% 안팎이라 남는다. 점 하나(\"·\")는 여기서 빠지지만 isDotFragment 가 어차피 버린다\n if (tuning.minInkContrast > 0 && ink.inkRatio < MIN_INK_RATIO) continue\n if (tuning.splitTall && b.h >= b.w * TALL_RATIO) {\n const bands = splitRowBands(gray, b.w, b.h, ink, 0.45)\n if (bands.length >= 2) {\n for (const sub of bandBoxes(b, bands, height)) jobs.push({ box: sub, rot: 0, group: group++ })\n continue\n }\n if (b.h >= b.w * ROTATE_RATIO) {\n for (const rot of [0, 90, 270] as const) jobs.push({ box: b, rot, group })\n group++\n continue\n }\n }\n // 한 줄 박스가 문 위아래 이웃 줄 글자 끝자락·좌우 끝 상자 테두리는 인식 crop 에서 배경으로 지운다 — 인식기가 받침·\"|\" 로\n // 읽는다 (line-split edgeTrim). 박스를 줄이면 인식 입력 배율이 바뀌어 가운뎃점이 \"•\" 로 커 보였다 — 박스·좌표는 그대로 둔다\n const trim = tuning.trimEdges ? edgeTrim(gray, b.w, b.h, ink) : null\n const keep = trim ? { ...trim, bg: median(gray) } : undefined\n // 목차 리더 점 무리는 인식하지 않고 앞뒤 글만 따로 인식한 뒤, 검출 박스 하나로 다시 합쳐 \"제목 … 쪽번호\" 아이템\n // 하나를 낸다 — 텍스트층도 목차 줄을 리더 글자까지 한 줄로 준다. 조각을 따로 두면 줄 기하가 바뀌어 뒤 단계가\n // 흔들렸다: 리더 자리를 비우면 속기록 1면 목차 줄이 2단 본문 줄로 잡혀 단 판정이 무너졌고(assembly-minutes-1179),\n // 리더를 따로 세우면 클러스터 표가 그것을 열로 삼았다(gwd-info-plan 목차). 리더 앞 조각은 점 한두 개까지 물려\n // 인식하고 물린 점은 결과 끝에서 지운다 — 끝 글자 바로 뒤에서 자르면 인식기가 오른쪽 맥락을 잃어 로마 숫자 Ⅰ 를\n // 1 로 읽었다(eval-rda \"전략목표 Ⅰ\"·\"성과목표 Ⅰ-1\", 박스 높이 0.5배 물림으로 Ⅰ·Ⅱ·Ⅲ 11줄 복원)\n const leaders = tuning.splitLeaders ? leaderRuns(gray, b.w, b.h, ink, LEADER_MIN_DOTS) : []\n if (leaders.length) {\n const join = joins.length\n joins.push({ box: b, parts: [], trailDots: false })\n let x0 = 0, dots = false\n for (const [a, c] of [...leaders, [b.w, b.w]]) {\n const bare = { x: b.x + x0, y: b.y, w: a - x0, h: b.h }\n const end = c > a ? Math.min(c, a + Math.round(b.h * LEADER_CONTEXT)) : a\n x0 = c\n if (bare.w >= DET_MIN_SIZE && inkStats(grayCrop(rgba, width, bare)).contrast >= Math.max(1, tuning.minInkContrast)) {\n jobs.push({ box: { ...bare, w: end - (bare.x - b.x) }, rot: 0, group: group++, join, dotsBefore: dots, trimDots: end > a })\n dots = false\n }\n if (c > a) dots = true\n }\n joins[join].trailDots = dots\n continue\n }\n // 지운 crop 은 원본 crop 과 한 그룹으로 둘 다 인식해 신뢰도가 높은 쪽을 쓴다 — 끝자락이 글자 획과 붙어 있거나\n // 인식기가 조각 없이도 흔들리는 줄(아이콘·로고 칸)에서 지우기가 오히려 틀리게 만들지 않게\n if (keep) jobs.push({ box: b, rot: 0, group, keep })\n jobs.push({ box: b, rot: 0, group: group++ })\n }\n\n const results = await this.recognizeJobs(rgba, width, jobs, tuning.recBatch)\n\n // 회전 후보 그룹은 최고 신뢰도 하나만\n const best = new Map<number, { job: LineJob; text: string; confidence: number; steps: number[]; stepPx: number }>()\n // 끝자락을 지운 crop 은 원본보다 신뢰도가 KEEP_MARGIN 넘게 높을 때만 — 받침 조각 오독은 원본 0.46~0.89 → 지운 쪽 0.99 로\n // 차이가 크고, 차이가 작은 쪽은 띄어쓰기·대시 길이 같은 잡음이었다(과학영재 안내문 \"gifted\" → \"gifed\" +0.015)\n const score = (job: LineJob, confidence: number) => confidence - (job.keep ? KEEP_MARGIN : 0)\n jobs.forEach((job, i) => {\n const r = results[i]\n if (!r) return\n const cur = best.get(job.group)\n if (!cur || score(job, r.confidence) > score(cur.job, cur.confidence)) best.set(job.group, { job, ...r })\n })\n\n let items: OcrItem[] = []\n for (const { job, text: read, confidence, steps, stepPx } of best.values()) {\n const note: { ringLead?: boolean } = {}\n const raw = tuning.postprocess && job.rot === 0 ? restoreGlyphs(rgba, width, job.box, read, steps, stepPx, note) : read\n let text = tuning.postprocess ? restoreSymbols(raw.trim(), note.ringLead) : raw\n if (!text.trim()) continue\n // 사전 밖·작은 점으로 읽히거나 빠지는 글머리(◎ ● ▪ □) — 첫 글리프 모양으로 되살린다 (line-split.ts)\n if (tuning.postprocess && job.rot === 0 && !/^[◎●▪□■○ㅇ]/.test(text)) {\n const chars = [...read], k = chars.findIndex(c => c.trim())\n if (k >= 0 && steps.length === chars.length) {\n const g = grayCrop(rgba, width, job.box)\n const b = leadingBullet(g, job.box.w, job.box.h, inkStats(g), (steps[k] + 0.5) * stepPx)\n // ◎ 는 \"O\" 로 잘못 읽은 자리만 바꾼다(장식 아이콘에 끼워 넣지 않게). ●▪ 는 본문 줄(뒤 글 한글 4음절 이상)에서만 —\n // 표 칸의 큰 가운뎃점(\"·수학\"·\"·승합\", 글꼴에 따라 네모·원으로 그려짐)은 정답도 \"·\" 다\n const body = (text.match(/[가-힣]/g) ?? []).length >= 4\n const miss = /^[Oo0•·ㆍ∙‧○]/.test(text)\n if (b?.mark === \"\\u25ce\" && b.covers && /^[Oo0○]/.test(text)) text = b.mark + \" \" + text.slice(1).trimStart()\n // □ 는 인식에서 빠진 자리만(첫 글자 앞) — 모델은 사전에 □ 가 있어도 내지 않고 통째로 빠뜨린다\n else if (b?.mark === \"\\u25a1\") { if (!b.covers && body) text = b.mark + \" \" + text }\n else if (b && b.mark !== \"\\u25ce\" && body) text = b.covers ? (miss ? b.mark + \" \" + text.slice(1).trimStart() : text) : b.mark + \" \" + text\n }\n }\n // 숫자 앞 △·▲ 는 사전 밖이라 빈칸으로 사라진다 — 박스 맨 앞 글자 모양으로 되살린다 (line-split.ts)\n if (tuning.postprocess && /^\\d/.test(text) && job.rot === 0) {\n const g = grayCrop(rgba, width, job.box)\n const tri = leadingTriangle(g, job.box.w, job.box.h, inkStats(g))\n if (tri) text = tri + text\n }\n if (tuning.postprocess && isDotFragment(text)) continue\n if (confidence < tuning.textScore) { if (stats) stats.droppedLowConf++; continue }\n if (job.join !== undefined) {\n if (job.trimDots) text = text.replace(/[\\s.:\\u00b7\\u2022\\u2024\\u2025\\u2026\\u2219\\u22c5\\u318d]+$/u, \"\")\n if (text) joins[job.join].parts.push({ x: job.box.x, text, dotsBefore: job.dotsBefore === true, confidence })\n continue\n }\n items.push({ text, ...this.itemBox(rgba, width, job.box, tuning), confidence })\n }\n const leaderEnds = new Map<OcrItem, { lead: boolean; trail: boolean }>()\n for (const j of joins) {\n if (!j.parts.length) continue\n j.parts.sort((a, b) => a.x - b.x)\n let text = \"\"\n for (const p of j.parts) text += (p.dotsBefore ? (text ? \" \\u2026 \" : \"\\u2026\") : text ? \" \" : \"\") + p.text\n if (j.trailDots) text += \" \\u2026\"\n const item = { text, ...this.itemBox(rgba, width, j.box, tuning), confidence: Math.min(...j.parts.map(p => p.confidence)) }\n items.push(item)\n leaderEnds.set(item, { lead: j.parts[0].dotsBefore, trail: j.trailDots })\n }\n if (leaderEnds.size) items = joinLeaderItems(items, leaderEnds)\n if (tuning.postprocess) restoreBulletItems(items)\n items.sort((a, b) => (a.y - b.y) || (a.x - b.x))\n return items\n }\n\n /** 결과 좌표 — det 박스 그대로 또는 박스 안 잉크 외곽 (tightBoxes) */\n private itemBox(rgba: Uint8Array, width: number, b: Box, tuning: Readonly<OcrTuning>): Box {\n if (!tuning.tightBoxes) return b\n const gray = grayCrop(rgba, width, b)\n const t = inkBounds(gray, b.w, b.h, inkStats(gray))\n return { x: b.x + t.x0, y: b.y + t.y0, w: t.x1 - t.x0, h: t.y1 - t.y0 }\n }\n\n // ─── det ─────────────────────────────────────────────\n\n private async detect(\n rgba: Uint8Array,\n width: number,\n height: number,\n tuning: Readonly<OcrTuning>,\n stats?: OcrPageStats,\n ): Promise<Box[]> {\n const ratio = tuning.detLongSide / Math.max(width, height)\n const dw = Math.max(32, Math.round((width * ratio) / 32) * 32)\n const dh = Math.max(32, Math.round((height * ratio) / 32) * 32)\n\n const rgb = await this.sharp(rgba, { raw: { width, height, channels: 4 } })\n .resize(dw, dh, { fit: \"fill\" })\n .removeAlpha()\n .raw()\n .toBuffer()\n\n // HWC RGB → CHW BGR float32 정규화\n const plane = dw * dh\n const input = new Float32Array(3 * plane)\n for (let i = 0; i < plane; i++) {\n const r = rgb[i * 3] / 255\n const g = rgb[i * 3 + 1] / 255\n const b = rgb[i * 3 + 2] / 255\n input[i] = (b - DET_MEAN[0]) / DET_STD[0]\n input[plane + i] = (g - DET_MEAN[1]) / DET_STD[1]\n input[2 * plane + i] = (r - DET_MEAN[2]) / DET_STD[2]\n }\n\n const tensor = new this.ort.Tensor(\"float32\", input, [1, 3, dh, dw])\n const out = await this.det.run({ [this.det.inputNames[0]]: tensor })\n const probMap = out[this.det.outputNames[0]].data as Float32Array\n\n const rawBoxes = componentBoxes(probMap, dw, dh, tuning.detThresh, tuning.detBoxThresh)\n if (stats) stats.truncatedBoxes = Math.max(0, rawBoxes.length - DET_MAX_BOXES)\n const sx = width / dw\n const sy = height / dh\n const boxes: Box[] = []\n for (const rb of rawBoxes.slice(0, DET_MAX_BOXES)) {\n // unclip: DB 는 학습 시 텍스트 영역을 수축시키므로 검출 박스를 되팽창\n const bw = rb.x2 - rb.x1 + 1\n const bh = rb.y2 - rb.y1 + 1\n const delta = (bw * bh * tuning.detUnclip) / (2 * (bw + bh))\n const x1 = Math.max(0, Math.floor((rb.x1 - delta) * sx))\n const y1 = Math.max(0, Math.floor((rb.y1 - delta) * sy))\n const x2 = Math.min(width, Math.ceil((rb.x2 + 1 + delta) * sx))\n const y2 = Math.min(height, Math.ceil((rb.y2 + 1 + delta) * sy))\n if (x2 - x1 < DET_MIN_SIZE || y2 - y1 < DET_MIN_SIZE) continue\n boxes.push({ x: x1, y: y1, w: x2 - x1, h: y2 - y1 })\n }\n return boxes\n }\n\n // ─── rec ─────────────────────────────────────────────\n\n /** 라인 작업들을 폭 비율 순으로 배치 인식 — 결과는 jobs 순서 */\n private async recognizeJobs(\n rgba: Uint8Array,\n pageW: number,\n jobs: LineJob[],\n batchSize: number,\n ): Promise<Array<{ text: string; confidence: number; steps: number[]; stepPx: number } | null>> {\n const crops = jobs.map(j => lineCrop(rgba, pageW, j.box, j.rot, j.keep))\n const order = crops.map((_, i) => i).sort((a, b) => crops[a].w - crops[b].w)\n const results: Array<{ text: string; confidence: number; steps: number[]; stepPx: number } | null> = new Array(jobs.length).fill(null)\n const plane = REC_HEIGHT\n for (let s = 0; s < order.length;) {\n // 폭 오름차순이라 배치 마지막 원소가 최대 폭\n let e = s + 1\n while (e < order.length && e - s < Math.max(1, batchSize)\n && (e - s + 1) * Math.max(REC_MIN_WIDTH, crops[order[e]].w) * plane <= REC_BATCH_MAX_PIXELS) e++\n const idx = order.slice(s, e)\n const bw = Math.max(REC_MIN_WIDTH, crops[idx[idx.length - 1]].w)\n const n = idx.length\n const chw = 3 * REC_HEIGHT * bw\n const input = new Float32Array(n * chw) // pad 영역 0 (공식 zero-pad 와 동일)\n idx.forEach((ci, k) => {\n const c = crops[ci]\n const base = k * chw\n const p = REC_HEIGHT * bw\n for (let y = 0; y < REC_HEIGHT; y++) {\n for (let x = 0; x < c.w; x++) {\n const src = (y * c.w + x) * 3\n const dst = base + y * bw + x\n // HWC RGB → CHW BGR, (x/255-0.5)/0.5\n input[dst] = c.rgb[src + 2] / 127.5 - 1\n input[dst + p] = c.rgb[src + 1] / 127.5 - 1\n input[dst + 2 * p] = c.rgb[src] / 127.5 - 1\n }\n }\n })\n const tensor = new this.ort.Tensor(\"float32\", input, [n, 3, REC_HEIGHT, bw])\n const out = await this.rec.run({ [this.rec.inputNames[0]]: tensor })\n const logits = out[this.rec.outputNames[0]]\n const [, T, C] = logits.dims as number[]\n const data = logits.data as Float32Array\n idx.forEach((ci, k) => {\n const r = ctcDecode(data.subarray(k * T * C, (k + 1) * T * C), T, C, this.dict)\n // CTC 시점 하나가 덮는 원본 픽셀 폭 — crop 은 높이 48 로 줄인 뒤 bw 까지 오른쪽을 채웠다 (회전 crop 은 세로 축)\n const job = jobs[ci], src = job.rot === 0 ? job.box.w : job.box.h\n // 채운 자리(crop 폭 밖)에 찍힌 글자 — CTC 는 짧은 박스의 진짜 끝 글자도 마지막 시점에 찍어(\"54\" → 시점 36·39) 자리만으로는 못 가른다.\n // crop 안 키 큰 잉크 덩어리보다 키 큰 글자가 많을 때 남는 것만 지어낸 것으로 버린다 — 칸에 \"/\" 하나만 든 박스가 \"/)\"·\"(/:)\" 로\n // 읽혔다(여수 인원표). 점·쉼표류는 덩어리로 안 세니 그대로 둔다. \"(cid:9)\" 환각은 restoreSymbols 가 통째로 걷도록 손대지 않는다.\n // crop 안 글자가 두 자 이하인 작은 박스만 — 긴 낱말은 그림 성분이 글자 높이를 부풀려 소문자를 덩어리로 못 세었다(\"ToContent\" → \"ToCont\")\n let kept = r\n const last = (crops[ci].w * T) / bw + 1\n const chars = r ? [...r.text] : []\n if (r && job.rot === 0 && chars.length === r.steps.length && r.steps.some(t => t > last) && !r.text.includes(\"(cid:\")) {\n const tallCh = (c: string) => !/[\\s.,:;\\u00b7\\u2026'\"\\u2018-\\u201d`\\-_~]/.test(c)\n const g = grayCrop(rgba, pageW, job.box)\n const inside = chars.filter((c, i) => r.steps[i] <= last && tallCh(c)).length\n let budget = inside <= 2 ? tallInkCount(g, job.box.w, job.box.h, inkStats(g)) - inside : Infinity\n const keep = chars.map((c, i) => r.steps[i] <= last || !tallCh(c) || budget-- > 0)\n if (!keep.every(Boolean)) kept = { ...r, text: chars.filter((_, i) => keep[i]).join(\"\"), steps: r.steps.filter((_, i) => keep[i]) }\n }\n results[ci] = kept && { ...kept, stepPx: (bw / T) * (src / crops[ci].w) }\n })\n s = e\n }\n return results\n }\n}\n\n/** 회색조 중앙값 — 글줄 박스는 배경 픽셀이 다수라 배경 휘도가 된다 */\nfunction median(gray: Uint8Array): number {\n const hist = new Uint32Array(256)\n for (let i = 0; i < gray.length; i++) hist[gray[i]]++\n for (let v = 0, n = 0; v < 256; v++) if ((n += hist[v]) * 2 >= gray.length) return v\n return 255\n}\n\n/** CTC greedy 디코드 — 연속 중복 붕괴 → blank(0) 제거 → 사전 매핑 (테스트용 export) */\nexport function ctcDecode(\n data: Float32Array,\n T: number,\n C: number,\n dict: string[],\n): { text: string; confidence: number; steps: number[] } | null {\n let text = \"\"\n let confSum = 0\n let confCount = 0\n let prev = -1\n /** 글자(코드 포인트)마다 CTC 시점 구간 [첫, 끝] — 괄호 모양 판별이 글자 자리를 픽셀로 옮길 때 쓴다 */\n const runs: Array<[number, number]> = []\n let open: Array<[number, number]> = []\n for (let t = 0; t < T; t++) {\n const off = t * C\n let best = 0\n let bestV = data[off]\n for (let c = 1; c < C; c++) {\n const v = data[off + c]\n if (v > bestV) { bestV = v; best = c }\n }\n const repeat = best === prev\n prev = best\n if (repeat && best !== 0) { for (const r of open) r[1] = t; continue }\n open = []\n if (best === 0) continue\n // 모델 출력이 softmax 확률이 아니면 (>1) 해당 스텝만 정규화\n let p = bestV\n if (p > 1.0001 || p < 0) {\n let denom = 0\n for (let c = 0; c < C; c++) denom += Math.exp(data[off + c] - bestV)\n p = 1 / denom\n }\n confSum += p\n confCount++\n const tok = best >= 1 && best <= dict.length ? dict[best - 1] : best === dict.length + 1 ? \" \" : \"\"\n text += tok\n for (const _ of tok) { const r: [number, number] = [t, t]; runs.push(r); open.push(r) }\n }\n if (!text) return null\n return { text, confidence: confCount > 0 ? confSum / confCount : 0, steps: runs.map(([a, b]) => (a + b) / 2) }\n}\n\n/** 이진화 확률맵의 4-연결 성분 bbox (score = 성분 평균 확률, 테스트용 export) */\nexport function componentBoxes(\n prob: Float32Array,\n w: number,\n h: number,\n thresh: number = DEFAULT_OCR_TUNING.detThresh,\n boxThresh: number = DEFAULT_OCR_TUNING.detBoxThresh,\n): Array<{ x1: number; y1: number; x2: number; y2: number }> {\n const visited = new Uint8Array(w * h)\n const boxes: Array<{ x1: number; y1: number; x2: number; y2: number; score: number }> = []\n const stack: number[] = []\n\n for (let start = 0; start < w * h; start++) {\n if (visited[start] || prob[start] <= thresh) continue\n let x1 = start % w, x2 = x1, y1 = (start / w) | 0, y2 = y1\n let sum = 0\n let count = 0\n stack.length = 0\n stack.push(start)\n visited[start] = 1\n while (stack.length) {\n const p = stack.pop()!\n const px = p % w\n const py = (p / w) | 0\n sum += prob[p]\n count++\n if (px < x1) x1 = px\n if (px > x2) x2 = px\n if (py < y1) y1 = py\n if (py > y2) y2 = py\n // 4-이웃\n if (px > 0 && !visited[p - 1] && prob[p - 1] > thresh) { visited[p - 1] = 1; stack.push(p - 1) }\n if (px < w - 1 && !visited[p + 1] && prob[p + 1] > thresh) { visited[p + 1] = 1; stack.push(p + 1) }\n if (py > 0 && !visited[p - w] && prob[p - w] > thresh) { visited[p - w] = 1; stack.push(p - w) }\n if (py < h - 1 && !visited[p + w] && prob[p + w] > thresh) { visited[p + w] = 1; stack.push(p + w) }\n }\n if (x2 - x1 + 1 < DET_MIN_SIZE && y2 - y1 + 1 < DET_MIN_SIZE) continue\n boxes.push({ x1, y1, x2, y2, score: sum / count })\n }\n\n return boxes\n .filter(b => b.score >= boxThresh)\n .sort((a, b) => (a.y1 - b.y1) || (a.x1 - b.x1))\n}\n\nasync function tryImport<T>(name: string, loader: () => Promise<T>): Promise<T> {\n try {\n return await loader()\n } catch (e) {\n throw new Error(\n `내장 OCR 을 사용하려면 optional dependency '${name}' 이 필요합니다. ` +\n `\\`npm install ${name}\\` 후 다시 실행하세요.${OPTIONAL_DEP_INSTALL_HINT} 원인: ${(e as Error).message}`,\n )\n }\n}\n\n// ─── 엔진 싱글턴 (watch/서버 장기 실행에서 세션 재사용) ───\nlet enginePromise: Promise<OcrEngine> | null = null\n\nexport function getOcrEngine(): Promise<OcrEngine> {\n if (!enginePromise) {\n enginePromise = OcrEngine.create().catch(err => {\n enginePromise = null // 실패는 캐시하지 않음 — 모델 설치 후 재시도 가능\n throw err\n })\n }\n return enginePromise\n}\n","/**\n * 검출 박스 픽셀 분석 — 행 밴드 분할 + 잉크 대비.\n *\n * DB 검출기는 줄 간격보다 글자 간격이 넓으면 글자를 세로로 잇는다: 표 머리의 세로쓰기\n * (\"국/균/도/시\", \"사회복지과\"), 균등배분 목차의 같은 열 글자들이 키 큰 박스 하나가 되고,\n * 인식기(높이 48 고정)는 이를 짓눌러 빈 문자열이나 저신뢰 쓰레기를 낸다(실측: 코퍼스\n * 80쪽에서 GT 글자 0.55% 가 이런 박스와 함께 폐기). 박스 안 행 투영의 빈 띠로 밴드를\n * 갈라 밴드마다 따로 인식하면 글자가 자기 위치(행)를 되찾는다.\n *\n * 잉크 대비는 배경 무늬(연한 바탕의 흰 도안)를 글자로 읽는 환각을 거른다 — 진짜 글자는\n * 전경/배경 평균 휘도 차가 크다.\n */\n\n/** RGBA 페이지에서 박스 영역 휘도(BT.601 정수 근사) 추출 */\nexport function grayCrop(\n rgba: Uint8Array,\n pageW: number,\n box: { x: number; y: number; w: number; h: number },\n): Uint8Array {\n const out = new Uint8Array(box.w * box.h)\n for (let y = 0; y < box.h; y++) {\n let si = ((box.y + y) * pageW + box.x) * 4\n let di = y * box.w\n for (let x = 0; x < box.w; x++, si += 4, di++) {\n out[di] = (rgba[si] * 77 + rgba[si + 1] * 150 + rgba[si + 2] * 29) >> 8\n }\n }\n return out\n}\n\nexport interface InkStats {\n /** Otsu 임계값 */\n threshold: number\n /** 잉크 = 소수 클래스. true 면 어두운 쪽이 잉크(일반 문서) */\n darkInk: boolean\n /** 두 클래스 평균 휘도 차 (0~255) — 글자 대비 */\n contrast: number\n /** 잉크 픽셀 비율 */\n inkRatio: number\n}\n\n/** Otsu 이진화 — 잉크 극성(소수 클래스)과 대비 */\nexport function inkStats(gray: Uint8Array): InkStats {\n const hist = new Uint32Array(256)\n for (let i = 0; i < gray.length; i++) hist[gray[i]]++\n const total = gray.length\n let sumAll = 0\n for (let v = 0; v < 256; v++) sumAll += v * hist[v]\n let wB = 0, sumB = 0, best = -1, thr = 127\n for (let t = 0; t < 256; t++) {\n wB += hist[t]\n if (wB === 0) continue\n const wF = total - wB\n if (wF === 0) break\n sumB += t * hist[t]\n const mB = sumB / wB\n const mF = (sumAll - sumB) / wF\n const between = wB * wF * (mB - mF) * (mB - mF)\n if (between > best) { best = between; thr = t }\n }\n let nDark = 0, sDark = 0\n for (let v = 0; v <= thr; v++) { nDark += hist[v]; sDark += v * hist[v] }\n const nLight = total - nDark\n const sLight = sumAll - sDark\n if (nDark === 0 || nLight === 0) return { threshold: thr, darkInk: true, contrast: 0, inkRatio: 0 }\n const darkInk = nDark <= nLight\n return {\n threshold: thr,\n darkInk,\n contrast: sLight / nLight - sDark / nDark,\n inkRatio: (darkInk ? nDark : nLight) / total,\n }\n}\n\n/**\n * 행 투영의 빈 띠로 밴드 분할. 반환: 밴드별 [y0, y1) 행 구간과 괘선을 뺀 잉크 [x0, x1) 열 구간\n * (박스 로컬). 분할 불가면 길이 1.\n * @param minBandRatio 밴드 최소 높이 = 이 비율 × 글자 크기. 이보다 얇은 조각(한 글자 안의\n * 획 띠 \"을\"의 ㅇ/ㅡ/ㄹ, 밑줄, 박스 끝에 걸린 이웃 글자 조각)은 간격이 좁은 쪽 이웃 밴드에\n * 흡수된다. 글자 크기는 밴드별 잉크 가로 폭의 중앙값 — 박스 폭은 unclip 여백만큼 글자보다\n * 넓고(◎ 40px 에 박스 92px) 박스 전체 잉크 폭은 옆 열 글자 조각에 끌려가서, 둘 다 쓰면\n * 제대로 된 글자 밴드까지 합쳐진다(함평 목차 실측). 획 조각도 가로 폭은 글자 폭(ㅡ)이라\n * 중앙값이 흔들리지 않는다\n */\nexport function splitRowBands(\n gray: Uint8Array,\n w: number,\n h: number,\n ink: InkStats,\n minBandRatio: number,\n): Array<{ y0: number; y1: number; x0: number; x1: number }> {\n const isInk = (v: number) => (ink.darkInk ? v <= ink.threshold : v > ink.threshold)\n // 박스를 관통하는 괘선 — 세로선(행 85%+ 에 잉크인 열)은 투영에서 빼고, 가로선(남은 폭\n // 85%+ 가 잉크인 행)은 빈 행(구분자)으로 본다. 표 칸 사이 세로쓰기 라벨(\"국/균/도/시\")\n // 박스는 칸 경계 세로선을 끼고 잡혀 빈 행이 하나도 없다(부천 예산서 실측)\n const colInk = new Uint32Array(w)\n for (let y = 0; y < h; y++) {\n const off = y * w\n for (let x = 0; x < w; x++) if (isInk(gray[off + x])) colInk[x]++\n }\n const ruleCol = new Uint8Array(w)\n let liveW = 0\n for (let x = 0; x < w; x++) { if (colInk[x] >= h * 0.85) ruleCol[x] = 1; else liveW++ }\n const rowInk = new Uint32Array(h)\n for (let y = 0; y < h; y++) {\n let n = 0\n const off = y * w\n for (let x = 0; x < w; x++) if (!ruleCol[x] && isInk(gray[off + x])) n++\n rowInk[y] = n >= liveW * 0.85 ? 0 : n\n }\n // 안티앨리어싱·잡티 허용: 폭의 2% (최소 1px) 이하면 빈 행\n const blank = Math.max(1, Math.floor(w * 0.02))\n let bands: Array<[number, number]> = []\n let start = -1\n for (let y = 0; y <= h; y++) {\n const on = y < h && rowInk[y] > blank\n if (on && start < 0) start = y\n else if (!on && start >= 0) { bands.push([start, y]); start = -1 }\n }\n const inkCols = (y0: number, y1: number): [number, number] => {\n let x0 = w, x1 = -1\n for (let y = y0; y < y1; y++) {\n const off = y * w\n for (let x = 0; x < w; x++) if (!ruleCol[x] && isInk(gray[off + x])) { if (x < x0) x0 = x; if (x > x1) x1 = x }\n }\n return x1 >= x0 ? [x0, x1 + 1] : [0, w]\n }\n if (bands.length <= 1) return [{ y0: bands[0]?.[0] ?? 0, y1: bands[0]?.[1] ?? h, x0: 0, x1: w }]\n const widths = bands.map(([y0, y1]) => { const [a, b] = inkCols(y0, y1); return b - a }).sort((a, b) => a - b)\n const charSize = widths[widths.length >> 1]\n const minBand = Math.max(3, minBandRatio * charSize)\n // 글자 안 빈 행(“업”의 어/ㅂ 사이 2px) — 간격이 글자 크기 15% 이하이고 합쳐도 한 글자\n // 높이(1.3배) 안이면 한 밴드. 세로쓰기의 글자 사이 간격은 이보다 넓고, 두 글자를 합치면\n // 높이 상한에 걸린다\n for (let i = 0; i + 1 < bands.length;) {\n const gap = bands[i + 1][0] - bands[i][1]\n if (gap <= Math.max(2, charSize * 0.15) && bands[i + 1][1] - bands[i][0] <= charSize * 1.3) {\n bands.splice(i, 2, [bands[i][0], bands[i + 1][1]])\n } else i++\n }\n // 박스 위아래 끝에 걸린 얇은 조각 = 이웃 줄 글자의 끝자락 — 합치지 않고 버린다\n while (bands.length > 1 && bands[0][0] <= 1 && bands[0][1] - bands[0][0] < minBand) bands.shift()\n while (bands.length > 1 && bands[bands.length - 1][1] >= h - 1 && bands[bands.length - 1][1] - bands[bands.length - 1][0] < minBand) bands.pop()\n // 얇은 밴드 흡수 — 간격이 더 좁은 쪽 이웃과 합침 (가장 얇은 것부터 반복)\n for (;;) {\n let idx = -1, minH = Infinity\n for (let i = 0; i < bands.length; i++) {\n const bh = bands[i][1] - bands[i][0]\n if (bh < minBand && bh < minH) { minH = bh; idx = i }\n }\n if (idx < 0 || bands.length === 1) break\n const gapPrev = idx > 0 ? bands[idx][0] - bands[idx - 1][1] : Infinity\n const gapNext = idx < bands.length - 1 ? bands[idx + 1][0] - bands[idx][1] : Infinity\n const j = gapPrev <= gapNext ? idx - 1 : idx + 1\n const a = Math.min(idx, j), b = Math.max(idx, j)\n bands = [...bands.slice(0, a), [bands[a][0], bands[b][1]], ...bands.slice(b + 1)]\n }\n if (bands.length === 1) return [{ y0: bands[0][0], y1: bands[0][1], x0: 0, x1: w }]\n return bands.map(([y0, y1]) => { const [x0, x1] = inkCols(y0, y1); return { y0, y1, x0, x1 } })\n}\n\ntype Comp = { x0: number; x1: number; y0: number; y1: number; id: number }\n\n/**\n * 글자 잉크 연결 성분(8-이웃) — 성분마다 bbox, label 은 픽셀별 성분 번호(0 = 배경). 박스를 관통하는 칸 경계\n * 괘선 성분(박스 높이·폭의 85%+, inkBounds 와 같은 기준)은 글자가 아니라 뺀다 — 괘선이 가장 큰 성분이 되면\n * 글자 높이가 부풀어 숫자들이 \"점\"으로 잡혔다(goesan-budget-2013 두 칸을 문 박스 \"8,000 │ 1,000\")\n */\nfunction components(gray: Uint8Array, w: number, h: number, ink: InkStats): { comps: Comp[]; label: Int32Array } {\n const isInk = (v: number) => (ink.darkInk ? v <= ink.threshold : v > ink.threshold)\n const comps: Comp[] = []\n const label = new Int32Array(w * h)\n const stack: number[] = []\n for (let p0 = 0; p0 < w * h; p0++) {\n if (label[p0] || !isInk(gray[p0])) continue\n const c = { x0: w, x1: 0, y0: h, y1: 0, id: comps.length + 1 }\n label[p0] = c.id\n stack.push(p0)\n while (stack.length) {\n const p = stack.pop()!\n const x = p % w, y = (p / w) | 0\n if (x < c.x0) c.x0 = x\n if (x + 1 > c.x1) c.x1 = x + 1\n if (y < c.y0) c.y0 = y\n if (y + 1 > c.y1) c.y1 = y + 1\n for (let dy = -1; dy <= 1; dy++) for (let dx = -1; dx <= 1; dx++) {\n const nx = x + dx, ny = y + dy\n if (nx < 0 || ny < 0 || nx >= w || ny >= h) continue\n const q = ny * w + nx\n if (!label[q] && isInk(gray[q])) { label[q] = c.id; stack.push(q) }\n }\n }\n if (c.y1 - c.y0 < h * 0.85 && c.x1 - c.x0 < w * 0.85) comps.push(c)\n }\n return { comps, label }\n}\n\n/**\n * 박스 맨 앞 글자가 삼각형(△ 감액·▲ 증가 표시)인지. 인식 사전에 △·▲ 가 없어 모델은 숫자 앞 삼각형을\n * 빈칸으로 버린다 — 예산서 \"△400,352\" → \"400,352\" (코퍼스 GT △ 81개 중 OCR 30개, 나머지 부호 소실).\n * 가장 왼쪽 성분(글자 높이 40%+)이 밑변(아래 두 줄이 폭 70%+)·좁은 꼭짓점(위 20% 줄이 폭 40% 이하·가운데)·\n * 양옆 빗변(높이 60% 줄의 잉크가 폭 30% 안쪽과 70% 바깥 양쪽)을 가지면 삼각형, 그 줄 가운데가 비면 △ 차면 ▲.\n * 숫자(4·1·2·7 등)는 밑변이나 꼭짓점·빗변 조건 중 하나에서 걸린다.\n */\nexport function leadingTriangle(gray: Uint8Array, w: number, h: number, ink: InkStats): \"\\u25b3\" | \"\\u25b2\" | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n const first = comps.filter(c => c.y1 - c.y0 >= charH * 0.4).sort((a, b) => a.x0 - b.x0)[0]\n if (!first || charH < 8) return null\n const cw = first.x1 - first.x0, ch = first.y1 - first.y0\n if (cw < ch * 0.8 || cw > ch * 1.8) return null\n const rowSpan = (y: number): { n: number; lo: number; hi: number; runs: number } => {\n let n = 0, lo = -1, hi = -1, runs = 0, prev = false\n for (let x = first.x0; x < first.x1; x++) {\n const on = label[y * w + x] === first.id\n if (on) { n++; if (lo < 0) lo = x - first.x0; hi = x - first.x0; if (!prev) runs++ }\n prev = on\n }\n return { n, lo, hi, runs }\n }\n const base = Math.max(rowSpan(first.y1 - 1).n, rowSpan(first.y1 - 2).n)\n if (base < cw * 0.7) return null\n for (let y = first.y0; y < first.y0 + Math.max(1, Math.round(ch * 0.2)); y++) {\n const r = rowSpan(y)\n if (r.n === 0) continue\n if (r.hi - r.lo + 1 > cw * 0.4 || (r.lo + r.hi) / 2 < cw * 0.25 || (r.lo + r.hi) / 2 > cw * 0.75) return null\n }\n const mid = rowSpan(first.y0 + Math.round(ch * 0.6))\n if (mid.lo < 0 || mid.lo > cw * 0.3 || mid.hi < cw * 0.7) return null\n return mid.runs >= 2 ? \"\\u25b3\" : \"\\u25b2\"\n}\n\n/**\n * 목차 리더 점(\"·········\")의 가로 구간들 (박스 로컬 [x0, x1)). 검출기는 쪽번호를 앞쪽 리더 점과 한 박스로\n * 묶는데, 인식기는 점 무리 뒤 숫자를 망친다 — \"·····5\"→\"…55\", \"·····141\"→\"…11\", \"·····203\"→\"03\"\n * (changwon-plan2026 목차 실측, 코퍼스 80쪽의 리더 섞인 박스 192개). 점 무리를 빼고 앞뒤 글만 따로 인식한다.\n * 잉크 연결 성분(8-이웃)을 x 가 겹치는 것끼리 묶은 글자 덩어리 단위로 본다 — 한글 한 글자는 여러 성분(\"소\" = ㅅ+ㅗ)\n * 이라 성분 하나로 글자 높이를 재면 굵은 리더 점(9px)이 점으로 안 잡혔다(yeosu 목차). 점: 글자 높이(가장 큰 덩어리\n * 높이) 30% 이하의 작은 덩어리이고 중심이 글자 띠(점 크기를 넘는 성분들의 세로 범위) 안 — 박스 위아래 여백에 걸친\n * 점선 괘선 조각은 띠 밖이다(changwon 정원표 칸 실측). 무리: x 순서로 연달아 놓인 점들이 세로 중심 한 줄(±20%)·\n * 간격 글자 높이 이하로 minDots 개+. 리더는 같은 줄 글자를 잇는다 — 무리 앞이나 뒤 글자 높이 2배 안에 점 높이를\n * 세로로 품는 글자 성분이 있어야 한다. 두 행 사이 점선 괘선을 문 박스(위아래 행 글자가 띠를 넓힘)는 여기서 걸린다.\n * 리더는 같은 글리프를 고른 간격으로 찍은 것이라 점 크기(최대/최소 2.5배 이내)·주기(1.8배 이내)가 고르다 — 작은\n * 글꼴의 가는 획이 이진화로 쪼갠 조각(\"gifted.kaist.ac.kr\", pen-cyberbridge 흐름도)은 여기서 걸린다. 박스 끝에 닿아\n * 잘린 점은 통계에서 빼고, 값이 5개 이상이면 양 끝값도 뺀다.\n */\nexport function leaderRuns(\n gray: Uint8Array,\n w: number,\n h: number,\n ink: InkStats,\n minDots: number,\n): Array<[number, number]> {\n const comps = components(gray, w, h, ink).comps.sort((a, b) => a.x0 - b.x0)\n // x 구간이 겹치는 성분끼리 한 덩어리\n const blobs: Array<{ x0: number; x1: number; y0: number; y1: number }> = []\n for (const c of comps) {\n const last = blobs[blobs.length - 1]\n if (last && c.x0 < last.x1) { last.x1 = Math.max(last.x1, c.x1); last.y0 = Math.min(last.y0, c.y0); last.y1 = Math.max(last.y1, c.y1) }\n else blobs.push({ x0: c.x0, x1: c.x1, y0: c.y0, y1: c.y1 })\n }\n let charH = 0\n for (const b of blobs) charH = Math.max(charH, b.y1 - b.y0)\n if (charH < 8) return []\n const small = (c: { x0: number; x1: number; y0: number; y1: number }) => c.x1 - c.x0 <= charH * 0.3 && c.y1 - c.y0 <= charH * 0.3\n let bandTop = h, bandBot = 0\n for (const c of comps) if (!small(c)) { bandTop = Math.min(bandTop, c.y0); bandBot = Math.max(bandBot, c.y1) }\n const cy = (c: { y0: number; y1: number }) => (c.y0 + c.y1) / 2\n const isDot = (b: { x0: number; x1: number; y0: number; y1: number }) => small(b) && cy(b) >= bandTop && cy(b) <= bandBot\n const runs: Array<[number, number]> = []\n for (let i = 0; i < blobs.length;) {\n if (!isDot(blobs[i])) { i++; continue }\n let j = i\n while (j + 1 < blobs.length && isDot(blobs[j + 1]) && blobs[j + 1].x0 - blobs[j].x1 <= charH\n && Math.abs(cy(blobs[j + 1]) - cy(blobs[i])) <= charH * 0.2) j++\n const x0 = blobs[i].x0, x1 = blobs[j].x1, y = cy(blobs[i])\n const onLine = comps.some(c => !small(c) && c.y0 <= y && c.y1 >= y\n && ((c.x1 <= x0 + 2 && c.x1 >= x0 - 2 * charH) || (c.x0 >= x1 - 2 && c.x0 <= x1 + 2 * charH)))\n const run = blobs.slice(i, j + 1).filter(b => b.x0 > 0 && b.x1 < w)\n const spread = (xs: number[]) => {\n const v = [...xs].sort((a, b) => a - b).slice(xs.length >= 5 ? 1 : 0, xs.length >= 5 ? -1 : undefined)\n return v[v.length - 1] / Math.max(1, v[0])\n }\n const even = run.length >= 2 && spread(run.map(b => b.x1 - b.x0)) <= 2.5 && spread(run.map(b => b.y1 - b.y0)) <= 2.5\n && spread(run.slice(1).map((b, k) => b.x0 - run[k].x0)) <= 1.8\n if (j - i + 1 >= minDots && onLine && even) runs.push([x0, x1])\n i = j + 1\n }\n return runs\n}\n\n/**\n * 박스 안 잉크 외곽 (박스 로컬, [x0,x1)·[y0,y1)) — 관통 괘선(행/열 85%+ 잉크)의 픽셀은 뺀다.\n * det 박스는 unclip 여백만큼 글자보다 커서(본문 10pt 에 박스 높이 ≈ 1.5em) 이를 그대로\n * 좌표로 넘기면 글자 크기·줄 기준선·칸 배정이 텍스트층 아이템과 어긋난다. 표 칸 숫자 박스는\n * 칸 경계 괘선을 물고 잡히므로(고산 예산서 실측) 괘선 픽셀을 빼지 않으면 외곽이 박스 전체가\n * 된다. 잉크가 없으면 박스 전체.\n */\nexport function inkBounds(\n gray: Uint8Array,\n w: number,\n h: number,\n ink: InkStats,\n): { x0: number; y0: number; x1: number; y1: number } {\n const isInk = (v: number) => (ink.darkInk ? v <= ink.threshold : v > ink.threshold)\n const colInk = new Uint32Array(w)\n const rowInk = new Uint32Array(h)\n for (let y = 0; y < h; y++) {\n const off = y * w\n for (let x = 0; x < w; x++) if (isInk(gray[off + x])) { colInk[x]++; rowInk[y]++ }\n }\n const ruleCol = new Uint8Array(w), ruleRow = new Uint8Array(h)\n for (let x = 0; x < w; x++) if (colInk[x] >= h * 0.85) ruleCol[x] = 1\n for (let y = 0; y < h; y++) if (rowInk[y] >= w * 0.85) ruleRow[y] = 1\n let x0 = w, x1 = -1, y0 = h, y1 = -1\n for (let y = 0; y < h; y++) {\n if (ruleRow[y]) continue\n const off = y * w\n for (let x = 0; x < w; x++) {\n if (ruleCol[x] || !isInk(gray[off + x])) continue\n if (x < x0) x0 = x\n if (x > x1) x1 = x\n if (y < y0) y0 = y\n if (y > y1) y1 = y\n }\n }\n if (x1 < x0 || y1 < y0) return { x0: 0, y0: 0, x1: w, y1: h }\n return { x0, y0, x1: x1 + 1, y1: y1 + 1 }\n}\n\n/**\n * 괄호 조각 모양 — 윗·아랫 띠(높이 15%)의 가로 획 길이(폭 대비)와 기울기 줄 비율(taper: 획 폭과 전체 폭 사이 폭인 줄 / 높이).\n * [ ] 는 윗·아랫변 뒤 한 번에 획 폭으로 떨어지고(taper ≈ 0), 【】 는 위아래에서 가운데로 폭이 줄어든다(창원 계획 【 0.19~0.52 · 강원 정보화 계획 [ 0.03~0.06)\n */\nexport interface BracketFeatures { top: number; bottom: number; taper: number; fill: number; cw: number; ch: number; charH: number }\n\n/** 박스 로컬 x 중심(cx) 자리의 괄호 조각 — 글자 높이 30% 이상 성분 가운데 cx 에 가장 가까운 것 (「」 는 글자 높이의 절반쯤이다) */\nexport function bracketFeatures(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): BracketFeatures | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 8) return null\n const tol = Math.max(2, charH * 0.3)\n let best: Comp | null = null, bestD = Infinity\n for (const c of comps) {\n if (c.y1 - c.y0 < charH * 0.3 || c.x1 < cx - tol || c.x0 > cx + tol) continue\n const d = Math.abs((c.x0 + c.x1) / 2 - cx)\n if (d < bestD) { bestD = d; best = c }\n }\n if (!best) return null\n const b = best\n const cw = b.x1 - b.x0, ch = b.y1 - b.y0\n if (cw < 3 || ch < 8) return null\n const spans: number[] = []\n for (let y = b.y0; y < b.y1; y++) {\n let n = 0\n for (let x = b.x0; x < b.x1; x++) if (label[y * w + x] === b.id) n++\n spans.push(n)\n }\n const band = Math.max(1, Math.round(ch * 0.15))\n const top = Math.max(...spans.slice(0, band)) / cw, bottom = Math.max(...spans.slice(ch - band)) / cw\n const midRows = spans.slice(Math.floor(ch * 0.3), Math.ceil(ch * 0.7)).sort((p, q) => p - q)\n const stroke = midRows[midRows.length >> 1] ?? 0\n const taper = spans.filter(n => n > stroke && n < cw).length / ch\n const fill = spans.reduce((a, n) => a + n, 0) / (cw * ch)\n return { top, bottom, taper, fill, cw, ch, charH }\n}\n\n/**\n * 로마 숫자 세로 획 수 — 사전에 Ⅰ~Ⅲ 가 있어도 모델은 한 글리프 Ⅲ 을 \"II\"·\"I\" 로, Ⅱ 를 \"I\" 로 줄여 읽는다(코퍼스 장 제목·목차).\n * 앞뒤 글자의 CTC 자리(prevX·nextX, 박스 로컬) 사이에 중심이 든 키 큰 성분(글자 높이 60% 이상)의 가운데 절반 줄에서 잉크 토막을 센다 —\n * CTC 자리는 글리프 한쪽에 치우치기도 해 가운데 금이 아니라 이웃 글자 자리에서 글자 높이 0.35배 떨어진 곳까지 본다.\n * 세리프 Ⅲ 은 위아래 가로대로 이어진 한 성분이어도 가운데 줄은 세 토막이다. 줄의 70% 이상이 같은 수이고 토막이 가늘 때(세로 획)만 낸다\n */\nexport function romanStems(gray: Uint8Array, w: number, h: number, ink: InkStats, prevX: number, nextX: number): number | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return null\n const x0 = prevX + charH * 0.35, x1 = nextX - charH * 0.35\n const sel = comps.filter(c => c.y1 - c.y0 >= charH * 0.6 && (c.x0 + c.x1) / 2 >= x0 && (c.x0 + c.x1) / 2 < x1)\n if (!sel.length) return null\n const ids = new Set(sel.map(c => c.id))\n const ux0 = Math.min(...sel.map(c => c.x0)), ux1 = Math.max(...sel.map(c => c.x1))\n const uy0 = Math.min(...sel.map(c => c.y0)), uy1 = Math.max(...sel.map(c => c.y1))\n const uh = uy1 - uy0\n const counts = new Map<number, number>()\n let rows = 0\n for (let y = uy0 + Math.floor(uh * 0.25); y < uy1 - Math.floor(uh * 0.25); y++) {\n let runs = 0, len = 0, thick = false\n for (let x = ux0; x <= ux1; x++) {\n const on = x < ux1 && ids.has(label[y * w + x])\n if (on) len++\n else if (len) { runs++; if (len > uh * 0.35) thick = true; len = 0 }\n }\n rows++\n if (!thick) counts.set(runs, (counts.get(runs) ?? 0) + 1)\n }\n const [n, k] = [...counts].sort((a, b) => b[1] - a[1])[0] ?? [0, 0]\n return n >= 1 && n <= 3 && k >= rows * 0.7 ? n : null\n}\n\n/**\n * 원문자 숫자 — 사전에 ①~⑨ 가 있어도 모델은 고리를 버리고 숫자만 읽는다(항 번호 \"① 문서는 …\" → \"1문서는\").\n * xs(박스 로컬 — 숫자 글자의 CTC 자리)마다 그 자리를 품는 둥근 고리 성분(글자 높이 55% 이상, 가로세로 0.8~1.25배)이 키 35% 이상\n * 성분(숫자)을 안에 두면 원문자다. 괄호 숫자 \"(1)\"·네모 칸은 고리가 아니라 걸리지 않는다\n */\nexport function circledAt(gray: Uint8Array, w: number, h: number, ink: InkStats, xs: number[]): boolean[] {\n const { comps } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n const rings = charH < 10 ? [] : comps.filter(r => {\n const rw = r.x1 - r.x0, rh = r.y1 - r.y0\n return rh >= charH * 0.55 && rw >= rh * 0.8 && rw <= rh * 1.25\n && comps.some(d => d !== r && d.x0 > r.x0 && d.x1 < r.x1 && d.y0 > r.y0 && d.y1 < r.y1 && d.y1 - d.y0 >= rh * 0.35)\n })\n return xs.map(x => rings.some(r => x >= r.x0 && x <= r.x1))\n}\n\n/**\n * 따옴표 머리 위치 — 모델은 ‘ ’ 를 곧은 ' 로 읽어 방향은 문맥(smartQuotes)이 정하는데, 연도 앞 \"‘24년\"·\"’24년\" 은 문서마다\n * 섞여 문맥으로 못 가른다. cx(박스 로컬 — 따옴표 글자의 CTC 자리)에 가장 가까운 작은 성분(글자 높이 12~50%, 글줄 위쪽 절반)의\n * 잉크 무게중심 높이를 성분 높이 비로 낸다 — 둥근 머리가 아래인 ‘(6 꼴)는 크고 위인 ’(9 꼴)는 작다\n */\nexport function quoteHead(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): number | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return null\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.6)\n if (!tall.length) return null\n const mid = (Math.min(...tall.map(c => c.y0)) + Math.max(...tall.map(c => c.y1))) / 2\n let best: Comp | null = null, bestD = charH * 0.4\n for (const c of comps) {\n const ch = c.y1 - c.y0, d = Math.abs((c.x0 + c.x1) / 2 - cx)\n if (ch < charH * 0.12 || ch > charH * 0.5 || (c.y0 + c.y1) / 2 > mid || d > bestD) continue\n bestD = d; best = c\n }\n if (!best) return null\n let n = 0, sy = 0\n for (let y = best.y0; y < best.y1; y++) for (let x = best.x0; x < best.x1; x++) if (label[y * w + x] === best.id) { n++; sy += y }\n return n ? (sy / n - best.y0) / (best.y1 - best.y0) : null\n}\n\n/**\n * 한 줄 박스 위아래 끝에 걸린 이웃 줄 글자 끝자락 — 줄 간격이 좁은 칸(조직도 상자 \"노동 / 시장 / 정책관\")은 검출 박스가 위아래 줄\n * 글자 끝을 물어, 인식기가 그 조각을 받침으로 읽었다(\"노동\" → \"논동\"·\"시장\" → \"싫장\"·\"근로\" → \"근록\", web068). 박스 끝 행(1px 안)에\n * 닿은 잉크 띠가 빈 행으로 글줄과 떨어져 있고 가장 높은 띠의 45% 미만이면, 그 띠와 다음 띠 사이 빈 행 가운데까지 잘라낸 세로 구간을\n * 낸다(높이 24px 이상, 남는 띠가 글자 두 자 이상인 글줄일 때만). 괘선(행·열 85% 이상 잉크)은 splitRowBands 처럼 빼고 본다. 좌우 끝 20% 안의 세로 테두리(상자 테두리 — 인식기가 \"|\"·\"[\"·\"(\" 로\n * 읽었다)도 그 바깥에 글 잉크가 없으면 괘선 안쪽으로 잘라낸다. 걸린 것이 없으면 null\n */\nexport function edgeTrim(gray: Uint8Array, w: number, h: number, ink: InkStats): { x0: number; x1: number; y0: number; y1: number } | null {\n const isInk = (v: number) => (ink.darkInk ? v <= ink.threshold : v > ink.threshold)\n const colInk = new Uint32Array(w)\n for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) if (isInk(gray[y * w + x])) colInk[x]++\n const ruleCol = new Uint8Array(w)\n let liveW = 0\n for (let x = 0; x < w; x++) { if (colInk[x] >= h * 0.85) ruleCol[x] = 1; else liveW++ }\n const blank = Math.max(1, Math.floor(w * 0.02))\n const bands: Array<[number, number]> = []\n let start = -1\n for (let y = 0; y <= h; y++) {\n let n = 0\n if (y < h) for (let x = 0; x < w; x++) if (!ruleCol[x] && isInk(gray[y * w + x])) n++\n const on = y < h && n > blank && n < liveW * 0.85\n if (on && start < 0) start = y\n else if (!on && start >= 0) { bands.push([start, y]); start = -1 }\n }\n let y0 = 0, y1 = h\n if (bands.length >= 2 && h >= 24) {\n const mh = Math.max(...bands.map(([a, b]) => b - a))\n const [top, next] = [bands[0], bands[1]], [bot, prev] = [bands[bands.length - 1], bands[bands.length - 2]]\n if (top[0] <= 1 && top[1] - top[0] < mh * 0.45) y0 = (top[1] + next[0]) >> 1\n if (bot[1] >= h - 1 && bot[1] - bot[0] < mh * 0.45) y1 = (bot[0] + prev[1] + 1) >> 1\n // 남는 띠가 글줄이어야 한다 — 글자 크기(띠 높이 30% 이상 폭) 잉크 열 토막이 둘 이상. 아이콘(\"Q\" 로 읽힌 돋보기)·큰 장 번호 한 자\n // (옅은 \"6\" 의 끊긴 윗곡선이 조각으로 잘렸다)는 그대로 둔다\n if (y0 > 0 || y1 < h) {\n let runs = 0, len = 0\n for (let x = 0; x <= w; x++) {\n let on = false\n if (x < w && !ruleCol[x]) for (let y = y0; y < y1 && !on; y++) on = isInk(gray[y * w + x])\n if (on) len++\n else { if (len >= (y1 - y0) * 0.3) runs++; len = 0 }\n }\n if (runs < 2) { y0 = 0; y1 = h }\n }\n }\n // 좌우 끝 세로 괘선 — 박스 높이 95% 이상을 관통하는 열이고, 그 바깥 열엔 잉크가 없고, 안쪽으로 빈 열 틈(높이 10%, 2px 이상)을\n // 두고 글이 시작해야 한다. 큰 제목 글자의 세로 줄기(\"D\")도 박스 높이 85% 를 넘어 테두리로 잘렸다(ODL 073 \"Defensoria\" → \"ria\")\n const textCol = (x: number) => { for (let y = y0; y < y1; y++) if (isInk(gray[y * w + x])) return true; return false }\n const border = (x: number) => colInk[x] >= h * 0.95\n const gap = Math.max(2, Math.round(h * 0.1))\n const clearFrom = (x: number, dir: 1 | -1) => { for (let k = 0; k < gap; k++) { const c = x + dir * k; if (c < 0 || c >= w || textCol(c)) return false } return true }\n let x0 = 0, x1 = w\n for (let x = 0; x < w * 0.2; x++) {\n if (border(x)) { let e = x; while (e + 1 < w && border(e + 1)) e++; if (clearFrom(e + 1, 1)) x0 = e + 1; break }\n if (textCol(x)) break\n }\n for (let x = w - 1; x >= w * 0.8; x--) {\n if (border(x)) { let e = x; while (e - 1 >= 0 && border(e - 1)) e--; if (clearFrom(e - 1, -1)) x1 = e; break }\n if (textCol(x)) break\n }\n return y0 > 0 || y1 < h || x0 > 0 || x1 < w ? { x0, x1, y0, y1 } : null\n}\n\n/** 키 큰 잉크 덩어리 수 — 글자 높이 절반 이상 성분을 x 가 겹치는 것끼리 묶어 센다(한 글자 = 한 덩어리, 점·쉼표는 안 셈) */\nexport function tallInkCount(gray: Uint8Array, w: number, h: number, ink: InkStats): number {\n const { comps } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.5).sort((a, b) => a.x0 - b.x0)\n let n = 0, end = -1\n for (const c of tall) { if (c.x0 >= end) n++; end = Math.max(end, c.x1) }\n return n\n}\n\n/**\n * 두 글자 사이에서 통째로 빠진 기호 — 인식기가 사전에 없거나(「」) 드물게 배운 기호(▲ □ · . 。)를 글자 자리 없이 건너뛴다. 글줄 띠(키 큰\n * 성분 위아래)와 x 가 겹치는 다른 성분이 없는(빈 열로 떨어진) 조각만 모양으로 가른다:\n * · 가운데 높이(띠 30~70%)의 작은 둥근 점(띠 높이 8%·3px 이상 25% 이하, 채움 60% 이상 — 1px 잡티는 빼고), 아래쪽(75% 아래)이면 .\n * 2px 까지 작은 점은 \"·\\u0001\" — 모델이 공백으로 읽은 자리에서만 쓴다\n * 。 아래쪽(60% 아래) 작은 고리(띠 높이 40% 이하, 가운데 줄 두 토막)\n * ▲ 띠 높이 50% 이상·가로세로 0.9~1.4배, 위로 갈수록 좁아지고 줄마다 한 토막인 속 찬 삼각형\n * 「 」 띠 높이 30~65%, 위(「)·아래(」)에 붙어 그 변이 폭 70% 넘게 차고 반대쪽 변은 절반 이하, 줄기가 왼쪽(「)·오른쪽(」)\n * / 띠 높이 60% 이상의 가는 사선(분수 칸 \"7/5\" — 모델이 숫자 사이 빗금을 빠뜨림)\n * - 가운데 높이의 짧은 가로 막대(쪽번호 꼬리말 \"- 1 -\" 의 앞 막대 — 줄 머리에서만 쓴다)\n * □ 띠 높이 60~92%·가로세로 0.8~1.25배, 위아래 변이 폭 80% 넘게 차고 가운데 줄은 양끝 두 획. 줄에서 가장 큰 조각이면(글 없이 정사각만\n * 늘어선 칸 \"□□-□□□\") \"□\\0\" — 새로 넣지는 않고 0·O 로 읽힌 자리만 바꾼다(제목 앞 도형 네모와 섞이지 않게)\n * 칸 경계 세로선(띠 높이 90% 이상·가는 열)은 뺀다. 반환은 박스 로컬 x 구간과 기호, 글줄 띠 높이\n */\nexport function gapGlyphs(gray: Uint8Array, w: number, h: number, ink: InkStats): { glyphs: Array<{ x0: number; x1: number; mark: string }>; bandH: number } {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return { glyphs: [], bandH: 0 }\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.6)\n const bandT = Math.min(...tall.map(c => c.y0)), bandB = Math.max(...tall.map(c => c.y1)), bh = bandB - bandT\n const inBand = (c: Comp) => c.y1 > bandT && c.y0 < bandB\n const out: Array<{ x0: number; x1: number; mark: string }> = []\n for (const c of comps) {\n if (!inBand(c)) continue\n const cw = c.x1 - c.x0, ch = c.y1 - c.y0\n if (ch >= bh * 0.9 && cw <= bh * 0.15) continue\n // 빈 열로 떨어진 조각 — 안에 든 성분(□ 속 잡티)은 괜찮다\n const others = comps.filter(o => o !== c && inBand(o) && !(o.x0 >= c.x0 && o.x1 <= c.x1 && o.y0 >= c.y0 && o.y1 <= c.y1))\n const apart = !others.some(o => o.x0 < c.x1 + 1 && o.x1 > c.x0 - 1)\n // 빗금은 이웃 숫자와 x 가 2px 까지 겹쳐도 된다(사선이라 촘촘히 짠 \"7/5\" 에서 양옆 숫자 밑·위로 들어간다)\n const nearlyApart = !others.some(o => Math.min(o.x1, c.x1) - Math.max(o.x0, c.x0) > 2)\n const spans: number[] = [], runs: number[] = []\n let n = 0\n for (let y = c.y0; y < c.y1; y++) {\n let s = 0, r = 0, prev = false\n for (let x = c.x0; x < c.x1; x++) { const on = label[y * w + x] === c.id; if (on) { s++; if (!prev) r++ } prev = on }\n spans.push(s); runs.push(r); n += s\n }\n const fill = n / (cw * ch), cy = ((c.y0 + c.y1) / 2 - bandT) / bh\n const band = Math.max(1, Math.round(ch * 0.15))\n const top = Math.max(...spans.slice(0, band)) / cw, bottom = Math.max(...spans.slice(ch - band)) / cw\n let mark: string | null = null\n const speck = Math.max(3, bh * 0.08)\n const dot = ch <= bh * 0.25 && cw <= bh * 0.25 && ch >= speck && cw >= speck && cw >= ch * 0.6 && cw <= ch * 1.6\n // 이웃 글자와 x 가 겹치거나(촘촘한 글꼴 \"개발·보급\") 2px 까지 작은 둥근 점은 공백 자리 대체용으로만 — 한글 자모엔 떨어진 둥근 점이 없다\n const small = ch <= bh * 0.25 && cw <= bh * 0.25 && ch >= 2 && cw >= 2 && cw >= ch * 0.6 && cw <= ch * 1.6 && fill >= 0.6 && cy >= 0.3 && cy <= 0.7\n if (!apart && !(nearlyApart && ch >= bh * 0.6)) { if (small) out.push({ x0: c.x0, x1: c.x1, mark: \"\\u00b7\\u0001\" }); continue }\n if (!apart) { /* 빗금 후보만 아래에서 */ } else if (dot && fill >= 0.6 && cy >= 0.3 && cy <= 0.7) mark = \"\\u00b7\"\n else if (small) mark = \"\\u00b7\\u0001\"\n else if (dot && fill >= 0.6 && cy >= 0.75 && cw >= ch * 0.8) mark = \".\" // 꼬리 달린 쉼표(세로로 긴 점)는 빼고\n else if (ch <= bh * 0.4 && ch >= speck && cw >= ch * 0.75 && cw <= ch * 1.3 && fill < 0.6 && runs[ch >> 1] === 2 && cy >= 0.6) mark = \"\\u3002\"\n else if (ch <= bh * 0.15 && cw >= ch * 2 && cw <= bh * 0.8 && fill >= 0.7 && cy >= 0.35 && cy <= 0.75) mark = \"-\"\n else if (ch >= bh * 0.5 && cw >= ch * 0.9 && cw <= ch * 1.4 && fill >= 0.4 && runs.every(r => r <= 1)\n && top <= 0.4 && bottom >= 0.8) mark = \"\\u25b2\"\n else if (ch >= bh * 0.3 && ch <= bh * 0.65 && fill < 0.5) {\n // 줄기 쪽 — 가로 변을 뺀 줄의 잉크 x 평균(폭 비). 「 는 왼쪽, 」 는 오른쪽 (한글 ㄱ·ㄴ 은 반대쪽이라 걸리지 않는다)\n const stem = (from: number, to: number) => {\n let sx = 0, k = 0\n for (let y = from; y < to; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) { sx += x - c.x0; k++ }\n return k ? sx / k / cw : 0.5\n }\n if (c.y0 <= bandT + bh * 0.15 && top >= 0.7 && bottom <= 0.5 && stem(c.y0 + band, c.y1) <= 0.35) mark = \"\\u300c\"\n else if (c.y1 >= bandB - bh * 0.15 && bottom >= 0.7 && top <= 0.5 && stem(c.y0, c.y1 - band) >= 0.65) mark = \"\\u300d\"\n } else if (ch >= charH * 0.6 && cw >= ch * 0.8 && cw <= ch * 1.25 && fill < 0.5 && top >= 0.8 && bottom >= 0.8\n && runs[ch >> 1] === 2) mark = ch <= charH * 0.92 ? \"\\u25a1\" : \"\\u25a1\\u0000\"\n // 빗금 / — 띠 높이 60% 이상의 가는 사선(폭이 높이의 0.25~0.7배, 줄마다 한 토막, 위쪽이 오른쪽으로 폭의 절반 넘게 치우침)\n if (!mark && ch >= bh * 0.6 && cw >= ch * 0.25 && cw <= ch * 0.7 && fill <= 0.4 && runs.every(r => r <= 1)) {\n const mx = (y: number) => { let sx = 0, k = 0; for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) { sx += x; k++ } return k ? sx / k : NaN }\n if (mx(c.y0 + band) - mx(c.y1 - 1 - band) >= cw * 0.5) mark = \"/\"\n }\n if (mark) out.push({ x0: c.x0, x1: c.x1, mark })\n }\n return { glyphs: out, bandH: bh }\n}\n\n/**\n * 줄 머리 고리 글머리 ○ / ㅇ — 모델은 같은 글리프를 \"O\"·\"ㅇ\" 로 오락가락 읽는다(장흥 계획 ○ 27개 중 9개가 ㅇ). cx(첫 글자의 CTC 자리)에\n * 가장 가까운 키 30% 이상 성분이 고리(가로세로 0.85~1.2배, 가운데 가로·세로줄 모두 두 토막)면 크기·채움으로 가른다 — 도형 ○ 는 글줄 띠\n * 높이의 0.65~1.0배에 획이 가늘고(폭의 10% 이하, 채움 0.23 이하 — 그림자 진 고리는 가는 쪽 획 8% 이하·채움 0.33 이하), 자모 ㅇ 은\n * 0.47~0.56배에 채움 0.24 이상(코퍼스 9문서 실측), 라틴 o 는 0.6~0.8배로 줄 아래쪽에 앉는다\n */\nexport function ringBullet(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): \"\\u25cb\" | \"\\u3147\" | \"o\" | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return null\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.6)\n const bandT = Math.min(...tall.map(c => c.y0)), bh = Math.max(...tall.map(c => c.y1)) - bandT\n let best: Comp | null = null, bestD = bh * 0.6\n for (const c of comps) {\n const d = Math.abs((c.x0 + c.x1) / 2 - cx)\n if (c.y1 - c.y0 >= bh * 0.3 && d < bestD) { bestD = d; best = c }\n }\n if (!best) return null\n const c = best, cw = c.x1 - c.x0, ch = c.y1 - c.y0\n if (cw < ch * 0.85 || cw > ch * 1.2) return null\n const runs = (xs: number[], at: (k: number) => boolean) => {\n let n = 0, len = 0, mx = 0, mn = Infinity\n for (const k of [...xs, -1]) { if (k >= 0 && at(k)) { if (!len) n++; len++; mx = Math.max(mx, len) } else { if (len) mn = Math.min(mn, len); len = 0 } }\n return { n, mx, mn }\n }\n const my = (c.y0 + c.y1) >> 1, mx = (c.x0 + c.x1) >> 1\n const row = runs(Array.from({ length: cw }, (_, k) => c.x0 + k), x => label[my * w + x] === c.id)\n const col = runs(Array.from({ length: ch }, (_, k) => c.y0 + k), y => label[y * w + mx] === c.id)\n if (row.n !== 2 || col.n !== 2) return null\n let n = 0\n for (let y = c.y0; y < c.y1; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) n++\n const fill = n / (cw * ch), rel = ch / bh\n // 그림자 진 고리(한쪽 획만 두꺼움 — ❍, 글꼴에 따라 ○ 도 이렇게 그려진다)도 가는 쪽 획이 가늘면 도형 ○\n if (rel >= 0.62 && (fill <= 0.23 ? row.mx <= cw * 0.1 : fill <= 0.33 && row.mn <= cw * 0.08)) return \"\\u25cb\"\n if (rel <= 0.58 && fill >= 0.24) return \"\\u3147\"\n // 라틴 소문자 o — x 높이(띠 0.6~0.8배)로 줄 아래쪽에 앉은 굵은 고리(속초 예산서 \"o 기본급\", 모델은 숫자 0 으로 읽음). 숫자 0 은 세로로 길고\n // (폭/높이 0.58) 자모 ㅇ 은 띠 가운데(0.41~0.51)에 뜬다\n if (rel >= 0.6 && rel <= 0.8 && fill >= 0.3 && ((c.y0 + c.y1) / 2 - bandT) / bh >= 0.55) return \"o\"\n return null\n}\n\n/** cx 자리 성분이 큰 속 찬 원(●)인가 — 글줄 띠 높이의 45~105%, 가로세로 0.8~1.25배, 채움 0.65~0.9. 가운뎃점은 크게 그려도 띠의 32% 안팎 */\nexport function discAt(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): boolean {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return false\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.6)\n const bh = Math.max(...tall.map(c => c.y1)) - Math.min(...tall.map(c => c.y0))\n const c = comps.filter(o => Math.abs((o.x0 + o.x1) / 2 - cx) <= bh * 0.4).sort((a, b) => Math.abs((a.x0 + a.x1) / 2 - cx) - Math.abs((b.x0 + b.x1) / 2 - cx))[0]\n if (!c) return false\n const cw = c.x1 - c.x0, ch = c.y1 - c.y0\n if (ch < bh * 0.45 || ch > bh * 1.05 || cw < ch * 0.8 || cw > ch * 1.25) return false\n let n = 0\n for (let y = c.y0; y < c.y1; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) n++\n const fill = n / (cw * ch)\n return fill >= 0.65 && fill <= 0.9\n}\n\n/**\n * 숫자 1 로 읽은 로마 숫자 Ⅰ — 세리프 Ⅰ 은 윗머리·아랫머리가 줄기 양쪽으로 고르게 뻗고, 숫자 1 은 윗머리가 왼쪽(깃)으로만 뻗는다\n * (코퍼스 실측: Ⅰ 좌우 0.8·0.8·1.3·1.3 줄기 폭, 숫자 1 오른쪽 0). cx 자리를 품는 가장 키 큰 성분의 위·아래 20% 줄 잉크 범위를\n * 가운데 줄(40~60%) 줄기와 견준다. 세리프 없는 막대는 가를 수 없어 false\n */\nexport function serifOne(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): boolean {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return false\n const c = comps.filter(o => o.x0 - 3 <= cx && o.x1 + 3 >= cx && o.y1 - o.y0 >= charH * 0.6).sort((a, b) => (b.y1 - b.y0) - (a.y1 - a.y0))[0]\n if (!c) return false\n const ch = c.y1 - c.y0\n const span = (a: number, b: number) => {\n let mn = Infinity, mx = -1\n for (let y = c.y0 + Math.floor(ch * a); y < c.y0 + Math.ceil(ch * b); y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) { mn = Math.min(mn, x); mx = Math.max(mx, x) }\n return [mn, mx]\n }\n const [m0, m1] = span(0.4, 0.6), [t0, t1] = span(0, 0.2), [b0, b1] = span(0.8, 1)\n const sw = m1 - m0 + 1\n const even = (l: number, r: number) => l >= sw * 0.4 && r >= sw * 0.4 && Math.abs(l - r) <= Math.max(l, r) * 0.35\n return sw >= 2 && sw <= ch * 0.3 && even(m0 - t0, t1 - m1) && even(m0 - b0, b1 - m1)\n}\n\n/**\n * 이어진 별표 수 — CTC 는 같은 글자가 붙어 나오면 하나로 합친다(\"등록증**\" → \"등록증*\"). cx(별표 글자의 CTC 자리)에 가장 가까운 별표\n * 꼴 조각(글줄 띠 높이 20~50%, 가로세로 0.7~1.4배, 채움 0.25~0.65, 띠 위쪽 절반)에서 좌우로 틈이 조각 폭 이하인 같은 꼴 조각을 센다\n */\nexport function starRun(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): number {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return 0\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.6)\n const bandT = Math.min(...tall.map(c => c.y0)), bh = Math.max(...tall.map(c => c.y1)) - bandT\n const star = (c: Comp) => {\n const cw = c.x1 - c.x0, ch = c.y1 - c.y0\n if (ch < bh * 0.2 || ch > bh * 0.5 || cw < ch * 0.7 || cw > ch * 1.4 || ((c.y0 + c.y1) / 2 - bandT) / bh > 0.55) return false\n let n = 0\n for (let y = c.y0; y < c.y1; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) n++\n const fill = n / (cw * ch)\n return fill >= 0.25 && fill <= 0.65\n }\n const stars = comps.filter(star).sort((a, b) => a.x0 - b.x0)\n const k = stars.findIndex(c => cx >= c.x0 - (c.x1 - c.x0) && cx <= c.x1 + (c.x1 - c.x0))\n if (k < 0) return 0\n let lo = k, hi = k\n while (lo > 0 && stars[lo].x0 - stars[lo - 1].x1 <= stars[lo].x1 - stars[lo].x0) lo--\n while (hi + 1 < stars.length && stars[hi + 1].x0 - stars[hi].x1 <= stars[hi].x1 - stars[hi].x0) hi++\n return hi - lo + 1\n}\n\n/** 【】 로 볼 기울기 줄 비율 — 코퍼스 실측 [ ] 최대 0.13, 【】 최소 0.19 */\nconst BRACKET_TAPER = 0.16\n\n/** 【】 로 볼 채움·폭 하한 — 【】 는 속이 찬 렌즈 꼴로 폭이 글자 높이의 0.28~0.44배·기울기 줄 0.24~0.65(코퍼스 실측), 모서리가 둥근\n * 소괄호 ( ) 는 기울기 줄이 있어도 좁고 적다(굵은 압축 글꼴 0.22~0.25배·0.17~0.25 — 방송통신위원회 보도자료·산림청 공고에서 모델이 [ ] 로 읽음) */\nconst BRACKET_SOLID = 0.4\nconst BRACKET_WIDE = 0.265\nconst BRACKET_LENS = 0.35\n\n/** 괄호 모양 판별 — 모를 때 null (인식 결과 [ ] 를 둔다). 곧은 ㄱ·ㄴ 꼴은 「」, 휜 조각(기울기 줄)은 ( ) */\nexport function bracketShape(f: BracketFeatures, close: boolean): string | null {\n const [near, far] = close ? [f.bottom, f.top] : [f.top, f.bottom]\n const paren = close ? \")\" : \"(\"\n if (near >= 0.7 && far <= 0.5) return f.taper < BRACKET_TAPER ? (close ? \"\\u300d\" : \"\\u300c\") : paren\n if (near >= 0.7 && far >= 0.7 && f.taper >= BRACKET_TAPER) {\n return f.fill >= BRACKET_SOLID && (f.cw >= f.ch * BRACKET_WIDE || f.taper >= BRACKET_LENS) ? (close ? \"\\u3011\" : \"\\u3010\") : paren\n }\n return null\n}\n\n\n/**\n * 박스 맨 앞 글머리 기호 — 인식 사전에 없거나(◎ ▪) 모델이 작은 점으로 읽거나(● → •·) 통째로 빠뜨리는(□) 공문서 글머리를 잉크 조각 모양으로 가른다.\n * 맨 앞 덩어리(x 가 겹치는 성분 묶음)가 글자 높이 대비 크기·채움·겹침으로:\n * ◎ 이중 원 — 성분 둘 이상이 안팎으로 겹치고 속이 빈 둥근 조각 (함평 계획 21개가 \"O\")\n * ● 큰 속 찬 원 — 채움 0.65~0.88(원 π/4≈0.79), 글자 높이 0.45배 이상 (교육청 안내문 17개가 \"•\"·누락)\n * ▪ 작은 속 찬 네모 — 채움 0.9 이상, 글자 높이 0.28~0.6배 (가운뎃점 \"·\" 은 0.21배 안팎)\n * 속 빈 원(○·ㅇ·❍)은 픽셀로 못 가르니 건드리지 않는다. firstX 는 첫 인식 글자의 CTC 자리(박스 로컬) —\n * 덩어리가 그 앞에서 끝나면 인식에서 빠진 것, 그 글자 자리에 걸치면 그 글자가 이 기호를 잘못 읽은 것이다\n */\nexport function leadingBullet(gray: Uint8Array, w: number, h: number, ink: InkStats, firstX: number): { mark: \"◎\" | \"●\" | \"▪\" | \"□\"; covers: boolean } | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return null\n const cand = comps.filter(c => c.y1 - c.y0 >= charH * 0.15).sort((a, b) => a.x0 - b.x0)\n const first = cand[0]\n if (!first) return null\n const cl = cand.filter(c => c.x0 < first.x1 && c.x1 > first.x0)\n const x0 = Math.min(...cl.map(c => c.x0)), x1 = Math.max(...cl.map(c => c.x1)), y0 = Math.min(...cl.map(c => c.y0)), y1 = Math.max(...cl.map(c => c.y1))\n const cw = x1 - x0, ch = y1 - y0\n if (cw < ch * 0.8 || cw > ch * 1.25) return null\n // 덩어리 뒤에 틈이 있어야 글머리다 (글자 획이 아님). 기호 하나만 든 상자(목차 열의 ◎)는 뒤가 비어 있다\n const next = cand.find(c => c.x0 >= x1)\n if (next && next.x0 - x1 < ch * 0.3) return null\n let inkN = 0\n for (let y = y0; y < y1; y++) for (let x = x0; x < x1; x++) if (cl.some(c => label[y * w + x] === c.id)) inkN++\n const fill = inkN / (cw * ch)\n const rel = ch / charH\n // 이중 원 — 안쪽 조각도 가운데 놓인 둥근 고리여야 한다 (원문자 ①② 는 안쪽이 숫자라 좁다)\n const ring = (c: Comp) => { const a = c.x1 - c.x0, b = c.y1 - c.y0; return a >= b * 0.75 && a <= b * 1.33 }\n const nested = cl.length >= 2 && cl.some(a => cl.some(b => a !== b && b.x0 > a.x0 && b.x1 < a.x1 && b.y0 > a.y0 && b.y1 < a.y1 && ring(b)\n && Math.abs((b.x0 + b.x1) - (a.x0 + a.x1)) <= (a.x1 - a.x0) * 0.2 && Math.abs((b.y0 + b.y1) - (a.y0 + a.y1)) <= (a.y1 - a.y0) * 0.2))\n // 속 빈 정사각 □ — 윗·아랫 띠(높이 15%)가 폭 80% 넘게 차고 가운데 줄이 양끝 두 획뿐. 글자 높이의 0.6~0.92배\n // (제목 앞 도형 네모는 글자 높이만큼 커 0.98배, 한글 첫소리 ㅁ 은 인식된 글자라 covers 로 걸러진다)\n const span = (y: number) => { let n = 0; for (let x = x0; x < x1; x++) if (cl.some(c => label[y * w + x] === c.id)) n++; return n }\n const band = Math.max(1, Math.round(ch * 0.15))\n const edgeFull = (from: number, dir: 1 | -1) => { let m = 0; for (let k = 0; k < band; k++) m = Math.max(m, span(from + dir * k)); return m >= cw * 0.8 }\n let midRuns = 0\n { let prev = false; const my = y0 + (ch >> 1); for (let x = x0; x < x1; x++) { const on = cl.some(c => label[my * w + x] === c.id); if (on && !prev) midRuns++; prev = on } }\n const hollowSquare = cl.length === 1 && fill < 0.5 && midRuns === 2 && edgeFull(y0, 1) && edgeFull(y1 - 1, -1)\n let mark: \"\\u25ce\" | \"\\u25cf\" | \"\\u25aa\" | \"\\u25a1\" | null = null\n if (hollowSquare && rel >= 0.6 && rel <= 0.92) mark = \"\\u25a1\"\n else if (nested && fill < 0.45 && rel >= 0.6) mark = \"\\u25ce\"\n else if (cl.length === 1 && fill >= 0.9 && rel >= 0.28 && rel <= 0.6) mark = \"\\u25aa\"\n else if (cl.length === 1 && fill >= 0.65 && fill <= 0.88 && rel >= 0.5 && rel <= 0.8) mark = \"\\u25cf\"\n if (!mark) return null\n return { mark, covers: firstX <= x1 + ch * 0.3 }\n}\n","/**\n * 인식 결과 글리프 되살리기 — CTC 글자 자리(steps × stepPx, 박스 로컬 x)를 박스 픽셀로 옮겨 그 자리 잉크 조각 모양으로, 사전 밖이거나\n * 모델이 줄여·바꿔·빠뜨려 읽는 글자를 고친다(괄호 「」【】·여는 따옴표·원문자·로마 숫자·두 글자 사이에서 빠진 기호). 모양 판정은\n * line-split.ts, 여기는 글자열 배선만. 글자 배열은 CTC 글자와 1:1 로 두고 칸마다 바꿔 넣거나(빈 글·여러 글자 허용) 끝에 잇는다\n */\nimport { bracketFeatures, bracketShape, circledAt, discAt, gapGlyphs, grayCrop, inkStats, quoteHead, ringBullet, romanStems, serifOne, starRun } from \"./line-split.js\"\nimport type { InkStats } from \"./line-split.js\"\nimport type { Box } from \"./crop.js\"\n\ninterface Ctx { chars: string[]; cx: (i: number) => number; gray: Uint8Array; w: number; h: number; ink: InkStats }\n\n/** text 는 CTC 글자와 1:1 이어야 한다 — 아니면 그대로 돌려준다. note.ringLead: 줄 머리 고리를 픽셀로 정했다(restoreSymbols 의 O → ○ 를 건너뛸 것) */\nexport function restoreGlyphs(rgba: Uint8Array, pageW: number, box: Box, text: string, steps: number[], stepPx: number, note: { ringLead?: boolean } = {}): string {\n const chars = [...text]\n if (chars.length !== steps.length) return text\n const gray = grayCrop(rgba, pageW, box)\n const c: Ctx = { chars, cx: i => (steps[i] + 0.5) * stepPx, gray, w: box.w, h: box.h, ink: inkStats(gray) }\n if (/[[\\]]/.test(text)) brackets(c)\n if (/['\"]/.test(text)) quotes(c)\n if (/(^|\\D)[1-9](\\D|$)/.test(text)) circled(c)\n if (text.includes(\"*\")) stars(c)\n if (/[\\u00b7\\u2022]/.test(text)) discs(c)\n gaps(c)\n note.ringLead = ring(c)\n if (/[I1Ⅰ-Ⅲ]|^\\s*\\./.test(text)) roman(c)\n return chars.join(\"\")\n}\n\n/**\n * 사전 밖 괄호 — 인식 사전에 「」·【】 가 없어 모델은 모두 [ ] 로 읽는다(코퍼스 정답 「」44·「」23·【】41·[]159 쌍 ↔ OCR [ 274).\n * [ ] 자리 잉크 조각이 속이 찬 조각이면 【】, 윗변 가로 획만이면 「, 아랫변 가로 획만이면 」 ([ ] 는 위아래 모두)\n */\nfunction brackets({ chars, cx, gray, w, h, ink }: Ctx) {\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] !== \"[\" && chars[i] !== \"]\") continue\n const f = bracketFeatures(gray, w, h, ink, cx(i))\n const shape = f && bracketShape(f, chars[i] === \"]\")\n if (shape) chars[i] = shape\n }\n}\n\n/**\n * 여는 따옴표 — 곧은 ' \" 로 읽은 자리의 머리가 뚜렷이 아래(line-split quoteHead ≥ 0.47, 실측 닫는 따옴표 최대 0.46 바로 위)면 ‘ “ 로 정한다. smartQuotes 문맥 규칙은\n * 연도 생략을 늘 ’ 로 두는데 \"(‘11.3월 구성)\"처럼 여는 따옴표로 쓴 문서가 있다. 닫는 쪽은 글꼴마다 겹쳐(작은 글씨 여는 따옴표 0.23~0.45,\n * 닫는 0.28~0.46 — 코퍼스 61곳 실측) 문맥에 맡긴다\n */\nfunction quotes({ chars, cx, gray, w, h, ink }: Ctx) {\n // smartQuotes 는 남은 곧은 따옴표를 홀짝으로 여닫으니, 짝 계산에 드는 자리를 바꾸면 나머지가 어긋난다 — 짝에서 빠지는\n // 연도 생략('24)과 그 줄에 하나뿐인 곧은 따옴표만 본다. 짝을 기다리는 여는 따옴표 뒤는 닫는 자리다(모델이 여는 쪽만 ‘ 로 읽은 줄)\n const year = (i: number) => chars[i] === \"'\" && !/[\\p{L}\\p{N}]/u.test(chars[i - 1] ?? \"\") && /^\\d{2}(?!\\d)/.test(chars.slice(i + 1, i + 4).join(\"\"))\n const single = { \"'\": chars.filter((c, i) => c === \"'\" && !year(i)).length === 1, '\"': chars.filter(c => c === '\"').length === 1 }\n const open = { \"'\": false, '\"': false }\n for (let i = 0; i < chars.length; i++) {\n const c = chars[i]\n const kind = c === \"'\" || c === \"‘\" || c === \"’\" ? \"'\" : c === '\"' || c === \"“\" || c === \"”\" ? '\"' : null\n if (!kind) continue\n if (c !== kind) { open[kind] = c === \"‘\" || c === \"“\"; continue }\n if (open[kind]) { open[kind] = false; continue }\n if (!year(i) && !single[kind]) continue\n const r = quoteHead(gray, w, h, ink, cx(i))\n if (r !== null && r >= 0.47) { chars[i] = kind === \"'\" ? \"‘\" : \"“\"; open[kind] = true }\n }\n}\n\n/** 원문자 숫자 — 모델이 고리를 버리고 읽은 홀로 선 숫자 1~9(앞뒤가 숫자 아님)를 그 자리 고리 성분(line-split circledAt)으로 ①~⑨ */\nfunction circled({ chars, cx, gray, w, h, ink }: Ctx) {\n const at = chars.flatMap((c, i) => /^[1-9]$/.test(c) && !/\\d/.test(chars[i - 1] ?? \"\") && !/\\d/.test(chars[i + 1] ?? \"\") ? [i] : [])\n if (!at.length) return\n const hit = circledAt(gray, w, h, ink, at.map(cx))\n at.forEach((i, k) => { if (hit[k]) chars[i] = String.fromCharCode(0x245f + Number(chars[i])) })\n}\n\n/** 별표 겹침 — CTC 가 붙은 같은 글자를 하나로 합친 \"**\" → \"*\" 를 그 자리 별표 조각 수(line-split starRun)만큼 채운다 */\nfunction stars({ chars, cx, gray, w, h, ink }: Ctx) {\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] !== \"*\" || chars[i - 1] === \"*\") continue\n let e = i\n while (chars[e + 1] === \"*\") e++\n const n = starRun(gray, w, h, ink, cx(i))\n if (n > e - i + 1 && n <= 4) chars[e] += \"*\".repeat(n - (e - i + 1))\n i = e\n }\n}\n\n/** 큰 속 찬 원 ● — 모델은 줄 중간 글머리 ● 를 가운뎃점 · · • 로 줄여 읽는다(목차 \"…171●부록●186\") */\nfunction discs({ chars, cx, gray, w, h, ink }: Ctx) {\n for (let i = 0; i < chars.length; i++) if (/^[\\u00b7\\u2022]$/.test(chars[i]) && discAt(gray, w, h, ink, cx(i))) chars[i] = \"\\u25cf\"\n}\n\n/**\n * 두 글자 사이에서 빠진 기호 — 빈 열로 떨어진 잉크 조각의 모양(line-split gapGlyphs)이 · . 。 ▲ 「 」 □ 인데 그 가까이(글자 간격 0.45)에\n * CTC 글자 자리가 없으면 앞 글자 뒤에 넣는다. 모델은 가운뎃점을 공백으로 읽기도 해(\"개발·보급\" → \"개발 보급\") 그 구간의 공백은\n * · 로 바꾸고, □ 는 0·O 로 읽기도 해(\"□□-□□□\" → \"00-000\") 그 구간의 한 글자가 그것이면 바꾼다\n */\nfunction gaps({ chars, cx, gray, w, h, ink }: Ctx) {\n const { glyphs, bandH } = gapGlyphs(gray, w, h, ink)\n if (!glyphs.length) return\n const live = chars.map((c, i) => i).filter(i => chars[i].trim())\n if (!live.length) return\n // 글자 간격 — 이웃한 한글 두 자의 CTC 자리 차 중앙값(없으면 글줄 띠 높이). 조각 가운데에서 0.45 간격 안에 글자 자리가 있으면 덮인 것\n // (작은 점은 CTC 자리가 조각 x 구간을 1~2px 비껴 조각 구간만 보면 이미 읽은 \"·\" 옆에 또 넣었다)\n const d: number[] = []\n for (let k = 0; k + 1 < live.length; k++) if (/[가-힣]$/.test(chars[live[k]]) && /^[가-힣]/.test(chars[live[k + 1]])) d.push(cx(live[k + 1]) - cx(live[k]))\n const pitch = d.length >= 2 ? d.sort((a, b) => a - b)[d.length >> 1] : bandH\n const nearTo = (g: { x0: number; x1: number }) => (i: number) => Math.abs(cx(i) - (g.x0 + g.x1) / 2) <= Math.max(pitch * 0.45, (g.x1 - g.x0) / 2 + 1)\n const loose = glyphs.filter(g => /^[\\u00b7.]/.test(g.mark) && !live.some(nearTo(g)))\n for (const g of glyphs.sort((a, b) => a.x0 - b.x0)) {\n const mid = (g.x0 + g.x1) / 2\n const near = nearTo(g)\n const cover = live.filter(near)\n if (g.mark === \"\\u00b7\\u0001\") {\n // 작은 점·글자에 붙은 점은 모델이 공백으로 읽은 자리만(덮임 판정 앞 — 공백 자리가 증거다) — 다른 점이 늘어서지 않고 앞뒤가 글자일 때\n const sp = chars.findIndex((c, i) => c === \" \" && near(i))\n const p = sp >= 0 ? chars.slice(0, sp).reverse().find(c => c.trim()) : undefined, q = sp >= 0 ? chars.slice(sp + 1).find(c => c.trim()) : undefined\n // 앞뒤 모두 한글 — 라틴 글은 소문자 i·j 의 점이 공백 옆에 붙어 걸렸다(\"Keeps open\" → \"Keeps·open\", ODL 106)\n if (p && q && /[가-힣]$/.test(p) && /^[가-힣]/.test(q) && !loose.some(o => o !== g && Math.abs((o.x0 + o.x1) / 2 - mid) <= pitch * 1.5)) chars[sp] = \"\\u00b7\"\n continue\n }\n if (cover.length) {\n if (g.mark.startsWith(\"\\u25a1\") && cover.length === 1 && /^[0Oo\\u25cb]$/.test(chars[cover[0]])) chars[cover[0]] = \"\\u25a1\"\n continue\n }\n if (g.mark === \"\\u25a1\\u0000\") continue\n // 앞뒤 글자 사이 — 줄 끝은 마침표만(문장 끝 \"…습니다.\")\n const before = live.filter(i => cx(i) < mid), after = live.filter(i => cx(i) > mid)\n // 줄 머리는 뒤가 한글인 。 · 「 ▲ 만(예산서 세부 항목 \"。사무실운영\" — □ 는 glyph 판정이 엄한 leadingBullet 몫)\n if (!before.length) {\n if (after.length && /^[\\u3002\\u00b7\\u300c\\u25b2]$/.test(g.mark) && /^[가-힣]/.test(chars[after[0]])) chars[after[0]] = g.mark + chars[after[0]]\n // 쪽번호 꼬리말 \"- 1 -\" 를 \"1 -\" 로 읽은 줄 — 뒤 막대가 읽혔으면 앞 막대도 붙인다\n else if (g.mark === \"-\" && /^[\\dⅰ-ⅹivx]+\\s*-$/.test(chars.join(\"\").trim())) chars[after[0]] = \"-\" + chars[after[0]]\n continue\n }\n if (!after.length && g.mark !== \".\") continue\n if (g.mark === \"/\" && !(/\\d$/.test(chars[before[before.length - 1]]) && /^\\d/.test(chars[after[0]]))) continue // 빗금은 숫자 사이만(분수)\n const prev = chars[before[before.length - 1]], next = after.length ? chars[after[0]] : \"\"\n if (g.mark === \"\\u00b7\" || g.mark === \".\") {\n // 목차 리더·말줄임(안 읽힌 점이 둘 이상 늘어섬, 옆 글자가 … · .)은 빠진 기호가 아니다. 가운뎃점은 쪽번호 앞 점도 아니다\n if (loose.some(o => o !== g && Math.abs((o.x0 + o.x1) / 2 - mid) <= pitch * 1.5)) continue\n if (/[\\u2026.\\u00b7]$/.test(prev) || /^[\\u2026.\\u00b7]/.test(next)) continue\n }\n if (g.mark === \"\\u00b7\") {\n if (/^\\d/.test(next)) continue\n const sp = chars.findIndex((c, i) => c === \" \" && near(i))\n if (sp >= 0) { chars[sp] = g.mark; continue }\n }\n chars[before[before.length - 1]] += g.mark\n }\n}\n\n/**\n * 줄 머리 고리 글머리 — 첫 글자가 ㅇ·O·o·0·○ 이고 뒤가 한글(여는 괄호 뒤 한글 포함)이면 그 자리 고리의 크기·채움(line-split ringBullet)으로 ○ / ㅇ / o 를 정한다.\n * 모델이 같은 도형 ○ 를 \"O\"(→ restoreSymbols 가 ○)·\"ㅇ\" 로 오락가락 읽고, 자모 글머리 ㅇ 도 \"O\" 로 읽어 ○ 가 됐다\n */\nfunction ring({ chars, cx, gray, w, h, ink }: Ctx): boolean {\n const k = chars.findIndex(c => c.trim())\n if (k < 0 || !/^[\\u3147Oo0\\u25cb]$/.test(chars[k])) return false\n // 뒤 글이 한글이거나 여는 괄호 뒤 한글(\"❍(정책) 민생성장\")\n const rest = chars.slice(k + 1).join(\"\").trimStart()\n if (!/^[(\\[「【<]?[가-힣]/.test(rest)) return false\n const r = ringBullet(gray, w, h, ink, cx(k))\n if (r) chars[k] = r\n return r !== null\n}\n\n/**\n * 로마 숫자 획 수 — 모델은 한 글리프 Ⅲ 을 \"II\"·\"I\" 로, Ⅱ 를 \"I\" 로 줄여 읽는다(장 제목 \"Ⅲ. 2026년 …\" → \"II. 2026년 …\").\n * 라틴 글자에 붙지 않은 I·Ⅰ~Ⅲ 토막마다 그 자리 세로 획 수(line-split romanStems)를 세어 읽은 수와 다르면 Ⅰ~Ⅲ 한 글자로 바꾼다\n * (토막 첫 칸에 넣고 나머지 칸은 비운다). 숫자를 빠뜨리고 \".\" 부터 읽은 줄은 점 앞 잉크로 채운다\n */\nfunction roman({ chars, cx, gray, w, h, ink }: Ctx) {\n const ROMAN = /^[IⅠ-Ⅲ]$/, LATIN = /[A-Za-z]$/\n // 숫자 1 로 읽은 Ⅰ — 앞뒤가 숫자·라틴 글자가 아닌 홀로 선 1 이 좌우 대칭 세리프면(line-split serifOne). \"토픽1\" → \"토픽Ⅰ\"\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] !== \"1\" || /[\\dA-Za-z]$/.test(chars[i - 1] ?? \"\") || /^[\\dA-Za-z,]/.test(chars[i + 1] ?? \"\")) continue\n if (serifOne(gray, w, h, ink, cx(i))) chars[i] = \"Ⅰ\"\n }\n // 로마 숫자에 붙은 1 은 같은 토막으로 센다 (\"[표 Ⅱ-4]\" → \"[표I1-4]\")\n const inRoman = (i: number) => ROMAN.test(chars[i]) || (chars[i] === \"1\" && (ROMAN.test(chars[i - 1] ?? \"\") || ROMAN.test(chars[i + 1] ?? \"\")))\n // 숫자를 통째로 빠뜨리고 \".\" 부터 읽은 제목 줄(\".세입·세출 …\") — 점 앞 잉크가 세로 획이면 되살린다\n const k = chars.findIndex(c => c.trim())\n if (chars[k] === \".\" && chars.slice(k + 1).some(c => /[가-힣A-Za-z0-9]/.test(c))) {\n const n = romanStems(gray, w, h, ink, -Infinity, cx(k))\n if (n) chars[k] = String.fromCharCode(0x215f + n) + chars[k]\n }\n for (let s = 0; s < chars.length;) {\n if (!inRoman(s) || (s > 0 && LATIN.test(chars[s - 1]))) { s++; continue }\n let e = s\n while (e < chars.length && inRoman(e)) e++\n const tok = chars.slice(s, e).join(\"\")\n if (e < chars.length && /^[A-Za-z]/.test(chars[e])) { s = e; continue }\n let p = s - 1, q = e\n while (p >= 0 && !chars[p].trim()) p--\n while (q < chars.length && !chars[q].trim()) q++\n const n = romanStems(gray, w, h, ink, p >= 0 ? cx(p) : -Infinity, q < chars.length ? cx(q) : Infinity)\n const canon = n ? [[\"Ⅰ\", \"I\"], [\"Ⅱ\", \"II\"], [\"Ⅲ\", \"III\"]][n - 1] : null\n if (canon && !canon.includes(tok)) { chars[s] = canon[0]; for (let i = s + 1; i < e; i++) chars[i] = \"\" }\n s = e\n }\n}\n","/**\n * OCR 인식 문자열 후처리 — 한국 공문서 표기 관행 복원.\n *\n * PP-OCRv5 korean 인식기의 사전(11,945자)에는 공문서 글머리·표기 기호 일부가 없다\n * (○ U+25CB·△ U+25B3·◎·■·「」·【】 — 사전 실측). 모델은 사전 안의 닮은 글자로\n * 읽는다: ○ → 라틴 O(코퍼스 박스 단위 실측 145회)·o, △ → 증가 기호 ∆(29회).\n * 공문서에서 쓰이지 않는 쪽만 되돌린다 — 모호한 것(ㅇ 글머리는 실제 자모, 0 은\n * \"0원\" 같은 숫자)은 건드리지 않는다.\n *\n * 따옴표: 모델은 ‘ ’ 를 곧은 ' 로 읽는다(114회). 공문서 텍스트층은 둥근 따옴표가 압도적\n * (코퍼스 GT ‘’ 129 : ' 7 — 한컴 자동 고침) → 여닫음 문맥으로 둥근 따옴표를 복원한다.\n */\n\nconst HANGUL_START = /^[\\uac00-\\ud7a3]/\n\n/** 박스 텍스트 한 줄 후처리 (위치 독립 규칙) */\nexport function restoreSymbols(text: string, ringDecided = false): string {\n let s = text\n // ○ 글머리: 줄 머리 O/o + (공백) + 한글 — 줄 머리 고리를 픽셀로 이미 정했으면(glyph-restore ring) 건너뛴다\n if (!ringDecided) s = s.replace(/^([Oo])(\\s?)(?=[\\uac00-\\ud7a3])/, \"\\u25cb$2\")\n // ○○ 자리표시(○○시·○○○ 과장): 라틴 글자와 붙지 않은 O 2개 이상이 한글과 (공백 하나 사이로) 이웃\n s = s.replace(/(?<![A-Za-z])O{2,}(?![A-Za-z])/g, (m, i: number) =>\n /[\\uac00-\\ud7a3]$/.test(s.slice(Math.max(0, i - 2), i).trimEnd()) || /^\\s?[\\uac00-\\ud7a3]/.test(s.slice(i + m.length))\n ? \"\\u25cb\".repeat(m.length) : m)\n // △ 감액 표시: 사전 밖 → ∆(U+2206)·그리스 Δ(U+0394) 로 읽힘\n s = s.replace(/[\\u2206\\u0394]/g, \"\\u25b3\")\n // \"(cid:NN)\" 은 PDF 텍스트 추출기가 유니코드 없는 글리프에 쓰는 표기 — 인식기가 학습 자료에서 배워 티끌·가는\n // 막대 박스에 낸다(pcccr·rda-planfarm·yeosu 실측, 박스 5~16px). 인쇄된 글자일 수 없으니 지운다\n s = s.replace(/\\(cid:\\d*\\)/g, \"\")\n return smartQuotes(joinDigitGroups(s))\n}\n\n/**\n * 천 단위 숫자 안의 끼어든 공백 제거 — 모델이 쉼표 뒤에 공백을 넣는다(\"385, 426\"·\"4,802, 164\",\n * 예산서 표에서 수십 회 실측). 쉼표 앞이 1~3자리, 뒤가 정확히 3자리인 무리만 잇는다\n * (\"1, 2, 3\" 같은 목록·\"10, 20명\"은 뒤가 3자리가 아니라 그대로).\n */\nexport function joinDigitGroups(s: string): string {\n return s.replace(/(?<![\\d,])\\d{1,3}(?:, ?\\d{3})+(?![\\d])/g, m => m.replace(/, /g, \",\"))\n}\n\n/**\n * 곧은 따옴표 → 둥근 따옴표. 한 줄 안의 따옴표를 짝으로 보고 여닫음을 번갈아 준다 —\n * OCR 띄어쓰기가 불안정해(\"내에서'기록관리시스템'\") 앞 글자가 공백인지로는 여는 자리를\n * 가를 수 없다. 개수가 홀수면(줄바꿈에 걸친 인용) 첫 따옴표가 여는 자리(줄 머리·공백·\n * 여는 괄호 뒤)가 아닐 때 닫는 것부터. 연도 생략 '24 는 짝에서 빼고 ’.\n */\nexport function smartQuotes(s: string): string {\n if (!/['\"]/.test(s)) return s\n const chars = [...s]\n for (const q of [\"'\", '\"']) {\n const [open, close] = q === \"'\" ? [\"\\u2018\", \"\\u2019\"] : [\"\\u201c\", \"\\u201d\"]\n const pos: number[] = []\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] !== q) continue\n const prev = i > 0 ? chars[i - 1] : \"\"\n if (q === \"'\" && !/[\\p{L}\\p{N}]/u.test(prev) && /^\\d{2}(?!\\d)/.test(chars.slice(i + 1, i + 4).join(\"\"))) {\n chars[i] = close // 연도 생략\n continue\n }\n pos.push(i)\n }\n if (pos.length === 0) continue\n const first = pos[0]\n const prev = first > 0 ? chars[first - 1] : \"\"\n const atOpen = prev === \"\" || /[\\s(\\[{<\\u300c\\u300e\\u3010\\u3008\\u300a\\u2018\\u201c·,:]/.test(prev)\n let isOpen = pos.length % 2 === 0 || atOpen\n for (const i of pos) { chars[i] = isOpen ? open : close; isOpen = !isOpen }\n }\n return chars.join(\"\")\n}\n\n/** 점류만으로 된 조각 — 목차 리더·잡티(\".\", \"..\", \"…\", \"·\"). 단독으로는 뜻이 없다 */\nexport function isDotFragment(text: string): boolean {\n return /^[\\s.\\u00b7\\u2024\\u2025\\u2026\\u2027\\u2219\\u22c5\\u318d]+$/.test(text)\n}\n\ntype Placed = { text: string; x: number; y: number; w: number; h: number; confidence: number }\n\n/**\n * 목차 한 줄 잇기. 텍스트층은 목차 줄을 리더 글자까지 한 아이템(\"제목 ······ 12\")으로 주는데, 검출기는 리더\n * 가운데를 비워 [제목 ···] [··· 12] 두 박스로 낸다. 그러면 줄마다 큰 틈이 생겨 클러스터 표 감지가 목차·머리\n * 영역을 표로 잡고, 그 뒤 2단 본문을 줄 단위로 섞어 읽었다(assembly-minutes-1179 1면 — 목차 쪽번호 하나를 더\n * 제대로 읽자 표 감지가 발화). 엔진이 박스 끝에서 확인한 리더 점(ends: lead = 박스가 점으로 시작, trail = 점으로\n * 끝남)이 마주 보는 같은 줄 가장 가까운 이웃과 \"제목 … 12\" 한 아이템으로 합친다.\n */\nexport function joinLeaderItems<T extends Placed>(items: T[], ends: Map<T, { lead: boolean; trail: boolean }>): T[] {\n const gone = new Set<T>()\n const sameLine = (a: T, b: T) => Math.abs(a.y + a.h / 2 - (b.y + b.h / 2)) <= Math.max(a.h, b.h) / 2\n const merge = (left: T, right: T): void => {\n const x2 = Math.max(left.x + left.w, right.x + right.w), y2 = Math.max(left.y + left.h, right.y + right.h)\n left.text = left.text.replace(/\\s*\\u2026$/, \"\") + \" \\u2026 \" + right.text.replace(/^\\u2026\\s*/, \"\")\n left.x = Math.min(left.x, right.x)\n left.y = Math.min(left.y, right.y)\n left.w = x2 - left.x\n left.h = y2 - left.y\n left.confidence = Math.min(left.confidence, right.confidence)\n gone.add(right)\n }\n const neighbor = (it: T, toLeft: boolean): T | null => {\n let best: T | null = null\n for (const o of items) {\n if (o === it || gone.has(o) || !sameLine(o, it)) continue\n if (toLeft ? o.x + o.w > it.x + 2 : o.x < it.x + it.w - 2) continue\n if (!best || (toLeft ? o.x + o.w > best.x + best.w : o.x < best.x)) best = o\n }\n return best\n }\n // 오른쪽부터 — 쪽번호 쪽(\"… 12\")을 왼쪽 이웃에 붙이고, 제목 쪽(\"제목 …\")은 오른쪽 이웃을 당겨 붙인다\n for (const it of [...items].sort((a, b) => b.x - a.x)) {\n if (gone.has(it) || !ends.get(it)?.lead) continue\n const left = neighbor(it, true)\n if (left) merge(left, it)\n }\n for (const it of [...items].sort((a, b) => a.x - b.x)) {\n if (gone.has(it) || !ends.get(it)?.trail) continue\n const right = neighbor(it, false)\n if (right) merge(it, right)\n }\n // 리더 점을 못 찾은 목차 줄 — 잡음·흐림에 점이 덜 잡히면 몇 줄만 [제목][쪽번호] 두 아이템으로 남고, 이어진 줄들 사이의\n // 그 두 줄이 클러스터 표를 불러 목차 전체를 칸에 섞었다(archives-record-duty 잡음 σ12: 29줄 중 3줄). 같은 쪽에서 리더로\n // 이은 줄 둘 이상과 오른쪽 끝(쪽번호 열)이 맞는 숫자 아이템은 쪽번호로 보고 같은 줄 왼쪽 이웃과 잇는다\n const toc = items.filter(it => !gone.has(it) && /\\s\\u2026\\s\\d{1,4}$/.test(it.text))\n if (toc.length >= 2) {\n for (const it of items) {\n if (gone.has(it) || toc.includes(it) || !/^[\\s.:\\u00b7\\u2026]*\\d{1,4}$/.test(it.text)) continue\n const x2 = it.x + it.w\n if (toc.filter(t => Math.abs(t.x + t.w - x2) <= Math.max(t.h, it.h)).length < 2) continue\n const left = neighbor(it, true)\n if (!left || toc.includes(left)) continue\n left.text = left.text.replace(/[\\s.:\\u00b7\\u2026]+$/, \"\")\n it.text = it.text.replace(/^[\\s.:\\u00b7\\u2026]+/, \"\")\n merge(left, it)\n }\n }\n return items.filter(it => !gone.has(it))\n}\n\n/**\n * 이웃 인지 ○ 복원 — 글머리 ○ 가 제 박스로 떨어져 \"O\" 한 글자로 읽힌 경우,\n * 같은 줄(세로 중심 차 < 높이 절반) 바로 오른쪽(글자 높이 3배 이내) 박스가 한글로 시작하면 ○.\n */\nexport function restoreBulletItems<T extends { text: string; x: number; y: number; w: number; h: number }>(items: T[]): void {\n for (const it of items) {\n if (it.text !== \"O\" && it.text !== \"o\") continue\n const cy = it.y + it.h / 2\n let next: T | null = null\n for (const o of items) {\n if (o === it || o.x < it.x + it.w * 0.5) continue\n if (Math.abs(o.y + o.h / 2 - cy) > Math.max(it.h, o.h) / 2) continue\n if (o.x - (it.x + it.w) > it.h * 3) continue\n if (!next || o.x < next.x) next = o\n }\n if (next && HANGUL_START.test(next.text.trimStart())) it.text = \"\\u25cb\"\n }\n}\n","/**\n * 인식 입력 준비 — 밴드 서브 박스 좌표, 라인 crop 리사이즈(회전 포함).\n * (engine.ts 에서 분리 — 엔진은 세션·배치·후처리 흐름만)\n */\n\nexport interface Box { x: number; y: number; w: number; h: number }\n\n/** rec 입력 높이 (공식 RecResizeImg image_shape [3, 48, 320]) */\nexport const REC_HEIGHT = 48\nconst REC_MAX_WIDTH = 3200\nconst MIN_SIZE = 3\n\n/**\n * 밴드 → 페이지 좌표 서브 박스. 위아래는 밴드 높이 20% 여유(이웃 밴드와의 간격 절반 이내),\n * 좌우는 괘선을 뺀 잉크 폭 + 밴드 높이 20% 여유(원 박스 안) — 칸 경계 세로선이 crop 에\n * 들어가 \"|국\" 으로 읽히지 않게\n */\nexport function bandBoxes(b: Box, bands: Array<{ y0: number; y1: number; x0: number; x1: number }>, pageH: number): Box[] {\n const out: Box[] = []\n for (let i = 0; i < bands.length; i++) {\n const { y0, y1, x0, x1 } = bands[i]\n const bh = y1 - y0\n const upGap = i > 0 ? (y0 - bands[i - 1].y1) / 2 : y0\n const downGap = i < bands.length - 1 ? (bands[i + 1].y0 - y1) / 2 : b.h - y1\n const top = Math.max(0, Math.round(b.y + y0 - Math.min(bh * 0.2, upGap)))\n const bot = Math.min(pageH, Math.round(b.y + y1 + Math.min(bh * 0.2, downGap)))\n const left = Math.max(b.x, Math.round(b.x + x0 - bh * 0.2))\n const right = Math.min(b.x + b.w, Math.round(b.x + x1 + bh * 0.2))\n if (bot - top >= MIN_SIZE && right - left >= MIN_SIZE) out.push({ x: left, y: top, w: right - left, h: bot - top })\n }\n return out\n}\n\n/**\n * 라인 crop → rec 입력 크기(높이 48, 비율 유지 폭) RGB. 회전은 crop 좌표계에서\n * (90 = 반시계 np.rot90, 270 = 시계). 리사이즈는 bilinear(반픽셀 중심, cv2 INTER_LINEAR 등가)\n * — 공식 전처리(cv2.resize 기본)와 같은 보간.\n */\n/** keep: 박스 로컬 [x0, x1)×[y0, y1) 밖은 배경 휘도 bg 로 칠한다 (rot 0 만 — 박스 끝에 걸린 이웃 줄 조각·상자 테두리 지우기) */\nexport function lineCrop(rgba: Uint8Array, pageW: number, box: Box, rot: 0 | 90 | 270, keep?: { x0: number; x1: number; y0: number; y1: number; bg: number }): { rgb: Uint8Array; w: number } {\n const srcW = rot === 0 ? box.w : box.h\n const srcH = rot === 0 ? box.h : box.w\n const rw = Math.min(REC_MAX_WIDTH, Math.max(16, Math.round((srcW * REC_HEIGHT) / srcH)))\n const rgb = new Uint8Array(rw * REC_HEIGHT * 3)\n // 회전 좌표 → 페이지 픽셀\n const at = (u: number, v: number): number => {\n let px: number, py: number\n if (rot === 0) { px = u; py = v }\n else if (rot === 90) { px = box.w - 1 - v; py = u }\n else { px = v; py = box.h - 1 - u }\n return ((box.y + py) * pageW + (box.x + px)) * 4\n }\n const fx = srcW / rw\n const fy = srcH / REC_HEIGHT\n for (let dy = 0; dy < REC_HEIGHT; dy++) {\n let sy = (dy + 0.5) * fy - 0.5\n if (sy < 0) sy = 0\n const y0 = Math.min(srcH - 1, Math.floor(sy))\n const y1 = Math.min(srcH - 1, y0 + 1)\n const wy = sy - y0\n for (let dx = 0; dx < rw; dx++) {\n let sx = (dx + 0.5) * fx - 0.5\n if (sx < 0) sx = 0\n const x0 = Math.min(srcW - 1, Math.floor(sx))\n const x1 = Math.min(srcW - 1, x0 + 1)\n const wx = sx - x0\n const i00 = at(x0, y0), i01 = at(x1, y0), i10 = at(x0, y1), i11 = at(x1, y1)\n const o = (dy * rw + dx) * 3\n if (keep && rot === 0 && (sx < keep.x0 || sx >= keep.x1 || sy < keep.y0 || sy >= keep.y1)) {\n rgb[o] = rgb[o + 1] = rgb[o + 2] = keep.bg\n continue\n }\n for (let c = 0; c < 3; c++) {\n const top = rgba[i00 + c] * (1 - wx) + rgba[i01 + c] * wx\n const bottom = rgba[i10 + c] * (1 - wx) + rgba[i11 + c] * wx\n rgb[o + c] = Math.round(top * (1 - wy) + bottom * wy)\n }\n }\n }\n return { rgb, w: rw }\n}\n\n\n/** Split a detected line at ruled cell boundaries before recognizing its text. */\nexport function splitBoxAtCellRules(b: Box, rules: Array<{ x1: number; y1: number; y2: number; thicknessPx: number }>): Box[] {\n const cuts = rules.filter(r => r.x1 > b.x + b.h && r.x1 < b.x + b.w - b.h\n && r.y1 <= b.y + b.h * 0.25 && r.y2 >= b.y + b.h * 0.75).sort((a, c) => a.x1 - c.x1)\n if (!cuts.length) return [b]\n const out: Box[] = []\n let left = b.x\n for (const r of cuts) {\n const edge = Math.floor(r.x1 - r.thicknessPx / 2 - 1)\n if (edge - left < b.h) continue\n out.push({ ...b, x: left, w: edge - left })\n left = Math.ceil(r.x1 + r.thicknessPx / 2 + 1)\n }\n if (left < b.x + b.w) out.push({ ...b, x: left, w: b.x + b.w - left })\n return out\n}\n","/**\n * 스캔 기울기 보정 — 투영 프로파일 방식.\n *\n * 스캔·사진 입력은 0.5~3° 기울기가 흔하다. det 은 축정렬 박스(connected-component bbox)\n * 라 기울어진 줄은 박스가 위아래 줄을 물고, 괘선 감지(ruling-lines.ts)는 축정렬 런렝스라\n * 기울면 표 괘선이 통째로 사라진다. 인식 전에 페이지를 바로 세운다.\n *\n * 추정: 페이지를 긴 변 ~1000px 로 줄여 잉크 픽셀을 모으고, 후보 각 θ 마다\n * y' = y·cosθ + x·sinθ 의 행 히스토그램 제곱합(줄이 수평일 때 가장 뾰족)을 비교 —\n * ±MAX 를 0.2° 간격으로 훑고 최댓값 주변을 0.02° 간격으로 다듬는다.\n * 적용 조건: |θ| ≥ MIN_APPLY_DEG 이고 0° 대비 뾰족함이 뚜렷할 때만 (클린 렌더는 무보정).\n */\n\n/** 추정 범위 (°) — 이보다 큰 회전은 기울기가 아니라 방향 문제 (범위 밖) */\nconst MAX_SKEW_DEG = 5\n/** 이보다 작은 기울기는 보정하지 않음 — 리샘플 흐림이 이득보다 크다 */\nconst MIN_APPLY_DEG = 0.25\n/** 0° 대비 투영 뾰족함 비율 하한 — 글자 적은 페이지·도형의 우연한 봉우리 거부 */\nconst MIN_GAIN = 1.03\nconst TARGET_LONG = 1000\n\nexport interface SkewEstimate {\n /** 페이지 기울기 (°, 양수 = 시계 방향으로 기움 → 같은 각만큼 반시계로 돌리면 바로 섬) */\n angle: number\n /** 최적각 투영 점수 / 0° 점수 */\n gain: number\n}\n\n/** 기울기 추정 (적용 여부와 무관한 원값) */\nexport function estimateSkew(rgba: Uint8Array, width: number, height: number): SkewEstimate {\n const step = Math.max(1, Math.ceil(Math.max(width, height) / TARGET_LONG))\n const sw = Math.floor(width / step), sh = Math.floor(height / step)\n // 축소 휘도 + 전역 문턱 (잉크 = 어두운 픽셀)\n const xs: number[] = [], ys: number[] = []\n for (let y = 0; y < sh; y++) {\n for (let x = 0; x < sw; x++) {\n const i = ((y * step) * width + x * step) * 4\n const l = (rgba[i] * 77 + rgba[i + 1] * 150 + rgba[i + 2] * 29) >> 8\n if (l < 128) { xs.push(x); ys.push(y) }\n }\n }\n if (xs.length < 200) return { angle: 0, gain: 1 }\n const diag = Math.ceil(Math.hypot(sw, sh))\n const hist = new Float64Array(2 * diag + 2)\n const score = (deg: number): number => {\n const t = (deg * Math.PI) / 180\n const c = Math.cos(t), s = Math.sin(t)\n hist.fill(0)\n for (let k = 0; k < xs.length; k++) hist[Math.round(ys[k] * c + xs[k] * s) + diag]++\n let sum = 0\n for (let i = 0; i < hist.length; i++) sum += hist[i] * hist[i]\n return sum\n }\n const s0 = score(0)\n let best = 0, bestS = s0\n for (let d = -MAX_SKEW_DEG; d <= MAX_SKEW_DEG + 1e-9; d += 0.2) {\n const v = score(d)\n if (v > bestS) { bestS = v; best = d }\n }\n const coarse = best\n for (let d = coarse - 0.2; d <= coarse + 0.2 + 1e-9; d += 0.02) {\n const v = score(d)\n if (v > bestS) { bestS = v; best = d }\n }\n // 투영 회전각 θ 에서 줄이 수평 → 페이지는 −θ 만큼 기운 것\n return { angle: +(-best).toFixed(2), gain: s0 > 0 ? bestS / s0 : 1 }\n}\n\n/**\n * 필요하면 페이지를 바로 세운 RGBA 를 돌려준다 (같은 크기, 중심 회전, 바깥은 흰색).\n * 보정하지 않으면 입력 그대로 + angle 0.\n */\nexport function deskewPage(rgba: Uint8Array, width: number, height: number): { rgba: Uint8Array; angle: number } {\n const est = estimateSkew(rgba, width, height)\n if (Math.abs(est.angle) < MIN_APPLY_DEG || est.gain < MIN_GAIN) return { rgba, angle: 0 }\n return { rgba: rotateRgba(rgba, width, height, est.angle), angle: est.angle }\n}\n\n/**\n * 중심 기준 회전 (deg, 양수 = 화면상 반시계), 같은 캔버스 크기, bilinear, 바깥 흰색.\n * 출력 픽셀 (x,y) 는 입력의 역회전 위치에서 표본.\n */\nexport function rotateRgba(rgba: Uint8Array, width: number, height: number, deg: number): Uint8Array {\n const out = new Uint8Array(rgba.length)\n const t = (deg * Math.PI) / 180\n const c = Math.cos(t), s = Math.sin(t)\n const cx = (width - 1) / 2, cy = (height - 1) / 2\n for (let y = 0; y < height; y++) {\n const dy = y - cy\n for (let x = 0; x < width; x++) {\n const dx = x - cx\n // 화면 좌표(y 아래)에서 반시계 deg 회전의 역변환\n const sx = c * dx - s * dy + cx\n const sy = s * dx + c * dy + cy\n const o = (y * width + x) * 4\n const x0 = Math.floor(sx), y0 = Math.floor(sy)\n if (x0 < 0 || y0 < 0 || x0 >= width - 1 || y0 >= height - 1) {\n out[o] = 255; out[o + 1] = 255; out[o + 2] = 255; out[o + 3] = 255\n continue\n }\n const wx = sx - x0, wy = sy - y0\n const i00 = (y0 * width + x0) * 4, i01 = i00 + 4, i10 = i00 + width * 4, i11 = i10 + 4\n for (let ch = 0; ch < 4; ch++) {\n const top = rgba[i00 + ch] * (1 - wx) + rgba[i01 + ch] * wx\n const bot = rgba[i10 + ch] * (1 - wx) + rgba[i11 + ch] * wx\n out[o + ch] = Math.round(top * (1 - wy) + bot * wy)\n }\n }\n }\n return out\n}\n","/**\n * PDF OCR 브릿지 — 대상 페이지를 pdfium 으로 래스터해 내장 엔진 또는\n * 사용자 OcrProvider 로 인식하고, 페이지별 IRBlock[] 을 돌려준다.\n *\n * - 내장 엔진: OcrItem 좌표를 PDF 포인트로 환산해 기존 블록 파이프라인\n * (extractPageBlocksWithLines — xy-cut 읽기순서·클러스터 표 감지)에 태운다.\n * 스캔 문서도 표 구조 복원이 가능한 이유.\n * - 사용자 프로바이더: 페이지 PNG → 텍스트 → 페이지당 paragraph 블록 (종전 계약).\n *\n * 에러 계약 (v4.1.0 리뷰 F6/F7):\n * - 환경 오류(의존성·모델 미설치, PDF 오픈 실패)는 throw — 호출자가 NEEDS_OCR 폴백.\n * - 페이지 단위 실패는 본문 오염 대신 warnings(OCR_FAILED) 로 기록하고 계속.\n */\n\nimport type { IRBlock, OcrProvider, ParseWarning } from \"../types.js\"\nimport type { NormItem } from \"../pdf/text-line.js\"\nimport type { LineSegment } from \"../pdf/line-types.js\"\nimport { extractPageBlocksWithLines } from \"../pdf/page-blocks.js\"\nimport { UNRULED_REGION_TABLES } from \"../pdf/ocr-region-merge.js\"\nimport { detectRulingLines, rulingToPdfLines } from \"./ruling-lines.js\"\nimport { DEFAULT_OCR_TUNING, getOcrEngine, type OcrItem, type OcrPageStats, type OcrTuning } from \"./engine.js\"\nimport { deskewPage } from \"./deskew.js\"\nimport { ensureOcrModels } from \"./models.js\"\nimport { OPTIONAL_DEP_INSTALL_HINT } from \"../utils.js\"\n\n/** OCR 렌더 스케일 (72dpi × 3 = 216dpi) — 10pt 본문이 rec 입력 높이(48px)에 근접 */\nconst OCR_RENDER_SCALE = 3\n/**\n * OCR 래스터 픽셀 상한 (쪽·이미지 공통) — 이보다 큰 쪽은 배율을 낮춰 이 안에 맞춘다. 쪽 크기를 가리지 않고 ×3 으로 그리면 628B PDF\n * (4000pt 정사각 쪽)가 12000² 래스터에 사본·괘선 마스크까지 2.38GB 를 먹었다(16000² PNG 1.84GB). A2(1191×1684pt)도 216dpi 로 18MP 라\n * 공문서 판형은 줄지 않는다\n */\nexport const MAX_OCR_PIXELS = 24_000_000\n/** 페이지 하나당 OCR 타임아웃 — det+rec 수십 라인 기준 넉넉히 */\nconst PAGE_TIMEOUT_MS = 120_000\n\nexport type OcrMode = \"builtin\" | OcrProvider\n\n/** pdfjs 연산자 목록 (그래픽만 쓴다 — 괘선·채움·그림 영역) */\nexport type PageOps = { fnArray: Uint32Array | number[]; argsArray: unknown[][] }\n\n/**\n * 대상 페이지들을 OCR 해 페이지별 블록 맵 반환.\n * @param buffer 원본 PDF (pdfjs 가 detach 하기 전에 clone 해 둔 것)\n * @param targets 1-based 페이지 번호 집합\n * @param vectorOps 벡터 글자 쪽(글자를 곡선으로 그린 쪽)의 그래픽(vector-glyphs.ts ocrVectorOps) — 그 쪽은 표 구조를\n * 래스터 괘선 감지 대신 이것(실제 괘선)으로 복원한다. 스캔 쪽은 벡터가 없으니 없다\n */\nexport async function runPdfOcr(\n buffer: ArrayBuffer,\n targets: Set<number>,\n mode: OcrMode,\n warnings: ParseWarning[],\n onProgress?: (current: number, total: number) => void,\n detectTables = true,\n vectorOps?: Map<number, PageOps>,\n imageRegions?: Map<number, Array<{ x1: number; y1: number; x2: number; y2: number }>>,\n): Promise<Map<number, IRBlock[]>> {\n const result = new Map<number, IRBlock[]>()\n if (targets.size === 0) return result\n\n // 환경 준비 — 실패는 그대로 throw (호출자가 NEEDS_OCR 폴백)\n const pdfiumMod = await tryImport<typeof import(\"@hyzyla/pdfium\")>(\n \"@hyzyla/pdfium\",\n () => import(\"@hyzyla/pdfium\"),\n )\n if (mode === \"builtin\") {\n await ensureOcrModels(p => {\n if (p.phase === \"download\" && p.downloaded === 0) {\n process.stderr.write(`[kordoc-ocr] ${p.spec.name} 다운로드 중 (~${p.spec.sizeMb}MB)...\\n`)\n }\n })\n }\n const engine = mode === \"builtin\" ? await getOcrEngine() : null\n\n const pdfium = await pdfiumMod.PDFiumLibrary.init()\n const doc = await pdfium.loadDocument(new Uint8Array(buffer))\n try {\n let done = 0\n // 대상 쪽만 연다 — doc.pages() 는 모든 쪽을 불러오고, 쪽은 render() 가 끝에서만 닫아 대상 밖 쪽이 문서를 닫을 때까지 남았다\n // (changwon 328쪽 문서의 한 쪽 OCR: 6ms·26MB → 전 쪽 순회 970ms·330MB). pdfium 쪽 번호는 0-based — 대외 계약(1-based)으로 환산\n const count = doc.getPageCount()\n for (const pageNo of [...targets].filter(p => p >= 1 && p <= count).sort((a, b) => a - b)) {\n const page = doc.getPage(pageNo - 1)\n onProgress?.(++done, targets.size)\n try {\n const blocks = await withTimeout(\n ocrOnePage(page, pageNo, mode, engine, warnings, detectTables, vectorOps?.get(pageNo), imageRegions?.get(pageNo)),\n PAGE_TIMEOUT_MS,\n `OCR 페이지 ${pageNo} 타임아웃 (${PAGE_TIMEOUT_MS / 1000}초)`,\n )\n result.set(pageNo, blocks)\n } catch (e) {\n warnings.push({\n page: pageNo,\n message: `페이지 ${pageNo} OCR 실패: ${e instanceof Error ? e.message : String(e)}`,\n code: \"OCR_FAILED\",\n })\n }\n }\n } finally {\n doc.destroy()\n pdfium.destroy()\n }\n return result\n}\n\nasync function ocrOnePage(\n page: import(\"@hyzyla/pdfium\").PDFiumPage,\n pageNo: number,\n mode: OcrMode,\n engine: Awaited<ReturnType<typeof getOcrEngine>> | null,\n warnings: ParseWarning[],\n detectTables: boolean,\n vectorOps?: PageOps,\n regions?: Array<{ x1: number; y1: number; x2: number; y2: number }>,\n): Promise<IRBlock[]> {\n const { originalWidth: pdfW, originalHeight: pdfH } = page.getOriginalSize()\n const renderScale = Math.min(OCR_RENDER_SCALE, Math.sqrt(MAX_OCR_PIXELS / Math.max(1, pdfW * pdfH)))\n if (renderScale < OCR_RENDER_SCALE) {\n warnings.push({ page: pageNo, code: \"PARTIAL_PARSE\", message: `OCR 래스터 픽셀 상한으로 렌더 해상도를 축소했습니다 (작은 글자 인식 결손 가능)` })\n }\n // 그림 영역만 읽는 쪽은 두 배로 한 번 그려 영역 다시 읽기(closer)에 쓰고, 쪽 배율 래스터는 2×2 평균으로 줄여 만든다\n // (pdfium 은 같은 쪽을 두 번 그리면 wasm 서명 오류가 난다)\n const closer = regions && mode === \"builtin\" && renderScale * 2 <= Math.sqrt(MAX_OCR_PIXELS / Math.max(1, pdfW * pdfH))\n const rendered = await page.render({\n scale: closer ? renderScale * 2 : renderScale,\n render: async ({ data }) => data,\n })\n const hiRgba = closer ? bgraToRgba(rendered.data) : null\n const { rgba, width: rw, height: rh } = hiRgba\n ? halve(hiRgba, rendered.width, rendered.height)\n : { rgba: bgraToRgba(rendered.data), width: rendered.width, height: rendered.height }\n\n if (mode === \"builtin\") {\n // 스캔 기울기 보정 — 인식과 괘선 감지가 같은(바로 선) 래스터를 본다. 클린 렌더는 무보정.\n // 벡터 글자 쪽은 보정하지 않는다 — 글자 좌표가 돌면 그 쪽 벡터 괘선과 어긋난다\n const upright = vectorOps ? rgba : deskewPage(rgba, rw, rh).rgba\n const stats: OcrPageStats = { droppedLowConf: 0 }\n const ruling = vectorOps ? undefined : detectRulingLines(upright, rw, rh, rh / pdfH)\n const items = await engine!.recognizePage(upright, rw, rh, stats, regions ? REGION_TUNING : undefined, ruling?.cellDividers)\n if (stats.droppedLowConf > 0) {\n warnings.push({\n page: pageNo,\n message: `페이지 ${pageNo}: 저신뢰 OCR 라인 ${stats.droppedLowConf}개 폐기 (인식 결손 가능)`,\n code: \"OCR_LOW_CONF\",\n })\n }\n if (stats.truncatedBoxes) {\n warnings.push({ page: pageNo, message: `페이지 ${pageNo}: OCR 검출 상자가 너무 많아 ${stats.truncatedBoxes}개는 인식하지 않음 (일부 글 결손)`, code: \"PARTIAL_PARSE\" })\n }\n const scale = rh / pdfH\n // 텍스트층이 있는 쪽의 그림 영역만 읽을 때는 영역마다 그 안 글줄로 따로 블록을 만든다 — 쪽 전체로 묶으면 본문 줄과 그림 글이\n // 한 문단으로 합쳐져 영역 판정(mergeOcrImageRegions)에서 빠진다\n if (regions) {\n const inside = (it: OcrItem, r: { x1: number; y1: number; x2: number; y2: number }) => {\n const cx = (it.x + it.w / 2) / scale, cy = pdfH - (it.y + it.h / 2) / scale\n return cx >= r.x1 && cx <= r.x2 && cy >= r.y1 && cy <= r.y2\n }\n const reads = hiRgba ? await closerReads(hiRgba, rw * 2, rh * 2, pdfH, scale * 2, regions, engine!) : []\n return regions.flatMap((r, k) => {\n let own = items.filter(it => inside(it, r))\n // 그림 속 글은 작다(차트 눈금·범례 6~8pt) — 영역만 두 배로 다시 읽어 글자 수로 가중한 평균 신뢰도가 높은 쪽을 쓴다\n const near = reads[k]\n if (near?.length && meanConfidence(near) > meanConfidence(own)) own = near\n if (!own.length) return []\n const blocks = ocrItemsToBlocks(own, pageNo, pdfW, pdfH, scale, ruling && rulingToPdfLines(ruling, scale, pdfH), detectTables, undefined, true)\n // 영역 안 세로 괘선이 둘 미만이면 그 영역의 OCR 표는 글 정렬만으로 묶은 것이다 — 그림 영역 병합이 표로 받지 않는다\n const x1 = r.x1 * scale - 2, x2 = r.x2 * scale + 2, y1 = (pdfH - r.y2) * scale - 2, y2 = (pdfH - r.y1) * scale + 2\n const columnRules = ruling?.verticals.filter(s => Math.min(s.x1, s.x2) >= x1 && Math.max(s.x1, s.x2) <= x2 && Math.min(s.y1, s.y2) >= y1 && Math.max(s.y1, s.y2) <= y2).length ?? 0\n if (columnRules < 2) for (const b of blocks) if (b.type === \"table\") UNRULED_REGION_TABLES.add(b)\n return blocks\n })\n }\n // 벡터 글자 쪽: 표 구조는 그 쪽의 실제 괘선으로 (rhwp cairo 13쌍 46표 exact: 래스터 괘선 14 → 실제 괘선 20)\n if (vectorOps) return ocrItemsToBlocks(items, pageNo, pdfW, pdfH, scale, undefined, detectTables, vectorOps)\n // 래스터에서 표 괘선 감지 — 스캔본 병합셀 서식도 선 기반 표 파이프라인을 탄다\n const extraLines = rulingToPdfLines(ruling!, scale, pdfH)\n return ocrItemsToBlocks(items, pageNo, pdfW, pdfH, scale, extraLines, detectTables)\n }\n\n // 사용자 프로바이더 — PNG 인코딩 후 호출, 페이지당 paragraph (종전 계약)\n type SharpPngFactory = (\n input: Uint8Array,\n opts: { raw: { width: number; height: number; channels: number } },\n ) => { png(): { toBuffer(): Promise<Buffer> } }\n const sharpModRaw = await tryImport<{ default?: SharpPngFactory } & SharpPngFactory>(\n \"sharp\",\n () => import(\"sharp\") as unknown as Promise<{ default?: SharpPngFactory } & SharpPngFactory>,\n )\n const sharpAny = sharpModRaw as { default?: SharpPngFactory } | SharpPngFactory\n const sharp: SharpPngFactory =\n typeof sharpAny === \"function\" ? sharpAny : (sharpAny.default ?? (sharpAny as unknown as SharpPngFactory))\n const png = await sharp(rgba, { raw: { width: rw, height: rh, channels: 4 } })\n .png()\n .toBuffer()\n\n const text = await mode(new Uint8Array(png), pageNo, \"image/png\")\n if (!text.trim()) {\n warnings.push({ page: pageNo, message: `페이지 ${pageNo} OCR 결과 없음`, code: \"OCR_FAILED\" })\n return []\n }\n return [{ type: \"paragraph\", text: text.trim(), pageNumber: pageNo }]\n}\n\n/** 2×2 평균 축소 (RGBA) */\nfunction halve(src: Uint8Array, w: number, h: number): { rgba: Uint8Array; width: number; height: number } {\n const W = w >> 1, H = h >> 1\n const out = new Uint8Array(W * H * 4)\n for (let y = 0; y < H; y++) for (let x = 0; x < W; x++) {\n const a = ((2 * y) * w + 2 * x) * 4, b = a + w * 4, o = (y * W + x) * 4\n for (let c = 0; c < 4; c++) out[o + c] = (src[a + c] + src[a + 4 + c] + src[b + c] + src[b + 4 + c] + 2) >> 2\n }\n return { rgba: out, width: W, height: H }\n}\n\n/** 그림 영역만 읽을 때 — 끝자락 지우기를 끈다 (engine OcrTuning.trimEdges 주석) */\nconst REGION_TUNING: Readonly<OcrTuning> = Object.freeze({ ...DEFAULT_OCR_TUNING, trimEdges: false })\n\nfunction meanConfidence(items: OcrItem[]): number {\n let n = 0, sum = 0\n for (const it of items) { const len = [...it.text].length; n += len; sum += it.confidence * len }\n return n ? sum / n : 0\n}\n\n/** 그림 영역마다 두 배 래스터에서 잘라 다시 인식한 글줄 — 좌표는 쪽 배율 래스터 기준으로 되돌린다 */\nasync function closerReads(\n rgba: Uint8Array, rw: number, rh: number, pdfH: number, hi: number,\n regions: Array<{ x1: number; y1: number; x2: number; y2: number }>,\n engine: NonNullable<Awaited<ReturnType<typeof getOcrEngine>>>,\n): Promise<Array<OcrItem[] | null>> {\n const out: Array<OcrItem[] | null> = []\n for (const r of regions) {\n const x0 = Math.max(0, Math.floor(r.x1 * hi)), y0 = Math.max(0, Math.floor((pdfH - r.y2) * hi))\n const cw = Math.min(rw, Math.ceil(r.x2 * hi)) - x0, ch = Math.min(rh, Math.ceil((pdfH - r.y1) * hi)) - y0\n if (cw < 16 || ch < 16) { out.push(null); continue }\n const crop = new Uint8Array(cw * ch * 4)\n for (let y = 0; y < ch; y++) crop.set(rgba.subarray(((y0 + y) * rw + x0) * 4, ((y0 + y) * rw + x0 + cw) * 4), y * cw * 4)\n const items = await engine.recognizePage(crop, cw, ch, undefined, REGION_TUNING)\n out.push(items.map(it => ({ ...it, x: (it.x + x0) / 2, y: (it.y + y0) / 2, w: it.w / 2, h: it.h / 2 })))\n }\n return out\n}\n\n/**\n * OcrItem(렌더 픽셀, top-left origin) → NormItem(PDF pt, bottom-up baseline)\n * 으로 환산해 기존 블록 파이프라인에 태운다. 괘선은 래스터 감지 결과(extraLines)로\n * 공급 — 없으면 클러스터 감지기 몫이다. 벡터 글자 쪽은 그 쪽 그래픽 연산자 목록(opList)을\n * 넘겨 실제 괘선을 쓴다.\n * (이미지 직접 입력 경로 image-ocr.ts 와 공유)\n */\n/**\n * OCR 박스를 줄로 묶는다(박스 번호 묶음). 같은 줄 조각도 글자 크기(큰 대표 줄)·숫자 하강부·기울어진 감열지 때문에 박스 아래 끝이\n * 몇 pt 씩 어긋나, 박스마다 아래 끝을 기준선으로 넘기면 블록 파이프라인의 줄 묶음(3pt)이 한 줄을 여럿으로 쪼개고 위쪽 y 순으로\n * 뒤집는다(#141 영수증: \"탄현점 / 이마트\", 품목 바코드·단가·금액이 다른 행). 중심 y 차이 ≤ 작은 박스 높이의 절반이면 한 줄,\n * 가로로 크게 겹치는 박스는 같은 줄에 넣지 않는다(큰 로고 박스가 위아래 두 줄을 잇지 않게).\n * 한 줄 조각은 높이가 엇비슷하다 — 줄 높이 중앙값과 두 배 넘게 다른 박스는 인식 신뢰도 0.8 미만 박스(아이콘·로고·QR 잡음)가 낄 때\n * 묶지 않는다. 높이는 줄 높이 중앙값과 잰다(줄의 작은 숫자 박스 하나와 재면 두 행에 걸친 칸 박스가 제 행을 놓친다, changwon-plan2026\n * \"3/8\"). 신뢰도가 높으면 높이 차가 커도 같은 줄 — 기울어진 스캔의 긴 글줄 박스는 기울기만큼 키가 크고 체크 표 \"√\" 옆 라벨·두 줄이 한\n * 박스로 붙은 칸도 2~2.7배다(열화 서식 OCR 다섯 쪽 CER 상승). 그림 영역에서는 높이의 8배 넘게 떨어진 조각은 세로 중심이 작은 박스\n * 높이의 0.35 안일 때만 같은 줄(차트 범례와 먼 축 눈금 — 쪽 전체 OCR 의 서식 먼 칸은 쪽이 기운 만큼 어긋난다). 긴 글줄(폭이 높이의\n * 7배 이상 — 서식 라벨 \"주민등록번호\" 6배는 아니다, 숫자가 30% 넘는 금액 칸도 아니다 — 예산 표 행의 항목명과 \"경정4,200,000원\")은 줄 안\n * 가장 가까운 긴 글줄과 높이의 5배 넘게 떨어지면 묶지 않는다(범례 라벨 사이 3~4배는 한 줄). 짧은 조각(숫자·라벨 칸)은 멀어도 묶는다\n * (영수증 금액 칸).\n * 두 단 글의 좌우 줄은 높이가 엇비슷해도 다른 줄이다(ODL 141 두 단 카드 인포그래픽: 좌우 카드 줄 틈 7~60배 — 4.21.3 에서 한 줄로\n * 묶여 단 분리가 깨지고 가짜 표가 됐다, NID 0.96 → 0.44).\n */\n/** 긴 글줄 상자 — 폭이 높이의 7배 이상이고 숫자가 글자의 30% 미만(금액 칸 \"경정4,200,000원\"·\"210mm×297mm\" 은 표 칸이다) */\nconst proseBox = (b: OcrItem) => {\n const t = b.text.replace(/\\s/g, \"\")\n return b.w >= b.h * 7 && (t.match(/\\d/g)?.length ?? 0) < t.length * 0.3\n}\n\nexport function groupOcrLines(items: OcrItem[], figureRegion = false): number[][] {\n const order = items.map((_, i) => i).sort((a, b) => (items[a].y + items[a].h / 2) - (items[b].y + items[b].h / 2))\n const accepts = (l: number[], i: number): boolean => {\n const it = items[i], c = it.y + it.h / 2\n const lc = l.reduce((s, j) => s + items[j].y + items[j].h / 2, 0) / l.length\n const minH = Math.min(it.h, ...l.map(j => items[j].h))\n if (Math.abs(c - lc) > minH / 2) return false\n const hs = l.map(j => items[j].h).sort((a, b) => a - b), med = hs[hs.length >> 1]\n const weak = it.confidence < 0.8 || l.some(j => items[j].confidence < 0.8)\n if (weak && Math.max(it.h, med) > Math.min(it.h, med) * 2) return false\n let nearLong = 0, gap = Infinity\n for (const j of l) {\n const o = items[j]\n // 박스는 잉크 외곽에 여백이 붙어 이웃 낱말과 조금 겹친다(이마트·탄현점 32px) — 좁은 쪽 폭의 절반 넘게 겹칠 때만 다른 줄\n const ov = Math.min(it.x + it.w, o.x + o.w) - Math.max(it.x, o.x)\n if (ov >= Math.min(it.w, o.w) / 2) return false\n gap = Math.min(gap, Math.max(0, -ov))\n if (proseBox(it) && proseBox(o)) nearLong = Math.min(nearLong || Infinity, Math.max(0, -ov) / Math.min(it.h, o.h))\n }\n // 그림 영역에서 높이의 8배 넘게 떨어진 조각은 세로로 거의 같은 줄이어야 한다 — 영수증 먼 칸은 중심 어긋남이 작은 박스 높이의 0.22 안, 원그래프\n // 값과 범례(ODL 148 \"18.9%\"·\"Project Manager\")는 0.31, 차트 범례 라벨과 멀리 왼쪽 축 눈금은 0.37~0.47 이라 반쯤 어긋난 채 묶여\n // 기준선이 옮겨지고 읽기 순서가 바뀌었다(ODL 128·140·057)\n if (figureRegion && gap > 8 * minH && Math.abs(c - lc) > minH * 0.35) return false\n // 긴 글줄은 줄 안 가장 가까운 긴 글줄과 높이의 5배 안이어야 한다 — 사이에 짧은 상자(카드 번호)가 끼어도 다리가 되지 않는다\n return nearLong <= 5\n }\n const lines: number[][] = []\n for (const i of order) {\n const line = lines.find(l => accepts(l, i))\n if (line) line.push(i)\n else lines.push([i])\n }\n // 홀로 남은 박스는 줄이 다 선 뒤 한 번 더 넣어 본다 — 먼저 만난 줄에 먼 긴 글줄만 있어 갈린 범례 라벨(ODL 059 \"Construction | Waste\")\n for (let k = 0; k < lines.length; k++) {\n if (lines[k].length !== 1) continue\n const i = lines[k][0]\n const target = lines.find((l, m) => m !== k && l.length > 0 && accepts(l, i))\n if (target) { target.push(i); lines[k] = [] }\n }\n return lines.filter(l => l.length > 0)\n}\n\nexport function ocrItemsToBlocks(\n items: OcrItem[],\n pageNumber: number,\n pdfW: number,\n pdfH: number,\n scale: number,\n extraLines?: { horizontals: LineSegment[]; verticals: LineSegment[] },\n detectTables = true,\n opList: PageOps = { fnArray: [], argsArray: [] },\n figureRegion = false,\n): IRBlock[] {\n // 줄마다 아래 끝을 중앙값으로 맞추고, 겹친 이웃 박스는 겹친 구간 가운데서 갈라 낱말 경계(따로 검출된 상자)를 공백으로 남긴다\n const bottoms = items.map(it => it.y + it.h)\n const xs = items.map(it => ({ x: it.x, r: it.x + it.w, space: false }))\n for (const line of groupOcrLines(items, figureRegion)) {\n if (line.length < 2) continue\n const sorted = line.map(j => items[j].y + items[j].h).sort((a, b) => a - b)\n for (const j of line) bottoms[j] = sorted[Math.floor(sorted.length / 2)]\n const byX = [...line].sort((a, b) => items[a].x - items[b].x)\n for (let k = 1; k < byX.length; k++) {\n const L = xs[byX[k - 1]], R = xs[byX[k]]\n if (R.x >= L.r) continue\n const mid = (R.x + L.r) / 2, half = Math.min(items[byX[k - 1]].h, items[byX[k]].h) * 0.15\n L.r = Math.max(L.x + 1, mid - half)\n R.x = Math.min(R.r - 1, mid + half)\n R.space = true\n }\n }\n const norm: NormItem[] = items.map((it, i) => {\n // 그림 영역은 기준선을 줄 중앙값으로 옮겨도 박스 위 끝은 그대로 — 높이째 옮기면 키 큰 칸 박스가 윗행 칸과 더 겹쳐 그 칸에 붙었다(ODL 110\n // 그림 속 표 \"14\"·\"15\" → \"1415\"). 쪽 전체 OCR 은 높이째 옮긴다 — 위 끝을 지키자 스캔 쪽 셋의 CER 이 올랐다(topik 1.50 → 1.88%).\n // 글자 크기는 원래 박스 높이로 잰다\n const h = (figureRegion ? Math.max(1, bottoms[i] - it.y) : it.h) / scale\n return {\n text: it.text,\n x: Math.round(xs[i].x / scale),\n // NormItem.y 는 pdfjs transform[5] = 베이스라인 (bottom-up) — 잉크 하단으로 근사\n y: Math.round(pdfH - bottoms[i] / scale),\n w: Math.round((xs[i].r - xs[i].x) / scale),\n h: Math.round(h),\n // 박스는 잉크 외곽(engine tightBoxes) — 한글 줄 잉크 높이 ≈ 0.9em\n fontSize: Math.max(1, Math.round(it.h / scale / 0.9)),\n fontName: \"ocr\",\n isHidden: false,\n ...(xs[i].space ? { hasSpaceBefore: true } : {}),\n }\n })\n return extractPageBlocksWithLines(norm, pageNumber, opList, pdfW, pdfH, extraLines, detectTables)\n}\n\nasync function tryImport<T>(name: string, loader: () => Promise<T>): Promise<T> {\n try {\n return await loader()\n } catch (e) {\n throw new Error(\n `OCR 을 사용하려면 optional dependency '${name}' 이 필요합니다. ` +\n `\\`npm install ${name}\\` 후 다시 실행하세요.${OPTIONAL_DEP_INSTALL_HINT} 원인: ${(e as Error).message}`,\n )\n }\n}\n\nasync function withTimeout<T>(promise: Promise<T>, ms: number, msg: string): Promise<T> {\n // 타임아웃 패배 후 원 promise 의 사후 reject 가 unhandled rejection 이 되지 않게 흡수\n promise.catch(() => {})\n let timer: NodeJS.Timeout | undefined\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(msg)), ms)\n }),\n ])\n } finally {\n if (timer) clearTimeout(timer)\n }\n}\n\n/** pdfium BGRA → RGBA */\nfunction bgraToRgba(bgra: Uint8Array): Uint8Array {\n const out = new Uint8Array(bgra.length)\n for (let i = 0; i < bgra.length; i += 4) {\n out[i] = bgra[i + 2]\n out[i + 1] = bgra[i + 1]\n out[i + 2] = bgra[i]\n out[i + 3] = bgra[i + 3]\n }\n return out\n}\n"]}
1
+ {"version":3,"sources":["/Users/mong-e/workspace/kordoc/dist/chunk-EGYLKSA4.cjs","../src/ocr/ruling-lines.ts","../src/ocr/engine.ts","../src/ocr/line-split.ts","../src/ocr/glyph-restore.ts","../src/ocr/postprocess.ts","../src/ocr/crop.ts","../src/ocr/deskew.ts","../src/ocr/pdf-ocr.ts"],"names":["median","gaps","c","n","mx","stars","ring","prev","join"],"mappings":"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","file":"/Users/mong-e/workspace/kordoc/dist/chunk-EGYLKSA4.cjs","sourcesContent":[null,"/**\n * 래스터 괘선 감지 — 스캔/이미지 페이지의 픽셀에서 표 괘선(수평/수직 선)을\n * 찾아 선 기반 표 파이프라인(line-detector → table-grid)에 공급한다.\n *\n * PDF 그래픽 ops 가 없는 OCR 경로는 종전에 클러스터 감지기만 탔는데,\n * 병합 라벨 셀 + 다중줄 서술형 서식(정부 제출 서식류)은 라인 클러스터로\n * 행 경계를 잡을 수 없다. 괘선은 이미지에 실존하므로 이진화 + 런렝스로\n * 직접 감지한다 — ML 없음, 축 정렬 전제(스캔 스큐 보정은 스코프 밖).\n *\n * 오탐 방어 3겹 (실측: 우수사례 제출 서식 스캔 — 진짜 괘선은 길고 얇음):\n * - 최소 길이 20pt: 글리프 획(가로 ≤한 글자폭·세로 ≤글자높이)은 걸러짐\n * - 두께 상한 2.5pt: 굵은 제목 획(6~13px)·텍스트 줄 밴드·채운 색상바 탈락\n * - 양측 잉크 포위 제외: 색상바(붙임 박스 등) 안 흰 글자 틈새 슬리버 탈락\n *\n * 텍스트층 경로가 선으로 받는 것 중 잉크 런렝스로 안 보이는 두 가지도 선으로 낸다 — 점선 괘선(DOT_*),\n * 채움 사각형의 변(FILL_*). 둘 다 표 괘선에 맞물린 것만.\n */\n\nimport type { LineSegment } from \"../pdf/line-types.js\"\n\n/**\n * 잉크 판정 휘도 상한 — 셀 배경 음영(회색 ~220)은 통과, 실선(진회~검정·남색)만 잉크. 0.12mm 가는 괘선이 픽셀 경계에\n * 걸려 두 픽셀로 번지면 픽셀마다 192~207 이라 190 에선 놓쳤다(ice-geomjeong 시험일정표 \"구분│일자\" 세로선, ktdb 목록표)\n */\nconst INK_LUMA_MAX = 205\n/** 최소 선 길이 (pt) — 최소 셀 변(≈7mm)과 대형 글리프 획(≤1em) 사이 */\nconst MIN_LINE_LENGTH_PT = 20\n/** 선 두께 상한 (pt) — 진짜 괘선(0.12~0.7mm ≈ 0.3~2pt)과 굵은 글리프 획(2pt+) 분리 */\nconst MAX_LINE_WIDTH_PT = 2.5\n/** 런 내 허용 끊김 (px) — 스캔 노이즈/JPEG 아티팩트 */\nconst GAP_TOL_PX = 2\n/** 밴드 병합 시 요구하는 x(또는 y) 범위 겹침 비율 (짧은 쪽 기준) */\nconst BAND_OVERLAP_RATIO = 0.5\n/** 밴드 양측(±2px)이 이 비율 이상 잉크면 채운 영역 내부 슬리버로 판정 */\nconst SURROUND_INK_RATIO = 0.35\n/**\n * 점선·파선 괘선. 텍스트층 경로(line-extract.ts)는 대시 패턴을 보지 않고 경로 기하만 읽어 점선 괘선도\n * 실선으로 받는데, 래스터에선 점 사이 간격(216dpi 에서 2~4px)이 GAP_TOL_PX 를 넘어 선이 조각난다 —\n * 점선으로 행을 가른 표가 OCR 경로에서만 한 행으로 뭉쳤다(changwon-plan2026 p5 정원표 22행 → 2행,\n * ice-geomjeong-plan p3 세로 점선 표 → 열 없는 한 칸). 점 사이 간격 상한 1.3pt 안에서 짧은 점(대시 4pt 이하)이\n * 8개+ 이어지면 점선 후보. 목차 리더 점(\"······\")도 같은 모양이라 주기로 가른다 — 코퍼스 실측 괘선 점선 주기\n * 0.8~2.0pt(점 ≈ 간격), 리더 2.5~3.3pt(간격 ≈ 점 × 2). 대시가 간격보다 확연히 긴(1.5배+) 파선은 주기 무관.\n * 마지막으로 수직 방향 괘선(실선·점선)과 닿는 것만 남긴다 — 리더는 글자 사이에 떠 있고 괘선은 표·상자 테두리에 물린다.\n */\nconst DOT_MAX_GAP_PT = 1.3\nconst DOT_MAX_DASH_PT = 4\nconst DOT_MAX_PERIOD_PT = 2.2\nconst DOT_MIN_COUNT = 8\n/** 점선 후보가 수직 괘선에 닿았다고 보는 거리 (pt) */\nconst DOT_TOUCH_PT = 1.5\n/**\n * 채움 경계. 텍스트층 경로는 순수 채움 경로(머리 행 음영·색 칸의 사각형)의 변도 선으로 받는다(line-extract.ts\n * flushPath → classifyAndAdd). 잉크 감지(휘도 ≤ 190)는 연한 채움과 흰 바탕의 경계를 못 봐, 머리 행에만 좌우 변이\n * 있는 개방 변 표 두 개를 가상 테두리가 한 격자로 용접했고(ice-election-cases p5 8×3·10×3 → 19×5, seoul-archives p3,\n * ice-geomjeong p3), 흰 틈으로 칸을 가른 색 머리 행이 한 칸으로 뭉쳤다(cbe-record-guide). 쪽 바탕(휘도 최빈값)보다\n * FILL_DELTA 이상 어두운 곳이 안쪽으로 FILL_MIN_DEPTH_PT 이상 이어지는 바깥 경계 픽셀 런을 선으로 낸다 — 괘선(≤ 2.5pt)과\n * 글자 획은 그보다 얇다. 바탕을 흰색으로 못박으면 크림색 바탕 쪽 전체가 채움이 되어 본문이 통째로 표가 됐다\n * (pen-cyberbridge p2 바탕 휘도 242). 경계 안쪽 휘도가 고르지 않은 것(사진·그림·배경 도안)은 채움이 아니다.\n */\nconst FILL_DELTA = 10\n/** 채움 경계 최소 길이 (pt) — 색 머리 행 높이(15~18pt)의 칸 틈도 잡게 괘선(20pt)보다 짧게. 글자 획은 두께 조건이 막는다 */\nconst FILL_MIN_LENGTH_PT = 10\nconst FILL_MIN_DEPTH_PT = 4\nconst FILL_FLAT_TOL = 12\nconst FILL_FLAT_RATIO = 0.8\n\n/** 픽셀 공간(top-left origin) 선분 — 두께는 밴드 픽셀 수 */\nexport interface PxSegment {\n x1: number; y1: number\n x2: number; y2: number\n thicknessPx: number\n}\n\nexport interface RulingLines {\n /** Newly recovered faint column rules, used to split OCR boxes before recognition. */\n cellDividers?: PxSegment[]\n horizontals: PxSegment[]\n verticals: PxSegment[]\n}\n\n/**\n * RGBA 래스터에서 수평/수직 괘선 감지.\n * @param scale 렌더 스케일 (px/pt) — 길이·두께 임계를 pt 기준으로 환산\n */\nexport function detectRulingLines(\n rgba: Uint8Array,\n width: number,\n height: number,\n scale: number,\n): RulingLines {\n const minLenPx = Math.round(MIN_LINE_LENGTH_PT * scale)\n const maxThickPx = Math.max(1, Math.floor(MAX_LINE_WIDTH_PT * scale))\n\n // 잉크 마스크 1회 구축 — 수평/수직 두 패스가 공유\n const ink = new Uint8Array(width * height)\n // 휘도는 채움 경계(fillEdges)도 쓴다 — 한 번만 계산\n const luma = new Uint8Array(width * height)\n for (let p = 0, i = 0; p < ink.length; p++, i += 4) {\n // ITU-R BT.601 휘도 근사 (정수 시프트)\n const l = (rgba[i] * 77 + rgba[i + 1] * 150 + rgba[i + 2] * 29) >> 8\n luma[p] = l\n if (l <= INK_LUMA_MAX && rgba[i + 3] >= 128) ink[p] = 1\n }\n\n const solid: RunReader = (m, base, step, span) => solidRuns(m, base, step, span, minLenPx)\n const dot = {\n maxGap: Math.max(2, Math.round(DOT_MAX_GAP_PT * scale)),\n maxDash: Math.max(2, Math.round(DOT_MAX_DASH_PT * scale)),\n maxPeriod: DOT_MAX_PERIOD_PT * scale,\n }\n const dotted: RunReader = (m, base, step, span) => dottedRuns(m, base, step, span, minLenPx, dot.maxGap, dot.maxDash, dot.maxPeriod)\n const horizontals = detectBands(ink, width, height, maxThickPx, false, solid)\n const verticals = detectBands(ink, width, height, maxThickPx, true, solid)\n const dotH = detectBands(ink, width, height, maxThickPx, false, dotted)\n const dotV = detectBands(ink, width, height, maxThickPx, true, dotted)\n const tol = Math.max(2, Math.round(DOT_TOUCH_PT * scale))\n const allH = [...horizontals, ...dotH], allV = [...verticals, ...dotV]\n // 가로 a 가 세로 선(p.x1 = p.x2)과 만나거나 끝이 닿는지 (세로 a 는 축을 바꿔 같은 판정)\n const touchesV = (a: PxSegment) => allV.some(p => p.x1 >= a.x1 - tol && p.x1 <= a.x2 + tol && a.y1 >= p.y1 - tol && a.y1 <= p.y2 + tol)\n const touchesH = (a: PxSegment) => allH.some(p => p.y1 >= a.y1 - tol && p.y1 <= a.y2 + tol && a.x1 >= p.x1 - tol && a.x1 <= p.x2 + tol)\n horizontals.push(...dotH.filter(touchesV))\n verticals.push(...dotV.filter(touchesH))\n // 채움 경계는 표 괘선에 맞물린 것만 쓴다 — 머리 행 음영의 윗변·아랫변은 표 가로 괘선(세로 괘선과 만나는 것)과 폭(양 끝)이\n // 같고, 좌우 변은 그 가로선 끝점에, 칸 사이 흰 틈은 바로 위아래 본문 세로 괘선과 같은 x 에 선다. 칸 안에 놓인 단색\n // 로고·그림의 변은 어느 쪽도 아니다(kmcc-press 참여 기업 표: 로고 칸이 행·열을 쪼갰다 — 로고 밑줄은 잉크 선으로 잡히지만\n // 세로 괘선과 만나지 않는다)\n const inkV = [...verticals]\n const ruleH = horizontals.filter(p => inkV.some(v => v.x1 >= p.x1 - tol && v.x1 <= p.x2 + tol && p.y1 >= v.y1 - tol && p.y1 <= v.y2 + tol))\n const fill = fillEdges(luma, width, height, scale)\n const fillH = fill.horizontals.filter(a => ruleH.some(p => Math.abs(p.x1 - a.x1) <= tol && Math.abs(p.x2 - a.x2) <= tol))\n horizontals.push(...fillH)\n const edgeH = [...ruleH, ...fillH]\n verticals.push(...fill.verticals.filter(a =>\n inkV.some(p => Math.abs(p.x1 - a.x1) <= tol && p.y1 <= a.y2 + tol && p.y2 >= a.y1 - tol) ||\n edgeH.some(p => (Math.abs(p.x1 - a.x1) <= tol || Math.abs(p.x2 - a.x1) <= tol) && p.y1 >= a.y1 - tol && p.y1 <= a.y2 + tol)))\n // Faint internal rules are evidence only when enclosed by an existing dark\n // frame and repeated across both axes. Do not brighten the whole page's grid.\n const cellDividers: PxSegment[] = []\n const frames: Array<{ x1: number; x2: number; y1: number; y2: number }> = []\n for (let i = 0; i < horizontals.length && frames.length < 32; i++) {\n const a = horizontals[i]\n for (let j = i + 1; j < horizontals.length && frames.length < 32; j++) {\n const b = horizontals[j]\n if (Math.abs(a.x1 - b.x1) > tol || Math.abs(a.x2 - b.x2) > tol) continue\n const y1 = Math.min(a.y1, b.y1), y2 = Math.max(a.y1, b.y1)\n if (a.x2 - a.x1 < minLenPx * 3 || y2 - y1 < minLenPx * 2) continue\n if (![a.x1, a.x2].every(x => verticals.some(v => Math.abs(v.x1 - x) <= tol && v.y1 <= y1 + tol && v.y2 >= y2 - tol))) continue\n frames.push({ x1: a.x1, x2: a.x2, y1, y2 })\n }\n }\n if (frames.length) {\n const faint = new Uint8Array(ink.length)\n for (let p = 0; p < faint.length; p++) if (luma[p] <= 240 && rgba[p * 4 + 3] >= 128) faint[p] = 1\n const hs = detectBands(faint, width, height, maxThickPx, false, solid)\n const vs = detectBands(faint, width, height, maxThickPx, true, solid)\n for (const f of frames) {\n const innerH = hs.filter(h => h.y1 > f.y1 + tol && h.y1 < f.y2 - tol && Math.abs(h.x1 - f.x1) <= tol && Math.abs(h.x2 - f.x2) <= tol)\n const innerV = vs.filter(v => v.x1 > f.x1 + tol && v.x1 < f.x2 - tol && Math.abs(v.y1 - f.y1) <= tol && Math.abs(v.y2 - f.y2) <= tol)\n if (innerH.length < 3 || innerV.length < 1) continue\n for (const h of innerH) if (!horizontals.some(p => Math.abs(p.y1 - h.y1) <= tol && p.x1 <= h.x1 + tol && p.x2 >= h.x2 - tol)) horizontals.push(h)\n for (const v of innerV) if (!verticals.some(p => Math.abs(p.x1 - v.x1) <= tol && p.y1 <= v.y1 + tol && p.y2 >= v.y2 - tol)) { verticals.push(v); cellDividers.push(v) }\n }\n }\n return { horizontals, verticals, ...(cellDividers.length ? { cellDividers } : {}) }\n}\n\n/**\n * 채움 영역의 바깥 경계 선 (FILL_* 주석). 채움 경계는 칸 크기 단위라 해상도가 필요 없어 k×k(≈1pt) 블록으로 줄여 본다 —\n * 블록 휘도는 가장 밝은 픽셀(칸 사이 1~3px 흰 틈이 채움에 묻히지 않게). 방향마다 안쪽 연속 채움 길이를 한 번 누적해\n * 경계 마스크를 만들고, 찾은 선은 원래 픽셀 좌표로 되돌린다\n */\nfunction fillEdges(pageLuma: Uint8Array, width: number, height: number, scale: number): RulingLines {\n const k = Math.max(1, Math.round(scale))\n const w = Math.floor(width / k), h = Math.floor(height / k), n = w * h\n const luma = new Uint8Array(n)\n const hist = new Uint32Array(256)\n for (let y = 0; y < h; y++) {\n for (let x = 0; x < w; x++) {\n let mx = 0\n for (let by = 0; by < k; by++) {\n let i = (y * k + by) * width + x * k\n for (let bx = 0; bx < k; bx++, i++) if (pageLuma[i] > mx) mx = pageLuma[i]\n }\n luma[y * w + x] = mx\n hist[mx]++\n }\n }\n let bg = 255\n for (let v = 0; v < 256; v++) if (hist[v] > hist[bg]) bg = v\n const tint = new Uint8Array(n)\n for (let p = 0; p < n; p++) if (luma[p] < bg - FILL_DELTA) tint[p] = 1\n const depth = Math.max(2, Math.round(FILL_MIN_DEPTH_PT * scale / k))\n const minLen = Math.round(FILL_MIN_LENGTH_PT * scale / k)\n const solid: RunReader = (m, base, step, span) => solidRuns(m, base, step, span, minLen)\n const run = new Uint16Array(n)\n const mask = new Uint8Array(n)\n const out: RulingLines = { horizontals: [], verticals: [] }\n // dx,dy = 채움 안쪽 방향. 위 변(0,1)·아래 변(0,-1)·왼 변(1,0)·오른 변(-1,0)\n for (const [dx, dy] of [[0, 1], [0, -1], [1, 0], [-1, 0]] as const) {\n // run[p] = p 에서 안쪽 방향으로 이어지는 채움 길이 (안쪽 끝부터 거꾸로 누적)\n const step = dy * w + dx\n const ys = dy > 0 ? [h - 1, -1, -1] : [0, h, 1]\n const xs = dx > 0 ? [w - 1, -1, -1] : [0, w, 1]\n for (let y = ys[0]; y !== ys[1]; y += ys[2]) {\n for (let x = xs[0]; x !== xs[1]; x += xs[2]) {\n const p = y * w + x\n const nx = x + dx, ny = y + dy\n run[p] = tint[p] ? (nx >= 0 && nx < w && ny >= 0 && ny < h ? Math.min(65535, run[p + step] + 1) : 1) : 0\n }\n }\n mask.fill(0)\n for (let y = 0; y < h; y++) {\n for (let x = 0; x < w; x++) {\n const p = y * w + x\n if (run[p] < depth) continue\n const ox = x - dx, oy = y - dy // 바깥 이웃\n if (ox < 0 || oy < 0 || ox >= w || oy >= h || !tint[p - step]) mask[p] = 1\n }\n }\n const vertical = dx !== 0\n const flat = (s: PxSegment) => {\n // 경계 안쪽 depth/2 지점의 휘도가 고른지 — 사진·도안 탈락\n const d = depth >> 1\n const vals: number[] = []\n if (vertical) {\n const x = Math.round(s.x1) + dx * d\n for (let y = Math.round(s.y1); y <= s.y2; y++) if (x >= 0 && x < w) vals.push(luma[y * w + x])\n } else {\n const y = Math.round(s.y1) + dy * d\n for (let x = Math.round(s.x1); x <= s.x2; x++) if (y >= 0 && y < h) vals.push(luma[y * w + x])\n }\n if (!vals.length) return false\n const med = [...vals].sort((a, b) => a - b)[vals.length >> 1]\n return vals.filter(v => Math.abs(v - med) <= FILL_FLAT_TOL).length >= vals.length * FILL_FLAT_RATIO\n }\n for (const s of detectBands(mask, w, h, 1, vertical, solid)) {\n if (!flat(s)) continue\n const c = (v: number) => v * k + (k - 1) / 2\n ;(vertical ? out.verticals : out.horizontals).push({ x1: c(s.x1), y1: c(s.y1), x2: c(s.x2), y2: c(s.y2), thicknessPx: 1 })\n }\n }\n return out\n}\n\n/**\n * 스캔라인 하나의 런 판독 — 마스크의 base + pos·step 픽셀(pos = 0..span-1). 가로 스캔은 step 1, 세로 스캔은 step = 쪽 폭.\n * 픽셀마다 접근 함수를 부르던 종전 모양은 괘선 감지 시간의 40% 가 그 호출이었다(쪽당 4패스 × 450만 픽셀)\n */\ntype RunReader = (mask: Uint8Array, base: number, step: number, span: number) => Array<{ lo: number; hi: number }>\n\n/** 스캔라인 하나의 실선 런 (GAP_TOL_PX 이하 끊김 허용, 최소 길이 이상) */\nfunction solidRuns(mask: Uint8Array, base: number, step: number, span: number, minLenPx: number): Array<{ lo: number; hi: number }> {\n const runs: Array<{ lo: number; hi: number }> = []\n let runStart = -1\n let gap = 0\n for (let pos = 0; pos <= span; pos++) {\n const on = pos < span && mask[base + pos * step] === 1\n if (on) {\n if (runStart < 0) runStart = pos\n gap = 0\n } else if (runStart >= 0) {\n if (++gap > GAP_TOL_PX || pos >= span) {\n const hi = pos - gap\n if (hi - runStart + 1 >= minLenPx) runs.push({ lo: runStart, hi })\n runStart = -1\n gap = 0\n }\n }\n }\n return runs\n}\n\n/** 스캔라인 하나의 점선 런 — 짧은 잉크 조각(≤ maxDash)이 간격 ≤ maxGap 으로 DOT_MIN_COUNT 개+ 이어진 사슬 (DOT_* 주석) */\nfunction dottedRuns(\n mask: Uint8Array,\n base: number,\n step: number,\n span: number,\n minLenPx: number,\n maxGap: number,\n maxDash: number,\n maxPeriod: number,\n): Array<{ lo: number; hi: number }> {\n const runs: Array<{ lo: number; hi: number }> = []\n // 사슬 조각의 [lo, hi] — 사슬이 끊길 때만 통계를 본다 (대부분 스캔라인은 사슬이 없다)\n const chain: number[] = []\n const median = (xs: number[]) => xs.sort((a, b) => a - b)[xs.length >> 1]\n const flush = () => {\n const cnt = chain.length >> 1\n if (cnt >= DOT_MIN_COUNT && chain[chain.length - 1] - chain[0] + 1 >= minLenPx) {\n const periods: number[] = [], dashes: number[] = [], gaps: number[] = []\n for (let k = 0; k < cnt; k++) {\n dashes.push(chain[2 * k + 1] - chain[2 * k] + 1)\n if (k) { periods.push(chain[2 * k] - chain[2 * k - 2]); gaps.push(chain[2 * k] - chain[2 * k - 1] - 1) }\n }\n if (median(periods) <= maxPeriod || median(dashes) >= 1.5 * median(gaps)) runs.push({ lo: chain[0], hi: chain[chain.length - 1] })\n }\n chain.length = 0\n }\n let s = -1\n for (let pos = 0; pos <= span; pos++) {\n const on = pos < span && mask[base + pos * step] === 1\n if (on) { if (s < 0) s = pos; continue }\n if (s < 0) continue\n const lo = s, hi = pos - 1\n s = -1\n if (hi - lo + 1 > maxDash) { flush(); continue }\n if (chain.length && lo - chain[chain.length - 1] - 1 > maxGap) flush()\n chain.push(lo, hi)\n }\n flush()\n return runs\n}\n\n/** 열린 밴드 — 인접 스캔라인의 런을 누적 */\ninterface Band {\n lo: number // 런 진행축 시작 (h: x1, v: y1)\n hi: number // 런 진행축 끝\n first: number // 직교축 시작 스캔라인 (h: yTop, v: xLeft)\n last: number // 직교축 마지막 스캔라인\n}\n\n/**\n * 스캔라인 런렝스 → 인접 라인 밴드 병합 → 두께 필터 → 선분 방출.\n * transpose=false 면 수평선(행 스캔), true 면 수직선(열 스캔).\n */\nfunction detectBands(\n ink: Uint8Array,\n width: number,\n height: number,\n maxThickPx: number,\n transpose: boolean,\n readRuns: RunReader,\n): PxSegment[] {\n const lines = transpose ? width : height // 스캔라인 개수 (직교축)\n const span = transpose ? height : width // 런 진행축 길이\n const step = transpose ? width : 1\n const baseOf = (line: number) => (transpose ? line : line * width)\n\n const out: PxSegment[] = []\n let open: Band[] = []\n\n /** 밴드 양측(±2px 스캔라인)의 잉크 비율 — 채운 색상바 안 흰 글자 틈새 슬리버 판별 */\n const surroundInkRatio = (b: Band, side: number): number => {\n if (side < 0 || side >= lines) return 0\n let dark = 0, total = 0\n const base = baseOf(side)\n for (let pos = b.lo; pos <= b.hi; pos += 3) {\n total++\n if (ink[base + pos * step] === 1) dark++\n }\n return total > 0 ? dark / total : 0\n }\n\n const emit = (b: Band) => {\n const thick = b.last - b.first + 1\n if (thick > maxThickPx) return // 색상바·텍스트 밴드\n if (\n surroundInkRatio(b, b.first - 2) >= SURROUND_INK_RATIO &&\n surroundInkRatio(b, b.last + 2) >= SURROUND_INK_RATIO\n ) return // 채운 영역 내부 슬리버\n const center = (b.first + b.last) / 2\n out.push(\n transpose\n ? { x1: center, y1: b.lo, x2: center, y2: b.hi, thicknessPx: thick }\n : { x1: b.lo, y1: center, x2: b.hi, y2: center, thicknessPx: thick },\n )\n }\n\n for (let line = 0; line < lines; line++) {\n // 1) 이 스캔라인의 런 (실선 또는 점선 사슬)\n const runs = readRuns(ink, baseOf(line), step, span)\n\n // 2) 열린 밴드와 병합 — 직전 스캔라인까지 이어졌고 범위가 겹치면 확장\n const next: Band[] = []\n const used = new Set<number>()\n for (const band of open) {\n if (band.last !== line - 1) { emit(band); continue } // 연속 끊김 → 확정\n let merged = false\n for (let r = 0; r < runs.length; r++) {\n if (used.has(r)) continue\n const run = runs[r]\n const overlap = Math.min(band.hi, run.hi) - Math.max(band.lo, run.lo) + 1\n const shorter = Math.min(band.hi - band.lo, run.hi - run.lo) + 1\n if (overlap >= shorter * BAND_OVERLAP_RATIO) {\n band.lo = Math.min(band.lo, run.lo)\n band.hi = Math.max(band.hi, run.hi)\n band.last = line\n next.push(band)\n used.add(r)\n merged = true\n break\n }\n }\n if (!merged) emit(band)\n }\n for (let r = 0; r < runs.length; r++) {\n if (!used.has(r)) next.push({ lo: runs[r].lo, hi: runs[r].hi, first: line, last: line })\n }\n open = next\n }\n for (const band of open) emit(band)\n return out\n}\n\n/**\n * 픽셀 선분 → PDF pt LineSegment (bottom-up, classifyAndAdd 규약:\n * 수평선 y1==y2·x1<x2, 수직선 x1==x2·y1<y2).\n */\nexport function rulingToPdfLines(\n ruling: RulingLines,\n scale: number,\n pdfHeight: number,\n): { horizontals: LineSegment[]; verticals: LineSegment[] } {\n const horizontals: LineSegment[] = ruling.horizontals.map(s => {\n const y = pdfHeight - (s.y1 + s.y2) / 2 / scale\n return {\n x1: Math.min(s.x1, s.x2) / scale,\n y1: y,\n x2: Math.max(s.x1, s.x2) / scale,\n y2: y,\n lineWidth: s.thicknessPx / scale,\n }\n })\n const verticals: LineSegment[] = ruling.verticals.map(s => {\n const x = (s.x1 + s.x2) / 2 / scale\n const yA = pdfHeight - Math.max(s.y1, s.y2) / scale\n const yB = pdfHeight - Math.min(s.y1, s.y2) / scale\n return { x1: x, y1: yA, x2: x, y2: yB, lineWidth: s.thicknessPx / scale }\n })\n return { horizontals, verticals }\n}\n","/**\n * 내장 텍스트 OCR 엔진 — PP-OCRv5 korean (det DBNet + rec SVTR/CTC) ONNX 추론.\n *\n * 파이프라인: 페이지 RGBA → det(선 검출) → 박스 픽셀 분석(대비·행 밴드) → 라인 crop\n * → rec 배치(CTC 인식) → 표기 후처리 → OcrItem[]\n * (좌표는 입력 픽셀 기준 top-left origin — 호출자가 PDF 좌표계로 변환).\n *\n * 전·후처리는 공식 inference.yml 스펙 그대로:\n * - det: BGR, 긴 변 960 리사이즈(32 배수), mean/std [0.485,0.456,0.406]/[0.229,0.224,0.225],\n * DBPostProcess thresh 0.3 / box_thresh 0.6 / unclip_ratio 1.5\n * - rec: BGR, 높이 48 고정 비율 리사이즈 + 우측 zero-pad(최소 폭 320), (x/255-0.5)/0.5,\n * CTC 디코드 (blank=0, 1..N=사전, N+1=공백), text_score 0.5.\n * 배치(recBatch>1)는 공식처럼 폭 비율로 정렬해 묶고 배치 최대 폭까지 zero-pad — 기본은 1\n * DB 후처리의 contour+minAreaRect 는 축정렬 connected-component bbox 로 근사\n * (공문서 스캔은 수평 텍스트가 지배적).\n *\n * 공식 파이프라인 밖의 보강 (근거는 bench/ocr-accuracy.mjs 코퍼스 실측, 각 모듈 주석):\n * - 키 큰 박스(세로로 쌓인 글자)는 행 밴드로 갈라 밴드마다 인식 (line-split.ts)\n * - 잉크 대비가 낮은 박스(배경 도안)는 인식하지 않음 — 환각 방지\n * - 사전 밖 공문서 기호(○ △)·둥근 따옴표·천 단위 숫자 공백 복원, 점류 조각 폐기 (postprocess.ts)\n * - 결과 좌표는 det 박스(unclip 여백) 대신 박스 안 잉크 외곽 — 텍스트층 아이템과 같은 기하\n *\n * 의존성(onnxruntime-node, sharp)은 optional — 미설치 시 create()가 명확한 에러.\n * 모델 미다운로드 시에도 즉시 실패 — 호출자가 ensureOcrModels() 먼저.\n */\n\nimport type { InferenceSession } from \"onnxruntime-node\"\nimport { readFile } from \"fs/promises\"\nimport { join } from \"path\"\nimport { OPTIONAL_DEP_INSTALL_HINT } from \"../utils.js\"\nimport {\n OCR_DET_MODEL,\n OCR_REC_MODEL,\n OCR_REC_DICT,\n getOcrModelsDir,\n parseCharacterDict,\n} from \"./models.js\"\nimport { edgeTrim, leadingBullet, tallInkCount, grayCrop, inkBounds, inkStats, leaderRuns, leadingTriangle, splitRowBands } from \"./line-split.js\"\nimport { restoreGlyphs } from \"./glyph-restore.js\"\nimport { isDotFragment, joinLeaderItems, restoreBulletItems, restoreSymbols } from \"./postprocess.js\"\nimport { bandBoxes, splitBoxAtCellRules, lineCrop, type Box, REC_HEIGHT } from \"./crop.js\"\nimport { disableOrtTelemetry } from \"./runtime-env.js\"\n\n/** OCR 인식 결과 한 줄 — 좌표는 입력 이미지 픽셀 (top-left origin, y down) */\nexport interface OcrItem {\n text: string\n x: number\n y: number\n w: number\n h: number\n /** CTC 평균 신뢰도 0~1 */\n confidence: number\n}\n\nexport interface OcrPageStats {\n droppedLowConf: number\n truncatedBoxes?: number\n}\n\n/**\n * 엔진 튜닝 — 기본값이 제품 동작. 벤치·실험만 덮어쓴다 (공개 API 아님).\n */\nexport interface OcrTuning {\n /** det 입력 긴 변 (공식 resize_long). 1920 보존 실험은 recall Δ median +0.04pp에\n * 속도 -25%로 기각 (2026-08-02) */\n detLongSide: number\n detThresh: number\n detBoxThresh: number\n detUnclip: number\n /** 인식 신뢰도 하한 (공식 drop_score) */\n textScore: number\n /** rec 배치 크기. 공식 rec_batch_num 은 6 이지만 onnxruntime CPU 에선 배치(최대 폭까지\n * zero-pad)가 오히려 느리다 — 코퍼스 16쪽 교대 실측 1: 0.57 · 4: 0.93 · 8: 0.87 s/page,\n * 정확도 차는 박스 내 CER 0.08pp (2026-09-23). 기본 1 */\n recBatch: number\n /** 키 큰 박스 행 밴드 분할 */\n splitTall: boolean\n /** 한 줄 박스에 걸린 이웃 줄 끝자락·상자 테두리를 지운 crop 도 인식 (line-split edgeTrim). 그림 영역만 읽을 때는 끈다 —\n * 쪽 배율·두 배 재인식 중 평균 신뢰도로 한쪽을 통째로 고르는데 지운 판이 한쪽 신뢰도만 올려 선택이 뒤집혔다(ODL 073) */\n trimEdges: boolean\n /** 이 대비(전경/배경 평균 휘도 차) 미만 박스는 글자가 아님 — 0 이면 끔 */\n minInkContrast: number\n /** 기호·따옴표 복원 + 점류 조각 폐기 */\n postprocess: boolean\n /** 결과 좌표를 det 박스(unclip 여백 포함) 대신 박스 안 잉크 외곽으로 */\n tightBoxes: boolean\n /** 목차 리더 점 무리를 빼고 앞뒤를 따로 인식 (line-split.ts leaderRuns) */\n splitLeaders: boolean\n}\n\nexport const DEFAULT_OCR_TUNING: Readonly<OcrTuning> = Object.freeze({\n detLongSide: 960,\n detThresh: 0.3,\n detBoxThresh: 0.6,\n detUnclip: 1.5,\n textScore: 0.5,\n recBatch: 1,\n splitTall: true,\n trimEdges: true,\n minInkContrast: 35,\n postprocess: true,\n tightBoxes: true,\n splitLeaders: true,\n})\n\nconst DET_MIN_SIZE = 3\nconst DET_MAX_BOXES = 3000\nconst REC_MIN_WIDTH = 320\n/** 배치 텐서 폭 합 상한 — 긴 줄 여러 개를 한 텐서로 묶어 메모리가 튀지 않게 */\nconst REC_BATCH_MAX_PIXELS = 48 * 16000\n/** 키 큰 박스 판정 (공식 파이프라인의 세로 판정 h/w ≥ 1.5 와 같은 문턱) */\nconst TALL_RATIO = 1.5\n/** 밴드로 갈라지지 않는 키 큰 박스 중 이 비율 이상은 90° 회전 글자 후보 */\nconst ROTATE_RATIO = 3\n/** 이웃 줄 끝자락을 지운 crop 이 원본 crop 을 이기려면 넘어야 할 신뢰도 차 (recognizePage 주석) */\nconst KEEP_MARGIN = 0.06\n/** 리더로 볼 최소 점 수 — 말줄임표 \"…\"(3점)보다 많이. 목차 쪽번호 박스가 무는 점은 코퍼스 실측 4~9개가 대부분 */\nconst LEADER_MIN_DOTS = 4\n/** 리더 앞 조각 crop 을 리더 안쪽으로 더 무는 폭 (박스 높이 배수, recognizePage 주석) */\nconst LEADER_CONTEXT = 0.5\n/** 박스 잉크 비율 하한 (engine recognizePage 주석) */\nconst MIN_INK_RATIO = 0.01\n\n// det: BGR 채널 순서에 yml 기재 순서 그대로 적용 (mean[0]→B)\nconst DET_MEAN = [0.485, 0.456, 0.406]\nconst DET_STD = [0.229, 0.224, 0.225]\n\ntype SharpFactory = (\n input: Uint8Array | Buffer,\n options?: { raw?: { width: number; height: number; channels: number } },\n) => SharpChain\ninterface SharpChain {\n resize(w: number, h: number, opts?: { fit?: string }): SharpChain\n removeAlpha(): SharpChain\n raw(): { toBuffer(): Promise<Buffer> }\n}\n\n/** 인식 대상 한 줄 — rot 는 crop 회전(90=반시계, 270=시계). join: 리더로 가른 박스 번호, dotsBefore: 앞에 리더가 있었는지,\n * trimDots: crop 이 뒤 리더 점을 물었는지(결과 끝 점을 지운다) */\n/** keep: 인식 crop 에서 남길 박스 로컬 구간 — 밖(이웃 줄 끝자락·상자 테두리)은 배경으로 칠한다 (edgeTrim) */\ninterface LineJob { box: Box; rot: 0 | 90 | 270; group: number; join?: number; dotsBefore?: boolean; trimDots?: boolean; keep?: { x0: number; x1: number; y0: number; y1: number; bg: number } }\n\nexport class OcrEngine {\n private det: InferenceSession\n private rec: InferenceSession\n private dict: string[]\n private ort: typeof import(\"onnxruntime-node\")\n private sharp: SharpFactory\n\n private constructor(parts: {\n det: InferenceSession\n rec: InferenceSession\n dict: string[]\n ort: typeof import(\"onnxruntime-node\")\n sharp: SharpFactory\n }) {\n this.det = parts.det\n this.rec = parts.rec\n this.dict = parts.dict\n this.ort = parts.ort\n this.sharp = parts.sharp\n }\n\n static async create(): Promise<OcrEngine> {\n disableOrtTelemetry()\n const [ortMod, sharpModRaw] = await Promise.all([\n tryImport<typeof import(\"onnxruntime-node\")>(\"onnxruntime-node\", () => import(\"onnxruntime-node\")),\n tryImport<{ default?: SharpFactory } & SharpFactory>(\n \"sharp\",\n () => import(\"sharp\") as unknown as Promise<{ default?: SharpFactory } & SharpFactory>,\n ),\n ])\n const sharpAny = sharpModRaw as { default?: SharpFactory } | SharpFactory\n const sharpMod: SharpFactory =\n typeof sharpAny === \"function\" ? sharpAny : (sharpAny.default ?? (sharpAny as unknown as SharpFactory))\n\n const dir = getOcrModelsDir()\n const sessionOpts: import(\"onnxruntime-node\").InferenceSession.SessionOptions = {\n graphOptimizationLevel: \"all\",\n executionProviders: [\"cpu\"],\n logSeverityLevel: 3, // paddle2onnx 변환 잔여물 W 로그 폭주 억제\n }\n const [det, rec, dictYml] = await Promise.all([\n ortMod.InferenceSession.create(join(dir, OCR_DET_MODEL.filename), sessionOpts),\n ortMod.InferenceSession.create(join(dir, OCR_REC_MODEL.filename), sessionOpts),\n readFile(join(dir, OCR_REC_DICT.filename), \"utf-8\"),\n ])\n const dict = parseCharacterDict(dictYml)\n if (dict.length === 0) throw new Error(\"OCR 사전 파싱 실패 — 모델 캐시를 삭제 후 재다운로드하세요\")\n\n return new OcrEngine({ det, rec, dict, ort: ortMod, sharp: sharpMod })\n }\n\n /** onnxruntime-node 1.14+ InferenceSession.release() — 구버전은 무시 */\n async destroy(): Promise<void> {\n for (const s of [this.det, this.rec]) {\n const rel = (s as unknown as { release?: () => Promise<void> }).release\n if (typeof rel === \"function\") {\n try { await rel.call(s) } catch { /* ignore */ }\n }\n }\n }\n\n /**\n * 페이지 RGBA 픽셀 → 텍스트 라인 인식.\n * 반환 좌표는 입력 픽셀 기준. 라인은 위→아래, 좌→우 정렬.\n * @param stats 저신뢰(conf<0.5) 폐기 라인 카운트 출력 — 종전엔 무음 폐기라 관측 불가\n */\n async recognizePage(\n rgba: Uint8Array,\n width: number,\n height: number,\n stats?: OcrPageStats,\n tuning: Readonly<OcrTuning> = DEFAULT_OCR_TUNING,\n cellRules: Array<{ x1: number; y1: number; y2: number; thicknessPx: number }> = [],\n ): Promise<OcrItem[]> {\n if (width < DET_MIN_SIZE || height < DET_MIN_SIZE) return []\n const detected = await this.detect(rgba, width, height, tuning, stats)\n const boxes = cellRules.length ? detected.flatMap(b => splitBoxAtCellRules(b, cellRules)) : detected\n\n // 박스 픽셀 분석 → 인식 작업(라인) 목록. group = 한 결과로 합칠 후보 묶음(회전 후보)\n const jobs: LineJob[] = []\n /** 리더로 가른 검출 박스 — 조각 인식 결과를 모아 한 아이템으로 합친다 */\n const joins: Array<{ box: Box; parts: Array<{ x: number; text: string; dotsBefore: boolean; confidence: number }>; trailDots: boolean }> = []\n let group = 0\n for (const b of boxes) {\n const gray = grayCrop(rgba, width, b)\n const ink = inkStats(gray)\n if (tuning.minInkContrast > 0 && ink.contrast < tuning.minInkContrast) continue\n // 잉크가 박스의 1% 미만이면 가는 선·티끌이다 — 연한 배경 도안 띠를 가로지르는 파란 세로선이 대비 검사를\n // 통과시키고 인식기가 도안을 \"D D D … O\" 로 읽었다(ice-election-cases 표지, 잉크 0.4%). 가장 가는 글자(\"-\")도\n // 여백 포함 박스의 1.5% 안팎이라 남는다. 점 하나(\"·\")는 여기서 빠지지만 isDotFragment 가 어차피 버린다\n if (tuning.minInkContrast > 0 && ink.inkRatio < MIN_INK_RATIO) continue\n if (tuning.splitTall && b.h >= b.w * TALL_RATIO) {\n const bands = splitRowBands(gray, b.w, b.h, ink, 0.45)\n if (bands.length >= 2) {\n for (const sub of bandBoxes(b, bands, height)) jobs.push({ box: sub, rot: 0, group: group++ })\n continue\n }\n if (b.h >= b.w * ROTATE_RATIO) {\n for (const rot of [0, 90, 270] as const) jobs.push({ box: b, rot, group })\n group++\n continue\n }\n }\n // 한 줄 박스가 문 위아래 이웃 줄 글자 끝자락·좌우 끝 상자 테두리는 인식 crop 에서 배경으로 지운다 — 인식기가 받침·\"|\" 로\n // 읽는다 (line-split edgeTrim). 박스를 줄이면 인식 입력 배율이 바뀌어 가운뎃점이 \"•\" 로 커 보였다 — 박스·좌표는 그대로 둔다\n const trim = tuning.trimEdges ? edgeTrim(gray, b.w, b.h, ink) : null\n const keep = trim ? { ...trim, bg: median(gray) } : undefined\n // 목차 리더 점 무리는 인식하지 않고 앞뒤 글만 따로 인식한 뒤, 검출 박스 하나로 다시 합쳐 \"제목 … 쪽번호\" 아이템\n // 하나를 낸다 — 텍스트층도 목차 줄을 리더 글자까지 한 줄로 준다. 조각을 따로 두면 줄 기하가 바뀌어 뒤 단계가\n // 흔들렸다: 리더 자리를 비우면 속기록 1면 목차 줄이 2단 본문 줄로 잡혀 단 판정이 무너졌고(assembly-minutes-1179),\n // 리더를 따로 세우면 클러스터 표가 그것을 열로 삼았다(gwd-info-plan 목차). 리더 앞 조각은 점 한두 개까지 물려\n // 인식하고 물린 점은 결과 끝에서 지운다 — 끝 글자 바로 뒤에서 자르면 인식기가 오른쪽 맥락을 잃어 로마 숫자 Ⅰ 를\n // 1 로 읽었다(eval-rda \"전략목표 Ⅰ\"·\"성과목표 Ⅰ-1\", 박스 높이 0.5배 물림으로 Ⅰ·Ⅱ·Ⅲ 11줄 복원)\n const leaders = tuning.splitLeaders ? leaderRuns(gray, b.w, b.h, ink, LEADER_MIN_DOTS) : []\n if (leaders.length) {\n const join = joins.length\n joins.push({ box: b, parts: [], trailDots: false })\n let x0 = 0, dots = false\n for (const [a, c] of [...leaders, [b.w, b.w]]) {\n const bare = { x: b.x + x0, y: b.y, w: a - x0, h: b.h }\n const end = c > a ? Math.min(c, a + Math.round(b.h * LEADER_CONTEXT)) : a\n x0 = c\n if (bare.w >= DET_MIN_SIZE && inkStats(grayCrop(rgba, width, bare)).contrast >= Math.max(1, tuning.minInkContrast)) {\n jobs.push({ box: { ...bare, w: end - (bare.x - b.x) }, rot: 0, group: group++, join, dotsBefore: dots, trimDots: end > a })\n dots = false\n }\n if (c > a) dots = true\n }\n joins[join].trailDots = dots\n continue\n }\n // 지운 crop 은 원본 crop 과 한 그룹으로 둘 다 인식해 신뢰도가 높은 쪽을 쓴다 — 끝자락이 글자 획과 붙어 있거나\n // 인식기가 조각 없이도 흔들리는 줄(아이콘·로고 칸)에서 지우기가 오히려 틀리게 만들지 않게\n if (keep) jobs.push({ box: b, rot: 0, group, keep })\n jobs.push({ box: b, rot: 0, group: group++ })\n }\n\n const results = await this.recognizeJobs(rgba, width, jobs, tuning.recBatch)\n\n // 회전 후보 그룹은 최고 신뢰도 하나만\n const best = new Map<number, { job: LineJob; text: string; confidence: number; steps: number[]; stepPx: number }>()\n // 끝자락을 지운 crop 은 원본보다 신뢰도가 KEEP_MARGIN 넘게 높을 때만 — 받침 조각 오독은 원본 0.46~0.89 → 지운 쪽 0.99 로\n // 차이가 크고, 차이가 작은 쪽은 띄어쓰기·대시 길이 같은 잡음이었다(과학영재 안내문 \"gifted\" → \"gifed\" +0.015)\n const score = (job: LineJob, confidence: number) => confidence - (job.keep ? KEEP_MARGIN : 0)\n jobs.forEach((job, i) => {\n const r = results[i]\n if (!r) return\n const cur = best.get(job.group)\n if (!cur || score(job, r.confidence) > score(cur.job, cur.confidence)) best.set(job.group, { job, ...r })\n })\n\n let items: OcrItem[] = []\n for (const { job, text: read, confidence, steps, stepPx } of best.values()) {\n const note: { ringLead?: boolean } = {}\n const raw = tuning.postprocess && job.rot === 0 ? restoreGlyphs(rgba, width, job.box, read, steps, stepPx, note) : read\n let text = tuning.postprocess ? restoreSymbols(raw.trim(), note.ringLead) : raw\n if (!text.trim()) continue\n // 사전 밖·작은 점으로 읽히거나 빠지는 글머리(◎ ● ▪ □) — 첫 글리프 모양으로 되살린다 (line-split.ts)\n if (tuning.postprocess && job.rot === 0 && !/^[◎●▪□■○ㅇ]/.test(text)) {\n const chars = [...read], k = chars.findIndex(c => c.trim())\n if (k >= 0 && steps.length === chars.length) {\n const g = grayCrop(rgba, width, job.box)\n const b = leadingBullet(g, job.box.w, job.box.h, inkStats(g), (steps[k] + 0.5) * stepPx)\n // ◎ 는 \"O\" 로 잘못 읽은 자리만 바꾼다(장식 아이콘에 끼워 넣지 않게). ●▪ 는 본문 줄(뒤 글 한글 4음절 이상)에서만 —\n // 표 칸의 큰 가운뎃점(\"·수학\"·\"·승합\", 글꼴에 따라 네모·원으로 그려짐)은 정답도 \"·\" 다\n const body = (text.match(/[가-힣]/g) ?? []).length >= 4\n const miss = /^[Oo0•·ㆍ∙‧○]/.test(text)\n if (b?.mark === \"\\u25ce\" && b.covers && /^[Oo0○]/.test(text)) text = b.mark + \" \" + text.slice(1).trimStart()\n // □ 는 인식에서 빠진 자리만(첫 글자 앞) — 모델은 사전에 □ 가 있어도 내지 않고 통째로 빠뜨린다\n else if (b?.mark === \"\\u25a1\") { if (!b.covers && body) text = b.mark + \" \" + text }\n else if (b && b.mark !== \"\\u25ce\" && body) text = b.covers ? (miss ? b.mark + \" \" + text.slice(1).trimStart() : text) : b.mark + \" \" + text\n }\n }\n // 숫자 앞 △·▲ 는 사전 밖이라 빈칸으로 사라진다 — 박스 맨 앞 글자 모양으로 되살린다 (line-split.ts)\n if (tuning.postprocess && /^\\d/.test(text) && job.rot === 0) {\n const g = grayCrop(rgba, width, job.box)\n const tri = leadingTriangle(g, job.box.w, job.box.h, inkStats(g))\n if (tri) text = tri + text\n }\n if (tuning.postprocess && isDotFragment(text)) continue\n if (confidence < tuning.textScore) { if (stats) stats.droppedLowConf++; continue }\n if (job.join !== undefined) {\n if (job.trimDots) text = text.replace(/[\\s.:\\u00b7\\u2022\\u2024\\u2025\\u2026\\u2219\\u22c5\\u318d]+$/u, \"\")\n if (text) joins[job.join].parts.push({ x: job.box.x, text, dotsBefore: job.dotsBefore === true, confidence })\n continue\n }\n items.push({ text, ...this.itemBox(rgba, width, job.box, tuning), confidence })\n }\n const leaderEnds = new Map<OcrItem, { lead: boolean; trail: boolean }>()\n for (const j of joins) {\n if (!j.parts.length) continue\n j.parts.sort((a, b) => a.x - b.x)\n let text = \"\"\n for (const p of j.parts) text += (p.dotsBefore ? (text ? \" \\u2026 \" : \"\\u2026\") : text ? \" \" : \"\") + p.text\n if (j.trailDots) text += \" \\u2026\"\n const item = { text, ...this.itemBox(rgba, width, j.box, tuning), confidence: Math.min(...j.parts.map(p => p.confidence)) }\n items.push(item)\n leaderEnds.set(item, { lead: j.parts[0].dotsBefore, trail: j.trailDots })\n }\n if (leaderEnds.size) items = joinLeaderItems(items, leaderEnds)\n if (tuning.postprocess) restoreBulletItems(items)\n items.sort((a, b) => (a.y - b.y) || (a.x - b.x))\n return items\n }\n\n /** 결과 좌표 — det 박스 그대로 또는 박스 안 잉크 외곽 (tightBoxes) */\n private itemBox(rgba: Uint8Array, width: number, b: Box, tuning: Readonly<OcrTuning>): Box {\n if (!tuning.tightBoxes) return b\n const gray = grayCrop(rgba, width, b)\n const t = inkBounds(gray, b.w, b.h, inkStats(gray))\n return { x: b.x + t.x0, y: b.y + t.y0, w: t.x1 - t.x0, h: t.y1 - t.y0 }\n }\n\n // ─── det ─────────────────────────────────────────────\n\n private async detect(\n rgba: Uint8Array,\n width: number,\n height: number,\n tuning: Readonly<OcrTuning>,\n stats?: OcrPageStats,\n ): Promise<Box[]> {\n const ratio = tuning.detLongSide / Math.max(width, height)\n const dw = Math.max(32, Math.round((width * ratio) / 32) * 32)\n const dh = Math.max(32, Math.round((height * ratio) / 32) * 32)\n\n const rgb = await this.sharp(rgba, { raw: { width, height, channels: 4 } })\n .resize(dw, dh, { fit: \"fill\" })\n .removeAlpha()\n .raw()\n .toBuffer()\n\n // HWC RGB → CHW BGR float32 정규화\n const plane = dw * dh\n const input = new Float32Array(3 * plane)\n for (let i = 0; i < plane; i++) {\n const r = rgb[i * 3] / 255\n const g = rgb[i * 3 + 1] / 255\n const b = rgb[i * 3 + 2] / 255\n input[i] = (b - DET_MEAN[0]) / DET_STD[0]\n input[plane + i] = (g - DET_MEAN[1]) / DET_STD[1]\n input[2 * plane + i] = (r - DET_MEAN[2]) / DET_STD[2]\n }\n\n const tensor = new this.ort.Tensor(\"float32\", input, [1, 3, dh, dw])\n const out = await this.det.run({ [this.det.inputNames[0]]: tensor })\n const probMap = out[this.det.outputNames[0]].data as Float32Array\n\n const rawBoxes = componentBoxes(probMap, dw, dh, tuning.detThresh, tuning.detBoxThresh)\n if (stats) stats.truncatedBoxes = Math.max(0, rawBoxes.length - DET_MAX_BOXES)\n const sx = width / dw\n const sy = height / dh\n const boxes: Box[] = []\n for (const rb of rawBoxes.slice(0, DET_MAX_BOXES)) {\n // unclip: DB 는 학습 시 텍스트 영역을 수축시키므로 검출 박스를 되팽창\n const bw = rb.x2 - rb.x1 + 1\n const bh = rb.y2 - rb.y1 + 1\n const delta = (bw * bh * tuning.detUnclip) / (2 * (bw + bh))\n const x1 = Math.max(0, Math.floor((rb.x1 - delta) * sx))\n const y1 = Math.max(0, Math.floor((rb.y1 - delta) * sy))\n const x2 = Math.min(width, Math.ceil((rb.x2 + 1 + delta) * sx))\n const y2 = Math.min(height, Math.ceil((rb.y2 + 1 + delta) * sy))\n if (x2 - x1 < DET_MIN_SIZE || y2 - y1 < DET_MIN_SIZE) continue\n boxes.push({ x: x1, y: y1, w: x2 - x1, h: y2 - y1 })\n }\n return boxes\n }\n\n // ─── rec ─────────────────────────────────────────────\n\n /** 라인 작업들을 폭 비율 순으로 배치 인식 — 결과는 jobs 순서 */\n private async recognizeJobs(\n rgba: Uint8Array,\n pageW: number,\n jobs: LineJob[],\n batchSize: number,\n ): Promise<Array<{ text: string; confidence: number; steps: number[]; stepPx: number } | null>> {\n const crops = jobs.map(j => lineCrop(rgba, pageW, j.box, j.rot, j.keep))\n const order = crops.map((_, i) => i).sort((a, b) => crops[a].w - crops[b].w)\n const results: Array<{ text: string; confidence: number; steps: number[]; stepPx: number } | null> = new Array(jobs.length).fill(null)\n const plane = REC_HEIGHT\n for (let s = 0; s < order.length;) {\n // 폭 오름차순이라 배치 마지막 원소가 최대 폭\n let e = s + 1\n while (e < order.length && e - s < Math.max(1, batchSize)\n && (e - s + 1) * Math.max(REC_MIN_WIDTH, crops[order[e]].w) * plane <= REC_BATCH_MAX_PIXELS) e++\n const idx = order.slice(s, e)\n const bw = Math.max(REC_MIN_WIDTH, crops[idx[idx.length - 1]].w)\n const n = idx.length\n const chw = 3 * REC_HEIGHT * bw\n const input = new Float32Array(n * chw) // pad 영역 0 (공식 zero-pad 와 동일)\n idx.forEach((ci, k) => {\n const c = crops[ci]\n const base = k * chw\n const p = REC_HEIGHT * bw\n for (let y = 0; y < REC_HEIGHT; y++) {\n for (let x = 0; x < c.w; x++) {\n const src = (y * c.w + x) * 3\n const dst = base + y * bw + x\n // HWC RGB → CHW BGR, (x/255-0.5)/0.5\n input[dst] = c.rgb[src + 2] / 127.5 - 1\n input[dst + p] = c.rgb[src + 1] / 127.5 - 1\n input[dst + 2 * p] = c.rgb[src] / 127.5 - 1\n }\n }\n })\n const tensor = new this.ort.Tensor(\"float32\", input, [n, 3, REC_HEIGHT, bw])\n const out = await this.rec.run({ [this.rec.inputNames[0]]: tensor })\n const logits = out[this.rec.outputNames[0]]\n const [, T, C] = logits.dims as number[]\n const data = logits.data as Float32Array\n idx.forEach((ci, k) => {\n const r = ctcDecode(data.subarray(k * T * C, (k + 1) * T * C), T, C, this.dict)\n // CTC 시점 하나가 덮는 원본 픽셀 폭 — crop 은 높이 48 로 줄인 뒤 bw 까지 오른쪽을 채웠다 (회전 crop 은 세로 축)\n const job = jobs[ci], src = job.rot === 0 ? job.box.w : job.box.h\n // 채운 자리(crop 폭 밖)에 찍힌 글자 — CTC 는 짧은 박스의 진짜 끝 글자도 마지막 시점에 찍어(\"54\" → 시점 36·39) 자리만으로는 못 가른다.\n // crop 안 키 큰 잉크 덩어리보다 키 큰 글자가 많을 때 남는 것만 지어낸 것으로 버린다 — 칸에 \"/\" 하나만 든 박스가 \"/)\"·\"(/:)\" 로\n // 읽혔다(여수 인원표). 점·쉼표류는 덩어리로 안 세니 그대로 둔다. \"(cid:9)\" 환각은 restoreSymbols 가 통째로 걷도록 손대지 않는다.\n // crop 안 글자가 두 자 이하인 작은 박스만 — 긴 낱말은 그림 성분이 글자 높이를 부풀려 소문자를 덩어리로 못 세었다(\"ToContent\" → \"ToCont\")\n let kept = r\n const last = (crops[ci].w * T) / bw + 1\n const chars = r ? [...r.text] : []\n if (r && job.rot === 0 && chars.length === r.steps.length && r.steps.some(t => t > last) && !r.text.includes(\"(cid:\")) {\n const tallCh = (c: string) => !/[\\s.,:;\\u00b7\\u2026'\"\\u2018-\\u201d`\\-_~]/.test(c)\n const g = grayCrop(rgba, pageW, job.box)\n const inside = chars.filter((c, i) => r.steps[i] <= last && tallCh(c)).length\n let budget = inside <= 2 ? tallInkCount(g, job.box.w, job.box.h, inkStats(g)) - inside : Infinity\n const keep = chars.map((c, i) => r.steps[i] <= last || !tallCh(c) || budget-- > 0)\n if (!keep.every(Boolean)) kept = { ...r, text: chars.filter((_, i) => keep[i]).join(\"\"), steps: r.steps.filter((_, i) => keep[i]) }\n }\n results[ci] = kept && { ...kept, stepPx: (bw / T) * (src / crops[ci].w) }\n })\n s = e\n }\n return results\n }\n}\n\n/** 회색조 중앙값 — 글줄 박스는 배경 픽셀이 다수라 배경 휘도가 된다 */\nfunction median(gray: Uint8Array): number {\n const hist = new Uint32Array(256)\n for (let i = 0; i < gray.length; i++) hist[gray[i]]++\n for (let v = 0, n = 0; v < 256; v++) if ((n += hist[v]) * 2 >= gray.length) return v\n return 255\n}\n\n/** CTC greedy 디코드 — 연속 중복 붕괴 → blank(0) 제거 → 사전 매핑 (테스트용 export) */\nexport function ctcDecode(\n data: Float32Array,\n T: number,\n C: number,\n dict: string[],\n): { text: string; confidence: number; steps: number[] } | null {\n let text = \"\"\n let confSum = 0\n let confCount = 0\n let prev = -1\n /** 글자(코드 포인트)마다 CTC 시점 구간 [첫, 끝] — 괄호 모양 판별이 글자 자리를 픽셀로 옮길 때 쓴다 */\n const runs: Array<[number, number]> = []\n let open: Array<[number, number]> = []\n for (let t = 0; t < T; t++) {\n const off = t * C\n let best = 0\n let bestV = data[off]\n for (let c = 1; c < C; c++) {\n const v = data[off + c]\n if (v > bestV) { bestV = v; best = c }\n }\n const repeat = best === prev\n prev = best\n if (repeat && best !== 0) { for (const r of open) r[1] = t; continue }\n open = []\n if (best === 0) continue\n // 모델 출력이 softmax 확률이 아니면 (>1) 해당 스텝만 정규화\n let p = bestV\n if (p > 1.0001 || p < 0) {\n let denom = 0\n for (let c = 0; c < C; c++) denom += Math.exp(data[off + c] - bestV)\n p = 1 / denom\n }\n confSum += p\n confCount++\n const tok = best >= 1 && best <= dict.length ? dict[best - 1] : best === dict.length + 1 ? \" \" : \"\"\n text += tok\n for (const _ of tok) { const r: [number, number] = [t, t]; runs.push(r); open.push(r) }\n }\n if (!text) return null\n return { text, confidence: confCount > 0 ? confSum / confCount : 0, steps: runs.map(([a, b]) => (a + b) / 2) }\n}\n\n/** 이진화 확률맵의 4-연결 성분 bbox (score = 성분 평균 확률, 테스트용 export) */\nexport function componentBoxes(\n prob: Float32Array,\n w: number,\n h: number,\n thresh: number = DEFAULT_OCR_TUNING.detThresh,\n boxThresh: number = DEFAULT_OCR_TUNING.detBoxThresh,\n): Array<{ x1: number; y1: number; x2: number; y2: number }> {\n const visited = new Uint8Array(w * h)\n const boxes: Array<{ x1: number; y1: number; x2: number; y2: number; score: number }> = []\n const stack: number[] = []\n\n for (let start = 0; start < w * h; start++) {\n if (visited[start] || prob[start] <= thresh) continue\n let x1 = start % w, x2 = x1, y1 = (start / w) | 0, y2 = y1\n let sum = 0\n let count = 0\n stack.length = 0\n stack.push(start)\n visited[start] = 1\n while (stack.length) {\n const p = stack.pop()!\n const px = p % w\n const py = (p / w) | 0\n sum += prob[p]\n count++\n if (px < x1) x1 = px\n if (px > x2) x2 = px\n if (py < y1) y1 = py\n if (py > y2) y2 = py\n // 4-이웃\n if (px > 0 && !visited[p - 1] && prob[p - 1] > thresh) { visited[p - 1] = 1; stack.push(p - 1) }\n if (px < w - 1 && !visited[p + 1] && prob[p + 1] > thresh) { visited[p + 1] = 1; stack.push(p + 1) }\n if (py > 0 && !visited[p - w] && prob[p - w] > thresh) { visited[p - w] = 1; stack.push(p - w) }\n if (py < h - 1 && !visited[p + w] && prob[p + w] > thresh) { visited[p + w] = 1; stack.push(p + w) }\n }\n if (x2 - x1 + 1 < DET_MIN_SIZE && y2 - y1 + 1 < DET_MIN_SIZE) continue\n boxes.push({ x1, y1, x2, y2, score: sum / count })\n }\n\n return boxes\n .filter(b => b.score >= boxThresh)\n .sort((a, b) => (a.y1 - b.y1) || (a.x1 - b.x1))\n}\n\nasync function tryImport<T>(name: string, loader: () => Promise<T>): Promise<T> {\n try {\n return await loader()\n } catch (e) {\n throw new Error(\n `내장 OCR 을 사용하려면 optional dependency '${name}' 이 필요합니다. ` +\n `\\`npm install ${name}\\` 후 다시 실행하세요.${OPTIONAL_DEP_INSTALL_HINT} 원인: ${(e as Error).message}`,\n )\n }\n}\n\n// ─── 엔진 싱글턴 (watch/서버 장기 실행에서 세션 재사용) ───\nlet enginePromise: Promise<OcrEngine> | null = null\n\nexport function getOcrEngine(): Promise<OcrEngine> {\n if (!enginePromise) {\n enginePromise = OcrEngine.create().catch(err => {\n enginePromise = null // 실패는 캐시하지 않음 — 모델 설치 후 재시도 가능\n throw err\n })\n }\n return enginePromise\n}\n","/**\n * 검출 박스 픽셀 분석 — 행 밴드 분할 + 잉크 대비.\n *\n * DB 검출기는 줄 간격보다 글자 간격이 넓으면 글자를 세로로 잇는다: 표 머리의 세로쓰기\n * (\"국/균/도/시\", \"사회복지과\"), 균등배분 목차의 같은 열 글자들이 키 큰 박스 하나가 되고,\n * 인식기(높이 48 고정)는 이를 짓눌러 빈 문자열이나 저신뢰 쓰레기를 낸다(실측: 코퍼스\n * 80쪽에서 GT 글자 0.55% 가 이런 박스와 함께 폐기). 박스 안 행 투영의 빈 띠로 밴드를\n * 갈라 밴드마다 따로 인식하면 글자가 자기 위치(행)를 되찾는다.\n *\n * 잉크 대비는 배경 무늬(연한 바탕의 흰 도안)를 글자로 읽는 환각을 거른다 — 진짜 글자는\n * 전경/배경 평균 휘도 차가 크다.\n */\n\n/** RGBA 페이지에서 박스 영역 휘도(BT.601 정수 근사) 추출 */\nexport function grayCrop(\n rgba: Uint8Array,\n pageW: number,\n box: { x: number; y: number; w: number; h: number },\n): Uint8Array {\n const out = new Uint8Array(box.w * box.h)\n for (let y = 0; y < box.h; y++) {\n let si = ((box.y + y) * pageW + box.x) * 4\n let di = y * box.w\n for (let x = 0; x < box.w; x++, si += 4, di++) {\n out[di] = (rgba[si] * 77 + rgba[si + 1] * 150 + rgba[si + 2] * 29) >> 8\n }\n }\n return out\n}\n\nexport interface InkStats {\n /** Otsu 임계값 */\n threshold: number\n /** 잉크 = 소수 클래스. true 면 어두운 쪽이 잉크(일반 문서) */\n darkInk: boolean\n /** 두 클래스 평균 휘도 차 (0~255) — 글자 대비 */\n contrast: number\n /** 잉크 픽셀 비율 */\n inkRatio: number\n}\n\n/** Otsu 이진화 — 잉크 극성(소수 클래스)과 대비 */\nexport function inkStats(gray: Uint8Array): InkStats {\n const hist = new Uint32Array(256)\n for (let i = 0; i < gray.length; i++) hist[gray[i]]++\n const total = gray.length\n let sumAll = 0\n for (let v = 0; v < 256; v++) sumAll += v * hist[v]\n let wB = 0, sumB = 0, best = -1, thr = 127\n for (let t = 0; t < 256; t++) {\n wB += hist[t]\n if (wB === 0) continue\n const wF = total - wB\n if (wF === 0) break\n sumB += t * hist[t]\n const mB = sumB / wB\n const mF = (sumAll - sumB) / wF\n const between = wB * wF * (mB - mF) * (mB - mF)\n if (between > best) { best = between; thr = t }\n }\n let nDark = 0, sDark = 0\n for (let v = 0; v <= thr; v++) { nDark += hist[v]; sDark += v * hist[v] }\n const nLight = total - nDark\n const sLight = sumAll - sDark\n if (nDark === 0 || nLight === 0) return { threshold: thr, darkInk: true, contrast: 0, inkRatio: 0 }\n const darkInk = nDark <= nLight\n return {\n threshold: thr,\n darkInk,\n contrast: sLight / nLight - sDark / nDark,\n inkRatio: (darkInk ? nDark : nLight) / total,\n }\n}\n\n/**\n * 행 투영의 빈 띠로 밴드 분할. 반환: 밴드별 [y0, y1) 행 구간과 괘선을 뺀 잉크 [x0, x1) 열 구간\n * (박스 로컬). 분할 불가면 길이 1.\n * @param minBandRatio 밴드 최소 높이 = 이 비율 × 글자 크기. 이보다 얇은 조각(한 글자 안의\n * 획 띠 \"을\"의 ㅇ/ㅡ/ㄹ, 밑줄, 박스 끝에 걸린 이웃 글자 조각)은 간격이 좁은 쪽 이웃 밴드에\n * 흡수된다. 글자 크기는 밴드별 잉크 가로 폭의 중앙값 — 박스 폭은 unclip 여백만큼 글자보다\n * 넓고(◎ 40px 에 박스 92px) 박스 전체 잉크 폭은 옆 열 글자 조각에 끌려가서, 둘 다 쓰면\n * 제대로 된 글자 밴드까지 합쳐진다(함평 목차 실측). 획 조각도 가로 폭은 글자 폭(ㅡ)이라\n * 중앙값이 흔들리지 않는다\n */\nexport function splitRowBands(\n gray: Uint8Array,\n w: number,\n h: number,\n ink: InkStats,\n minBandRatio: number,\n): Array<{ y0: number; y1: number; x0: number; x1: number }> {\n const isInk = (v: number) => (ink.darkInk ? v <= ink.threshold : v > ink.threshold)\n // 박스를 관통하는 괘선 — 세로선(행 85%+ 에 잉크인 열)은 투영에서 빼고, 가로선(남은 폭\n // 85%+ 가 잉크인 행)은 빈 행(구분자)으로 본다. 표 칸 사이 세로쓰기 라벨(\"국/균/도/시\")\n // 박스는 칸 경계 세로선을 끼고 잡혀 빈 행이 하나도 없다(부천 예산서 실측)\n const colInk = new Uint32Array(w)\n for (let y = 0; y < h; y++) {\n const off = y * w\n for (let x = 0; x < w; x++) if (isInk(gray[off + x])) colInk[x]++\n }\n const ruleCol = new Uint8Array(w)\n let liveW = 0\n for (let x = 0; x < w; x++) { if (colInk[x] >= h * 0.85) ruleCol[x] = 1; else liveW++ }\n const rowInk = new Uint32Array(h)\n for (let y = 0; y < h; y++) {\n let n = 0\n const off = y * w\n for (let x = 0; x < w; x++) if (!ruleCol[x] && isInk(gray[off + x])) n++\n rowInk[y] = n >= liveW * 0.85 ? 0 : n\n }\n // 안티앨리어싱·잡티 허용: 폭의 2% (최소 1px) 이하면 빈 행\n const blank = Math.max(1, Math.floor(w * 0.02))\n let bands: Array<[number, number]> = []\n let start = -1\n for (let y = 0; y <= h; y++) {\n const on = y < h && rowInk[y] > blank\n if (on && start < 0) start = y\n else if (!on && start >= 0) { bands.push([start, y]); start = -1 }\n }\n const inkCols = (y0: number, y1: number): [number, number] => {\n let x0 = w, x1 = -1\n for (let y = y0; y < y1; y++) {\n const off = y * w\n for (let x = 0; x < w; x++) if (!ruleCol[x] && isInk(gray[off + x])) { if (x < x0) x0 = x; if (x > x1) x1 = x }\n }\n return x1 >= x0 ? [x0, x1 + 1] : [0, w]\n }\n if (bands.length <= 1) return [{ y0: bands[0]?.[0] ?? 0, y1: bands[0]?.[1] ?? h, x0: 0, x1: w }]\n const widths = bands.map(([y0, y1]) => { const [a, b] = inkCols(y0, y1); return b - a }).sort((a, b) => a - b)\n const charSize = widths[widths.length >> 1]\n const minBand = Math.max(3, minBandRatio * charSize)\n // 글자 안 빈 행(“업”의 어/ㅂ 사이 2px) — 간격이 글자 크기 15% 이하이고 합쳐도 한 글자\n // 높이(1.3배) 안이면 한 밴드. 세로쓰기의 글자 사이 간격은 이보다 넓고, 두 글자를 합치면\n // 높이 상한에 걸린다\n for (let i = 0; i + 1 < bands.length;) {\n const gap = bands[i + 1][0] - bands[i][1]\n if (gap <= Math.max(2, charSize * 0.15) && bands[i + 1][1] - bands[i][0] <= charSize * 1.3) {\n bands.splice(i, 2, [bands[i][0], bands[i + 1][1]])\n } else i++\n }\n // 박스 위아래 끝에 걸린 얇은 조각 = 이웃 줄 글자의 끝자락 — 합치지 않고 버린다\n while (bands.length > 1 && bands[0][0] <= 1 && bands[0][1] - bands[0][0] < minBand) bands.shift()\n while (bands.length > 1 && bands[bands.length - 1][1] >= h - 1 && bands[bands.length - 1][1] - bands[bands.length - 1][0] < minBand) bands.pop()\n // 얇은 밴드 흡수 — 간격이 더 좁은 쪽 이웃과 합침 (가장 얇은 것부터 반복)\n for (;;) {\n let idx = -1, minH = Infinity\n for (let i = 0; i < bands.length; i++) {\n const bh = bands[i][1] - bands[i][0]\n if (bh < minBand && bh < minH) { minH = bh; idx = i }\n }\n if (idx < 0 || bands.length === 1) break\n const gapPrev = idx > 0 ? bands[idx][0] - bands[idx - 1][1] : Infinity\n const gapNext = idx < bands.length - 1 ? bands[idx + 1][0] - bands[idx][1] : Infinity\n const j = gapPrev <= gapNext ? idx - 1 : idx + 1\n const a = Math.min(idx, j), b = Math.max(idx, j)\n bands = [...bands.slice(0, a), [bands[a][0], bands[b][1]], ...bands.slice(b + 1)]\n }\n if (bands.length === 1) return [{ y0: bands[0][0], y1: bands[0][1], x0: 0, x1: w }]\n return bands.map(([y0, y1]) => { const [x0, x1] = inkCols(y0, y1); return { y0, y1, x0, x1 } })\n}\n\ntype Comp = { x0: number; x1: number; y0: number; y1: number; id: number }\n\n/**\n * 글자 잉크 연결 성분(8-이웃) — 성분마다 bbox, label 은 픽셀별 성분 번호(0 = 배경). 박스를 관통하는 칸 경계\n * 괘선 성분(박스 높이·폭의 85%+, inkBounds 와 같은 기준)은 글자가 아니라 뺀다 — 괘선이 가장 큰 성분이 되면\n * 글자 높이가 부풀어 숫자들이 \"점\"으로 잡혔다(goesan-budget-2013 두 칸을 문 박스 \"8,000 │ 1,000\")\n */\nfunction components(gray: Uint8Array, w: number, h: number, ink: InkStats): { comps: Comp[]; label: Int32Array } {\n const isInk = (v: number) => (ink.darkInk ? v <= ink.threshold : v > ink.threshold)\n const comps: Comp[] = []\n const label = new Int32Array(w * h)\n const stack: number[] = []\n for (let p0 = 0; p0 < w * h; p0++) {\n if (label[p0] || !isInk(gray[p0])) continue\n const c = { x0: w, x1: 0, y0: h, y1: 0, id: comps.length + 1 }\n label[p0] = c.id\n stack.push(p0)\n while (stack.length) {\n const p = stack.pop()!\n const x = p % w, y = (p / w) | 0\n if (x < c.x0) c.x0 = x\n if (x + 1 > c.x1) c.x1 = x + 1\n if (y < c.y0) c.y0 = y\n if (y + 1 > c.y1) c.y1 = y + 1\n for (let dy = -1; dy <= 1; dy++) for (let dx = -1; dx <= 1; dx++) {\n const nx = x + dx, ny = y + dy\n if (nx < 0 || ny < 0 || nx >= w || ny >= h) continue\n const q = ny * w + nx\n if (!label[q] && isInk(gray[q])) { label[q] = c.id; stack.push(q) }\n }\n }\n if (c.y1 - c.y0 < h * 0.85 && c.x1 - c.x0 < w * 0.85) comps.push(c)\n }\n return { comps, label }\n}\n\n/**\n * 박스 맨 앞 글자가 삼각형(△ 감액·▲ 증가 표시)인지. 인식 사전에 △·▲ 가 없어 모델은 숫자 앞 삼각형을\n * 빈칸으로 버린다 — 예산서 \"△400,352\" → \"400,352\" (코퍼스 GT △ 81개 중 OCR 30개, 나머지 부호 소실).\n * 가장 왼쪽 성분(글자 높이 40%+)이 밑변(아래 두 줄이 폭 70%+)·좁은 꼭짓점(위 20% 줄이 폭 40% 이하·가운데)·\n * 양옆 빗변(높이 60% 줄의 잉크가 폭 30% 안쪽과 70% 바깥 양쪽)을 가지면 삼각형, 그 줄 가운데가 비면 △ 차면 ▲.\n * 숫자(4·1·2·7 등)는 밑변이나 꼭짓점·빗변 조건 중 하나에서 걸린다.\n */\nexport function leadingTriangle(gray: Uint8Array, w: number, h: number, ink: InkStats): \"\\u25b3\" | \"\\u25b2\" | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n const first = comps.filter(c => c.y1 - c.y0 >= charH * 0.4).sort((a, b) => a.x0 - b.x0)[0]\n if (!first || charH < 8) return null\n const cw = first.x1 - first.x0, ch = first.y1 - first.y0\n if (cw < ch * 0.8 || cw > ch * 1.8) return null\n const rowSpan = (y: number): { n: number; lo: number; hi: number; runs: number } => {\n let n = 0, lo = -1, hi = -1, runs = 0, prev = false\n for (let x = first.x0; x < first.x1; x++) {\n const on = label[y * w + x] === first.id\n if (on) { n++; if (lo < 0) lo = x - first.x0; hi = x - first.x0; if (!prev) runs++ }\n prev = on\n }\n return { n, lo, hi, runs }\n }\n const base = Math.max(rowSpan(first.y1 - 1).n, rowSpan(first.y1 - 2).n)\n if (base < cw * 0.7) return null\n for (let y = first.y0; y < first.y0 + Math.max(1, Math.round(ch * 0.2)); y++) {\n const r = rowSpan(y)\n if (r.n === 0) continue\n if (r.hi - r.lo + 1 > cw * 0.4 || (r.lo + r.hi) / 2 < cw * 0.25 || (r.lo + r.hi) / 2 > cw * 0.75) return null\n }\n const mid = rowSpan(first.y0 + Math.round(ch * 0.6))\n if (mid.lo < 0 || mid.lo > cw * 0.3 || mid.hi < cw * 0.7) return null\n return mid.runs >= 2 ? \"\\u25b3\" : \"\\u25b2\"\n}\n\n/**\n * 목차 리더 점(\"·········\")의 가로 구간들 (박스 로컬 [x0, x1)). 검출기는 쪽번호를 앞쪽 리더 점과 한 박스로\n * 묶는데, 인식기는 점 무리 뒤 숫자를 망친다 — \"·····5\"→\"…55\", \"·····141\"→\"…11\", \"·····203\"→\"03\"\n * (changwon-plan2026 목차 실측, 코퍼스 80쪽의 리더 섞인 박스 192개). 점 무리를 빼고 앞뒤 글만 따로 인식한다.\n * 잉크 연결 성분(8-이웃)을 x 가 겹치는 것끼리 묶은 글자 덩어리 단위로 본다 — 한글 한 글자는 여러 성분(\"소\" = ㅅ+ㅗ)\n * 이라 성분 하나로 글자 높이를 재면 굵은 리더 점(9px)이 점으로 안 잡혔다(yeosu 목차). 점: 글자 높이(가장 큰 덩어리\n * 높이) 30% 이하의 작은 덩어리이고 중심이 글자 띠(점 크기를 넘는 성분들의 세로 범위) 안 — 박스 위아래 여백에 걸친\n * 점선 괘선 조각은 띠 밖이다(changwon 정원표 칸 실측). 무리: x 순서로 연달아 놓인 점들이 세로 중심 한 줄(±20%)·\n * 간격 글자 높이 이하로 minDots 개+. 리더는 같은 줄 글자를 잇는다 — 무리 앞이나 뒤 글자 높이 2배 안에 점 높이를\n * 세로로 품는 글자 성분이 있어야 한다. 두 행 사이 점선 괘선을 문 박스(위아래 행 글자가 띠를 넓힘)는 여기서 걸린다.\n * 리더는 같은 글리프를 고른 간격으로 찍은 것이라 점 크기(최대/최소 2.5배 이내)·주기(1.8배 이내)가 고르다 — 작은\n * 글꼴의 가는 획이 이진화로 쪼갠 조각(\"gifted.kaist.ac.kr\", pen-cyberbridge 흐름도)은 여기서 걸린다. 박스 끝에 닿아\n * 잘린 점은 통계에서 빼고, 값이 5개 이상이면 양 끝값도 뺀다.\n */\nexport function leaderRuns(\n gray: Uint8Array,\n w: number,\n h: number,\n ink: InkStats,\n minDots: number,\n): Array<[number, number]> {\n const comps = components(gray, w, h, ink).comps.sort((a, b) => a.x0 - b.x0)\n // x 구간이 겹치는 성분끼리 한 덩어리\n const blobs: Array<{ x0: number; x1: number; y0: number; y1: number }> = []\n for (const c of comps) {\n const last = blobs[blobs.length - 1]\n if (last && c.x0 < last.x1) { last.x1 = Math.max(last.x1, c.x1); last.y0 = Math.min(last.y0, c.y0); last.y1 = Math.max(last.y1, c.y1) }\n else blobs.push({ x0: c.x0, x1: c.x1, y0: c.y0, y1: c.y1 })\n }\n let charH = 0\n for (const b of blobs) charH = Math.max(charH, b.y1 - b.y0)\n if (charH < 8) return []\n const small = (c: { x0: number; x1: number; y0: number; y1: number }) => c.x1 - c.x0 <= charH * 0.3 && c.y1 - c.y0 <= charH * 0.3\n let bandTop = h, bandBot = 0\n for (const c of comps) if (!small(c)) { bandTop = Math.min(bandTop, c.y0); bandBot = Math.max(bandBot, c.y1) }\n const cy = (c: { y0: number; y1: number }) => (c.y0 + c.y1) / 2\n const isDot = (b: { x0: number; x1: number; y0: number; y1: number }) => small(b) && cy(b) >= bandTop && cy(b) <= bandBot\n const runs: Array<[number, number]> = []\n for (let i = 0; i < blobs.length;) {\n if (!isDot(blobs[i])) { i++; continue }\n let j = i\n while (j + 1 < blobs.length && isDot(blobs[j + 1]) && blobs[j + 1].x0 - blobs[j].x1 <= charH\n && Math.abs(cy(blobs[j + 1]) - cy(blobs[i])) <= charH * 0.2) j++\n const x0 = blobs[i].x0, x1 = blobs[j].x1, y = cy(blobs[i])\n const onLine = comps.some(c => !small(c) && c.y0 <= y && c.y1 >= y\n && ((c.x1 <= x0 + 2 && c.x1 >= x0 - 2 * charH) || (c.x0 >= x1 - 2 && c.x0 <= x1 + 2 * charH)))\n const run = blobs.slice(i, j + 1).filter(b => b.x0 > 0 && b.x1 < w)\n const spread = (xs: number[]) => {\n const v = [...xs].sort((a, b) => a - b).slice(xs.length >= 5 ? 1 : 0, xs.length >= 5 ? -1 : undefined)\n return v[v.length - 1] / Math.max(1, v[0])\n }\n const even = run.length >= 2 && spread(run.map(b => b.x1 - b.x0)) <= 2.5 && spread(run.map(b => b.y1 - b.y0)) <= 2.5\n && spread(run.slice(1).map((b, k) => b.x0 - run[k].x0)) <= 1.8\n if (j - i + 1 >= minDots && onLine && even) runs.push([x0, x1])\n i = j + 1\n }\n return runs\n}\n\n/**\n * 박스 안 잉크 외곽 (박스 로컬, [x0,x1)·[y0,y1)) — 관통 괘선(행/열 85%+ 잉크)의 픽셀은 뺀다.\n * det 박스는 unclip 여백만큼 글자보다 커서(본문 10pt 에 박스 높이 ≈ 1.5em) 이를 그대로\n * 좌표로 넘기면 글자 크기·줄 기준선·칸 배정이 텍스트층 아이템과 어긋난다. 표 칸 숫자 박스는\n * 칸 경계 괘선을 물고 잡히므로(고산 예산서 실측) 괘선 픽셀을 빼지 않으면 외곽이 박스 전체가\n * 된다. 잉크가 없으면 박스 전체.\n */\nexport function inkBounds(\n gray: Uint8Array,\n w: number,\n h: number,\n ink: InkStats,\n): { x0: number; y0: number; x1: number; y1: number } {\n const isInk = (v: number) => (ink.darkInk ? v <= ink.threshold : v > ink.threshold)\n const colInk = new Uint32Array(w)\n const rowInk = new Uint32Array(h)\n for (let y = 0; y < h; y++) {\n const off = y * w\n for (let x = 0; x < w; x++) if (isInk(gray[off + x])) { colInk[x]++; rowInk[y]++ }\n }\n const ruleCol = new Uint8Array(w), ruleRow = new Uint8Array(h)\n for (let x = 0; x < w; x++) if (colInk[x] >= h * 0.85) ruleCol[x] = 1\n for (let y = 0; y < h; y++) if (rowInk[y] >= w * 0.85) ruleRow[y] = 1\n let x0 = w, x1 = -1, y0 = h, y1 = -1\n for (let y = 0; y < h; y++) {\n if (ruleRow[y]) continue\n const off = y * w\n for (let x = 0; x < w; x++) {\n if (ruleCol[x] || !isInk(gray[off + x])) continue\n if (x < x0) x0 = x\n if (x > x1) x1 = x\n if (y < y0) y0 = y\n if (y > y1) y1 = y\n }\n }\n if (x1 < x0 || y1 < y0) return { x0: 0, y0: 0, x1: w, y1: h }\n return { x0, y0, x1: x1 + 1, y1: y1 + 1 }\n}\n\n/**\n * 괄호 조각 모양 — 윗·아랫 띠(높이 15%)의 가로 획 길이(폭 대비)와 기울기 줄 비율(taper: 획 폭과 전체 폭 사이 폭인 줄 / 높이).\n * [ ] 는 윗·아랫변 뒤 한 번에 획 폭으로 떨어지고(taper ≈ 0), 【】 는 위아래에서 가운데로 폭이 줄어든다(창원 계획 【 0.19~0.52 · 강원 정보화 계획 [ 0.03~0.06)\n */\nexport interface BracketFeatures { top: number; bottom: number; taper: number; fill: number; cw: number; ch: number; charH: number }\n\n/** 박스 로컬 x 중심(cx) 자리의 괄호 조각 — 글자 높이 30% 이상 성분 가운데 cx 에 가장 가까운 것 (「」 는 글자 높이의 절반쯤이다) */\nexport function bracketFeatures(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): BracketFeatures | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 8) return null\n const tol = Math.max(2, charH * 0.3)\n let best: Comp | null = null, bestD = Infinity\n for (const c of comps) {\n if (c.y1 - c.y0 < charH * 0.3 || c.x1 < cx - tol || c.x0 > cx + tol) continue\n const d = Math.abs((c.x0 + c.x1) / 2 - cx)\n if (d < bestD) { bestD = d; best = c }\n }\n if (!best) return null\n const b = best\n const cw = b.x1 - b.x0, ch = b.y1 - b.y0\n if (cw < 3 || ch < 8) return null\n const spans: number[] = []\n for (let y = b.y0; y < b.y1; y++) {\n let n = 0\n for (let x = b.x0; x < b.x1; x++) if (label[y * w + x] === b.id) n++\n spans.push(n)\n }\n const band = Math.max(1, Math.round(ch * 0.15))\n const top = Math.max(...spans.slice(0, band)) / cw, bottom = Math.max(...spans.slice(ch - band)) / cw\n const midRows = spans.slice(Math.floor(ch * 0.3), Math.ceil(ch * 0.7)).sort((p, q) => p - q)\n const stroke = midRows[midRows.length >> 1] ?? 0\n const taper = spans.filter(n => n > stroke && n < cw).length / ch\n const fill = spans.reduce((a, n) => a + n, 0) / (cw * ch)\n return { top, bottom, taper, fill, cw, ch, charH }\n}\n\n/**\n * 로마 숫자 세로 획 수 — 사전에 Ⅰ~Ⅲ 가 있어도 모델은 한 글리프 Ⅲ 을 \"II\"·\"I\" 로, Ⅱ 를 \"I\" 로 줄여 읽는다(코퍼스 장 제목·목차).\n * 앞뒤 글자의 CTC 자리(prevX·nextX, 박스 로컬) 사이에 중심이 든 키 큰 성분(글자 높이 60% 이상)의 가운데 절반 줄에서 잉크 토막을 센다 —\n * CTC 자리는 글리프 한쪽에 치우치기도 해 가운데 금이 아니라 이웃 글자 자리에서 글자 높이 0.35배 떨어진 곳까지 본다.\n * 세리프 Ⅲ 은 위아래 가로대로 이어진 한 성분이어도 가운데 줄은 세 토막이다. 줄의 70% 이상이 같은 수이고 토막이 가늘 때(세로 획)만 낸다\n */\nexport function romanStems(gray: Uint8Array, w: number, h: number, ink: InkStats, prevX: number, nextX: number): number | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return null\n const x0 = prevX + charH * 0.35, x1 = nextX - charH * 0.35\n const sel = comps.filter(c => c.y1 - c.y0 >= charH * 0.6 && (c.x0 + c.x1) / 2 >= x0 && (c.x0 + c.x1) / 2 < x1)\n if (!sel.length) return null\n const ids = new Set(sel.map(c => c.id))\n const ux0 = Math.min(...sel.map(c => c.x0)), ux1 = Math.max(...sel.map(c => c.x1))\n const uy0 = Math.min(...sel.map(c => c.y0)), uy1 = Math.max(...sel.map(c => c.y1))\n const uh = uy1 - uy0\n const counts = new Map<number, number>()\n let rows = 0\n for (let y = uy0 + Math.floor(uh * 0.25); y < uy1 - Math.floor(uh * 0.25); y++) {\n let runs = 0, len = 0, thick = false\n for (let x = ux0; x <= ux1; x++) {\n const on = x < ux1 && ids.has(label[y * w + x])\n if (on) len++\n else if (len) { runs++; if (len > uh * 0.35) thick = true; len = 0 }\n }\n rows++\n if (!thick) counts.set(runs, (counts.get(runs) ?? 0) + 1)\n }\n const [n, k] = [...counts].sort((a, b) => b[1] - a[1])[0] ?? [0, 0]\n return n >= 1 && n <= 3 && k >= rows * 0.7 ? n : null\n}\n\n/**\n * 원문자 숫자 — 사전에 ①~⑨ 가 있어도 모델은 고리를 버리고 숫자만 읽는다(항 번호 \"① 문서는 …\" → \"1문서는\").\n * xs(박스 로컬 — 숫자 글자의 CTC 자리)마다 그 자리를 품는 둥근 고리 성분(글자 높이 55% 이상, 가로세로 0.8~1.25배)이 키 35% 이상\n * 성분(숫자)을 안에 두면 원문자다. 괄호 숫자 \"(1)\"·네모 칸은 고리가 아니라 걸리지 않는다\n */\nexport function circledAt(gray: Uint8Array, w: number, h: number, ink: InkStats, xs: number[]): boolean[] {\n const { comps } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n const rings = charH < 10 ? [] : comps.filter(r => {\n const rw = r.x1 - r.x0, rh = r.y1 - r.y0\n return rh >= charH * 0.55 && rw >= rh * 0.8 && rw <= rh * 1.25\n && comps.some(d => d !== r && d.x0 > r.x0 && d.x1 < r.x1 && d.y0 > r.y0 && d.y1 < r.y1 && d.y1 - d.y0 >= rh * 0.35)\n })\n return xs.map(x => rings.some(r => x >= r.x0 && x <= r.x1))\n}\n\n/**\n * 따옴표 머리 위치 — 모델은 ‘ ’ 를 곧은 ' 로 읽어 방향은 문맥(smartQuotes)이 정하는데, 연도 앞 \"‘24년\"·\"’24년\" 은 문서마다\n * 섞여 문맥으로 못 가른다. cx(박스 로컬 — 따옴표 글자의 CTC 자리)에 가장 가까운 작은 성분(글자 높이 12~50%, 글줄 위쪽 절반)의\n * 잉크 무게중심 높이를 성분 높이 비로 낸다 — 둥근 머리가 아래인 ‘(6 꼴)는 크고 위인 ’(9 꼴)는 작다\n */\nexport function quoteHead(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): number | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return null\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.6)\n if (!tall.length) return null\n const mid = (Math.min(...tall.map(c => c.y0)) + Math.max(...tall.map(c => c.y1))) / 2\n let best: Comp | null = null, bestD = charH * 0.4\n for (const c of comps) {\n const ch = c.y1 - c.y0, d = Math.abs((c.x0 + c.x1) / 2 - cx)\n if (ch < charH * 0.12 || ch > charH * 0.5 || (c.y0 + c.y1) / 2 > mid || d > bestD) continue\n bestD = d; best = c\n }\n if (!best) return null\n let n = 0, sy = 0\n for (let y = best.y0; y < best.y1; y++) for (let x = best.x0; x < best.x1; x++) if (label[y * w + x] === best.id) { n++; sy += y }\n return n ? (sy / n - best.y0) / (best.y1 - best.y0) : null\n}\n\n/**\n * 한 줄 박스 위아래 끝에 걸린 이웃 줄 글자 끝자락 — 줄 간격이 좁은 칸(조직도 상자 \"노동 / 시장 / 정책관\")은 검출 박스가 위아래 줄\n * 글자 끝을 물어, 인식기가 그 조각을 받침으로 읽었다(\"노동\" → \"논동\"·\"시장\" → \"싫장\"·\"근로\" → \"근록\", web068). 박스 끝 행(1px 안)에\n * 닿은 잉크 띠가 빈 행으로 글줄과 떨어져 있고 가장 높은 띠의 45% 미만이면, 그 띠와 다음 띠 사이 빈 행 가운데까지 잘라낸 세로 구간을\n * 낸다(높이 24px 이상, 남는 띠가 글자 두 자 이상인 글줄일 때만). 괘선(행·열 85% 이상 잉크)은 splitRowBands 처럼 빼고 본다. 좌우 끝 20% 안의 세로 테두리(상자 테두리 — 인식기가 \"|\"·\"[\"·\"(\" 로\n * 읽었다)도 그 바깥에 글 잉크가 없으면 괘선 안쪽으로 잘라낸다. 걸린 것이 없으면 null\n */\nexport function edgeTrim(gray: Uint8Array, w: number, h: number, ink: InkStats): { x0: number; x1: number; y0: number; y1: number } | null {\n const isInk = (v: number) => (ink.darkInk ? v <= ink.threshold : v > ink.threshold)\n const colInk = new Uint32Array(w)\n for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) if (isInk(gray[y * w + x])) colInk[x]++\n const ruleCol = new Uint8Array(w)\n let liveW = 0\n for (let x = 0; x < w; x++) { if (colInk[x] >= h * 0.85) ruleCol[x] = 1; else liveW++ }\n const blank = Math.max(1, Math.floor(w * 0.02))\n const bands: Array<[number, number]> = []\n let start = -1\n for (let y = 0; y <= h; y++) {\n let n = 0\n if (y < h) for (let x = 0; x < w; x++) if (!ruleCol[x] && isInk(gray[y * w + x])) n++\n const on = y < h && n > blank && n < liveW * 0.85\n if (on && start < 0) start = y\n else if (!on && start >= 0) { bands.push([start, y]); start = -1 }\n }\n let y0 = 0, y1 = h\n if (bands.length >= 2 && h >= 24) {\n const mh = Math.max(...bands.map(([a, b]) => b - a))\n const [top, next] = [bands[0], bands[1]], [bot, prev] = [bands[bands.length - 1], bands[bands.length - 2]]\n if (top[0] <= 1 && top[1] - top[0] < mh * 0.45) y0 = (top[1] + next[0]) >> 1\n if (bot[1] >= h - 1 && bot[1] - bot[0] < mh * 0.45) y1 = (bot[0] + prev[1] + 1) >> 1\n // 남는 띠가 글줄이어야 한다 — 글자 크기(띠 높이 30% 이상 폭) 잉크 열 토막이 둘 이상. 아이콘(\"Q\" 로 읽힌 돋보기)·큰 장 번호 한 자\n // (옅은 \"6\" 의 끊긴 윗곡선이 조각으로 잘렸다)는 그대로 둔다\n if (y0 > 0 || y1 < h) {\n let runs = 0, len = 0\n for (let x = 0; x <= w; x++) {\n let on = false\n if (x < w && !ruleCol[x]) for (let y = y0; y < y1 && !on; y++) on = isInk(gray[y * w + x])\n if (on) len++\n else { if (len >= (y1 - y0) * 0.3) runs++; len = 0 }\n }\n if (runs < 2) { y0 = 0; y1 = h }\n }\n }\n // 좌우 끝 세로 괘선 — 박스 높이 95% 이상을 관통하는 열이고, 그 바깥 열엔 잉크가 없고, 안쪽으로 빈 열 틈(높이 10%, 2px 이상)을\n // 두고 글이 시작해야 한다. 큰 제목 글자의 세로 줄기(\"D\")도 박스 높이 85% 를 넘어 테두리로 잘렸다(ODL 073 \"Defensoria\" → \"ria\")\n const textCol = (x: number) => { for (let y = y0; y < y1; y++) if (isInk(gray[y * w + x])) return true; return false }\n const border = (x: number) => colInk[x] >= h * 0.95\n const gap = Math.max(2, Math.round(h * 0.1))\n const clearFrom = (x: number, dir: 1 | -1) => { for (let k = 0; k < gap; k++) { const c = x + dir * k; if (c < 0 || c >= w || textCol(c)) return false } return true }\n let x0 = 0, x1 = w\n for (let x = 0; x < w * 0.2; x++) {\n if (border(x)) { let e = x; while (e + 1 < w && border(e + 1)) e++; if (clearFrom(e + 1, 1)) x0 = e + 1; break }\n if (textCol(x)) break\n }\n for (let x = w - 1; x >= w * 0.8; x--) {\n if (border(x)) { let e = x; while (e - 1 >= 0 && border(e - 1)) e--; if (clearFrom(e - 1, -1)) x1 = e; break }\n if (textCol(x)) break\n }\n return y0 > 0 || y1 < h || x0 > 0 || x1 < w ? { x0, x1, y0, y1 } : null\n}\n\n/** 키 큰 잉크 덩어리 수 — 글자 높이 절반 이상 성분을 x 가 겹치는 것끼리 묶어 센다(한 글자 = 한 덩어리, 점·쉼표는 안 셈) */\nexport function tallInkCount(gray: Uint8Array, w: number, h: number, ink: InkStats): number {\n const { comps } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.5).sort((a, b) => a.x0 - b.x0)\n let n = 0, end = -1\n for (const c of tall) { if (c.x0 >= end) n++; end = Math.max(end, c.x1) }\n return n\n}\n\n/**\n * 두 글자 사이에서 통째로 빠진 기호 — 인식기가 사전에 없거나(「」) 드물게 배운 기호(▲ □ · . 。)를 글자 자리 없이 건너뛴다. 글줄 띠(키 큰\n * 성분 위아래)와 x 가 겹치는 다른 성분이 없는(빈 열로 떨어진) 조각만 모양으로 가른다:\n * · 가운데 높이(띠 30~70%)의 작은 둥근 점(띠 높이 8%·3px 이상 25% 이하, 채움 60% 이상 — 1px 잡티는 빼고), 아래쪽(75% 아래)이면 .\n * 2px 까지 작은 점은 \"·\\u0001\" — 모델이 공백으로 읽은 자리에서만 쓴다\n * 。 아래쪽(60% 아래) 작은 고리(띠 높이 40% 이하, 가운데 줄 두 토막)\n * ▲ 띠 높이 50% 이상·가로세로 0.9~1.4배, 위로 갈수록 좁아지고 줄마다 한 토막인 속 찬 삼각형\n * 「 」 띠 높이 30~65%, 위(「)·아래(」)에 붙어 그 변이 폭 70% 넘게 차고 반대쪽 변은 절반 이하, 줄기가 왼쪽(「)·오른쪽(」)\n * / 띠 높이 60% 이상의 가는 사선(분수 칸 \"7/5\" — 모델이 숫자 사이 빗금을 빠뜨림)\n * - 가운데 높이의 짧은 가로 막대(쪽번호 꼬리말 \"- 1 -\" 의 앞 막대 — 줄 머리에서만 쓴다)\n * □ 띠 높이 60~92%·가로세로 0.8~1.25배, 위아래 변이 폭 80% 넘게 차고 가운데 줄은 양끝 두 획. 줄에서 가장 큰 조각이면(글 없이 정사각만\n * 늘어선 칸 \"□□-□□□\") \"□\\0\" — 새로 넣지는 않고 0·O 로 읽힌 자리만 바꾼다(제목 앞 도형 네모와 섞이지 않게)\n * 칸 경계 세로선(띠 높이 90% 이상·가는 열)은 뺀다. 반환은 박스 로컬 x 구간과 기호, 글줄 띠 높이\n */\nexport function gapGlyphs(gray: Uint8Array, w: number, h: number, ink: InkStats): { glyphs: Array<{ x0: number; x1: number; mark: string }>; bandH: number } {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return { glyphs: [], bandH: 0 }\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.6)\n const bandT = Math.min(...tall.map(c => c.y0)), bandB = Math.max(...tall.map(c => c.y1)), bh = bandB - bandT\n const inBand = (c: Comp) => c.y1 > bandT && c.y0 < bandB\n const out: Array<{ x0: number; x1: number; mark: string }> = []\n for (const c of comps) {\n if (!inBand(c)) continue\n const cw = c.x1 - c.x0, ch = c.y1 - c.y0\n if (ch >= bh * 0.9 && cw <= bh * 0.15) continue\n // 빈 열로 떨어진 조각 — 안에 든 성분(□ 속 잡티)은 괜찮다\n const others = comps.filter(o => o !== c && inBand(o) && !(o.x0 >= c.x0 && o.x1 <= c.x1 && o.y0 >= c.y0 && o.y1 <= c.y1))\n const apart = !others.some(o => o.x0 < c.x1 + 1 && o.x1 > c.x0 - 1)\n // 빗금은 이웃 숫자와 x 가 2px 까지 겹쳐도 된다(사선이라 촘촘히 짠 \"7/5\" 에서 양옆 숫자 밑·위로 들어간다)\n const nearlyApart = !others.some(o => Math.min(o.x1, c.x1) - Math.max(o.x0, c.x0) > 2)\n const spans: number[] = [], runs: number[] = []\n let n = 0\n for (let y = c.y0; y < c.y1; y++) {\n let s = 0, r = 0, prev = false\n for (let x = c.x0; x < c.x1; x++) { const on = label[y * w + x] === c.id; if (on) { s++; if (!prev) r++ } prev = on }\n spans.push(s); runs.push(r); n += s\n }\n const fill = n / (cw * ch), cy = ((c.y0 + c.y1) / 2 - bandT) / bh\n const band = Math.max(1, Math.round(ch * 0.15))\n const top = Math.max(...spans.slice(0, band)) / cw, bottom = Math.max(...spans.slice(ch - band)) / cw\n let mark: string | null = null\n const speck = Math.max(3, bh * 0.08)\n const dot = ch <= bh * 0.25 && cw <= bh * 0.25 && ch >= speck && cw >= speck && cw >= ch * 0.6 && cw <= ch * 1.6\n // 이웃 글자와 x 가 겹치거나(촘촘한 글꼴 \"개발·보급\") 2px 까지 작은 둥근 점은 공백 자리 대체용으로만 — 한글 자모엔 떨어진 둥근 점이 없다\n const small = ch <= bh * 0.25 && cw <= bh * 0.25 && ch >= 2 && cw >= 2 && cw >= ch * 0.6 && cw <= ch * 1.6 && fill >= 0.6 && cy >= 0.3 && cy <= 0.7\n if (!apart && !(nearlyApart && ch >= bh * 0.6)) { if (small) out.push({ x0: c.x0, x1: c.x1, mark: \"\\u00b7\\u0001\" }); continue }\n if (!apart) { /* 빗금 후보만 아래에서 */ } else if (dot && fill >= 0.6 && cy >= 0.3 && cy <= 0.7) mark = \"\\u00b7\"\n else if (small) mark = \"\\u00b7\\u0001\"\n else if (dot && fill >= 0.6 && cy >= 0.75 && cw >= ch * 0.8) mark = \".\" // 꼬리 달린 쉼표(세로로 긴 점)는 빼고\n else if (ch <= bh * 0.4 && ch >= speck && cw >= ch * 0.75 && cw <= ch * 1.3 && fill < 0.6 && runs[ch >> 1] === 2 && cy >= 0.6) mark = \"\\u3002\"\n else if (ch <= bh * 0.15 && cw >= ch * 2 && cw <= bh * 0.8 && fill >= 0.7 && cy >= 0.35 && cy <= 0.75) mark = \"-\"\n else if (ch >= bh * 0.5 && cw >= ch * 0.9 && cw <= ch * 1.4 && fill >= 0.4 && runs.every(r => r <= 1)\n && top <= 0.4 && bottom >= 0.8) mark = \"\\u25b2\"\n else if (ch >= bh * 0.3 && ch <= bh * 0.65 && fill < 0.5) {\n // 줄기 쪽 — 가로 변을 뺀 줄의 잉크 x 평균(폭 비). 「 는 왼쪽, 」 는 오른쪽 (한글 ㄱ·ㄴ 은 반대쪽이라 걸리지 않는다)\n const stem = (from: number, to: number) => {\n let sx = 0, k = 0\n for (let y = from; y < to; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) { sx += x - c.x0; k++ }\n return k ? sx / k / cw : 0.5\n }\n if (c.y0 <= bandT + bh * 0.15 && top >= 0.7 && bottom <= 0.5 && stem(c.y0 + band, c.y1) <= 0.35) mark = \"\\u300c\"\n else if (c.y1 >= bandB - bh * 0.15 && bottom >= 0.7 && top <= 0.5 && stem(c.y0, c.y1 - band) >= 0.65) mark = \"\\u300d\"\n } else if (ch >= charH * 0.6 && cw >= ch * 0.8 && cw <= ch * 1.25 && fill < 0.5 && top >= 0.8 && bottom >= 0.8\n && runs[ch >> 1] === 2) mark = ch <= charH * 0.92 ? \"\\u25a1\" : \"\\u25a1\\u0000\"\n // 빗금 / — 띠 높이 60% 이상의 가는 사선(폭이 높이의 0.25~0.7배, 줄마다 한 토막, 위쪽이 오른쪽으로 폭의 절반 넘게 치우침)\n if (!mark && ch >= bh * 0.6 && cw >= ch * 0.25 && cw <= ch * 0.7 && fill <= 0.4 && runs.every(r => r <= 1)) {\n const mx = (y: number) => { let sx = 0, k = 0; for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) { sx += x; k++ } return k ? sx / k : NaN }\n if (mx(c.y0 + band) - mx(c.y1 - 1 - band) >= cw * 0.5) mark = \"/\"\n }\n if (mark) out.push({ x0: c.x0, x1: c.x1, mark })\n }\n return { glyphs: out, bandH: bh }\n}\n\n/**\n * 줄 머리 고리 글머리 ○ / ㅇ — 모델은 같은 글리프를 \"O\"·\"ㅇ\" 로 오락가락 읽는다(장흥 계획 ○ 27개 중 9개가 ㅇ). cx(첫 글자의 CTC 자리)에\n * 가장 가까운 키 30% 이상 성분이 고리(가로세로 0.85~1.2배, 가운데 가로·세로줄 모두 두 토막)면 크기·채움으로 가른다 — 도형 ○ 는 글줄 띠\n * 높이의 0.65~1.0배에 획이 가늘고(폭의 10% 이하, 채움 0.23 이하 — 그림자 진 고리는 가는 쪽 획 8% 이하·채움 0.33 이하), 자모 ㅇ 은\n * 0.47~0.56배에 채움 0.24 이상(코퍼스 9문서 실측), 라틴 o 는 0.6~0.8배로 줄 아래쪽에 앉는다\n */\nexport function ringBullet(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): \"\\u25cb\" | \"\\u3147\" | \"o\" | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return null\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.6)\n const bandT = Math.min(...tall.map(c => c.y0)), bh = Math.max(...tall.map(c => c.y1)) - bandT\n let best: Comp | null = null, bestD = bh * 0.6\n for (const c of comps) {\n const d = Math.abs((c.x0 + c.x1) / 2 - cx)\n if (c.y1 - c.y0 >= bh * 0.3 && d < bestD) { bestD = d; best = c }\n }\n if (!best) return null\n const c = best, cw = c.x1 - c.x0, ch = c.y1 - c.y0\n if (cw < ch * 0.85 || cw > ch * 1.2) return null\n const runs = (xs: number[], at: (k: number) => boolean) => {\n let n = 0, len = 0, mx = 0, mn = Infinity\n for (const k of [...xs, -1]) { if (k >= 0 && at(k)) { if (!len) n++; len++; mx = Math.max(mx, len) } else { if (len) mn = Math.min(mn, len); len = 0 } }\n return { n, mx, mn }\n }\n const my = (c.y0 + c.y1) >> 1, mx = (c.x0 + c.x1) >> 1\n const row = runs(Array.from({ length: cw }, (_, k) => c.x0 + k), x => label[my * w + x] === c.id)\n const col = runs(Array.from({ length: ch }, (_, k) => c.y0 + k), y => label[y * w + mx] === c.id)\n if (row.n !== 2 || col.n !== 2) return null\n let n = 0\n for (let y = c.y0; y < c.y1; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) n++\n const fill = n / (cw * ch), rel = ch / bh\n // 그림자 진 고리(한쪽 획만 두꺼움 — ❍, 글꼴에 따라 ○ 도 이렇게 그려진다)도 가는 쪽 획이 가늘면 도형 ○\n if (rel >= 0.62 && (fill <= 0.23 ? row.mx <= cw * 0.1 : fill <= 0.33 && row.mn <= cw * 0.08)) return \"\\u25cb\"\n if (rel <= 0.58 && fill >= 0.24) return \"\\u3147\"\n // 라틴 소문자 o — x 높이(띠 0.6~0.8배)로 줄 아래쪽에 앉은 굵은 고리(속초 예산서 \"o 기본급\", 모델은 숫자 0 으로 읽음). 숫자 0 은 세로로 길고\n // (폭/높이 0.58) 자모 ㅇ 은 띠 가운데(0.41~0.51)에 뜬다\n if (rel >= 0.6 && rel <= 0.8 && fill >= 0.3 && ((c.y0 + c.y1) / 2 - bandT) / bh >= 0.55) return \"o\"\n return null\n}\n\n/** cx 자리 성분이 큰 속 찬 원(●)인가 — 글줄 띠 높이의 45~105%, 가로세로 0.8~1.25배, 채움 0.65~0.9. 가운뎃점은 크게 그려도 띠의 32% 안팎 */\nexport function discAt(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): boolean {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return false\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.6)\n const bh = Math.max(...tall.map(c => c.y1)) - Math.min(...tall.map(c => c.y0))\n const c = comps.filter(o => Math.abs((o.x0 + o.x1) / 2 - cx) <= bh * 0.4).sort((a, b) => Math.abs((a.x0 + a.x1) / 2 - cx) - Math.abs((b.x0 + b.x1) / 2 - cx))[0]\n if (!c) return false\n const cw = c.x1 - c.x0, ch = c.y1 - c.y0\n if (ch < bh * 0.45 || ch > bh * 1.05 || cw < ch * 0.8 || cw > ch * 1.25) return false\n let n = 0\n for (let y = c.y0; y < c.y1; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) n++\n const fill = n / (cw * ch)\n return fill >= 0.65 && fill <= 0.9\n}\n\n/**\n * 숫자 1 로 읽은 로마 숫자 Ⅰ — 세리프 Ⅰ 은 윗머리·아랫머리가 줄기 양쪽으로 고르게 뻗고, 숫자 1 은 윗머리가 왼쪽(깃)으로만 뻗는다\n * (코퍼스 실측: Ⅰ 좌우 0.8·0.8·1.3·1.3 줄기 폭, 숫자 1 오른쪽 0). cx 자리를 품는 가장 키 큰 성분의 위·아래 20% 줄 잉크 범위를\n * 가운데 줄(40~60%) 줄기와 견준다. 세리프 없는 막대는 가를 수 없어 false\n */\nexport function serifOne(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): boolean {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return false\n const c = comps.filter(o => o.x0 - 3 <= cx && o.x1 + 3 >= cx && o.y1 - o.y0 >= charH * 0.6).sort((a, b) => (b.y1 - b.y0) - (a.y1 - a.y0))[0]\n if (!c) return false\n const ch = c.y1 - c.y0\n const span = (a: number, b: number) => {\n let mn = Infinity, mx = -1\n for (let y = c.y0 + Math.floor(ch * a); y < c.y0 + Math.ceil(ch * b); y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) { mn = Math.min(mn, x); mx = Math.max(mx, x) }\n return [mn, mx]\n }\n const [m0, m1] = span(0.4, 0.6), [t0, t1] = span(0, 0.2), [b0, b1] = span(0.8, 1)\n const sw = m1 - m0 + 1\n const even = (l: number, r: number) => l >= sw * 0.4 && r >= sw * 0.4 && Math.abs(l - r) <= Math.max(l, r) * 0.35\n return sw >= 2 && sw <= ch * 0.3 && even(m0 - t0, t1 - m1) && even(m0 - b0, b1 - m1)\n}\n\n/**\n * 이어진 별표 수 — CTC 는 같은 글자가 붙어 나오면 하나로 합친다(\"등록증**\" → \"등록증*\"). cx(별표 글자의 CTC 자리)에 가장 가까운 별표\n * 꼴 조각(글줄 띠 높이 20~50%, 가로세로 0.7~1.4배, 채움 0.25~0.65, 띠 위쪽 절반)에서 좌우로 틈이 조각 폭 이하인 같은 꼴 조각을 센다\n */\nexport function starRun(gray: Uint8Array, w: number, h: number, ink: InkStats, cx: number): number {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return 0\n const tall = comps.filter(c => c.y1 - c.y0 >= charH * 0.6)\n const bandT = Math.min(...tall.map(c => c.y0)), bh = Math.max(...tall.map(c => c.y1)) - bandT\n const star = (c: Comp) => {\n const cw = c.x1 - c.x0, ch = c.y1 - c.y0\n if (ch < bh * 0.2 || ch > bh * 0.5 || cw < ch * 0.7 || cw > ch * 1.4 || ((c.y0 + c.y1) / 2 - bandT) / bh > 0.55) return false\n let n = 0\n for (let y = c.y0; y < c.y1; y++) for (let x = c.x0; x < c.x1; x++) if (label[y * w + x] === c.id) n++\n const fill = n / (cw * ch)\n return fill >= 0.25 && fill <= 0.65\n }\n const stars = comps.filter(star).sort((a, b) => a.x0 - b.x0)\n const k = stars.findIndex(c => cx >= c.x0 - (c.x1 - c.x0) && cx <= c.x1 + (c.x1 - c.x0))\n if (k < 0) return 0\n let lo = k, hi = k\n while (lo > 0 && stars[lo].x0 - stars[lo - 1].x1 <= stars[lo].x1 - stars[lo].x0) lo--\n while (hi + 1 < stars.length && stars[hi + 1].x0 - stars[hi].x1 <= stars[hi].x1 - stars[hi].x0) hi++\n return hi - lo + 1\n}\n\n/** 【】 로 볼 기울기 줄 비율 — 코퍼스 실측 [ ] 최대 0.13, 【】 최소 0.19 */\nconst BRACKET_TAPER = 0.16\n\n/** 【】 로 볼 채움·폭 하한 — 【】 는 속이 찬 렌즈 꼴로 폭이 글자 높이의 0.28~0.44배·기울기 줄 0.24~0.65(코퍼스 실측), 모서리가 둥근\n * 소괄호 ( ) 는 기울기 줄이 있어도 좁고 적다(굵은 압축 글꼴 0.22~0.25배·0.17~0.25 — 방송통신위원회 보도자료·산림청 공고에서 모델이 [ ] 로 읽음) */\nconst BRACKET_SOLID = 0.4\nconst BRACKET_WIDE = 0.265\nconst BRACKET_LENS = 0.35\n\n/** 괄호 모양 판별 — 모를 때 null (인식 결과 [ ] 를 둔다). 곧은 ㄱ·ㄴ 꼴은 「」, 휜 조각(기울기 줄)은 ( ) */\nexport function bracketShape(f: BracketFeatures, close: boolean): string | null {\n const [near, far] = close ? [f.bottom, f.top] : [f.top, f.bottom]\n const paren = close ? \")\" : \"(\"\n if (near >= 0.7 && far <= 0.5) return f.taper < BRACKET_TAPER ? (close ? \"\\u300d\" : \"\\u300c\") : paren\n if (near >= 0.7 && far >= 0.7 && f.taper >= BRACKET_TAPER) {\n return f.fill >= BRACKET_SOLID && (f.cw >= f.ch * BRACKET_WIDE || f.taper >= BRACKET_LENS) ? (close ? \"\\u3011\" : \"\\u3010\") : paren\n }\n return null\n}\n\n\n/**\n * 박스 맨 앞 글머리 기호 — 인식 사전에 없거나(◎ ▪) 모델이 작은 점으로 읽거나(● → •·) 통째로 빠뜨리는(□) 공문서 글머리를 잉크 조각 모양으로 가른다.\n * 맨 앞 덩어리(x 가 겹치는 성분 묶음)가 글자 높이 대비 크기·채움·겹침으로:\n * ◎ 이중 원 — 성분 둘 이상이 안팎으로 겹치고 속이 빈 둥근 조각 (함평 계획 21개가 \"O\")\n * ● 큰 속 찬 원 — 채움 0.65~0.88(원 π/4≈0.79), 글자 높이 0.45배 이상 (교육청 안내문 17개가 \"•\"·누락)\n * ▪ 작은 속 찬 네모 — 채움 0.9 이상, 글자 높이 0.28~0.6배 (가운뎃점 \"·\" 은 0.21배 안팎)\n * 속 빈 원(○·ㅇ·❍)은 픽셀로 못 가르니 건드리지 않는다. firstX 는 첫 인식 글자의 CTC 자리(박스 로컬) —\n * 덩어리가 그 앞에서 끝나면 인식에서 빠진 것, 그 글자 자리에 걸치면 그 글자가 이 기호를 잘못 읽은 것이다\n */\nexport function leadingBullet(gray: Uint8Array, w: number, h: number, ink: InkStats, firstX: number): { mark: \"◎\" | \"●\" | \"▪\" | \"□\"; covers: boolean } | null {\n const { comps, label } = components(gray, w, h, ink)\n let charH = 0\n for (const c of comps) charH = Math.max(charH, c.y1 - c.y0)\n if (charH < 10) return null\n const cand = comps.filter(c => c.y1 - c.y0 >= charH * 0.15).sort((a, b) => a.x0 - b.x0)\n const first = cand[0]\n if (!first) return null\n const cl = cand.filter(c => c.x0 < first.x1 && c.x1 > first.x0)\n const x0 = Math.min(...cl.map(c => c.x0)), x1 = Math.max(...cl.map(c => c.x1)), y0 = Math.min(...cl.map(c => c.y0)), y1 = Math.max(...cl.map(c => c.y1))\n const cw = x1 - x0, ch = y1 - y0\n if (cw < ch * 0.8 || cw > ch * 1.25) return null\n // 덩어리 뒤에 틈이 있어야 글머리다 (글자 획이 아님). 기호 하나만 든 상자(목차 열의 ◎)는 뒤가 비어 있다\n const next = cand.find(c => c.x0 >= x1)\n if (next && next.x0 - x1 < ch * 0.3) return null\n let inkN = 0\n for (let y = y0; y < y1; y++) for (let x = x0; x < x1; x++) if (cl.some(c => label[y * w + x] === c.id)) inkN++\n const fill = inkN / (cw * ch)\n const rel = ch / charH\n // 이중 원 — 안쪽 조각도 가운데 놓인 둥근 고리여야 한다 (원문자 ①② 는 안쪽이 숫자라 좁다)\n const ring = (c: Comp) => { const a = c.x1 - c.x0, b = c.y1 - c.y0; return a >= b * 0.75 && a <= b * 1.33 }\n const nested = cl.length >= 2 && cl.some(a => cl.some(b => a !== b && b.x0 > a.x0 && b.x1 < a.x1 && b.y0 > a.y0 && b.y1 < a.y1 && ring(b)\n && Math.abs((b.x0 + b.x1) - (a.x0 + a.x1)) <= (a.x1 - a.x0) * 0.2 && Math.abs((b.y0 + b.y1) - (a.y0 + a.y1)) <= (a.y1 - a.y0) * 0.2))\n // 속 빈 정사각 □ — 윗·아랫 띠(높이 15%)가 폭 80% 넘게 차고 가운데 줄이 양끝 두 획뿐. 글자 높이의 0.6~0.92배\n // (제목 앞 도형 네모는 글자 높이만큼 커 0.98배, 한글 첫소리 ㅁ 은 인식된 글자라 covers 로 걸러진다)\n const span = (y: number) => { let n = 0; for (let x = x0; x < x1; x++) if (cl.some(c => label[y * w + x] === c.id)) n++; return n }\n const band = Math.max(1, Math.round(ch * 0.15))\n const edgeFull = (from: number, dir: 1 | -1) => { let m = 0; for (let k = 0; k < band; k++) m = Math.max(m, span(from + dir * k)); return m >= cw * 0.8 }\n let midRuns = 0\n { let prev = false; const my = y0 + (ch >> 1); for (let x = x0; x < x1; x++) { const on = cl.some(c => label[my * w + x] === c.id); if (on && !prev) midRuns++; prev = on } }\n const hollowSquare = cl.length === 1 && fill < 0.5 && midRuns === 2 && edgeFull(y0, 1) && edgeFull(y1 - 1, -1)\n let mark: \"\\u25ce\" | \"\\u25cf\" | \"\\u25aa\" | \"\\u25a1\" | null = null\n if (hollowSquare && rel >= 0.6 && rel <= 0.92) mark = \"\\u25a1\"\n else if (nested && fill < 0.45 && rel >= 0.6) mark = \"\\u25ce\"\n else if (cl.length === 1 && fill >= 0.9 && rel >= 0.28 && rel <= 0.6) mark = \"\\u25aa\"\n else if (cl.length === 1 && fill >= 0.65 && fill <= 0.88 && rel >= 0.5 && rel <= 0.8) mark = \"\\u25cf\"\n if (!mark) return null\n return { mark, covers: firstX <= x1 + ch * 0.3 }\n}\n","/**\n * 인식 결과 글리프 되살리기 — CTC 글자 자리(steps × stepPx, 박스 로컬 x)를 박스 픽셀로 옮겨 그 자리 잉크 조각 모양으로, 사전 밖이거나\n * 모델이 줄여·바꿔·빠뜨려 읽는 글자를 고친다(괄호 「」【】·여는 따옴표·원문자·로마 숫자·두 글자 사이에서 빠진 기호). 모양 판정은\n * line-split.ts, 여기는 글자열 배선만. 글자 배열은 CTC 글자와 1:1 로 두고 칸마다 바꿔 넣거나(빈 글·여러 글자 허용) 끝에 잇는다\n */\nimport { bracketFeatures, bracketShape, circledAt, discAt, gapGlyphs, grayCrop, inkStats, quoteHead, ringBullet, romanStems, serifOne, starRun } from \"./line-split.js\"\nimport type { InkStats } from \"./line-split.js\"\nimport type { Box } from \"./crop.js\"\n\ninterface Ctx { chars: string[]; cx: (i: number) => number; gray: Uint8Array; w: number; h: number; ink: InkStats }\n\n/** text 는 CTC 글자와 1:1 이어야 한다 — 아니면 그대로 돌려준다. note.ringLead: 줄 머리 고리를 픽셀로 정했다(restoreSymbols 의 O → ○ 를 건너뛸 것) */\nexport function restoreGlyphs(rgba: Uint8Array, pageW: number, box: Box, text: string, steps: number[], stepPx: number, note: { ringLead?: boolean } = {}): string {\n const chars = [...text]\n if (chars.length !== steps.length) return text\n const gray = grayCrop(rgba, pageW, box)\n const c: Ctx = { chars, cx: i => (steps[i] + 0.5) * stepPx, gray, w: box.w, h: box.h, ink: inkStats(gray) }\n if (/[[\\]]/.test(text)) brackets(c)\n if (/['\"]/.test(text)) quotes(c)\n if (/(^|\\D)[1-9](\\D|$)/.test(text)) circled(c)\n if (text.includes(\"*\")) stars(c)\n if (/[\\u00b7\\u2022]/.test(text)) discs(c)\n gaps(c)\n note.ringLead = ring(c)\n if (/[I1Ⅰ-Ⅲ]|^\\s*\\./.test(text)) roman(c)\n return chars.join(\"\")\n}\n\n/**\n * 사전 밖 괄호 — 인식 사전에 「」·【】 가 없어 모델은 모두 [ ] 로 읽는다(코퍼스 정답 「」44·「」23·【】41·[]159 쌍 ↔ OCR [ 274).\n * [ ] 자리 잉크 조각이 속이 찬 조각이면 【】, 윗변 가로 획만이면 「, 아랫변 가로 획만이면 」 ([ ] 는 위아래 모두)\n */\nfunction brackets({ chars, cx, gray, w, h, ink }: Ctx) {\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] !== \"[\" && chars[i] !== \"]\") continue\n const f = bracketFeatures(gray, w, h, ink, cx(i))\n const shape = f && bracketShape(f, chars[i] === \"]\")\n if (shape) chars[i] = shape\n }\n}\n\n/**\n * 여는 따옴표 — 곧은 ' \" 로 읽은 자리의 머리가 뚜렷이 아래(line-split quoteHead ≥ 0.47, 실측 닫는 따옴표 최대 0.46 바로 위)면 ‘ “ 로 정한다. smartQuotes 문맥 규칙은\n * 연도 생략을 늘 ’ 로 두는데 \"(‘11.3월 구성)\"처럼 여는 따옴표로 쓴 문서가 있다. 닫는 쪽은 글꼴마다 겹쳐(작은 글씨 여는 따옴표 0.23~0.45,\n * 닫는 0.28~0.46 — 코퍼스 61곳 실측) 문맥에 맡긴다\n */\nfunction quotes({ chars, cx, gray, w, h, ink }: Ctx) {\n // smartQuotes 는 남은 곧은 따옴표를 홀짝으로 여닫으니, 짝 계산에 드는 자리를 바꾸면 나머지가 어긋난다 — 짝에서 빠지는\n // 연도 생략('24)과 그 줄에 하나뿐인 곧은 따옴표만 본다. 짝을 기다리는 여는 따옴표 뒤는 닫는 자리다(모델이 여는 쪽만 ‘ 로 읽은 줄)\n const year = (i: number) => chars[i] === \"'\" && !/[\\p{L}\\p{N}]/u.test(chars[i - 1] ?? \"\") && /^\\d{2}(?!\\d)/.test(chars.slice(i + 1, i + 4).join(\"\"))\n const single = { \"'\": chars.filter((c, i) => c === \"'\" && !year(i)).length === 1, '\"': chars.filter(c => c === '\"').length === 1 }\n const open = { \"'\": false, '\"': false }\n for (let i = 0; i < chars.length; i++) {\n const c = chars[i]\n const kind = c === \"'\" || c === \"‘\" || c === \"’\" ? \"'\" : c === '\"' || c === \"“\" || c === \"”\" ? '\"' : null\n if (!kind) continue\n if (c !== kind) { open[kind] = c === \"‘\" || c === \"“\"; continue }\n if (open[kind]) { open[kind] = false; continue }\n if (!year(i) && !single[kind]) continue\n const r = quoteHead(gray, w, h, ink, cx(i))\n if (r !== null && r >= 0.47) { chars[i] = kind === \"'\" ? \"‘\" : \"“\"; open[kind] = true }\n }\n}\n\n/** 원문자 숫자 — 모델이 고리를 버리고 읽은 홀로 선 숫자 1~9(앞뒤가 숫자 아님)를 그 자리 고리 성분(line-split circledAt)으로 ①~⑨ */\nfunction circled({ chars, cx, gray, w, h, ink }: Ctx) {\n const at = chars.flatMap((c, i) => /^[1-9]$/.test(c) && !/\\d/.test(chars[i - 1] ?? \"\") && !/\\d/.test(chars[i + 1] ?? \"\") ? [i] : [])\n if (!at.length) return\n const hit = circledAt(gray, w, h, ink, at.map(cx))\n at.forEach((i, k) => { if (hit[k]) chars[i] = String.fromCharCode(0x245f + Number(chars[i])) })\n}\n\n/** 별표 겹침 — CTC 가 붙은 같은 글자를 하나로 합친 \"**\" → \"*\" 를 그 자리 별표 조각 수(line-split starRun)만큼 채운다 */\nfunction stars({ chars, cx, gray, w, h, ink }: Ctx) {\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] !== \"*\" || chars[i - 1] === \"*\") continue\n let e = i\n while (chars[e + 1] === \"*\") e++\n const n = starRun(gray, w, h, ink, cx(i))\n if (n > e - i + 1 && n <= 4) chars[e] += \"*\".repeat(n - (e - i + 1))\n i = e\n }\n}\n\n/** 큰 속 찬 원 ● — 모델은 줄 중간 글머리 ● 를 가운뎃점 · · • 로 줄여 읽는다(목차 \"…171●부록●186\") */\nfunction discs({ chars, cx, gray, w, h, ink }: Ctx) {\n for (let i = 0; i < chars.length; i++) if (/^[\\u00b7\\u2022]$/.test(chars[i]) && discAt(gray, w, h, ink, cx(i))) chars[i] = \"\\u25cf\"\n}\n\n/**\n * 두 글자 사이에서 빠진 기호 — 빈 열로 떨어진 잉크 조각의 모양(line-split gapGlyphs)이 · . 。 ▲ 「 」 □ 인데 그 가까이(글자 간격 0.45)에\n * CTC 글자 자리가 없으면 앞 글자 뒤에 넣는다. 모델은 가운뎃점을 공백으로 읽기도 해(\"개발·보급\" → \"개발 보급\") 그 구간의 공백은\n * · 로 바꾸고, □ 는 0·O 로 읽기도 해(\"□□-□□□\" → \"00-000\") 그 구간의 한 글자가 그것이면 바꾼다\n */\nfunction gaps({ chars, cx, gray, w, h, ink }: Ctx) {\n const { glyphs, bandH } = gapGlyphs(gray, w, h, ink)\n if (!glyphs.length) return\n const live = chars.map((c, i) => i).filter(i => chars[i].trim())\n if (!live.length) return\n // 글자 간격 — 이웃한 한글 두 자의 CTC 자리 차 중앙값(없으면 글줄 띠 높이). 조각 가운데에서 0.45 간격 안에 글자 자리가 있으면 덮인 것\n // (작은 점은 CTC 자리가 조각 x 구간을 1~2px 비껴 조각 구간만 보면 이미 읽은 \"·\" 옆에 또 넣었다)\n const d: number[] = []\n for (let k = 0; k + 1 < live.length; k++) if (/[가-힣]$/.test(chars[live[k]]) && /^[가-힣]/.test(chars[live[k + 1]])) d.push(cx(live[k + 1]) - cx(live[k]))\n const pitch = d.length >= 2 ? d.sort((a, b) => a - b)[d.length >> 1] : bandH\n const nearTo = (g: { x0: number; x1: number }) => (i: number) => Math.abs(cx(i) - (g.x0 + g.x1) / 2) <= Math.max(pitch * 0.45, (g.x1 - g.x0) / 2 + 1)\n const loose = glyphs.filter(g => /^[\\u00b7.]/.test(g.mark) && !live.some(nearTo(g)))\n for (const g of glyphs.sort((a, b) => a.x0 - b.x0)) {\n const mid = (g.x0 + g.x1) / 2\n const near = nearTo(g)\n const cover = live.filter(near)\n if (g.mark === \"\\u00b7\\u0001\") {\n // 작은 점·글자에 붙은 점은 모델이 공백으로 읽은 자리만(덮임 판정 앞 — 공백 자리가 증거다) — 다른 점이 늘어서지 않고 앞뒤가 글자일 때\n const sp = chars.findIndex((c, i) => c === \" \" && near(i))\n const p = sp >= 0 ? chars.slice(0, sp).reverse().find(c => c.trim()) : undefined, q = sp >= 0 ? chars.slice(sp + 1).find(c => c.trim()) : undefined\n // 앞뒤 모두 한글 — 라틴 글은 소문자 i·j 의 점이 공백 옆에 붙어 걸렸다(\"Keeps open\" → \"Keeps·open\", ODL 106)\n if (p && q && /[가-힣]$/.test(p) && /^[가-힣]/.test(q) && !loose.some(o => o !== g && Math.abs((o.x0 + o.x1) / 2 - mid) <= pitch * 1.5)) chars[sp] = \"\\u00b7\"\n continue\n }\n if (cover.length) {\n if (g.mark.startsWith(\"\\u25a1\") && cover.length === 1 && /^[0Oo\\u25cb]$/.test(chars[cover[0]])) chars[cover[0]] = \"\\u25a1\"\n continue\n }\n if (g.mark === \"\\u25a1\\u0000\") continue\n // 앞뒤 글자 사이 — 줄 끝은 마침표만(문장 끝 \"…습니다.\")\n const before = live.filter(i => cx(i) < mid), after = live.filter(i => cx(i) > mid)\n // 줄 머리는 뒤가 한글인 。 · 「 ▲ 만(예산서 세부 항목 \"。사무실운영\" — □ 는 glyph 판정이 엄한 leadingBullet 몫)\n if (!before.length) {\n if (after.length && /^[\\u3002\\u00b7\\u300c\\u25b2]$/.test(g.mark) && /^[가-힣]/.test(chars[after[0]])) chars[after[0]] = g.mark + chars[after[0]]\n // 쪽번호 꼬리말 \"- 1 -\" 를 \"1 -\" 로 읽은 줄 — 뒤 막대가 읽혔으면 앞 막대도 붙인다\n else if (g.mark === \"-\" && /^[\\dⅰ-ⅹivx]+\\s*-$/.test(chars.join(\"\").trim())) chars[after[0]] = \"-\" + chars[after[0]]\n continue\n }\n if (!after.length && g.mark !== \".\") continue\n if (g.mark === \"/\" && !(/\\d$/.test(chars[before[before.length - 1]]) && /^\\d/.test(chars[after[0]]))) continue // 빗금은 숫자 사이만(분수)\n const prev = chars[before[before.length - 1]], next = after.length ? chars[after[0]] : \"\"\n if (g.mark === \"\\u00b7\" || g.mark === \".\") {\n // 목차 리더·말줄임(안 읽힌 점이 둘 이상 늘어섬, 옆 글자가 … · .)은 빠진 기호가 아니다. 가운뎃점은 쪽번호 앞 점도 아니다\n if (loose.some(o => o !== g && Math.abs((o.x0 + o.x1) / 2 - mid) <= pitch * 1.5)) continue\n if (/[\\u2026.\\u00b7]$/.test(prev) || /^[\\u2026.\\u00b7]/.test(next)) continue\n }\n if (g.mark === \"\\u00b7\") {\n if (/^\\d/.test(next)) continue\n const sp = chars.findIndex((c, i) => c === \" \" && near(i))\n if (sp >= 0) { chars[sp] = g.mark; continue }\n }\n chars[before[before.length - 1]] += g.mark\n }\n}\n\n/**\n * 줄 머리 고리 글머리 — 첫 글자가 ㅇ·O·o·0·○ 이고 뒤가 한글(여는 괄호 뒤 한글 포함)이면 그 자리 고리의 크기·채움(line-split ringBullet)으로 ○ / ㅇ / o 를 정한다.\n * 모델이 같은 도형 ○ 를 \"O\"(→ restoreSymbols 가 ○)·\"ㅇ\" 로 오락가락 읽고, 자모 글머리 ㅇ 도 \"O\" 로 읽어 ○ 가 됐다\n */\nfunction ring({ chars, cx, gray, w, h, ink }: Ctx): boolean {\n const k = chars.findIndex(c => c.trim())\n if (k < 0 || !/^[\\u3147Oo0\\u25cb]$/.test(chars[k])) return false\n // 뒤 글이 한글이거나 여는 괄호 뒤 한글(\"❍(정책) 민생성장\")\n const rest = chars.slice(k + 1).join(\"\").trimStart()\n if (!/^[(\\[「【<]?[가-힣]/.test(rest)) return false\n const r = ringBullet(gray, w, h, ink, cx(k))\n if (r) chars[k] = r\n return r !== null\n}\n\n/**\n * 로마 숫자 획 수 — 모델은 한 글리프 Ⅲ 을 \"II\"·\"I\" 로, Ⅱ 를 \"I\" 로 줄여 읽는다(장 제목 \"Ⅲ. 2026년 …\" → \"II. 2026년 …\").\n * 라틴 글자에 붙지 않은 I·Ⅰ~Ⅲ 토막마다 그 자리 세로 획 수(line-split romanStems)를 세어 읽은 수와 다르면 Ⅰ~Ⅲ 한 글자로 바꾼다\n * (토막 첫 칸에 넣고 나머지 칸은 비운다). 숫자를 빠뜨리고 \".\" 부터 읽은 줄은 점 앞 잉크로 채운다\n */\nfunction roman({ chars, cx, gray, w, h, ink }: Ctx) {\n const ROMAN = /^[IⅠ-Ⅲ]$/, LATIN = /[A-Za-z]$/\n // 숫자 1 로 읽은 Ⅰ — 앞뒤가 숫자·라틴 글자가 아닌 홀로 선 1 이 좌우 대칭 세리프면(line-split serifOne). \"토픽1\" → \"토픽Ⅰ\"\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] !== \"1\" || /[\\dA-Za-z]$/.test(chars[i - 1] ?? \"\") || /^[\\dA-Za-z,]/.test(chars[i + 1] ?? \"\")) continue\n if (serifOne(gray, w, h, ink, cx(i))) chars[i] = \"Ⅰ\"\n }\n // 로마 숫자에 붙은 1 은 같은 토막으로 센다 (\"[표 Ⅱ-4]\" → \"[표I1-4]\")\n const inRoman = (i: number) => ROMAN.test(chars[i]) || (chars[i] === \"1\" && (ROMAN.test(chars[i - 1] ?? \"\") || ROMAN.test(chars[i + 1] ?? \"\")))\n // 숫자를 통째로 빠뜨리고 \".\" 부터 읽은 제목 줄(\".세입·세출 …\") — 점 앞 잉크가 세로 획이면 되살린다\n const k = chars.findIndex(c => c.trim())\n if (chars[k] === \".\" && chars.slice(k + 1).some(c => /[가-힣A-Za-z0-9]/.test(c))) {\n const n = romanStems(gray, w, h, ink, -Infinity, cx(k))\n if (n) chars[k] = String.fromCharCode(0x215f + n) + chars[k]\n }\n for (let s = 0; s < chars.length;) {\n if (!inRoman(s) || (s > 0 && LATIN.test(chars[s - 1]))) { s++; continue }\n let e = s\n while (e < chars.length && inRoman(e)) e++\n const tok = chars.slice(s, e).join(\"\")\n if (e < chars.length && /^[A-Za-z]/.test(chars[e])) { s = e; continue }\n let p = s - 1, q = e\n while (p >= 0 && !chars[p].trim()) p--\n while (q < chars.length && !chars[q].trim()) q++\n const n = romanStems(gray, w, h, ink, p >= 0 ? cx(p) : -Infinity, q < chars.length ? cx(q) : Infinity)\n const canon = n ? [[\"Ⅰ\", \"I\"], [\"Ⅱ\", \"II\"], [\"Ⅲ\", \"III\"]][n - 1] : null\n if (canon && !canon.includes(tok)) { chars[s] = canon[0]; for (let i = s + 1; i < e; i++) chars[i] = \"\" }\n s = e\n }\n}\n","/**\n * OCR 인식 문자열 후처리 — 한국 공문서 표기 관행 복원.\n *\n * PP-OCRv5 korean 인식기의 사전(11,945자)에는 공문서 글머리·표기 기호 일부가 없다\n * (○ U+25CB·△ U+25B3·◎·■·「」·【】 — 사전 실측). 모델은 사전 안의 닮은 글자로\n * 읽는다: ○ → 라틴 O(코퍼스 박스 단위 실측 145회)·o, △ → 증가 기호 ∆(29회).\n * 공문서에서 쓰이지 않는 쪽만 되돌린다 — 모호한 것(ㅇ 글머리는 실제 자모, 0 은\n * \"0원\" 같은 숫자)은 건드리지 않는다.\n *\n * 따옴표: 모델은 ‘ ’ 를 곧은 ' 로 읽는다(114회). 공문서 텍스트층은 둥근 따옴표가 압도적\n * (코퍼스 GT ‘’ 129 : ' 7 — 한컴 자동 고침) → 여닫음 문맥으로 둥근 따옴표를 복원한다.\n */\n\nconst HANGUL_START = /^[\\uac00-\\ud7a3]/\n\n/** 박스 텍스트 한 줄 후처리 (위치 독립 규칙) */\nexport function restoreSymbols(text: string, ringDecided = false): string {\n let s = text\n // ○ 글머리: 줄 머리 O/o + (공백) + 한글 — 줄 머리 고리를 픽셀로 이미 정했으면(glyph-restore ring) 건너뛴다\n if (!ringDecided) s = s.replace(/^([Oo])(\\s?)(?=[\\uac00-\\ud7a3])/, \"\\u25cb$2\")\n // ○○ 자리표시(○○시·○○○ 과장): 라틴 글자와 붙지 않은 O 2개 이상이 한글과 (공백 하나 사이로) 이웃\n s = s.replace(/(?<![A-Za-z])O{2,}(?![A-Za-z])/g, (m, i: number) =>\n /[\\uac00-\\ud7a3]$/.test(s.slice(Math.max(0, i - 2), i).trimEnd()) || /^\\s?[\\uac00-\\ud7a3]/.test(s.slice(i + m.length))\n ? \"\\u25cb\".repeat(m.length) : m)\n // △ 감액 표시: 사전 밖 → ∆(U+2206)·그리스 Δ(U+0394) 로 읽힘\n s = s.replace(/[\\u2206\\u0394]/g, \"\\u25b3\")\n // \"(cid:NN)\" 은 PDF 텍스트 추출기가 유니코드 없는 글리프에 쓰는 표기 — 인식기가 학습 자료에서 배워 티끌·가는\n // 막대 박스에 낸다(pcccr·rda-planfarm·yeosu 실측, 박스 5~16px). 인쇄된 글자일 수 없으니 지운다\n s = s.replace(/\\(cid:\\d*\\)/g, \"\")\n return smartQuotes(joinDigitGroups(s))\n}\n\n/**\n * 천 단위 숫자 안의 끼어든 공백 제거 — 모델이 쉼표 뒤에 공백을 넣는다(\"385, 426\"·\"4,802, 164\",\n * 예산서 표에서 수십 회 실측). 쉼표 앞이 1~3자리, 뒤가 정확히 3자리인 무리만 잇는다\n * (\"1, 2, 3\" 같은 목록·\"10, 20명\"은 뒤가 3자리가 아니라 그대로).\n */\nexport function joinDigitGroups(s: string): string {\n return s.replace(/(?<![\\d,])\\d{1,3}(?:, ?\\d{3})+(?![\\d])/g, m => m.replace(/, /g, \",\"))\n}\n\n/**\n * 곧은 따옴표 → 둥근 따옴표. 한 줄 안의 따옴표를 짝으로 보고 여닫음을 번갈아 준다 —\n * OCR 띄어쓰기가 불안정해(\"내에서'기록관리시스템'\") 앞 글자가 공백인지로는 여는 자리를\n * 가를 수 없다. 개수가 홀수면(줄바꿈에 걸친 인용) 첫 따옴표가 여는 자리(줄 머리·공백·\n * 여는 괄호 뒤)가 아닐 때 닫는 것부터. 연도 생략 '24 는 짝에서 빼고 ’.\n */\nexport function smartQuotes(s: string): string {\n if (!/['\"]/.test(s)) return s\n const chars = [...s]\n for (const q of [\"'\", '\"']) {\n const [open, close] = q === \"'\" ? [\"\\u2018\", \"\\u2019\"] : [\"\\u201c\", \"\\u201d\"]\n const pos: number[] = []\n for (let i = 0; i < chars.length; i++) {\n if (chars[i] !== q) continue\n const prev = i > 0 ? chars[i - 1] : \"\"\n if (q === \"'\" && !/[\\p{L}\\p{N}]/u.test(prev) && /^\\d{2}(?!\\d)/.test(chars.slice(i + 1, i + 4).join(\"\"))) {\n chars[i] = close // 연도 생략\n continue\n }\n pos.push(i)\n }\n if (pos.length === 0) continue\n const first = pos[0]\n const prev = first > 0 ? chars[first - 1] : \"\"\n const atOpen = prev === \"\" || /[\\s(\\[{<\\u300c\\u300e\\u3010\\u3008\\u300a\\u2018\\u201c·,:]/.test(prev)\n let isOpen = pos.length % 2 === 0 || atOpen\n for (const i of pos) { chars[i] = isOpen ? open : close; isOpen = !isOpen }\n }\n return chars.join(\"\")\n}\n\n/** 점류만으로 된 조각 — 목차 리더·잡티(\".\", \"..\", \"…\", \"·\"). 단독으로는 뜻이 없다 */\nexport function isDotFragment(text: string): boolean {\n return /^[\\s.\\u00b7\\u2024\\u2025\\u2026\\u2027\\u2219\\u22c5\\u318d]+$/.test(text)\n}\n\ntype Placed = { text: string; x: number; y: number; w: number; h: number; confidence: number }\n\n/**\n * 목차 한 줄 잇기. 텍스트층은 목차 줄을 리더 글자까지 한 아이템(\"제목 ······ 12\")으로 주는데, 검출기는 리더\n * 가운데를 비워 [제목 ···] [··· 12] 두 박스로 낸다. 그러면 줄마다 큰 틈이 생겨 클러스터 표 감지가 목차·머리\n * 영역을 표로 잡고, 그 뒤 2단 본문을 줄 단위로 섞어 읽었다(assembly-minutes-1179 1면 — 목차 쪽번호 하나를 더\n * 제대로 읽자 표 감지가 발화). 엔진이 박스 끝에서 확인한 리더 점(ends: lead = 박스가 점으로 시작, trail = 점으로\n * 끝남)이 마주 보는 같은 줄 가장 가까운 이웃과 \"제목 … 12\" 한 아이템으로 합친다.\n */\nexport function joinLeaderItems<T extends Placed>(items: T[], ends: Map<T, { lead: boolean; trail: boolean }>): T[] {\n const gone = new Set<T>()\n const sameLine = (a: T, b: T) => Math.abs(a.y + a.h / 2 - (b.y + b.h / 2)) <= Math.max(a.h, b.h) / 2\n const merge = (left: T, right: T): void => {\n const x2 = Math.max(left.x + left.w, right.x + right.w), y2 = Math.max(left.y + left.h, right.y + right.h)\n left.text = left.text.replace(/\\s*\\u2026$/, \"\") + \" \\u2026 \" + right.text.replace(/^\\u2026\\s*/, \"\")\n left.x = Math.min(left.x, right.x)\n left.y = Math.min(left.y, right.y)\n left.w = x2 - left.x\n left.h = y2 - left.y\n left.confidence = Math.min(left.confidence, right.confidence)\n gone.add(right)\n }\n const neighbor = (it: T, toLeft: boolean): T | null => {\n let best: T | null = null\n for (const o of items) {\n if (o === it || gone.has(o) || !sameLine(o, it)) continue\n if (toLeft ? o.x + o.w > it.x + 2 : o.x < it.x + it.w - 2) continue\n if (!best || (toLeft ? o.x + o.w > best.x + best.w : o.x < best.x)) best = o\n }\n return best\n }\n // 오른쪽부터 — 쪽번호 쪽(\"… 12\")을 왼쪽 이웃에 붙이고, 제목 쪽(\"제목 …\")은 오른쪽 이웃을 당겨 붙인다\n for (const it of [...items].sort((a, b) => b.x - a.x)) {\n if (gone.has(it) || !ends.get(it)?.lead) continue\n const left = neighbor(it, true)\n if (left) merge(left, it)\n }\n for (const it of [...items].sort((a, b) => a.x - b.x)) {\n if (gone.has(it) || !ends.get(it)?.trail) continue\n const right = neighbor(it, false)\n if (right) merge(it, right)\n }\n // 리더 점을 못 찾은 목차 줄 — 잡음·흐림에 점이 덜 잡히면 몇 줄만 [제목][쪽번호] 두 아이템으로 남고, 이어진 줄들 사이의\n // 그 두 줄이 클러스터 표를 불러 목차 전체를 칸에 섞었다(archives-record-duty 잡음 σ12: 29줄 중 3줄). 같은 쪽에서 리더로\n // 이은 줄 둘 이상과 오른쪽 끝(쪽번호 열)이 맞는 숫자 아이템은 쪽번호로 보고 같은 줄 왼쪽 이웃과 잇는다\n const toc = items.filter(it => !gone.has(it) && /\\s\\u2026\\s\\d{1,4}$/.test(it.text))\n if (toc.length >= 2) {\n for (const it of items) {\n if (gone.has(it) || toc.includes(it) || !/^[\\s.:\\u00b7\\u2026]*\\d{1,4}$/.test(it.text)) continue\n const x2 = it.x + it.w\n if (toc.filter(t => Math.abs(t.x + t.w - x2) <= Math.max(t.h, it.h)).length < 2) continue\n const left = neighbor(it, true)\n if (!left || toc.includes(left)) continue\n left.text = left.text.replace(/[\\s.:\\u00b7\\u2026]+$/, \"\")\n it.text = it.text.replace(/^[\\s.:\\u00b7\\u2026]+/, \"\")\n merge(left, it)\n }\n }\n return items.filter(it => !gone.has(it))\n}\n\n/**\n * 이웃 인지 ○ 복원 — 글머리 ○ 가 제 박스로 떨어져 \"O\" 한 글자로 읽힌 경우,\n * 같은 줄(세로 중심 차 < 높이 절반) 바로 오른쪽(글자 높이 3배 이내) 박스가 한글로 시작하면 ○.\n */\nexport function restoreBulletItems<T extends { text: string; x: number; y: number; w: number; h: number }>(items: T[]): void {\n for (const it of items) {\n if (it.text !== \"O\" && it.text !== \"o\") continue\n const cy = it.y + it.h / 2\n let next: T | null = null\n for (const o of items) {\n if (o === it || o.x < it.x + it.w * 0.5) continue\n if (Math.abs(o.y + o.h / 2 - cy) > Math.max(it.h, o.h) / 2) continue\n if (o.x - (it.x + it.w) > it.h * 3) continue\n if (!next || o.x < next.x) next = o\n }\n if (next && HANGUL_START.test(next.text.trimStart())) it.text = \"\\u25cb\"\n }\n}\n","/**\n * 인식 입력 준비 — 밴드 서브 박스 좌표, 라인 crop 리사이즈(회전 포함).\n * (engine.ts 에서 분리 — 엔진은 세션·배치·후처리 흐름만)\n */\n\nexport interface Box { x: number; y: number; w: number; h: number }\n\n/** rec 입력 높이 (공식 RecResizeImg image_shape [3, 48, 320]) */\nexport const REC_HEIGHT = 48\nconst REC_MAX_WIDTH = 3200\nconst MIN_SIZE = 3\n\n/**\n * 밴드 → 페이지 좌표 서브 박스. 위아래는 밴드 높이 20% 여유(이웃 밴드와의 간격 절반 이내),\n * 좌우는 괘선을 뺀 잉크 폭 + 밴드 높이 20% 여유(원 박스 안) — 칸 경계 세로선이 crop 에\n * 들어가 \"|국\" 으로 읽히지 않게\n */\nexport function bandBoxes(b: Box, bands: Array<{ y0: number; y1: number; x0: number; x1: number }>, pageH: number): Box[] {\n const out: Box[] = []\n for (let i = 0; i < bands.length; i++) {\n const { y0, y1, x0, x1 } = bands[i]\n const bh = y1 - y0\n const upGap = i > 0 ? (y0 - bands[i - 1].y1) / 2 : y0\n const downGap = i < bands.length - 1 ? (bands[i + 1].y0 - y1) / 2 : b.h - y1\n const top = Math.max(0, Math.round(b.y + y0 - Math.min(bh * 0.2, upGap)))\n const bot = Math.min(pageH, Math.round(b.y + y1 + Math.min(bh * 0.2, downGap)))\n const left = Math.max(b.x, Math.round(b.x + x0 - bh * 0.2))\n const right = Math.min(b.x + b.w, Math.round(b.x + x1 + bh * 0.2))\n if (bot - top >= MIN_SIZE && right - left >= MIN_SIZE) out.push({ x: left, y: top, w: right - left, h: bot - top })\n }\n return out\n}\n\n/**\n * 라인 crop → rec 입력 크기(높이 48, 비율 유지 폭) RGB. 회전은 crop 좌표계에서\n * (90 = 반시계 np.rot90, 270 = 시계). 리사이즈는 bilinear(반픽셀 중심, cv2 INTER_LINEAR 등가)\n * — 공식 전처리(cv2.resize 기본)와 같은 보간.\n */\n/** keep: 박스 로컬 [x0, x1)×[y0, y1) 밖은 배경 휘도 bg 로 칠한다 (rot 0 만 — 박스 끝에 걸린 이웃 줄 조각·상자 테두리 지우기) */\nexport function lineCrop(rgba: Uint8Array, pageW: number, box: Box, rot: 0 | 90 | 270, keep?: { x0: number; x1: number; y0: number; y1: number; bg: number }): { rgb: Uint8Array; w: number } {\n const srcW = rot === 0 ? box.w : box.h\n const srcH = rot === 0 ? box.h : box.w\n const rw = Math.min(REC_MAX_WIDTH, Math.max(16, Math.round((srcW * REC_HEIGHT) / srcH)))\n const rgb = new Uint8Array(rw * REC_HEIGHT * 3)\n // 회전 좌표 → 페이지 픽셀\n const at = (u: number, v: number): number => {\n let px: number, py: number\n if (rot === 0) { px = u; py = v }\n else if (rot === 90) { px = box.w - 1 - v; py = u }\n else { px = v; py = box.h - 1 - u }\n return ((box.y + py) * pageW + (box.x + px)) * 4\n }\n const fx = srcW / rw\n const fy = srcH / REC_HEIGHT\n for (let dy = 0; dy < REC_HEIGHT; dy++) {\n let sy = (dy + 0.5) * fy - 0.5\n if (sy < 0) sy = 0\n const y0 = Math.min(srcH - 1, Math.floor(sy))\n const y1 = Math.min(srcH - 1, y0 + 1)\n const wy = sy - y0\n for (let dx = 0; dx < rw; dx++) {\n let sx = (dx + 0.5) * fx - 0.5\n if (sx < 0) sx = 0\n const x0 = Math.min(srcW - 1, Math.floor(sx))\n const x1 = Math.min(srcW - 1, x0 + 1)\n const wx = sx - x0\n const i00 = at(x0, y0), i01 = at(x1, y0), i10 = at(x0, y1), i11 = at(x1, y1)\n const o = (dy * rw + dx) * 3\n if (keep && rot === 0 && (sx < keep.x0 || sx >= keep.x1 || sy < keep.y0 || sy >= keep.y1)) {\n rgb[o] = rgb[o + 1] = rgb[o + 2] = keep.bg\n continue\n }\n for (let c = 0; c < 3; c++) {\n const top = rgba[i00 + c] * (1 - wx) + rgba[i01 + c] * wx\n const bottom = rgba[i10 + c] * (1 - wx) + rgba[i11 + c] * wx\n rgb[o + c] = Math.round(top * (1 - wy) + bottom * wy)\n }\n }\n }\n return { rgb, w: rw }\n}\n\n\n/** Split a detected line at ruled cell boundaries before recognizing its text. */\nexport function splitBoxAtCellRules(b: Box, rules: Array<{ x1: number; y1: number; y2: number; thicknessPx: number }>): Box[] {\n const cuts = rules.filter(r => r.x1 > b.x + b.h && r.x1 < b.x + b.w - b.h\n && r.y1 <= b.y + b.h * 0.25 && r.y2 >= b.y + b.h * 0.75).sort((a, c) => a.x1 - c.x1)\n if (!cuts.length) return [b]\n const out: Box[] = []\n let left = b.x\n for (const r of cuts) {\n const edge = Math.floor(r.x1 - r.thicknessPx / 2 - 1)\n if (edge - left < b.h) continue\n out.push({ ...b, x: left, w: edge - left })\n left = Math.ceil(r.x1 + r.thicknessPx / 2 + 1)\n }\n if (left < b.x + b.w) out.push({ ...b, x: left, w: b.x + b.w - left })\n return out\n}\n","/**\n * 스캔 기울기 보정 — 투영 프로파일 방식.\n *\n * 스캔·사진 입력은 0.5~3° 기울기가 흔하다. det 은 축정렬 박스(connected-component bbox)\n * 라 기울어진 줄은 박스가 위아래 줄을 물고, 괘선 감지(ruling-lines.ts)는 축정렬 런렝스라\n * 기울면 표 괘선이 통째로 사라진다. 인식 전에 페이지를 바로 세운다.\n *\n * 추정: 페이지를 긴 변 ~1000px 로 줄여 잉크 픽셀을 모으고, 후보 각 θ 마다\n * y' = y·cosθ + x·sinθ 의 행 히스토그램 제곱합(줄이 수평일 때 가장 뾰족)을 비교 —\n * ±MAX 를 0.2° 간격으로 훑고 최댓값 주변을 0.02° 간격으로 다듬는다.\n * 적용 조건: |θ| ≥ MIN_APPLY_DEG 이고 0° 대비 뾰족함이 뚜렷할 때만 (클린 렌더는 무보정).\n */\n\n/** 추정 범위 (°) — 이보다 큰 회전은 기울기가 아니라 방향 문제 (범위 밖) */\nconst MAX_SKEW_DEG = 5\n/** 이보다 작은 기울기는 보정하지 않음 — 리샘플 흐림이 이득보다 크다 */\nconst MIN_APPLY_DEG = 0.25\n/** 0° 대비 투영 뾰족함 비율 하한 — 글자 적은 페이지·도형의 우연한 봉우리 거부 */\nconst MIN_GAIN = 1.03\nconst TARGET_LONG = 1000\n\nexport interface SkewEstimate {\n /** 페이지 기울기 (°, 양수 = 시계 방향으로 기움 → 같은 각만큼 반시계로 돌리면 바로 섬) */\n angle: number\n /** 최적각 투영 점수 / 0° 점수 */\n gain: number\n}\n\n/** 기울기 추정 (적용 여부와 무관한 원값) */\nexport function estimateSkew(rgba: Uint8Array, width: number, height: number): SkewEstimate {\n const step = Math.max(1, Math.ceil(Math.max(width, height) / TARGET_LONG))\n const sw = Math.floor(width / step), sh = Math.floor(height / step)\n // 축소 휘도 + 전역 문턱 (잉크 = 어두운 픽셀)\n const xs: number[] = [], ys: number[] = []\n for (let y = 0; y < sh; y++) {\n for (let x = 0; x < sw; x++) {\n const i = ((y * step) * width + x * step) * 4\n const l = (rgba[i] * 77 + rgba[i + 1] * 150 + rgba[i + 2] * 29) >> 8\n if (l < 128) { xs.push(x); ys.push(y) }\n }\n }\n if (xs.length < 200) return { angle: 0, gain: 1 }\n const diag = Math.ceil(Math.hypot(sw, sh))\n const hist = new Float64Array(2 * diag + 2)\n const score = (deg: number): number => {\n const t = (deg * Math.PI) / 180\n const c = Math.cos(t), s = Math.sin(t)\n hist.fill(0)\n for (let k = 0; k < xs.length; k++) hist[Math.round(ys[k] * c + xs[k] * s) + diag]++\n let sum = 0\n for (let i = 0; i < hist.length; i++) sum += hist[i] * hist[i]\n return sum\n }\n const s0 = score(0)\n let best = 0, bestS = s0\n for (let d = -MAX_SKEW_DEG; d <= MAX_SKEW_DEG + 1e-9; d += 0.2) {\n const v = score(d)\n if (v > bestS) { bestS = v; best = d }\n }\n const coarse = best\n for (let d = coarse - 0.2; d <= coarse + 0.2 + 1e-9; d += 0.02) {\n const v = score(d)\n if (v > bestS) { bestS = v; best = d }\n }\n // 투영 회전각 θ 에서 줄이 수평 → 페이지는 −θ 만큼 기운 것\n return { angle: +(-best).toFixed(2), gain: s0 > 0 ? bestS / s0 : 1 }\n}\n\n/**\n * 필요하면 페이지를 바로 세운 RGBA 를 돌려준다 (같은 크기, 중심 회전, 바깥은 흰색).\n * 보정하지 않으면 입력 그대로 + angle 0.\n */\nexport function deskewPage(rgba: Uint8Array, width: number, height: number): { rgba: Uint8Array; angle: number } {\n const est = estimateSkew(rgba, width, height)\n if (Math.abs(est.angle) < MIN_APPLY_DEG || est.gain < MIN_GAIN) return { rgba, angle: 0 }\n return { rgba: rotateRgba(rgba, width, height, est.angle), angle: est.angle }\n}\n\n/**\n * 중심 기준 회전 (deg, 양수 = 화면상 반시계), 같은 캔버스 크기, bilinear, 바깥 흰색.\n * 출력 픽셀 (x,y) 는 입력의 역회전 위치에서 표본.\n */\nexport function rotateRgba(rgba: Uint8Array, width: number, height: number, deg: number): Uint8Array {\n const out = new Uint8Array(rgba.length)\n const t = (deg * Math.PI) / 180\n const c = Math.cos(t), s = Math.sin(t)\n const cx = (width - 1) / 2, cy = (height - 1) / 2\n for (let y = 0; y < height; y++) {\n const dy = y - cy\n for (let x = 0; x < width; x++) {\n const dx = x - cx\n // 화면 좌표(y 아래)에서 반시계 deg 회전의 역변환\n const sx = c * dx - s * dy + cx\n const sy = s * dx + c * dy + cy\n const o = (y * width + x) * 4\n const x0 = Math.floor(sx), y0 = Math.floor(sy)\n if (x0 < 0 || y0 < 0 || x0 >= width - 1 || y0 >= height - 1) {\n out[o] = 255; out[o + 1] = 255; out[o + 2] = 255; out[o + 3] = 255\n continue\n }\n const wx = sx - x0, wy = sy - y0\n const i00 = (y0 * width + x0) * 4, i01 = i00 + 4, i10 = i00 + width * 4, i11 = i10 + 4\n for (let ch = 0; ch < 4; ch++) {\n const top = rgba[i00 + ch] * (1 - wx) + rgba[i01 + ch] * wx\n const bot = rgba[i10 + ch] * (1 - wx) + rgba[i11 + ch] * wx\n out[o + ch] = Math.round(top * (1 - wy) + bot * wy)\n }\n }\n }\n return out\n}\n","/**\n * PDF OCR 브릿지 — 대상 페이지를 pdfium 으로 래스터해 내장 엔진 또는\n * 사용자 OcrProvider 로 인식하고, 페이지별 IRBlock[] 을 돌려준다.\n *\n * - 내장 엔진: OcrItem 좌표를 PDF 포인트로 환산해 기존 블록 파이프라인\n * (extractPageBlocksWithLines — xy-cut 읽기순서·클러스터 표 감지)에 태운다.\n * 스캔 문서도 표 구조 복원이 가능한 이유.\n * - 사용자 프로바이더: 페이지 PNG → 텍스트 → 페이지당 paragraph 블록 (종전 계약).\n *\n * 에러 계약 (v4.1.0 리뷰 F6/F7):\n * - 환경 오류(의존성·모델 미설치, PDF 오픈 실패)는 throw — 호출자가 NEEDS_OCR 폴백.\n * - 페이지 단위 실패는 본문 오염 대신 warnings(OCR_FAILED) 로 기록하고 계속.\n */\n\nimport type { IRBlock, OcrProvider, ParseWarning } from \"../types.js\"\nimport type { NormItem } from \"../pdf/text-line.js\"\nimport type { LineSegment } from \"../pdf/line-types.js\"\nimport { extractPageBlocksWithLines } from \"../pdf/page-blocks.js\"\nimport { UNRULED_REGION_TABLES } from \"../pdf/ocr-region-merge.js\"\nimport { detectRulingLines, rulingToPdfLines } from \"./ruling-lines.js\"\nimport { DEFAULT_OCR_TUNING, getOcrEngine, type OcrItem, type OcrPageStats, type OcrTuning } from \"./engine.js\"\nimport { deskewPage } from \"./deskew.js\"\nimport { ensureOcrModels } from \"./models.js\"\nimport { OPTIONAL_DEP_INSTALL_HINT } from \"../utils.js\"\n\n/** OCR 렌더 스케일 (72dpi × 3 = 216dpi) — 10pt 본문이 rec 입력 높이(48px)에 근접 */\nconst OCR_RENDER_SCALE = 3\n/**\n * OCR 래스터 픽셀 상한 (쪽·이미지 공통) — 이보다 큰 쪽은 배율을 낮춰 이 안에 맞춘다. 쪽 크기를 가리지 않고 ×3 으로 그리면 628B PDF\n * (4000pt 정사각 쪽)가 12000² 래스터에 사본·괘선 마스크까지 2.38GB 를 먹었다(16000² PNG 1.84GB). A2(1191×1684pt)도 216dpi 로 18MP 라\n * 공문서 판형은 줄지 않는다\n */\nexport const MAX_OCR_PIXELS = 24_000_000\n/** 페이지 하나당 OCR 타임아웃 — det+rec 수십 라인 기준 넉넉히 */\nconst PAGE_TIMEOUT_MS = 120_000\n\nexport type OcrMode = \"builtin\" | OcrProvider\n\n/** pdfjs 연산자 목록 (그래픽만 쓴다 — 괘선·채움·그림 영역) */\nexport type PageOps = { fnArray: Uint32Array | number[]; argsArray: unknown[][] }\n\n/**\n * 대상 페이지들을 OCR 해 페이지별 블록 맵 반환.\n * @param buffer 원본 PDF (pdfjs 가 detach 하기 전에 clone 해 둔 것)\n * @param targets 1-based 페이지 번호 집합\n * @param vectorOps 벡터 글자 쪽(글자를 곡선으로 그린 쪽)의 그래픽(vector-glyphs.ts ocrVectorOps) — 그 쪽은 표 구조를\n * 래스터 괘선 감지 대신 이것(실제 괘선)으로 복원한다. 스캔 쪽은 벡터가 없으니 없다\n */\nexport async function runPdfOcr(\n buffer: ArrayBuffer,\n targets: Set<number>,\n mode: OcrMode,\n warnings: ParseWarning[],\n onProgress?: (current: number, total: number) => void,\n detectTables = true,\n vectorOps?: Map<number, PageOps>,\n imageRegions?: Map<number, Array<{ x1: number; y1: number; x2: number; y2: number }>>,\n): Promise<Map<number, IRBlock[]>> {\n const result = new Map<number, IRBlock[]>()\n if (targets.size === 0) return result\n\n // 환경 준비 — 실패는 그대로 throw (호출자가 NEEDS_OCR 폴백)\n const pdfiumMod = await tryImport<typeof import(\"@hyzyla/pdfium\")>(\n \"@hyzyla/pdfium\",\n () => import(\"@hyzyla/pdfium\"),\n )\n if (mode === \"builtin\") {\n await ensureOcrModels(p => {\n if (p.phase === \"download\" && p.downloaded === 0) {\n process.stderr.write(`[kordoc-ocr] ${p.spec.name} 다운로드 중 (~${p.spec.sizeMb}MB)...\\n`)\n }\n })\n }\n const engine = mode === \"builtin\" ? await getOcrEngine() : null\n\n const pdfium = await pdfiumMod.PDFiumLibrary.init()\n const doc = await pdfium.loadDocument(new Uint8Array(buffer))\n try {\n let done = 0\n // 대상 쪽만 연다 — doc.pages() 는 모든 쪽을 불러오고, 쪽은 render() 가 끝에서만 닫아 대상 밖 쪽이 문서를 닫을 때까지 남았다\n // (changwon 328쪽 문서의 한 쪽 OCR: 6ms·26MB → 전 쪽 순회 970ms·330MB). pdfium 쪽 번호는 0-based — 대외 계약(1-based)으로 환산\n const count = doc.getPageCount()\n for (const pageNo of [...targets].filter(p => p >= 1 && p <= count).sort((a, b) => a - b)) {\n const page = doc.getPage(pageNo - 1)\n onProgress?.(++done, targets.size)\n try {\n const blocks = await withTimeout(\n ocrOnePage(page, pageNo, mode, engine, warnings, detectTables, vectorOps?.get(pageNo), imageRegions?.get(pageNo)),\n PAGE_TIMEOUT_MS,\n `OCR 페이지 ${pageNo} 타임아웃 (${PAGE_TIMEOUT_MS / 1000}초)`,\n )\n result.set(pageNo, blocks)\n } catch (e) {\n warnings.push({\n page: pageNo,\n message: `페이지 ${pageNo} OCR 실패: ${e instanceof Error ? e.message : String(e)}`,\n code: \"OCR_FAILED\",\n })\n }\n }\n } finally {\n doc.destroy()\n pdfium.destroy()\n }\n return result\n}\n\nasync function ocrOnePage(\n page: import(\"@hyzyla/pdfium\").PDFiumPage,\n pageNo: number,\n mode: OcrMode,\n engine: Awaited<ReturnType<typeof getOcrEngine>> | null,\n warnings: ParseWarning[],\n detectTables: boolean,\n vectorOps?: PageOps,\n regions?: Array<{ x1: number; y1: number; x2: number; y2: number }>,\n): Promise<IRBlock[]> {\n const { originalWidth: pdfW, originalHeight: pdfH } = page.getOriginalSize()\n const renderScale = Math.min(OCR_RENDER_SCALE, Math.sqrt(MAX_OCR_PIXELS / Math.max(1, pdfW * pdfH)))\n if (renderScale < OCR_RENDER_SCALE) {\n warnings.push({ page: pageNo, code: \"PARTIAL_PARSE\", message: `OCR 래스터 픽셀 상한으로 렌더 해상도를 축소했습니다 (작은 글자 인식 결손 가능)` })\n }\n // 그림 영역만 읽는 쪽은 두 배로 한 번 그려 영역 다시 읽기(closer)에 쓰고, 쪽 배율 래스터는 2×2 평균으로 줄여 만든다\n // (pdfium 은 같은 쪽을 두 번 그리면 wasm 서명 오류가 난다)\n const closer = regions && mode === \"builtin\" && renderScale * 2 <= Math.sqrt(MAX_OCR_PIXELS / Math.max(1, pdfW * pdfH))\n const rendered = await page.render({\n scale: closer ? renderScale * 2 : renderScale,\n render: async ({ data }) => data,\n })\n const hiRgba = closer ? bgraToRgba(rendered.data) : null\n const { rgba, width: rw, height: rh } = hiRgba\n ? halve(hiRgba, rendered.width, rendered.height)\n : { rgba: bgraToRgba(rendered.data), width: rendered.width, height: rendered.height }\n\n if (mode === \"builtin\") {\n // 스캔 기울기 보정 — 인식과 괘선 감지가 같은(바로 선) 래스터를 본다. 클린 렌더는 무보정.\n // 벡터 글자 쪽은 보정하지 않는다 — 글자 좌표가 돌면 그 쪽 벡터 괘선과 어긋난다\n const upright = vectorOps ? rgba : deskewPage(rgba, rw, rh).rgba\n const stats: OcrPageStats = { droppedLowConf: 0 }\n const ruling = vectorOps ? undefined : detectRulingLines(upright, rw, rh, rh / pdfH)\n const items = await engine!.recognizePage(upright, rw, rh, stats, regions ? REGION_TUNING : undefined, ruling?.cellDividers)\n if (stats.droppedLowConf > 0) {\n warnings.push({\n page: pageNo,\n message: `페이지 ${pageNo}: 저신뢰 OCR 라인 ${stats.droppedLowConf}개 폐기 (인식 결손 가능)`,\n code: \"OCR_LOW_CONF\",\n })\n }\n if (stats.truncatedBoxes) {\n warnings.push({ page: pageNo, message: `페이지 ${pageNo}: OCR 검출 상자가 너무 많아 ${stats.truncatedBoxes}개는 인식하지 않음 (일부 글 결손)`, code: \"PARTIAL_PARSE\" })\n }\n const scale = rh / pdfH\n // 텍스트층이 있는 쪽의 그림 영역만 읽을 때는 영역마다 그 안 글줄로 따로 블록을 만든다 — 쪽 전체로 묶으면 본문 줄과 그림 글이\n // 한 문단으로 합쳐져 영역 판정(mergeOcrImageRegions)에서 빠진다\n if (regions) {\n const inside = (it: OcrItem, r: { x1: number; y1: number; x2: number; y2: number }) => {\n const cx = (it.x + it.w / 2) / scale, cy = pdfH - (it.y + it.h / 2) / scale\n return cx >= r.x1 && cx <= r.x2 && cy >= r.y1 && cy <= r.y2\n }\n const reads = hiRgba ? await closerReads(hiRgba, rw * 2, rh * 2, pdfH, scale * 2, regions, engine!) : []\n return regions.flatMap((r, k) => {\n let own = items.filter(it => inside(it, r))\n // 그림 속 글은 작다(차트 눈금·범례 6~8pt) — 영역만 두 배로 다시 읽어 글자 수로 가중한 평균 신뢰도가 높은 쪽을 쓴다\n const near = reads[k]\n if (near?.length && meanConfidence(near) > meanConfidence(own)) own = near\n if (!own.length) return []\n const blocks = ocrItemsToBlocks(own, pageNo, pdfW, pdfH, scale, ruling && rulingToPdfLines(ruling, scale, pdfH), detectTables, undefined, true)\n // 영역 안 세로 괘선이 둘 미만이면 그 영역의 OCR 표는 글 정렬만으로 묶은 것이다 — 그림 영역 병합이 표로 받지 않는다\n const x1 = r.x1 * scale - 2, x2 = r.x2 * scale + 2, y1 = (pdfH - r.y2) * scale - 2, y2 = (pdfH - r.y1) * scale + 2\n const columnRules = ruling?.verticals.filter(s => Math.min(s.x1, s.x2) >= x1 && Math.max(s.x1, s.x2) <= x2 && Math.min(s.y1, s.y2) >= y1 && Math.max(s.y1, s.y2) <= y2).length ?? 0\n if (columnRules < 2) for (const b of blocks) if (b.type === \"table\") UNRULED_REGION_TABLES.add(b)\n return blocks\n })\n }\n // 벡터 글자 쪽: 표 구조는 그 쪽의 실제 괘선으로 (rhwp cairo 13쌍 46표 exact: 래스터 괘선 14 → 실제 괘선 20)\n if (vectorOps) return ocrItemsToBlocks(items, pageNo, pdfW, pdfH, scale, undefined, detectTables, vectorOps)\n // 래스터에서 표 괘선 감지 — 스캔본 병합셀 서식도 선 기반 표 파이프라인을 탄다\n const extraLines = rulingToPdfLines(ruling!, scale, pdfH)\n return ocrItemsToBlocks(items, pageNo, pdfW, pdfH, scale, extraLines, detectTables)\n }\n\n // 사용자 프로바이더 — PNG 인코딩 후 호출, 페이지당 paragraph (종전 계약)\n type SharpPngFactory = (\n input: Uint8Array,\n opts: { raw: { width: number; height: number; channels: number } },\n ) => { png(): { toBuffer(): Promise<Buffer> } }\n const sharpModRaw = await tryImport<{ default?: SharpPngFactory } & SharpPngFactory>(\n \"sharp\",\n () => import(\"sharp\") as unknown as Promise<{ default?: SharpPngFactory } & SharpPngFactory>,\n )\n const sharpAny = sharpModRaw as { default?: SharpPngFactory } | SharpPngFactory\n const sharp: SharpPngFactory =\n typeof sharpAny === \"function\" ? sharpAny : (sharpAny.default ?? (sharpAny as unknown as SharpPngFactory))\n const png = await sharp(rgba, { raw: { width: rw, height: rh, channels: 4 } })\n .png()\n .toBuffer()\n\n const text = await mode(new Uint8Array(png), pageNo, \"image/png\")\n if (!text.trim()) {\n warnings.push({ page: pageNo, message: `페이지 ${pageNo} OCR 결과 없음`, code: \"OCR_FAILED\" })\n return []\n }\n return [{ type: \"paragraph\", text: text.trim(), pageNumber: pageNo }]\n}\n\n/** 2×2 평균 축소 (RGBA) */\nfunction halve(src: Uint8Array, w: number, h: number): { rgba: Uint8Array; width: number; height: number } {\n const W = w >> 1, H = h >> 1\n const out = new Uint8Array(W * H * 4)\n for (let y = 0; y < H; y++) for (let x = 0; x < W; x++) {\n const a = ((2 * y) * w + 2 * x) * 4, b = a + w * 4, o = (y * W + x) * 4\n for (let c = 0; c < 4; c++) out[o + c] = (src[a + c] + src[a + 4 + c] + src[b + c] + src[b + 4 + c] + 2) >> 2\n }\n return { rgba: out, width: W, height: H }\n}\n\n/** 그림 영역만 읽을 때 — 끝자락 지우기를 끈다 (engine OcrTuning.trimEdges 주석) */\nconst REGION_TUNING: Readonly<OcrTuning> = Object.freeze({ ...DEFAULT_OCR_TUNING, trimEdges: false })\n\nfunction meanConfidence(items: OcrItem[]): number {\n let n = 0, sum = 0\n for (const it of items) { const len = [...it.text].length; n += len; sum += it.confidence * len }\n return n ? sum / n : 0\n}\n\n/** 그림 영역마다 두 배 래스터에서 잘라 다시 인식한 글줄 — 좌표는 쪽 배율 래스터 기준으로 되돌린다 */\nasync function closerReads(\n rgba: Uint8Array, rw: number, rh: number, pdfH: number, hi: number,\n regions: Array<{ x1: number; y1: number; x2: number; y2: number }>,\n engine: NonNullable<Awaited<ReturnType<typeof getOcrEngine>>>,\n): Promise<Array<OcrItem[] | null>> {\n const out: Array<OcrItem[] | null> = []\n for (const r of regions) {\n const x0 = Math.max(0, Math.floor(r.x1 * hi)), y0 = Math.max(0, Math.floor((pdfH - r.y2) * hi))\n const cw = Math.min(rw, Math.ceil(r.x2 * hi)) - x0, ch = Math.min(rh, Math.ceil((pdfH - r.y1) * hi)) - y0\n if (cw < 16 || ch < 16) { out.push(null); continue }\n const crop = new Uint8Array(cw * ch * 4)\n for (let y = 0; y < ch; y++) crop.set(rgba.subarray(((y0 + y) * rw + x0) * 4, ((y0 + y) * rw + x0 + cw) * 4), y * cw * 4)\n const items = await engine.recognizePage(crop, cw, ch, undefined, REGION_TUNING)\n out.push(items.map(it => ({ ...it, x: (it.x + x0) / 2, y: (it.y + y0) / 2, w: it.w / 2, h: it.h / 2 })))\n }\n return out\n}\n\n/**\n * OcrItem(렌더 픽셀, top-left origin) → NormItem(PDF pt, bottom-up baseline)\n * 으로 환산해 기존 블록 파이프라인에 태운다. 괘선은 래스터 감지 결과(extraLines)로\n * 공급 — 없으면 클러스터 감지기 몫이다. 벡터 글자 쪽은 그 쪽 그래픽 연산자 목록(opList)을\n * 넘겨 실제 괘선을 쓴다.\n * (이미지 직접 입력 경로 image-ocr.ts 와 공유)\n */\n/**\n * OCR 박스를 줄로 묶는다(박스 번호 묶음). 같은 줄 조각도 글자 크기(큰 대표 줄)·숫자 하강부·기울어진 감열지 때문에 박스 아래 끝이\n * 몇 pt 씩 어긋나, 박스마다 아래 끝을 기준선으로 넘기면 블록 파이프라인의 줄 묶음(3pt)이 한 줄을 여럿으로 쪼개고 위쪽 y 순으로\n * 뒤집는다(#141 영수증: \"탄현점 / 이마트\", 품목 바코드·단가·금액이 다른 행). 중심 y 차이 ≤ 작은 박스 높이의 절반이면 한 줄,\n * 가로로 크게 겹치는 박스는 같은 줄에 넣지 않는다(큰 로고 박스가 위아래 두 줄을 잇지 않게).\n * 한 줄 조각은 높이가 엇비슷하다 — 줄 높이 중앙값과 두 배 넘게 다른 박스는 인식 신뢰도 0.8 미만 박스(아이콘·로고·QR 잡음)가 낄 때\n * 묶지 않는다. 높이는 줄 높이 중앙값과 잰다(줄의 작은 숫자 박스 하나와 재면 두 행에 걸친 칸 박스가 제 행을 놓친다, changwon-plan2026\n * \"3/8\"). 신뢰도가 높으면 높이 차가 커도 같은 줄 — 기울어진 스캔의 긴 글줄 박스는 기울기만큼 키가 크고 체크 표 \"√\" 옆 라벨·두 줄이 한\n * 박스로 붙은 칸도 2~2.7배다(열화 서식 OCR 다섯 쪽 CER 상승). 그림 영역에서는 높이의 8배 넘게 떨어진 조각은 세로 중심이 작은 박스\n * 높이의 0.35 안일 때만 같은 줄(차트 범례와 먼 축 눈금 — 쪽 전체 OCR 의 서식 먼 칸은 쪽이 기운 만큼 어긋난다). 긴 글줄(폭이 높이의\n * 7배 이상 — 서식 라벨 \"주민등록번호\" 6배는 아니다, 숫자가 30% 넘는 금액 칸도 아니다 — 예산 표 행의 항목명과 \"경정4,200,000원\")은 줄 안\n * 가장 가까운 긴 글줄과 높이의 5배 넘게 떨어지면 묶지 않는다(범례 라벨 사이 3~4배는 한 줄). 짧은 조각(숫자·라벨 칸)은 멀어도 묶는다\n * (영수증 금액 칸).\n * 두 단 글의 좌우 줄은 높이가 엇비슷해도 다른 줄이다(ODL 141 두 단 카드 인포그래픽: 좌우 카드 줄 틈 7~60배 — 4.21.3 에서 한 줄로\n * 묶여 단 분리가 깨지고 가짜 표가 됐다, NID 0.96 → 0.44).\n */\n/** 긴 글줄 상자 — 폭이 높이의 7배 이상이고 숫자가 글자의 30% 미만(금액 칸 \"경정4,200,000원\"·\"210mm×297mm\" 은 표 칸이다) */\nconst proseBox = (b: OcrItem) => {\n const t = b.text.replace(/\\s/g, \"\")\n return b.w >= b.h * 7 && (t.match(/\\d/g)?.length ?? 0) < t.length * 0.3\n}\n\nexport function groupOcrLines(items: OcrItem[], figureRegion = false): number[][] {\n const order = items.map((_, i) => i).sort((a, b) => (items[a].y + items[a].h / 2) - (items[b].y + items[b].h / 2))\n const accepts = (l: number[], i: number): boolean => {\n const it = items[i], c = it.y + it.h / 2\n const lc = l.reduce((s, j) => s + items[j].y + items[j].h / 2, 0) / l.length\n const minH = Math.min(it.h, ...l.map(j => items[j].h))\n if (Math.abs(c - lc) > minH / 2) return false\n const hs = l.map(j => items[j].h).sort((a, b) => a - b), med = hs[hs.length >> 1]\n const weak = it.confidence < 0.8 || l.some(j => items[j].confidence < 0.8)\n if (weak && Math.max(it.h, med) > Math.min(it.h, med) * 2) return false\n let nearLong = 0, gap = Infinity\n for (const j of l) {\n const o = items[j]\n // 박스는 잉크 외곽에 여백이 붙어 이웃 낱말과 조금 겹친다(이마트·탄현점 32px) — 좁은 쪽 폭의 절반 넘게 겹칠 때만 다른 줄\n const ov = Math.min(it.x + it.w, o.x + o.w) - Math.max(it.x, o.x)\n if (ov >= Math.min(it.w, o.w) / 2) return false\n gap = Math.min(gap, Math.max(0, -ov))\n if (proseBox(it) && proseBox(o)) nearLong = Math.min(nearLong || Infinity, Math.max(0, -ov) / Math.min(it.h, o.h))\n }\n // 그림 영역에서 높이의 8배 넘게 떨어진 조각은 세로로 거의 같은 줄이어야 한다 — 영수증 먼 칸은 중심 어긋남이 작은 박스 높이의 0.22 안, 원그래프\n // 값과 범례(ODL 148 \"18.9%\"·\"Project Manager\")는 0.31, 차트 범례 라벨과 멀리 왼쪽 축 눈금은 0.37~0.47 이라 반쯤 어긋난 채 묶여\n // 기준선이 옮겨지고 읽기 순서가 바뀌었다(ODL 128·140·057)\n if (figureRegion && gap > 8 * minH && Math.abs(c - lc) > minH * 0.35) return false\n // 긴 글줄은 줄 안 가장 가까운 긴 글줄과 높이의 5배 안이어야 한다 — 사이에 짧은 상자(카드 번호)가 끼어도 다리가 되지 않는다\n return nearLong <= 5\n }\n const lines: number[][] = []\n for (const i of order) {\n const line = lines.find(l => accepts(l, i))\n if (line) line.push(i)\n else lines.push([i])\n }\n // 홀로 남은 박스는 줄이 다 선 뒤 한 번 더 넣어 본다 — 먼저 만난 줄에 먼 긴 글줄만 있어 갈린 범례 라벨(ODL 059 \"Construction | Waste\")\n for (let k = 0; k < lines.length; k++) {\n if (lines[k].length !== 1) continue\n const i = lines[k][0]\n const target = lines.find((l, m) => m !== k && l.length > 0 && accepts(l, i))\n if (target) { target.push(i); lines[k] = [] }\n }\n return lines.filter(l => l.length > 0)\n}\n\nexport function ocrItemsToBlocks(\n items: OcrItem[],\n pageNumber: number,\n pdfW: number,\n pdfH: number,\n scale: number,\n extraLines?: { horizontals: LineSegment[]; verticals: LineSegment[] },\n detectTables = true,\n opList: PageOps = { fnArray: [], argsArray: [] },\n figureRegion = false,\n): IRBlock[] {\n // 줄마다 아래 끝을 중앙값으로 맞추고, 겹친 이웃 박스는 겹친 구간 가운데서 갈라 낱말 경계(따로 검출된 상자)를 공백으로 남긴다\n const bottoms = items.map(it => it.y + it.h)\n const xs = items.map(it => ({ x: it.x, r: it.x + it.w, space: false }))\n for (const line of groupOcrLines(items, figureRegion)) {\n if (line.length < 2) continue\n const sorted = line.map(j => items[j].y + items[j].h).sort((a, b) => a - b)\n for (const j of line) bottoms[j] = sorted[Math.floor(sorted.length / 2)]\n const byX = [...line].sort((a, b) => items[a].x - items[b].x)\n for (let k = 1; k < byX.length; k++) {\n const L = xs[byX[k - 1]], R = xs[byX[k]]\n if (R.x >= L.r) continue\n const mid = (R.x + L.r) / 2, half = Math.min(items[byX[k - 1]].h, items[byX[k]].h) * 0.15\n L.r = Math.max(L.x + 1, mid - half)\n R.x = Math.min(R.r - 1, mid + half)\n R.space = true\n }\n }\n const norm: NormItem[] = items.map((it, i) => {\n // 그림 영역은 기준선을 줄 중앙값으로 옮겨도 박스 위 끝은 그대로 — 높이째 옮기면 키 큰 칸 박스가 윗행 칸과 더 겹쳐 그 칸에 붙었다(ODL 110\n // 그림 속 표 \"14\"·\"15\" → \"1415\"). 쪽 전체 OCR 은 높이째 옮긴다 — 위 끝을 지키자 스캔 쪽 셋의 CER 이 올랐다(topik 1.50 → 1.88%).\n // 글자 크기는 원래 박스 높이로 잰다\n const h = (figureRegion ? Math.max(1, bottoms[i] - it.y) : it.h) / scale\n return {\n text: it.text,\n x: Math.round(xs[i].x / scale),\n // NormItem.y 는 pdfjs transform[5] = 베이스라인 (bottom-up) — 잉크 하단으로 근사\n y: Math.round(pdfH - bottoms[i] / scale),\n w: Math.round((xs[i].r - xs[i].x) / scale),\n h: Math.round(h),\n // 박스는 잉크 외곽(engine tightBoxes) — 한글 줄 잉크 높이 ≈ 0.9em\n fontSize: Math.max(1, Math.round(it.h / scale / 0.9)),\n fontName: \"ocr\",\n isHidden: false,\n ...(xs[i].space ? { hasSpaceBefore: true } : {}),\n }\n })\n return extractPageBlocksWithLines(norm, pageNumber, opList, pdfW, pdfH, extraLines, detectTables)\n}\n\nasync function tryImport<T>(name: string, loader: () => Promise<T>): Promise<T> {\n try {\n return await loader()\n } catch (e) {\n throw new Error(\n `OCR 을 사용하려면 optional dependency '${name}' 이 필요합니다. ` +\n `\\`npm install ${name}\\` 후 다시 실행하세요.${OPTIONAL_DEP_INSTALL_HINT} 원인: ${(e as Error).message}`,\n )\n }\n}\n\nasync function withTimeout<T>(promise: Promise<T>, ms: number, msg: string): Promise<T> {\n // 타임아웃 패배 후 원 promise 의 사후 reject 가 unhandled rejection 이 되지 않게 흡수\n promise.catch(() => {})\n let timer: NodeJS.Timeout | undefined\n try {\n return await Promise.race([\n promise,\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(msg)), ms)\n }),\n ])\n } finally {\n if (timer) clearTimeout(timer)\n }\n}\n\n/** pdfium BGRA → RGBA */\nfunction bgraToRgba(bgra: Uint8Array): Uint8Array {\n const out = new Uint8Array(bgra.length)\n for (let i = 0; i < bgra.length; i += 4) {\n out[i] = bgra[i + 2]\n out[i + 1] = bgra[i + 1]\n out[i + 2] = bgra[i]\n out[i + 3] = bgra[i + 3]\n }\n return out\n}\n"]}