Spaces:
Paused
Paused
| from typing import Any | |
| from pdf2zh.parser.utils.bbox import polygon_to_bbox | |
| from pdf2zh.parser.utils.ocr_text import extract_text_for_region, sort_text_lines | |
| def is_sparse_text_block( | |
| ocr_result: Any, | |
| block_bbox: list[float], | |
| always_convert: bool, | |
| ) -> tuple[bool, list[Any]]: | |
| text_lines = extract_text_for_region(ocr_result, block_bbox) | |
| if always_convert and len(text_lines) > 1: | |
| return True, text_lines | |
| if len(text_lines) < 2: | |
| return False, text_lines | |
| rows = cluster_text_lines_into_rows(text_lines) | |
| GAP_MULTIPLIER = 1.0 | |
| for row in rows: | |
| if len(row) < 2: | |
| continue | |
| row_boxes = [] | |
| for line in row: | |
| box = get_line_bbox(line) | |
| if box is not None: | |
| row_boxes.append(box) | |
| row_boxes = sort_text_lines(row_boxes) | |
| for i in range(len(row_boxes) - 1): | |
| prev_box = row_boxes[i] | |
| curr_box = row_boxes[i + 1] | |
| gap = curr_box[0] - prev_box[2] | |
| prev_height = prev_box[3] - prev_box[1] | |
| curr_height = curr_box[3] - curr_box[1] | |
| avg_height = (prev_height + curr_height) / 2.0 | |
| if gap > (avg_height * GAP_MULTIPLIER): | |
| return True, text_lines | |
| return False, text_lines | |
| def cluster_text_lines_into_rows(lines: list[Any]) -> list[list[Any]]: | |
| _ROW_Y_OVERLAP_RATIO = 0.4 | |
| rows: list[dict[str, Any]] = [] | |
| for line in lines: | |
| line_bbox = get_line_bbox(line) | |
| if line_bbox is None: | |
| continue | |
| _, y0, _, y1 = line_bbox | |
| placed = False | |
| for row in rows: | |
| row_y0 = row["y0"] | |
| row_y1 = row["y1"] | |
| overlap = max(0.0, min(y1, row_y1) - max(y0, row_y0)) | |
| line_height = max(1.0, y1 - y0) | |
| row_height = max(1.0, row_y1 - row_y0) | |
| overlap_ratio = overlap / min(line_height, row_height) | |
| if overlap_ratio >= _ROW_Y_OVERLAP_RATIO: | |
| row["lines"].append(line) | |
| row["y0"] = min(row_y0, y0) | |
| row["y1"] = max(row_y1, y1) | |
| placed = True | |
| break | |
| if not placed: | |
| rows.append({"y0": y0, "y1": y1, "lines": [line]}) | |
| rows.sort(key=lambda row: (row["y0"], row["y1"])) | |
| return [row["lines"] for row in rows] | |
| def get_line_bbox(line: Any) -> list[float] | None: | |
| line_bbox = getattr(line, "bbox", None) | |
| if line_bbox is not None: | |
| return list(line_bbox) | |
| if hasattr(line, "polygon"): | |
| return polygon_to_bbox(line.polygon) | |
| return None | |