fix: remove padding from GLMOCREndToEndService and clean up ruff violations

- Drop image padding in GLMOCREndToEndService.recognize(); use raw image directly
- Fix F821 undefined `padded` references replaced with `image`
- Fix F601 duplicate dict key "≠" in converter
- Fix F841 unused `image_cls_ids` variable in layout_postprocess
- Fix E702 semicolon-separated statements in layout_postprocess
- Fix UP031 percent-format replaced with f-string in logging_config
- Auto-fix 44 additional ruff violations (import order, UP035/UP045/UP006, F401, F541)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
liuyuanchuang
2026-03-10 19:52:22 +08:00
parent f8173f7c0a
commit 30d2c2f45b
16 changed files with 162 additions and 140 deletions

View File

@@ -15,16 +15,14 @@ the quality of the GLM-OCR SDK's layout pipeline.
from __future__ import annotations
from typing import Dict, List, Optional, Tuple, Union
import numpy as np
# ---------------------------------------------------------------------------
# Primitive geometry helpers
# ---------------------------------------------------------------------------
def iou(box1: List[float], box2: List[float]) -> float:
def iou(box1: list[float], box2: list[float]) -> float:
"""Compute IoU of two bounding boxes [x1, y1, x2, y2]."""
x1, y1, x2, y2 = box1
x1_p, y1_p, x2_p, y2_p = box2
@@ -41,7 +39,7 @@ def iou(box1: List[float], box2: List[float]) -> float:
return inter_area / float(box1_area + box2_area - inter_area)
def is_contained(box1: List[float], box2: List[float], overlap_threshold: float = 0.8) -> bool:
def is_contained(box1: list[float], box2: list[float], overlap_threshold: float = 0.8) -> bool:
"""Return True if box1 is contained within box2 (overlap ratio >= threshold).
box format: [cls_id, score, x1, y1, x2, y2]
@@ -66,11 +64,12 @@ def is_contained(box1: List[float], box2: List[float], overlap_threshold: float
# NMS
# ---------------------------------------------------------------------------
def nms(
boxes: np.ndarray,
iou_same: float = 0.6,
iou_diff: float = 0.98,
) -> List[int]:
) -> list[int]:
"""NMS with separate IoU thresholds for same-class and cross-class overlaps.
Args:
@@ -83,7 +82,7 @@ def nms(
"""
scores = boxes[:, 1]
indices = np.argsort(scores)[::-1].tolist()
selected: List[int] = []
selected: list[int] = []
while indices:
current = indices[0]
@@ -114,10 +113,10 @@ _PRESERVE_LABELS = {"image", "seal", "chart"}
def check_containment(
boxes: np.ndarray,
preserve_cls_ids: Optional[set] = None,
category_index: Optional[int] = None,
mode: Optional[str] = None,
) -> Tuple[np.ndarray, np.ndarray]:
preserve_cls_ids: set | None = None,
category_index: int | None = None,
mode: str | None = None,
) -> tuple[np.ndarray, np.ndarray]:
"""Compute containment flags for each box.
Args:
@@ -160,9 +159,10 @@ def check_containment(
# Box expansion (unclip)
# ---------------------------------------------------------------------------
def unclip_boxes(
boxes: np.ndarray,
unclip_ratio: Union[float, Tuple[float, float], Dict, List, None],
unclip_ratio: float | tuple[float, float] | dict | list | None,
) -> np.ndarray:
"""Expand bounding boxes by the given ratio.
@@ -215,13 +215,14 @@ def unclip_boxes(
# Main entry-point
# ---------------------------------------------------------------------------
def apply_layout_postprocess(
boxes: List[Dict],
img_size: Tuple[int, int],
boxes: list[dict],
img_size: tuple[int, int],
layout_nms: bool = True,
layout_unclip_ratio: Union[float, Tuple, Dict, None] = None,
layout_merge_bboxes_mode: Union[str, Dict, None] = "large",
) -> List[Dict]:
layout_unclip_ratio: float | tuple | dict | None = None,
layout_merge_bboxes_mode: str | dict | None = "large",
) -> list[dict]:
"""Apply GLM-OCR layout post-processing to PaddleOCR detection results.
Args:
@@ -250,7 +251,7 @@ def apply_layout_postprocess(
arr_rows.append([cls_id, score, x1, y1, x2, y2])
boxes_array = np.array(arr_rows, dtype=float)
all_labels: List[str] = [b.get("label", "") for b in boxes]
all_labels: list[str] = [b.get("label", "") for b in boxes]
# 1. NMS ---------------------------------------------------------------- #
if layout_nms and len(boxes_array) > 1:
@@ -262,17 +263,14 @@ def apply_layout_postprocess(
if len(boxes_array) > 1:
img_area = img_width * img_height
area_thres = 0.82 if img_width > img_height else 0.93
image_cls_ids = {
int(boxes_array[i, 0])
for i, lbl in enumerate(all_labels)
if lbl == "image"
}
keep_mask = np.ones(len(boxes_array), dtype=bool)
for i, lbl in enumerate(all_labels):
if lbl == "image":
x1, y1, x2, y2 = boxes_array[i, 2:6]
x1 = max(0.0, x1); y1 = max(0.0, y1)
x2 = min(float(img_width), x2); y2 = min(float(img_height), y2)
x1 = max(0.0, x1)
y1 = max(0.0, y1)
x2 = min(float(img_width), x2)
y2 = min(float(img_height), y2)
if (x2 - x1) * (y2 - y1) > area_thres * img_area:
keep_mask[i] = False
boxes_array = boxes_array[keep_mask]
@@ -281,9 +279,7 @@ def apply_layout_postprocess(
# 3. Containment analysis (merge_bboxes_mode) -------------------------- #
if layout_merge_bboxes_mode and len(boxes_array) > 1:
preserve_cls_ids = {
int(boxes_array[i, 0])
for i, lbl in enumerate(all_labels)
if lbl in _PRESERVE_LABELS
int(boxes_array[i, 0]) for i, lbl in enumerate(all_labels) if lbl in _PRESERVE_LABELS
}
if isinstance(layout_merge_bboxes_mode, str):
@@ -321,7 +317,7 @@ def apply_layout_postprocess(
boxes_array = unclip_boxes(boxes_array, layout_unclip_ratio)
# 5. Clamp to image boundaries + skip invalid -------------------------- #
result: List[Dict] = []
result: list[dict] = []
for i, row in enumerate(boxes_array):
cls_id = int(row[0])
score = float(row[1])
@@ -333,11 +329,13 @@ def apply_layout_postprocess(
if x1 >= x2 or y1 >= y2:
continue
result.append({
"cls_id": cls_id,
"label": all_labels[i],
"score": score,
"coordinate": [int(x1), int(y1), int(x2), int(y2)],
})
result.append(
{
"cls_id": cls_id,
"label": all_labels[i],
"score": score,
"coordinate": [int(x1), int(y1), int(x2), int(y2)],
}
)
return result