From 801e492fa9b0fda40c2f08443dbb8443a9398ac7 Mon Sep 17 00:00:00 2001 From: xiaoxue_admin <9283713@qq.com> Date: Mon, 22 Jun 2026 10:13:48 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=87=AD=E8=AF=81=E5=8F=B7=E6=8F=90?= =?UTF-8?q?=E5=8F=96=E6=94=B9=E8=BF=9B=20-=20=E5=8F=8C=E7=AE=A1=E7=BA=BFOC?= =?UTF-8?q?R=EF=BC=9A=E5=8E=9F=E5=9B=BE=E6=8F=90=E5=8F=96=E5=A4=B4?= =?UTF-8?q?=E9=83=A8(=E5=87=AD=E8=AF=81=E5=8F=B7/=E6=97=A5=E6=9C=9F)=20+?= =?UTF-8?q?=20=E9=A2=84=E5=A4=84=E7=90=86=E6=8F=90=E5=8F=96=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=20-=20=E6=AD=A3=E5=88=99=E5=85=BC=E5=AE=B9=E6=9B=B4?= =?UTF-8?q?=E5=AE=BD=E6=9D=BE=E6=A0=BC=E5=BC=8F(=E7=A9=BA=E6=A0=BC?= =?UTF-8?q?=E3=80=81=E7=A0=B4=E6=8A=98=E5=8F=B7)=20-=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E9=A2=84=E5=A4=84=E7=90=86=E7=A0=B4=E5=9D=8F=E5=B0=8F=E5=AD=97?= =?UTF-8?q?=E5=AF=BC=E8=87=B465/66=E5=8F=B7=E5=87=AD=E8=AF=81=E6=BC=8F?= =?UTF-8?q?=E8=AF=86=E5=88=AB=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/parser.py | 17 ++++++++++++----- kocr.py | 31 ++++++++++++++++++++++++++----- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/core/parser.py b/core/parser.py index fffdb96..bfc0319 100644 --- a/core/parser.py +++ b/core/parser.py @@ -43,13 +43,20 @@ class K3VoucherParser: except: pass - elif '凭证号' in text: - m = re.search(r'[\u8bb0\u51ed\u8bc1]-\s*(\d+)', text) + elif '凭证' in text: + # 兼容各种格式:记-45、记 - 45、记-45(1/3)、45(1/3) + m = re.search(r'[记凭证]\s*[-—]\s*(\d+)', text) if m: result['voucher_no'] = int(m.group(1)) - m2 = re.search(r'(\d+)(\d+/\d+)', text) # 多页凭证:123(1/3) - if m2: - result['voucher_no'] = int(m2.group(1)) + if not result['voucher_no']: + m2 = re.search(r'(?:记\s*)?[-—]?\s*(\d+)\s*[((]\d+[/]\d+[))]', text) + if m2: + result['voucher_no'] = int(m2.group(1)) + # 兜底:直接找"凭证号"后面的数字 + if not result['voucher_no']: + m3 = re.search(r'凭证号\s*[::]\s*记?\s*[-—]?\s*(\d+)', text) + if m3: + result['voucher_no'] = int(m3.group(1)) elif '附件数' in text: m = re.search(r'附件数[::](\d+)', text) diff --git a/kocr.py b/kocr.py index 22f2b66..fff41fd 100644 --- a/kocr.py +++ b/kocr.py @@ -159,7 +159,19 @@ def process_single(image_path, config, output_path=None, verbose=False, mark_don print(f" 📊 图像分析: 类型={quality.photo_type}, " f"亮度={quality.brightness}, 模糊={quality.blur_score}") - # 2. 自动调参 + 预处理 + # 2. 双管线:先对原图OCR提取头部(凭证号、日期对小字更敏感) + ocr_config = config.get('ocr', {}) + + # 2a. 原图OCR → 提取头部信息(预处理会破坏小字) + if verbose: + print(f" 📋 原图OCR提取头部...") + lines_raw = run_ocr(img, ocr_config, quality.photo_type, verbose=verbose) + parser_raw = K3VoucherParser(lines_raw) + header_info = parser_raw.parse() + if verbose and header_info['voucher_no']: + print(f" ✅ 原图识别到凭证号: 记-{header_info['voucher_no']}") + + # 2b. 自动调参 + 预处理 → 提取表格内容 preproc_config = config.get('preprocessing', {}) preprocessor = VoucherPreprocessor.from_config(preproc_config, quality.photo_type) processed = preprocessor.process(img) @@ -169,17 +181,26 @@ def process_single(image_path, config, output_path=None, verbose=False, mark_don f"去阴影={preprocessor.remove_shadow}, " f"锐化={preprocessor.sharpen}") - # 3. OCR 识别(自动选参数) - ocr_config = config.get('ocr', {}) lines = run_ocr(processed, ocr_config, quality.photo_type, verbose=verbose) if verbose: - print(f" OCR: {len(lines)} 行文字") + print(f" OCR: {len(lines)} 行文字(预处理后)") - # 4. 凭证解析 + # 3. 解析(合并原图头部 + 预处理表格) parser = K3VoucherParser(lines) voucher = parser.parse() + # 如果原图识别到了凭证号但预处理后没识别到,补回来 + if voucher['voucher_no'] is None and header_info['voucher_no'] is not None: + voucher['voucher_no'] = header_info['voucher_no'] + if verbose: + print(f" ✅ 使用原图凭证号: 记-{header_info['voucher_no']}") + # 同理补日期 + if voucher['date'] is None and header_info['date'] is not None: + voucher['date'] = header_info['date'] + if verbose: + print(f" ✅ 使用原图日期: {header_info['date'].strftime('%Y-%m-%d')}") + if verbose: print(f" 公司: {voucher['company']}") print(f" 日期: {voucher['date'].strftime('%Y-%m-%d') if voucher['date'] else '未识别'}")