kordoc 4.24.14 → 4.24.16
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.
- package/README.md +6 -6
- package/dist/{-MG25ST6Y.js → -ZKOPHIGY.js} +11 -11
- package/dist/{chunk-NVD24SLL.js → chunk-2UXGDAWQ.js} +2 -2
- package/dist/{chunk-MIJYCKJA.js → chunk-3TXAIEXL.js} +246 -14
- package/dist/chunk-3TXAIEXL.js.map +1 -0
- package/dist/{chunk-FUC3V2FR.js → chunk-5Y7E5VTW.js} +2 -2
- package/dist/{chunk-LMQT2JFS.js → chunk-6K2SYTNJ.js} +49 -11
- package/dist/chunk-6K2SYTNJ.js.map +1 -0
- package/dist/{chunk-MACV3MZF.js → chunk-6KELCESN.js} +50 -12
- package/dist/chunk-6KELCESN.js.map +1 -0
- package/dist/{chunk-ZIGWQ3IS.js → chunk-6PPVAQ2N.js} +2 -2
- package/dist/{chunk-UUNCLJB7.js → chunk-BHY2QAPM.js} +11 -11
- package/dist/{chunk-ZBHS7KLW.cjs → chunk-CCH6BUNI.cjs} +6 -6
- package/dist/{chunk-ZBHS7KLW.cjs.map → chunk-CCH6BUNI.cjs.map} +1 -1
- package/dist/{chunk-AM6TECXD.js → chunk-DH564VPR.js} +2 -2
- package/dist/{chunk-UTLHDVC5.js → chunk-F3VIVCIF.js} +2 -2
- package/dist/{chunk-LSFVBS2I.js → chunk-FK7KGS5D.js} +2 -2
- package/dist/{chunk-BUGXM2H5.cjs → chunk-GPZMU2CM.cjs} +3 -3
- package/dist/{chunk-BUGXM2H5.cjs.map → chunk-GPZMU2CM.cjs.map} +1 -1
- package/dist/{chunk-J3OJWUON.js → chunk-GYVSGOQW.js} +2 -2
- package/dist/{chunk-VBOFP27O.js → chunk-J5M5OW4S.js} +2 -2
- package/dist/{chunk-WFOPOJHN.js → chunk-JS5CL2ZI.js} +246 -14
- package/dist/chunk-JS5CL2ZI.js.map +1 -0
- package/dist/{chunk-SSDHVKLM.js → chunk-K3OLWLXH.js} +2 -2
- package/dist/{chunk-FGERVDQZ.js → chunk-LPNWTWOQ.js} +2 -2
- package/dist/{chunk-V26UPU2L.cjs → chunk-NS2F4DXC.cjs} +3 -3
- package/dist/{chunk-V26UPU2L.cjs.map → chunk-NS2F4DXC.cjs.map} +1 -1
- package/dist/{chunk-TPZPICDM.js → chunk-NUQ5B2ZM.js} +3 -3
- package/dist/{chunk-HVILFVAT.cjs → chunk-NVOB6OHS.cjs} +2 -2
- package/dist/{chunk-HVILFVAT.cjs.map → chunk-NVOB6OHS.cjs.map} +1 -1
- package/dist/{chunk-PVAJ4DBW.js → chunk-QJA3KGRP.js} +2 -2
- package/dist/{chunk-NIPFEMJJ.js → chunk-QOMLSZLM.js} +2 -2
- package/dist/{chunk-DIFJPJGN.js → chunk-S2VWNC2W.js} +3 -3
- package/dist/{chunk-GV7ECKOK.cjs → chunk-SR6DJBPM.cjs} +195 -157
- package/dist/chunk-SR6DJBPM.cjs.map +1 -0
- package/dist/{chunk-ERYRF3EA.js → chunk-TSCQDCAR.js} +2 -2
- package/dist/{chunk-3LFNTOL7.js → chunk-UCEGWDWX.js} +6 -6
- package/dist/{chunk-AULD3QAB.js → chunk-V5R3PJQH.js} +2 -2
- package/dist/{chunk-7VNYQHJV.js → chunk-VAMCM435.js} +2 -2
- package/dist/{chunk-ZX66BXB5.cjs → chunk-X2SPQOI7.cjs} +328 -96
- package/dist/chunk-X2SPQOI7.cjs.map +1 -0
- package/dist/chunks-BHTYFFI2.js +10 -0
- package/dist/cli.js +30 -30
- package/dist/{formula-4KFXQSEG.js → formula-4C7ADOLE.js} +4 -4
- package/dist/{formula-WAYIKS54.js → formula-4Y7UWTEG.js} +3 -3
- package/dist/{formula-N6GWFPHK.cjs → formula-KZWH4YUD.cjs} +9 -9
- package/dist/{formula-N6GWFPHK.cjs.map → formula-KZWH4YUD.cjs.map} +1 -1
- package/dist/{image-ocr-QBCR7ZD6.js → image-ocr-AEX2L326.js} +9 -9
- package/dist/{image-ocr-P5S2QDKW.js → image-ocr-ASLUPAQG.js} +6 -6
- package/dist/{image-ocr-GY7SZAHN.cjs → image-ocr-GT3NILUJ.cjs} +17 -17
- package/dist/{image-ocr-GY7SZAHN.cjs.map → image-ocr-GT3NILUJ.cjs.map} +1 -1
- package/dist/index.cjs +360 -360
- package/dist/index.js +6 -6
- package/dist/mcp.js +23 -23
- package/dist/{model-bundle-QAM24SYG.js → model-bundle-2TXD77HN.js} +5 -5
- package/dist/{models-YHC236MP.js → models-WRJKLZA6.js} +5 -5
- package/dist/{parse-worker-v2-LP7NKQBP.js → parse-worker-v2-C2GR62SO.js} +12 -12
- package/dist/{parser-JWU6HYZZ.cjs → parser-5R34V6PS.cjs} +159 -159
- package/dist/{parser-JWU6HYZZ.cjs.map → parser-5R34V6PS.cjs.map} +1 -1
- package/dist/{parser-26YUZU55.js → parser-GFZILOKI.js} +12 -12
- package/dist/{parser-DFJZ3CCE.js → parser-LU7BIHXD.js} +9 -9
- package/dist/pdf-ocr-QRBPEPOZ.cjs +35 -0
- package/dist/{pdf-ocr-Z4PBLB75.cjs.map → pdf-ocr-QRBPEPOZ.cjs.map} +1 -1
- package/dist/{pdf-ocr-EEWQFS7P.js → pdf-ocr-U2ZRNQD4.js} +6 -6
- package/dist/{pdf-ocr-BO6ACAGL.js → pdf-ocr-VNK6UIS2.js} +9 -9
- package/dist/{profile-io-PQXYWUBL.js → profile-io-J3IWFBCM.js} +3 -3
- package/dist/{rasterize-CS7WZUGF.js → rasterize-23MJWOUQ.js} +3 -3
- package/dist/{redact-doc-PI4JNHV6.js → redact-doc-GGCEGT74.js} +11 -11
- package/dist/{render-M2CIEOF4.js → render-M2UAFQSI.js} +7 -7
- package/dist/seal-EHZTTMNE.js +10 -0
- package/dist/{setup-HGPUR27M.js → setup-D7JWID23.js} +3 -3
- package/dist/visual-2ZLXZ5NN.js +21 -0
- package/dist/{watch-B5ISBY3N.js → watch-E2XCUIA5.js} +12 -12
- package/package.json +1 -1
- package/dist/chunk-GV7ECKOK.cjs.map +0 -1
- package/dist/chunk-LMQT2JFS.js.map +0 -1
- package/dist/chunk-MACV3MZF.js.map +0 -1
- package/dist/chunk-MIJYCKJA.js.map +0 -1
- package/dist/chunk-WFOPOJHN.js.map +0 -1
- package/dist/chunk-ZX66BXB5.cjs.map +0 -1
- package/dist/chunks-JGSWNVLF.js +0 -10
- package/dist/pdf-ocr-Z4PBLB75.cjs +0 -35
- package/dist/seal-4755WLFB.js +0 -10
- package/dist/visual-JWWGGTKQ.js +0 -21
- /package/dist/{-MG25ST6Y.js.map → -ZKOPHIGY.js.map} +0 -0
- /package/dist/{chunk-NVD24SLL.js.map → chunk-2UXGDAWQ.js.map} +0 -0
- /package/dist/{chunk-FUC3V2FR.js.map → chunk-5Y7E5VTW.js.map} +0 -0
- /package/dist/{chunk-ZIGWQ3IS.js.map → chunk-6PPVAQ2N.js.map} +0 -0
- /package/dist/{chunk-UUNCLJB7.js.map → chunk-BHY2QAPM.js.map} +0 -0
- /package/dist/{chunk-AM6TECXD.js.map → chunk-DH564VPR.js.map} +0 -0
- /package/dist/{chunk-UTLHDVC5.js.map → chunk-F3VIVCIF.js.map} +0 -0
- /package/dist/{chunk-LSFVBS2I.js.map → chunk-FK7KGS5D.js.map} +0 -0
- /package/dist/{chunk-J3OJWUON.js.map → chunk-GYVSGOQW.js.map} +0 -0
- /package/dist/{chunk-VBOFP27O.js.map → chunk-J5M5OW4S.js.map} +0 -0
- /package/dist/{chunk-SSDHVKLM.js.map → chunk-K3OLWLXH.js.map} +0 -0
- /package/dist/{chunk-FGERVDQZ.js.map → chunk-LPNWTWOQ.js.map} +0 -0
- /package/dist/{chunk-TPZPICDM.js.map → chunk-NUQ5B2ZM.js.map} +0 -0
- /package/dist/{chunk-PVAJ4DBW.js.map → chunk-QJA3KGRP.js.map} +0 -0
- /package/dist/{chunk-NIPFEMJJ.js.map → chunk-QOMLSZLM.js.map} +0 -0
- /package/dist/{chunk-DIFJPJGN.js.map → chunk-S2VWNC2W.js.map} +0 -0
- /package/dist/{chunk-ERYRF3EA.js.map → chunk-TSCQDCAR.js.map} +0 -0
- /package/dist/{chunk-3LFNTOL7.js.map → chunk-UCEGWDWX.js.map} +0 -0
- /package/dist/{chunk-AULD3QAB.js.map → chunk-V5R3PJQH.js.map} +0 -0
- /package/dist/{chunk-7VNYQHJV.js.map → chunk-VAMCM435.js.map} +0 -0
- /package/dist/{chunks-JGSWNVLF.js.map → chunks-BHTYFFI2.js.map} +0 -0
- /package/dist/{formula-4KFXQSEG.js.map → formula-4C7ADOLE.js.map} +0 -0
- /package/dist/{formula-WAYIKS54.js.map → formula-4Y7UWTEG.js.map} +0 -0
- /package/dist/{image-ocr-QBCR7ZD6.js.map → image-ocr-AEX2L326.js.map} +0 -0
- /package/dist/{image-ocr-P5S2QDKW.js.map → image-ocr-ASLUPAQG.js.map} +0 -0
- /package/dist/{model-bundle-QAM24SYG.js.map → model-bundle-2TXD77HN.js.map} +0 -0
- /package/dist/{models-YHC236MP.js.map → models-WRJKLZA6.js.map} +0 -0
- /package/dist/{parse-worker-v2-LP7NKQBP.js.map → parse-worker-v2-C2GR62SO.js.map} +0 -0
- /package/dist/{parser-26YUZU55.js.map → parser-GFZILOKI.js.map} +0 -0
- /package/dist/{parser-DFJZ3CCE.js.map → parser-LU7BIHXD.js.map} +0 -0
- /package/dist/{pdf-ocr-BO6ACAGL.js.map → pdf-ocr-U2ZRNQD4.js.map} +0 -0
- /package/dist/{pdf-ocr-EEWQFS7P.js.map → pdf-ocr-VNK6UIS2.js.map} +0 -0
- /package/dist/{profile-io-PQXYWUBL.js.map → profile-io-J3IWFBCM.js.map} +0 -0
- /package/dist/{rasterize-CS7WZUGF.js.map → rasterize-23MJWOUQ.js.map} +0 -0
- /package/dist/{redact-doc-PI4JNHV6.js.map → redact-doc-GGCEGT74.js.map} +0 -0
- /package/dist/{render-M2CIEOF4.js.map → render-M2UAFQSI.js.map} +0 -0
- /package/dist/{seal-4755WLFB.js.map → seal-EHZTTMNE.js.map} +0 -0
- /package/dist/{setup-HGPUR27M.js.map → setup-D7JWID23.js.map} +0 -0
- /package/dist/{visual-JWWGGTKQ.js.map → visual-2ZLXZ5NN.js.map} +0 -0
- /package/dist/{watch-B5ISBY3N.js.map → watch-E2XCUIA5.js.map} +0 -0
package/README.md
CHANGED
|
@@ -108,19 +108,19 @@ await writeFile("보고서.hwpx", Buffer.from(hwpx))
|
|
|
108
108
|
|
|
109
109
|
## 검증 결과
|
|
110
110
|
|
|
111
|
-
**4.22.14 · 2026-10-19 검증**(렌더
|
|
111
|
+
**4.22.14 · 2026-10-19 검증**(렌더 배치는 4.24.14, PDF 글·표·OCR 은 4.24.16 · 2026-10-28). 고정 코퍼스와 참조 기준으로 측정한 결과입니다.
|
|
112
112
|
|
|
113
113
|
| 대상 | 규모 | 결과 |
|
|
114
114
|
| --- | --- | --- |
|
|
115
115
|
| HWPX | 2,424문서 · 10,342표 | 표 구조 일치 **10,342/10,342 · 100%** |
|
|
116
116
|
| HWP 5.x ↔ HWPX | 1,130쌍 · 4,315표 | 짝 문서의 표 구조 일치 **100%** |
|
|
117
|
-
| PDF 글 | 744쌍 | 글자 재현율 **99.883%** · 정확도 **99.678%** · 읽기 순서 **99.312%** · 어절 F1 **99.
|
|
117
|
+
| PDF 글 | 744쌍 | 글자 재현율 **99.883%** · 정확도 **99.678%** · 읽기 순서 **99.312%** · 어절 F1 **99.067%** |
|
|
118
118
|
| PDF 표 | 708쌍 · 2,331표 | 표 탐지 **99.83%** · 구조 일치 **98.24%** · 칸 F1 **0.9919** |
|
|
119
119
|
| HWPX 재조판 | 다중줄 25,187문단 (12개 폴더) | 모든 줄 시작 일치 **24,941/25,187 · 99.02%** |
|
|
120
120
|
| PDF 중첩표 (텍스트층) | 29문서 · 101표 | 구조·칸 내용 **101/101 · 100%** |
|
|
121
121
|
| 법령 별표 | 272건 · 346표 | HWP **346/346**, PDF **342/346 · 98.84%** |
|
|
122
122
|
| PDF 전체 | 1,911문서 중 1,729건 채점 | 글 커버리지 **99.80%** |
|
|
123
|
-
| OCR | 53문서 · 102쪽 · 67표 | CER **0.
|
|
123
|
+
| OCR | 53문서 · 102쪽 · 67표 | CER **0.0250** · 글자 재현율 **99.27%** · 표 구조 일치 **26/67** |
|
|
124
124
|
| opendataloader-bench | PDF 200문서 | 종합 기본값 **0.964** · OCR 끔 **0.939** |
|
|
125
125
|
| HWPX 렌더 배치 (4.24.14) | 한컴 PDF 짝 · 글 조각 90,840 · 그림 4,107 | 글 위치(±1.5pt) **87,643 · 96.5%** · 그림 위치(±2pt) **4,019 · 97.9%** |
|
|
126
126
|
|
|
@@ -128,15 +128,15 @@ await writeFile("보고서.hwpx", Buffer.from(hwpx))
|
|
|
128
128
|
|
|
129
129
|
## 최근 업데이트
|
|
130
130
|
|
|
131
|
-
최신 배포: **[4.24.
|
|
131
|
+
최신 배포: **[4.24.16](https://github.com/chrisryugj/kordoc/releases/tag/v4.24.16)** · 2026-10-28
|
|
132
132
|
|
|
133
133
|
| 버전 | 주요 변경 | 수치 변화 |
|
|
134
134
|
| --- | --- | --- |
|
|
135
|
+
| 4.24.16 | OCR: 짧은 목차 리더 ··, 과제 번호의 Ⅲ(파·피로 읽음)·네모 번호 앞 [ ·붙임표가 붙은 원문자 ①, 한글 뒤 로마 숫자 획 수(Ⅰ↔Ⅱ), 칸 테두리 앞·빈칸 긴 서식 칸 끝 닫는 괄호 | OCR CER 0.0255 → **0.0250** · 글자 재현율 99.23% → **99.27%** · 정밀도 99.53% → **99.54%** · 열화 입력 8종 개선(원본 0.0397 → **0.0394**, 스캔만 0.0692 → 0.0693) |
|
|
136
|
+
| 4.24.15 | OCR: 검출기가 놓친 서식 빈칸 네모 □□-□□□·목차 줄 머리 대시·줄 끝 홑 쪽 번호, 큰 글머리 ■, 리터 ℓ, 작은 고리 。, 윗줄에 묻힌 줄 머리 가운뎃점, 빗금 칸 환각 · PDF: 줄 간격 넓은 중·일문 두 줄 묶음 문단 잇기 | OCR CER 0.0260 → **0.0255** · 글자 재현율 99.19% → **99.23%** · 열화 입력 8종 개선(원본 0.0405 → **0.0397**, 잡음만 0.0485 → 0.0486) · PDF 어절 F1 99.066% → **99.067%** |
|
|
135
137
|
| 4.24.14 | 렌더: 칸 간격(`cellSpacing`) 표의 칸 자리 · OCR: 공백·따옴표로 읽은 홑낫표 「, 검출기가 놓친 쪽 번호, 라틴 약어 앞·C 로 읽은 줄 머리 ○, 고리만 든 칸 ○, 마름모 글머리 ◆·◇·◈, 서식 칸 끝 닫는 괄호 | 렌더 글 위치 87,577 → **87,643** · OCR CER 0.0263 → **0.0260** · 열화 입력 9종 모두 개선(원본 0.0409 → **0.0405**) |
|
|
136
138
|
| 4.24.13 | 기관팩(`.kpack`): 기관 문서 몇 건으로 서식 묶음을 만들어 그 서식대로 새 문서 · OCR: 선 없는 표 칸 순서·넓게 벌린 균등배분, 글자 상자 안 획 조각, 줄 머리 □, 기간 날짜 끝점, 전화 기호 ☎ · PDF·HWP: 한컴 소프트 하이픈 붙임표(증감 칸 음수 부호) · patch 추가 문단 강조 서식·렌더 자란 표 겹침(#175) | 기관팩 처음 보는 문서 재현 서울 68.3% → **74.3%** · 광양 77.1% → **94.5%** · OCR CER 0.0281 → **0.0263** · 열화 입력 9종 모두 개선(원본 0.0429 → **0.0409**) |
|
|
137
139
|
| 4.24.12 | OCR: 조직도 상자 연결선을 괘선으로(과·팀 상자 열 단위 읽기), 요일 앞 날짜 마침표, 목차 리더 잡티, 화살표 모양 ⇨·➔·▶, 쉼표로 읽은 」 | OCR CER 0.0306 → **0.0281** · 글자 재현율 99.12% → **99.14%** · 열화 입력 9종 모두 개선(원본 0.0475 → **0.0429**) |
|
|
138
|
-
| 4.24.11 | OCR: 표 칸·행 경계를 가로지른 검출 박스 가르기, 날짜 쉼표, 직함 앞 전(前)·현(現) · 렌더: 쪽 번호 글자 크기 · 생성: 서울 방침서 제목 줄간격·요약 정렬 | OCR CER 0.0310 → **0.0306** · 글자 재현율 99.10% → **99.12%** · 렌더 글 위치 87,546 → **87,577** · 생성 재현 0.806 → **0.807** |
|
|
139
|
-
| 4.24.10 | 보안: 데모 lockfile 의 zod·fast-uri, 정부 GitLab 미러 복구(Java SDK `kordoc-pom.xml`) · OCR: 줄 머리 ▣·❐·‣, `\|` 로 읽은 로마 숫자, 날짜 끝 마침표 · PDF: 세로쓰기 、。, 그러데이션 배경 괘선, 중·일문 자동 간격 | OCR CER 0.0313 → **0.0310** · 글자 재현율 99.06% → **99.10%** · 열화 입력 9종 모두 개선(스캔 0.0734 → **0.0730**) · PDF 어절 F1 99.064% → **99.066%** |
|
|
140
140
|
|
|
141
141
|
이전 버전과 상세 내용은 [변경 이력](CHANGELOG.md)에 있습니다.
|
|
142
142
|
|
|
@@ -64,10 +64,10 @@ import {
|
|
|
64
64
|
usesGaejosikMunche,
|
|
65
65
|
usesLogicStructure,
|
|
66
66
|
validateHwpx
|
|
67
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-BHY2QAPM.js";
|
|
68
68
|
import {
|
|
69
69
|
blocksToChunks
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-2UXGDAWQ.js";
|
|
71
71
|
import {
|
|
72
72
|
SPACE_EM_FIXED,
|
|
73
73
|
SPACE_EM_FONT,
|
|
@@ -92,20 +92,20 @@ import {
|
|
|
92
92
|
renderSceneToHtml,
|
|
93
93
|
simulateWrap,
|
|
94
94
|
simulateWrapKeepWord
|
|
95
|
-
} from "./chunk-
|
|
96
|
-
import "./chunk-
|
|
95
|
+
} from "./chunk-UCEGWDWX.js";
|
|
96
|
+
import "./chunk-F3VIVCIF.js";
|
|
97
97
|
import {
|
|
98
98
|
blocksToPages
|
|
99
|
-
} from "./chunk-
|
|
99
|
+
} from "./chunk-FK7KGS5D.js";
|
|
100
100
|
import "./chunk-VKVDMH7X.js";
|
|
101
101
|
import "./chunk-VQFA55IC.js";
|
|
102
102
|
import "./chunk-BYMPPVT3.js";
|
|
103
|
-
import "./chunk-
|
|
103
|
+
import "./chunk-DH564VPR.js";
|
|
104
104
|
import {
|
|
105
105
|
blocksToMarkdown,
|
|
106
106
|
flattenLayoutTables,
|
|
107
107
|
hasStructuredCellContent
|
|
108
|
-
} from "./chunk-
|
|
108
|
+
} from "./chunk-QOMLSZLM.js";
|
|
109
109
|
import {
|
|
110
110
|
ValueCursor,
|
|
111
111
|
applySplices,
|
|
@@ -119,11 +119,11 @@ import {
|
|
|
119
119
|
isLabelCell,
|
|
120
120
|
placeSealHwpx,
|
|
121
121
|
scanSectionXml
|
|
122
|
-
} from "./chunk-
|
|
123
|
-
import "./chunk-
|
|
122
|
+
} from "./chunk-S2VWNC2W.js";
|
|
123
|
+
import "./chunk-TSCQDCAR.js";
|
|
124
124
|
import {
|
|
125
125
|
VERSION
|
|
126
|
-
} from "./chunk-
|
|
126
|
+
} from "./chunk-6PPVAQ2N.js";
|
|
127
127
|
import {
|
|
128
128
|
DEFAULT_REDACT_RULES,
|
|
129
129
|
redactMarkdown,
|
|
@@ -239,4 +239,4 @@ export {
|
|
|
239
239
|
usesLogicStructure,
|
|
240
240
|
validateHwpx
|
|
241
241
|
};
|
|
242
|
-
//# sourceMappingURL=-
|
|
242
|
+
//# sourceMappingURL=-ZKOPHIGY.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
assignTableIds,
|
|
4
4
|
blocksToMarkdown
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-QOMLSZLM.js";
|
|
6
6
|
|
|
7
7
|
// src/chunks.ts
|
|
8
8
|
var LIST_MARKER_RE = /^(?:[□■◇◆○◎●◦ㅇ•▪▸▶※-]|\d{1,3}[.)]|[가나다라마바사아자차카타파하][.)]|\([가나다라마바사아자차카타파하0-9]{1,3}\)|[①-⑳㉮-㉻㈎-㈛])\s/;
|
|
@@ -82,4 +82,4 @@ function blocksToChunks(blocks, options) {
|
|
|
82
82
|
export {
|
|
83
83
|
blocksToChunks
|
|
84
84
|
};
|
|
85
|
-
//# sourceMappingURL=chunk-
|
|
85
|
+
//# sourceMappingURL=chunk-2UXGDAWQ.js.map
|
|
@@ -30,7 +30,7 @@ import {
|
|
|
30
30
|
splitRowBands,
|
|
31
31
|
starRun,
|
|
32
32
|
tallInkCount
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-6K2SYTNJ.js";
|
|
34
34
|
import {
|
|
35
35
|
validateOcrOptions
|
|
36
36
|
} from "./chunk-BYMPPVT3.js";
|
|
@@ -41,11 +41,11 @@ import {
|
|
|
41
41
|
ocrSourcePath,
|
|
42
42
|
parseCharacterDict,
|
|
43
43
|
resolveOcrModels
|
|
44
|
-
} from "./chunk-
|
|
44
|
+
} from "./chunk-J5M5OW4S.js";
|
|
45
45
|
import {
|
|
46
46
|
KordocError,
|
|
47
47
|
OPTIONAL_DEP_INSTALL_HINT
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-6PPVAQ2N.js";
|
|
49
49
|
|
|
50
50
|
// src/ocr/ruling-lines.ts
|
|
51
51
|
var INK_LUMA_MAX = 205;
|
|
@@ -535,6 +535,14 @@ function gaps({ chars, cx, gray, w, h, ink }) {
|
|
|
535
535
|
const pitch = d.length >= 2 ? d.sort((a, b) => a - b)[d.length >> 1] : bandH;
|
|
536
536
|
const nearTo = (g) => (i) => Math.abs(cx(i) - (g.x0 + g.x1) / 2) <= Math.max(pitch * 0.45, (g.x1 - g.x0) / 2 + 1);
|
|
537
537
|
const loose = glyphs.filter((g) => /^[\u00b7.]/.test(g.mark) && !live.some(nearTo(g)));
|
|
538
|
+
const tail = [...live].reverse().findIndex((i) => !/^\d$/.test(chars[i]));
|
|
539
|
+
if (tail >= 1 && tail <= 3 && tail < live.length) {
|
|
540
|
+
const prev = live[live.length - 1 - tail], num = live[live.length - tail];
|
|
541
|
+
const run = loose.filter((g) => (g.x0 + g.x1) / 2 > cx(prev) && (g.x0 + g.x1) / 2 < cx(num));
|
|
542
|
+
const mark = run[0]?.mark[0];
|
|
543
|
+
if (run.length >= 2 && run.length <= 3 && run.every((g) => g.mark[0] === mark) && /^[가-힣?)]$/.test(chars[prev]) && !glyphs.some((g) => !run.includes(g) && (g.x0 + g.x1) / 2 > cx(prev) && (g.x0 + g.x1) / 2 < cx(num)))
|
|
544
|
+
chars[prev] += " " + mark.repeat(run.length) + " ";
|
|
545
|
+
}
|
|
538
546
|
for (const g of glyphs.sort((a, b) => a.x0 - b.x0)) {
|
|
539
547
|
const mid = (g.x0 + g.x1) / 2;
|
|
540
548
|
const near = nearTo(g);
|
|
@@ -547,6 +555,7 @@ function gaps({ chars, cx, gray, w, h, ink }) {
|
|
|
547
555
|
}
|
|
548
556
|
if (cover.length) {
|
|
549
557
|
if (g.mark.startsWith("\u25A1") && cover.length === 1 && /^[0Oo\u25cb]$/.test(chars[cover[0]])) chars[cover[0]] = "\u25A1";
|
|
558
|
+
if (g.mark === "\u3002" && cover.length === 1 && /^[\u00b7\u2022\u318d]$/.test(chars[cover[0]])) chars[cover[0]] = "\u3002";
|
|
550
559
|
continue;
|
|
551
560
|
}
|
|
552
561
|
if (g.mark === "\u25A1\0") continue;
|
|
@@ -611,13 +620,14 @@ function roman({ chars, cx, gray, w, h, ink }) {
|
|
|
611
620
|
if (serifOne(gray, w, h, ink, cx(i))) chars[i] = "\u2160";
|
|
612
621
|
}
|
|
613
622
|
for (let i = 0; i < chars.length; i++) {
|
|
614
|
-
|
|
623
|
+
const hangul = /^[파피]$/.test(chars[i]);
|
|
624
|
+
if (chars[i] !== "|" && !hangul || chars[i - 1] === "|" || chars[i + 1] === "|") continue;
|
|
615
625
|
let p = i - 1, q = i + 1;
|
|
616
626
|
while (p >= 0 && !chars[p].trim()) p--;
|
|
617
627
|
while (q < chars.length && !chars[q].trim()) q++;
|
|
618
|
-
const glued = /[가-힣]$/.test(chars[i - 1] ?? "") || (chars[i + 1] ?? "") === "." || chars[p] === "-" && chars[q] === "-";
|
|
628
|
+
const glued = hangul ? chars[p] === "(" && chars[q] === "-" : /[가-힣]$/.test(chars[i - 1] ?? "") || (chars[i + 1] ?? "") === "." || chars[p] === "-" && chars[q] === "-";
|
|
619
629
|
if (!glued) continue;
|
|
620
|
-
const n = romanStems(gray, w, h, ink, p >= 0 ? cx(p) : -Infinity, q < chars.length ? cx(q) : Infinity);
|
|
630
|
+
const n = romanStems(gray, w, h, ink, p >= 0 ? cx(p) : -Infinity, q < chars.length ? cx(q) : Infinity, /[가-힣]$/.test(chars[p] ?? ""));
|
|
621
631
|
if (n) chars[i] = String.fromCharCode(8543 + n);
|
|
622
632
|
}
|
|
623
633
|
const inRoman = (i) => ROMAN.test(chars[i]) || chars[i] === "1" && (ROMAN.test(chars[i - 1] ?? "") || ROMAN.test(chars[i + 1] ?? ""));
|
|
@@ -632,7 +642,7 @@ function roman({ chars, cx, gray, w, h, ink }) {
|
|
|
632
642
|
continue;
|
|
633
643
|
}
|
|
634
644
|
let e = s;
|
|
635
|
-
while (e < chars.length && inRoman(e)) e++;
|
|
645
|
+
while (e < chars.length && (inRoman(e) || e > s && chars[e] === "|" && chars[e + 1] !== "|")) e++;
|
|
636
646
|
const tok = chars.slice(s, e).join("");
|
|
637
647
|
if (e < chars.length && /^[A-Za-z]/.test(chars[e])) {
|
|
638
648
|
s = e;
|
|
@@ -641,7 +651,7 @@ function roman({ chars, cx, gray, w, h, ink }) {
|
|
|
641
651
|
let p = s - 1, q = e;
|
|
642
652
|
while (p >= 0 && !chars[p].trim()) p--;
|
|
643
653
|
while (q < chars.length && !chars[q].trim()) q++;
|
|
644
|
-
const n = romanStems(gray, w, h, ink, p >= 0 ? cx(p) : -Infinity, q < chars.length ? cx(q) : Infinity);
|
|
654
|
+
const n = romanStems(gray, w, h, ink, p >= 0 ? cx(p) : -Infinity, q < chars.length ? cx(q) : Infinity, /[가-힣]$/.test(chars[p] ?? ""));
|
|
645
655
|
const canon = n ? [["\u2160", "I"], ["\u2161", "II"], ["\u2162", "III"]][n - 1] : null;
|
|
646
656
|
if (canon && !canon.includes(tok)) {
|
|
647
657
|
chars[s] = canon[0];
|
|
@@ -660,7 +670,9 @@ function restoreSymbols(text, ringDecided = false) {
|
|
|
660
670
|
s = s.replace(/[\u2206\u0394]/g, "\u25B3");
|
|
661
671
|
s = s.replace(/\(cid:\d*\)/g, "");
|
|
662
672
|
s = s.replace(/(^|[^\uac00-\ud7a3])(전|현)\(\s?\)(?=\S)/g, (_, a, b) => `${a}${b}(${b === "\uC804" ? "\u524D" : "\u73FE"})`);
|
|
673
|
+
if (/[가-힣]/.test(s)) s = s.replace(/(\d)l(?![A-Za-z])/g, "$1\u2113");
|
|
663
674
|
s = s.replace(/([((])\s?[A-Za-z@&]\s?(?=(?:0\d{1,2}-)?\d{3,4}-\d{4}\b)/g, "$1\u260E");
|
|
675
|
+
if (!s.includes("]")) s = s.replace(/^\[(?=[\u2460-\u2473])/, "");
|
|
664
676
|
return smartQuotes(dateDots(dateCommas(joinDigitGroups(s))));
|
|
665
677
|
}
|
|
666
678
|
function dateCommas(s) {
|
|
@@ -907,6 +919,182 @@ var MIN_INK_RATIO = 0.01;
|
|
|
907
919
|
var MAX_LOCAL_MODEL_BYTES = 1024 * 1024 * 1024;
|
|
908
920
|
var DET_MEAN = [0.485, 0.456, 0.406];
|
|
909
921
|
var DET_STD = [0.229, 0.224, 0.225];
|
|
922
|
+
function rowHeadDashes(rgba, width, items) {
|
|
923
|
+
const out = [];
|
|
924
|
+
const dark = (x, y) => {
|
|
925
|
+
const p = (y * width + x) * 4;
|
|
926
|
+
return rgba[p] * 77 + rgba[p + 1] * 150 + rgba[p + 2] * 29 >> 8 < 160;
|
|
927
|
+
};
|
|
928
|
+
const inBox = (x, y) => items.some((b) => x >= b.x && x < b.x + b.w && y >= b.y && y < b.y + b.h);
|
|
929
|
+
const done = /* @__PURE__ */ new Set();
|
|
930
|
+
for (const it of [...items]) {
|
|
931
|
+
if (done.has(it) || it.h < 12) continue;
|
|
932
|
+
const row = items.filter((o) => Math.min(o.y + o.h, it.y + it.h) - Math.max(o.y, it.y) >= Math.min(o.h, it.h) * 0.6);
|
|
933
|
+
for (const o of row) done.add(o);
|
|
934
|
+
if (row.reduce((k, o) => k + (o.text.match(/[가-힣]/g)?.length ?? 0), 0) < 2) continue;
|
|
935
|
+
const first = row.reduce((m, o) => o.x < m.x ? o : m);
|
|
936
|
+
if (!/^[가-힣]/.test(first.text)) continue;
|
|
937
|
+
if (row.filter((o) => /\d/.test(o.text)).length >= 2) continue;
|
|
938
|
+
const y0 = Math.min(...row.map((o) => o.y)), y1 = Math.max(...row.map((o) => o.y + o.h)), h = y1 - y0;
|
|
939
|
+
const x0 = Math.max(0, Math.round(first.x - 2.5 * h)), x1 = first.x - 2;
|
|
940
|
+
let minX = -1, maxX = -1, minY = Infinity, maxY = -1, groups = 0;
|
|
941
|
+
for (let x = x0; x < x1; x++) {
|
|
942
|
+
let on = false;
|
|
943
|
+
for (let y = y0; y < y1; y++) if (dark(x, y) && !inBox(x, y)) {
|
|
944
|
+
on = true;
|
|
945
|
+
if (y < minY) minY = y;
|
|
946
|
+
if (y > maxY) maxY = y;
|
|
947
|
+
}
|
|
948
|
+
if (!on) continue;
|
|
949
|
+
if (maxX < 0 || x - maxX > 2) {
|
|
950
|
+
groups++;
|
|
951
|
+
if (groups === 1) minX = x;
|
|
952
|
+
}
|
|
953
|
+
maxX = x;
|
|
954
|
+
}
|
|
955
|
+
const bw = maxX - minX + 1, bh = maxY - minY + 1, cy = ((minY + maxY) / 2 - y0) / h;
|
|
956
|
+
if (groups !== 1 || bh > h * 0.2 || bw < h * 0.3 || bw > h * 1.2 || cy < 0.3 || cy > 0.7) continue;
|
|
957
|
+
const faint = (x, y) => {
|
|
958
|
+
const p = (y * width + x) * 4;
|
|
959
|
+
return rgba[p] * 77 + rgba[p + 1] * 150 + rgba[p + 2] * 29 >> 8 < 230;
|
|
960
|
+
};
|
|
961
|
+
let touch = minX <= x0;
|
|
962
|
+
for (let y = minY; y <= maxY && !touch; y++) for (let d = 2; d <= 4 && !touch; d++) touch = minX - d >= 0 && faint(minX - d, y) || faint(maxX + d, y);
|
|
963
|
+
if (touch) continue;
|
|
964
|
+
out.push({ text: "-", x: minX, y: y0, w: bw, h, confidence: first.confidence });
|
|
965
|
+
}
|
|
966
|
+
return out;
|
|
967
|
+
}
|
|
968
|
+
function rowTailBoxes(rgba, width, items) {
|
|
969
|
+
const out = [];
|
|
970
|
+
const dark = (x, y) => {
|
|
971
|
+
const p = (y * width + x) * 4;
|
|
972
|
+
return rgba[p] * 77 + rgba[p + 1] * 150 + rgba[p + 2] * 29 >> 8 < 160;
|
|
973
|
+
};
|
|
974
|
+
const done = /* @__PURE__ */ new Set();
|
|
975
|
+
for (const it of items) {
|
|
976
|
+
if (done.has(it) || it.h < 12) continue;
|
|
977
|
+
const row = items.filter((o) => Math.min(o.y + o.h, it.y + it.h) - Math.max(o.y, it.y) >= Math.min(o.h, it.h) * 0.6);
|
|
978
|
+
for (const o of row) done.add(o);
|
|
979
|
+
if (row.reduce((k, o) => k + (o.text.match(/[가-힣]/g)?.length ?? 0), 0) < 2) continue;
|
|
980
|
+
const last = row.reduce((m, o) => o.x + o.w > m.x + m.w ? o : m);
|
|
981
|
+
if (/\d$/.test(last.text.trim())) continue;
|
|
982
|
+
const y0 = Math.min(...row.map((o) => o.y)), y1 = Math.max(...row.map((o) => o.y + o.h)), h = y1 - y0;
|
|
983
|
+
const x0 = last.x + last.w + 4, x1 = Math.floor(width * 0.95);
|
|
984
|
+
if (x1 - x0 < h) continue;
|
|
985
|
+
let groups = 0, minX = -1, maxX = -1, minY = Infinity, maxY = -1;
|
|
986
|
+
for (let x = x0; x < x1; x++) {
|
|
987
|
+
let on = false;
|
|
988
|
+
for (let y = y0; y < y1; y++) if (dark(x, y)) {
|
|
989
|
+
on = true;
|
|
990
|
+
if (y < minY) minY = y;
|
|
991
|
+
if (y > maxY) maxY = y;
|
|
992
|
+
}
|
|
993
|
+
if (!on) continue;
|
|
994
|
+
if (maxX < 0 || x - maxX > h) {
|
|
995
|
+
groups++;
|
|
996
|
+
if (groups === 1) minX = x;
|
|
997
|
+
}
|
|
998
|
+
maxX = x;
|
|
999
|
+
}
|
|
1000
|
+
if (groups !== 1 || maxY - minY + 1 < h * 0.5 || maxX - minX + 1 > h * 4) continue;
|
|
1001
|
+
const height = Math.floor(rgba.length / 4 / width);
|
|
1002
|
+
let rule = false;
|
|
1003
|
+
for (let x = minX; x <= maxX && !rule; x++) rule = minY > 1 && dark(x, minY - 2) || maxY + 2 < height && dark(x, maxY + 2);
|
|
1004
|
+
if (rule) continue;
|
|
1005
|
+
const pad = 4;
|
|
1006
|
+
out.push({ x: Math.max(0, minX - pad), y: Math.max(0, minY - pad), w: maxX - minX + 1 + 2 * pad, h: maxY - minY + 1 + 2 * pad });
|
|
1007
|
+
}
|
|
1008
|
+
return out;
|
|
1009
|
+
}
|
|
1010
|
+
function placeholderSquares(rgba, width, height, items) {
|
|
1011
|
+
const dark = new Uint8Array(width * height);
|
|
1012
|
+
for (let p = 0, i = 0; p < dark.length; p++, i += 4) dark[p] = rgba[i] * 77 + rgba[i + 1] * 150 + rgba[i + 2] * 29 >> 8 < 128 ? 1 : 0;
|
|
1013
|
+
const covered = (x, y) => items.some((b) => x >= b.x - 2 && x < b.x + b.w + 2 && y >= b.y - 2 && y < b.y + b.h + 2);
|
|
1014
|
+
const seen = new Uint8Array(width * height);
|
|
1015
|
+
const squares = [], bars = [];
|
|
1016
|
+
const stack = [];
|
|
1017
|
+
for (let start = 0; start < dark.length; start++) {
|
|
1018
|
+
if (!dark[start] || seen[start]) continue;
|
|
1019
|
+
const c = { x0: width, y0: height, x1: -1, y1: -1, n: 0, px: [] };
|
|
1020
|
+
stack.push(start);
|
|
1021
|
+
seen[start] = 1;
|
|
1022
|
+
while (stack.length) {
|
|
1023
|
+
const p = stack.pop(), x = p % width, y = (p - x) / width;
|
|
1024
|
+
c.n++;
|
|
1025
|
+
if (c.px.length < 4e3) c.px.push(p);
|
|
1026
|
+
if (x < c.x0) c.x0 = x;
|
|
1027
|
+
if (x > c.x1) c.x1 = x;
|
|
1028
|
+
if (y < c.y0) c.y0 = y;
|
|
1029
|
+
if (y > c.y1) c.y1 = y;
|
|
1030
|
+
for (const q of [p - 1, p + 1, p - width, p + width]) if (q >= 0 && q < dark.length && !seen[q] && dark[q] && Math.abs(q % width - x) <= 1) {
|
|
1031
|
+
seen[q] = 1;
|
|
1032
|
+
stack.push(q);
|
|
1033
|
+
}
|
|
1034
|
+
if (c.n > 4e3) break;
|
|
1035
|
+
}
|
|
1036
|
+
while (stack.length) {
|
|
1037
|
+
const p = stack.pop();
|
|
1038
|
+
seen[p] = 1;
|
|
1039
|
+
}
|
|
1040
|
+
const w = c.x1 - c.x0 + 1, h = c.y1 - c.y0 + 1;
|
|
1041
|
+
if (c.n > 4e3 || covered(c.x0 + c.x1 >> 1, c.y0 + c.y1 >> 1)) continue;
|
|
1042
|
+
if (h >= 2 && h <= 6 && w >= 4 && w <= 30 && c.n >= w * h * 0.7) {
|
|
1043
|
+
bars.push(c);
|
|
1044
|
+
continue;
|
|
1045
|
+
}
|
|
1046
|
+
if (w < 12 || h < 12 || w > 60 || h > 60 || w > h * 1.33 || h > w * 1.33) continue;
|
|
1047
|
+
const at = (x, y) => dark[y * width + x] === 1;
|
|
1048
|
+
const row = (y) => {
|
|
1049
|
+
let k = 0;
|
|
1050
|
+
for (let x = c.x0; x <= c.x1; x++) if (at(x, y)) k++;
|
|
1051
|
+
return k / w;
|
|
1052
|
+
};
|
|
1053
|
+
const col = (x) => {
|
|
1054
|
+
let k = 0;
|
|
1055
|
+
for (let y = c.y0; y <= c.y1; y++) if (at(x, y)) k++;
|
|
1056
|
+
return k / h;
|
|
1057
|
+
};
|
|
1058
|
+
const edge = (vals) => Math.max(...vals) >= 0.8;
|
|
1059
|
+
const top = edge([row(c.y0), row(c.y0 + 1)]), bottom = edge([row(c.y1), row(c.y1 - 1)]), left = edge([col(c.x0), col(c.x0 + 1)]), right = edge([col(c.x1), col(c.x1 - 1)]);
|
|
1060
|
+
let inner = 0;
|
|
1061
|
+
for (let y = c.y0 + Math.ceil(h * 0.25); y <= c.y1 - Math.ceil(h * 0.25); y++) for (let x = c.x0 + Math.ceil(w * 0.25); x <= c.x1 - Math.ceil(w * 0.25); x++) if (at(x, y)) inner++;
|
|
1062
|
+
if (top && bottom && left && right && inner === 0) squares.push(c);
|
|
1063
|
+
}
|
|
1064
|
+
squares.sort((a, b) => a.y0 - b.y0 || a.x0 - b.x0);
|
|
1065
|
+
const out = [];
|
|
1066
|
+
const used = /* @__PURE__ */ new Set();
|
|
1067
|
+
for (const s0 of squares) {
|
|
1068
|
+
if (used.has(s0)) continue;
|
|
1069
|
+
const run = [s0];
|
|
1070
|
+
used.add(s0);
|
|
1071
|
+
const side = s0.y1 - s0.y0 + 1, cy = (s0.y0 + s0.y1) / 2;
|
|
1072
|
+
let text = "\u25A1";
|
|
1073
|
+
for (; ; ) {
|
|
1074
|
+
const last = run[run.length - 1];
|
|
1075
|
+
const next = squares.find((q) => !used.has(q) && Math.abs((q.y0 + q.y1) / 2 - cy) <= side * 0.3 && q.x0 > last.x1 && q.x0 - last.x1 <= side * 2);
|
|
1076
|
+
if (!next) break;
|
|
1077
|
+
const gap = next.x0 - last.x1;
|
|
1078
|
+
const bar = bars.find((b) => b.x0 > last.x1 && b.x1 < next.x0 && Math.abs((b.y0 + b.y1) / 2 - cy) <= side * 0.3);
|
|
1079
|
+
let stroke = 0;
|
|
1080
|
+
if (!bar) for (let y = Math.round(cy - side * 0.15); y <= Math.round(cy + side * 0.15); y++) {
|
|
1081
|
+
let k = 0;
|
|
1082
|
+
for (let x = last.x1 + 1; x < next.x0; x++) {
|
|
1083
|
+
k = dark[y * width + x] ? k + 1 : 0;
|
|
1084
|
+
if (k > stroke) stroke = k;
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
if (bar || stroke >= Math.max(4, side * 0.25)) text += "-";
|
|
1088
|
+
else if (gap > side) break;
|
|
1089
|
+
text += "\u25A1";
|
|
1090
|
+
used.add(next);
|
|
1091
|
+
run.push(next);
|
|
1092
|
+
}
|
|
1093
|
+
const x0 = run[0].x0, x1 = run[run.length - 1].x1;
|
|
1094
|
+
out.push({ text, x: x0, y: s0.y0, w: x1 - x0 + 1, h: side, confidence: 0.9 });
|
|
1095
|
+
}
|
|
1096
|
+
return out;
|
|
1097
|
+
}
|
|
910
1098
|
function footerInkBox(rgba, width, height, boxes) {
|
|
911
1099
|
const y0 = Math.floor(height * 0.88), x0 = Math.floor(width * 0.3), x1 = Math.ceil(width * 0.7);
|
|
912
1100
|
let minX = Infinity, maxX = -1, minY = Infinity, maxY = -1;
|
|
@@ -936,11 +1124,28 @@ function closingParens(rgba, width, items) {
|
|
|
936
1124
|
if ((t.match(/\(/g)?.length ?? 0) <= (t.match(/\)/g)?.length ?? 0) || !/\([^()]*$/.test(t)) continue;
|
|
937
1125
|
const x0 = it.x + it.w + 2;
|
|
938
1126
|
const next = items.filter((o) => o !== it && o.x >= x0 && o.y < it.y + it.h && o.y + o.h > it.y).reduce((m, o) => Math.min(m, o.x), Infinity);
|
|
939
|
-
|
|
1127
|
+
let x1 = Math.min(width, next, x0 + it.h * 16);
|
|
1128
|
+
const pageH = Math.floor(rgba.length / 4 / width);
|
|
1129
|
+
const colInk = (x) => {
|
|
1130
|
+
let k = 0;
|
|
1131
|
+
for (let y = it.y; y < it.y + it.h; y++) if (dark(x, y)) k++;
|
|
1132
|
+
return k;
|
|
1133
|
+
};
|
|
1134
|
+
for (let x = x0; x < x1; x++) if (colInk(x) >= it.h * 0.9) {
|
|
1135
|
+
x1 = x;
|
|
1136
|
+
while (x1 > x0 && colInk(x1 - 1) >= it.h * 0.5) x1--;
|
|
1137
|
+
break;
|
|
1138
|
+
}
|
|
1139
|
+
const ruleRow = /* @__PURE__ */ new Set();
|
|
1140
|
+
for (let y = it.y; y < it.y + it.h; y++) {
|
|
1141
|
+
let k = 0;
|
|
1142
|
+
for (let x = x0; x < x1; x++) if (dark(x, y)) k++;
|
|
1143
|
+
if (k > (x1 - x0) * 0.8) for (const d of [-1, 0, 1]) ruleRow.add(y + d);
|
|
1144
|
+
}
|
|
940
1145
|
let minX = Infinity, maxX = -1, minY = Infinity, maxY = -1, cols = 0, prevOn = false, runs = 0;
|
|
941
1146
|
for (let x = x0; x < x1; x++) {
|
|
942
1147
|
let on = false;
|
|
943
|
-
for (let y = it.y; y < it.y + it.h; y++) if (dark(x, y)) {
|
|
1148
|
+
for (let y = it.y; y < it.y + it.h; y++) if (!ruleRow.has(y) && dark(x, y)) {
|
|
944
1149
|
on = true;
|
|
945
1150
|
if (y < minY) minY = y;
|
|
946
1151
|
if (y > maxY) maxY = y;
|
|
@@ -954,9 +1159,14 @@ function closingParens(rgba, width, items) {
|
|
|
954
1159
|
prevOn = on;
|
|
955
1160
|
}
|
|
956
1161
|
if (runs !== 1 || maxX - minX + 1 > it.h * 0.5 || maxY - minY + 1 < it.h * 0.6) continue;
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
1162
|
+
const inkRow = (y) => {
|
|
1163
|
+
for (let x = minX; x <= maxX; x++) if (dark(x, y)) return true;
|
|
1164
|
+
return false;
|
|
1165
|
+
};
|
|
1166
|
+
let over = 0;
|
|
1167
|
+
for (let y = minY - 1; y >= 0 && !ruleRow.has(y) && inkRow(y) && over <= it.h; y--) over++;
|
|
1168
|
+
for (let y = maxY + 1; y < pageH && !ruleRow.has(y) && inkRow(y) && over <= it.h; y++) over++;
|
|
1169
|
+
if (over > it.h * 0.6) continue;
|
|
960
1170
|
const meanX = (ya, yb) => {
|
|
961
1171
|
let sx = 0, k = 0;
|
|
962
1172
|
for (let y = ya; y < yb; y++) for (let x = minX; x <= maxX; x++) if (dark(x, y)) {
|
|
@@ -1115,6 +1325,12 @@ var OcrEngine = class _OcrEngine {
|
|
|
1115
1325
|
const cur = best.get(job.group);
|
|
1116
1326
|
if (!cur || score(job, r.confidence) > score(cur.job, cur.confidence)) best.set(job.group, { job, ...r });
|
|
1117
1327
|
});
|
|
1328
|
+
jobs.forEach((job, i) => {
|
|
1329
|
+
const r = results[i], cur = best.get(job.group);
|
|
1330
|
+
if (!job.keep || !r || !cur || cur.job === job) return;
|
|
1331
|
+
const b = cur.text.replace(/\s/g, "");
|
|
1332
|
+
if (r.text.replace(/\s/g, "") === "\xB7" + b && /^[가-힣]/.test(b)) best.set(job.group, { ...cur, text: "\xB7" + cur.text, steps: [r.steps[0], ...cur.steps] });
|
|
1333
|
+
});
|
|
1118
1334
|
let items = [];
|
|
1119
1335
|
for (const r of best.values()) {
|
|
1120
1336
|
const { job, confidence, stepPx } = r;
|
|
@@ -1123,6 +1339,10 @@ var OcrEngine = class _OcrEngine {
|
|
|
1123
1339
|
const raw = tuning.postprocess && job.rot === 0 ? restoreGlyphs(rgba, width, job.box, read, steps, stepPx, note) : read;
|
|
1124
1340
|
let text = tuning.postprocess ? restoreSymbols(raw.trim(), note.ringLead) : raw;
|
|
1125
1341
|
if (!text.trim()) continue;
|
|
1342
|
+
if (tuning.postprocess && job.rot === 0 && text !== "/" && /^[(:;/)]+$/.test(text) && text.includes("/")) {
|
|
1343
|
+
const g = grayCrop(rgba, width, job.box);
|
|
1344
|
+
if (tallInkCount(g, job.box.w, job.box.h, inkStats(g)) === 1) text = "/";
|
|
1345
|
+
}
|
|
1126
1346
|
if (tuning.postprocess && job.rot === 0 && !/^[◎●▪□■▣❐❏○ㅇ◆◇◈]/.test(text)) {
|
|
1127
1347
|
const chars = [...read], k = chars.findIndex((c) => c.trim());
|
|
1128
1348
|
if (k >= 0 && steps.length === chars.length) {
|
|
@@ -1195,6 +1415,18 @@ var OcrEngine = class _OcrEngine {
|
|
|
1195
1415
|
if (tuning.postprocess) items = dropNestedFragments(items);
|
|
1196
1416
|
if (tuning.postprocess) for (const it of items) this.outerSquare(rgba, width, it, items);
|
|
1197
1417
|
if (tuning.postprocess) items.push(...closingParens(rgba, width, items));
|
|
1418
|
+
if (tuning.postprocess) items.push(...placeholderSquares(rgba, width, height, items));
|
|
1419
|
+
if (tuning.postprocess) items.push(...rowHeadDashes(rgba, width, items));
|
|
1420
|
+
if (tuning.postprocess) {
|
|
1421
|
+
const tails = rowTailBoxes(rgba, width, items);
|
|
1422
|
+
if (tails.length) {
|
|
1423
|
+
const res = await this.recognizeJobs(rgba, width, tails.map((box, k) => ({ box, rot: 0, group: k })), tuning.recBatch);
|
|
1424
|
+
tails.forEach((box, k) => {
|
|
1425
|
+
const t = res[k]?.text.trim() ?? "";
|
|
1426
|
+
if (/^\d{1,4}$/.test(t) && (res[k]?.confidence ?? 0) >= tuning.textScore) items.push({ text: t, ...this.itemBox(rgba, width, box, tuning), confidence: res[k].confidence });
|
|
1427
|
+
});
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1198
1430
|
if (tuning.postprocess) restoreBulletItems(items);
|
|
1199
1431
|
items.sort((a, b) => a.y - b.y || a.x - b.x);
|
|
1200
1432
|
return items;
|
|
@@ -1864,4 +2096,4 @@ export {
|
|
|
1864
2096
|
groupOcrLines,
|
|
1865
2097
|
ocrItemsToBlocks
|
|
1866
2098
|
};
|
|
1867
|
-
//# sourceMappingURL=chunk-
|
|
2099
|
+
//# sourceMappingURL=chunk-3TXAIEXL.js.map
|