作业帮式错题标注:OCR 定位错误红框 + 解题思路。

- PaddleOCR 行级坐标 + AI 识别错答区域,生成标注图

- 解法拆分为「解题思路」与「详细解答」

- 详情页标注图/原图切换,列表显示标注缩略图
This commit is contained in:
dekun
2026-06-28 13:50:20 +08:00
parent c30e21b51e
commit a2a6d59f7c
16 changed files with 852 additions and 507 deletions
+51 -10
View File
@@ -1,5 +1,7 @@
from pathlib import Path
from PIL import Image
from app.core.config import settings
_ocr_engine = None
@@ -14,18 +16,52 @@ def get_ocr_engine():
return _ocr_engine
def run_ocr(image_path: str) -> str:
def _bbox_from_box(box: list) -> list[float]:
xs = [float(p[0]) for p in box]
ys = [float(p[1]) for p in box]
return [min(xs), min(ys), max(xs), max(ys)]
def run_ocr_with_regions(image_path: str) -> dict:
"""Return OCR text plus line-level bounding boxes for annotation."""
engine = get_ocr_engine()
result = engine.ocr(image_path, cls=True)
if not result or not result[0]:
return ""
lines = []
for line in result[0]:
if line and len(line) >= 2:
text = line[1][0]
if text:
lines.append(text)
return "\n".join(lines)
lines: list[dict] = []
if result and result[0]:
for item in result[0]:
if not item or len(item) < 2:
continue
box, rec = item[0], item[1]
text = rec[0] if rec else ""
conf = float(rec[1]) if rec and len(rec) > 1 else 0.0
if not text:
continue
lines.append(
{
"text": text,
"confidence": conf,
"box": box,
"bbox": _bbox_from_box(box),
}
)
width, height = 0, 0
try:
with Image.open(image_path) as img:
width, height = img.size
except OSError:
pass
return {
"text": "\n".join(line["text"] for line in lines),
"lines": lines,
"width": width,
"height": height,
}
def run_ocr(image_path: str) -> str:
return run_ocr_with_regions(image_path)["text"]
def save_upload_file(user_id: str, question_id: str, filename: str, content: bytes) -> str:
@@ -38,3 +74,8 @@ def save_upload_file(user_id: str, question_id: str, filename: str, content: byt
full_path = Path(settings.UPLOAD_DIR) / rel_path
full_path.write_bytes(content)
return rel_path
def annotated_rel_path(original_rel: str) -> str:
p = Path(original_rel)
return str(p.parent / f"{p.stem}_marked.jpg")