From 20cdeeb15c0871a9fc674a1f2446327d7577c9e7 Mon Sep 17 00:00:00 2001 From: youpaishidifu Date: Sun, 26 Jul 2026 21:55:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D:=20OCR=20=E5=9B=BE=E5=83=8F?= =?UTF-8?q?=E9=A2=84=E5=A4=84=E7=90=86=202x=20=E6=94=BE=E5=A4=A7+=E9=94=90?= =?UTF-8?q?=E5=8C=96+=E5=AF=B9=E6=AF=94=E5=BA=A6=20+=20=E5=A2=9E=E5=BC=BA?= =?UTF-8?q?=20normalize=20=E7=BA=A0=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 图像预处理(截图保存后、OCR 前): - 2x LANCZOS 放大:Windows OCR 对高 DPI 输入识别更好 - 锐化 1.8x + 对比度 1.4x:字符边缘更清晰,减少 CJK 空格/字符混淆 预期:减少《→<错误、减少 CJK 间空格残留、减少字符分裂(什→亻牛) 2. 增强 _normalize_ocr_text: - 《》→ <> 修复:Minecraft 聊天 被 OCR 误读为中文书名号 - l→| 管道分隔符修复:|quiz| 误读为 lquizl,使用 (?<=\s)l(...)l(?=\s) 模式 - .→ . 全角点→半角数字小数点(0.45 → 0.45) 这些修复只在非 md 文本上运行(md 被 pre-split check 提前过滤) --- monitor.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/monitor.py b/monitor.py index 173c3c4..93a9cd4 100644 --- a/monitor.py +++ b/monitor.py @@ -17,7 +17,7 @@ import difflib import os from datetime import datetime import signal -from PIL import ImageGrab +from PIL import ImageGrab, ImageEnhance, ImageFilter from winrt.windows.media.ocr import OcrEngine from winrt.windows.globalization import Language from winrt.windows.graphics.imaging import SoftwareBitmap, BitmapPixelFormat @@ -523,6 +523,9 @@ class MessageMonitor: "问 题 1 : 你 答 : 你 好" → "问题1:你答:你好" "你 好 he llo" → "你好 he llo"(ASCII 词内空格保留) + + 此外修复常见 Windows OCR 字符混淆错误(只在非 md 文本上运行, + md 文档由 pre-split check 提前过滤,不受影响)。 """ # 所有紧邻 CJK/全角字符的空格全部去掉 # CJK 范围:汉字 (u4e00-) + 扩展 (u3400-) + 全角/兼容 (uff00-) @@ -536,6 +539,17 @@ class MessageMonitor: r'(?=[\u4e00-\u9fff\u3400-\u4dbf\uff00-\uffef\u3000-\u303f])', '', text ) + + # ⭐ Windows OCR 字符混淆修复 + # 《》→ <>:Minecraft 聊天大量使用 等尖括号,OCR 误读为中文书名号 + text = text.replace('《', '<').replace('》', '>') + + # l→| 管道分隔符:|quiz| / |start| / |info| 误读为 lquizl / lstartl / linfol + text = re.sub(r'(?<=\s)l([A-Za-z]\w*?)l(?=\s)', r'|\1|', text) + + # .→ . 全角点→半角数字小数点 (0.45 → 0.45) + text = re.sub(r'(\d)[.](\d)', r'\1.\2', text) + return text.strip() @staticmethod @@ -697,6 +711,18 @@ class MessageMonitor: _clean_old_ocr_debug(script_dir, keep=20) except Exception as e: logger.debug(f"[ocr] 保存截屏失败: {e}") + + # 图像预处理:提升 Windows OCR 识别准确率 + # Windows OCR 对低 DPI/未处理截图识别差——CJK 空格、字符混淆 + # 2x LANCZOS 放大 + 锐化 + 对比度增强 + try: + im = im.resize((im.width * 2, im.height * 2), Image.LANCZOS) + im = ImageEnhance.Sharpness(im).enhance(1.8) + im = ImageEnhance.Contrast(im).enhance(1.4) + logger.debug(f"[ocr] 预处理: resize 2x + sharpen(1.8) + contrast(1.4)") + except Exception as e: + logger.debug(f"[ocr] 预处理失败(跳过): {e}") + if im.mode != 'RGBA': im = im.convert('RGBA') sb = SoftwareBitmap(BitmapPixelFormat.RGBA8, im.width, im.height)