Spaces:
Sleeping
Sleeping
Commit ·
8b4e2a1
1
Parent(s): d0b9b19
Auto-update via watch script
Browse files
app.py
CHANGED
|
@@ -220,6 +220,66 @@ def _spinner(msg: str, color: str = "#3b82f6", bg: str = "rgba(59,130,246,0.08)"
|
|
| 220 |
# Main processing functions
|
| 221 |
# ---------------------------------------------------------------------------
|
| 222 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
def extract_full_article(image: Image.Image, hf_token: str) -> tuple[str, str]:
|
| 224 |
"""
|
| 225 |
Hybrid extraction:
|
|
|
|
| 220 |
# Main processing functions
|
| 221 |
# ---------------------------------------------------------------------------
|
| 222 |
|
| 223 |
+
def _preprocess_image(image: Image.Image) -> Image.Image:
|
| 224 |
+
img = image.convert("L")
|
| 225 |
+
w, h = img.size
|
| 226 |
+
if w < 1800:
|
| 227 |
+
scale = 1800 / w
|
| 228 |
+
img = img.resize((int(w * scale), int(h * scale)), getattr(Image, "Resampling", Image).LANCZOS)
|
| 229 |
+
img = ImageEnhance.Contrast(img).enhance(1.8)
|
| 230 |
+
img = ImageEnhance.Sharpness(img).enhance(2.0)
|
| 231 |
+
return img.convert("RGB")
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
def _column_aware_ocr(image: Image.Image) -> str:
|
| 235 |
+
data = pytesseract.image_to_data(image, config="--psm 11 -l eng", output_type=pytesseract.Output.DICT)
|
| 236 |
+
img_width = image.size[0]
|
| 237 |
+
|
| 238 |
+
words = []
|
| 239 |
+
for i, text in enumerate(data["text"]):
|
| 240 |
+
text = text.strip()
|
| 241 |
+
if not text or data["word_num"][i] == 0 or int(data["conf"][i]) < 30:
|
| 242 |
+
continue
|
| 243 |
+
words.append({"text": text, "x": data["left"][i], "y": data["top"][i]})
|
| 244 |
+
|
| 245 |
+
if not words:
|
| 246 |
+
return ""
|
| 247 |
+
|
| 248 |
+
gap_threshold = img_width * 0.15
|
| 249 |
+
sorted_x = sorted(set(w["x"] for w in words))
|
| 250 |
+
col_starts = [0]
|
| 251 |
+
for idx in range(1, len(sorted_x)):
|
| 252 |
+
if sorted_x[idx] - sorted_x[idx - 1] > gap_threshold:
|
| 253 |
+
col_starts.append(sorted_x[idx])
|
| 254 |
+
|
| 255 |
+
def assign_col(x):
|
| 256 |
+
col = 0
|
| 257 |
+
for j, start in enumerate(col_starts):
|
| 258 |
+
if x >= start:
|
| 259 |
+
col = j
|
| 260 |
+
return col
|
| 261 |
+
|
| 262 |
+
for word in words:
|
| 263 |
+
word["col"] = assign_col(word["x"])
|
| 264 |
+
|
| 265 |
+
result_parts = []
|
| 266 |
+
for col_idx in range(len(col_starts)):
|
| 267 |
+
col_words = sorted([w for w in words if w["col"] == col_idx], key=lambda w: (w["y"], w["x"]))
|
| 268 |
+
if not col_words:
|
| 269 |
+
continue
|
| 270 |
+
lines, current = [], [col_words[0]]
|
| 271 |
+
for word in col_words[1:]:
|
| 272 |
+
if abs(word["y"] - current[0]["y"]) <= 8:
|
| 273 |
+
current.append(word)
|
| 274 |
+
else:
|
| 275 |
+
lines.append(current)
|
| 276 |
+
current = [word]
|
| 277 |
+
lines.append(current)
|
| 278 |
+
result_parts.append("\n".join(" ".join(w["text"] for w in line) for line in lines))
|
| 279 |
+
|
| 280 |
+
return "\n\n".join(result_parts)
|
| 281 |
+
|
| 282 |
+
|
| 283 |
def extract_full_article(image: Image.Image, hf_token: str) -> tuple[str, str]:
|
| 284 |
"""
|
| 285 |
Hybrid extraction:
|