Update: Refactor to absolute imports, fix QPS limits, and enhance Gitea sync with SQLite support
This commit is contained in:
+27
-21
@@ -7,9 +7,9 @@ OCR服务模块
|
||||
from typing import Dict, List, Optional, Tuple, Union, Any, Callable
|
||||
import os
|
||||
|
||||
from ..config.settings import ConfigManager
|
||||
from ..core.utils.log_utils import get_logger
|
||||
from ..core.ocr.table_ocr import OCRProcessor
|
||||
from app.config.settings import ConfigManager
|
||||
from app.core.utils.log_utils import get_logger
|
||||
from app.core.ocr.table_ocr import OCRProcessor
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
@@ -62,16 +62,10 @@ class OCRService:
|
||||
if not self._is_valid_image(image_path):
|
||||
logger.error(f"不支持的文件类型: {image_path}")
|
||||
return None
|
||||
|
||||
# 检查是否已处理
|
||||
excel_file = self._get_excel_path(image_path)
|
||||
if os.path.exists(excel_file):
|
||||
logger.info(f"文件已处理过,跳过OCR识别: {image_path}")
|
||||
# 即使 xlsx 已存在,仍补写 meta.json(首次 OCR 后可能未生成)
|
||||
meta_path = str(excel_file).replace('.xlsx', '.meta.json')
|
||||
if not os.path.exists(meta_path):
|
||||
self._write_meta_json(str(excel_file), {}, image_path)
|
||||
return excel_file
|
||||
|
||||
# 不再做 xlsx 已存在就跳过的判断(xlsx 可能被业务层重命名过),
|
||||
# 跳过逻辑交给 OCRProcessor 内部的 record_manager.is_processed(image_path)
|
||||
# —— 由它读 processed_files.json(业务层会同步更新 xlsx 路径)
|
||||
|
||||
# 执行OCR识别
|
||||
result = self.ocr_processor.process_image(image_path)
|
||||
@@ -212,24 +206,36 @@ class OCRService:
|
||||
base = Path(excel_path)
|
||||
meta_path = base.with_suffix('.meta.json')
|
||||
|
||||
# 0) 优先:调百度通用文字识别(/accurate),覆盖全图文字(含手写抬头/日期)
|
||||
# 0) 优先:调百度通用票务识别(/general_ocr),精准捕获表头(含手写抬头/日期)
|
||||
general_text = ''
|
||||
general_lines = []
|
||||
try:
|
||||
# OCRService.ocr_processor = core.ocr.table_ocr.OCRProcessor
|
||||
# 其 .ocr_client = BaiduOCRClient (process_image 时初始化)
|
||||
client = getattr(self.ocr_processor, 'ocr_client', None)
|
||||
if client is None:
|
||||
# 显式触发一次 process_image 准备流程 (不会重复 OCR)
|
||||
try:
|
||||
self.ocr_processor._ensure_ocr_client()
|
||||
except Exception:
|
||||
pass
|
||||
client = getattr(self.ocr_processor, 'ocr_client', None)
|
||||
if client and hasattr(client, 'recognize_general') and image_path and os.path.exists(str(image_path)):
|
||||
|
||||
# 关键:在进行第二次 OCR (票务识别) 前稍微等待,避免触发 QPS 限制
|
||||
import time
|
||||
time.sleep(0.5)
|
||||
|
||||
# 优先使用票务识别 (Ticket OCR)
|
||||
if client and hasattr(client, 'recognize_ticket') and image_path and os.path.exists(str(image_path)):
|
||||
logger.info("使用通用票务识别捕获表头元数据...")
|
||||
words = client.recognize_ticket(str(image_path))
|
||||
if words:
|
||||
general_lines = [(w.get('words') or '').strip() for w in words if (w.get('words') or '').strip()]
|
||||
general_text = '\n'.join(general_lines)
|
||||
logger.info(f"票务识别获取 {len(general_lines)} 行文字")
|
||||
|
||||
# 如果票务识别无结果或不可用,则兜底使用高精度文字识别
|
||||
if not general_lines and client and hasattr(client, 'recognize_general') and image_path and os.path.exists(str(image_path)):
|
||||
logger.info("尝试高精度文字识别作为兜底...")
|
||||
words = client.recognize_general(str(image_path))
|
||||
if words:
|
||||
# 按 location.top 排序(顶部先),方便后续提取供应商/日期
|
||||
def _top(w):
|
||||
loc = w.get('location') or {}
|
||||
try:
|
||||
@@ -239,9 +245,9 @@ class OCRService:
|
||||
words_sorted = sorted(words, key=_top)
|
||||
general_lines = [(w.get('words') or '').strip() for w in words_sorted if (w.get('words') or '').strip()]
|
||||
general_text = '\n'.join(general_lines)
|
||||
logger.info(f"通用识别获取 {len(general_lines)} 行文字")
|
||||
logger.info(f"通用高精度识别获取 {len(general_lines)} 行文字")
|
||||
except Exception as e:
|
||||
logger.warning(f"通用识别失败(不影响主流程): {e}")
|
||||
logger.warning(f"获取元数据识别失败(不影响主流程): {e}")
|
||||
|
||||
# 1) 表格识别 header/body 拼表内文字(已在前面逻辑处理)
|
||||
ocr_text = ''
|
||||
|
||||
Reference in New Issue
Block a user