hoytshao commited on
Commit
53dfd3e
·
verified ·
1 Parent(s): 966ed33

Update app.py

Browse files

1. Pad small header/footer crops instead of skipping
2. Asyncio patch moved to the top

Files changed (1) hide show
  1. app.py +28 -21
app.py CHANGED
@@ -2,6 +2,19 @@
2
  GLM-OCR Hugging Face Space app with client-side header/footer fallback for MaaS.
3
  Works for every PDF and every image: uses API bboxes when available, else minimal band.
4
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  import logging
6
  import os
7
  import re
@@ -21,19 +34,6 @@ logging.basicConfig(
21
  )
22
  log = logging.getLogger("glmocr_app")
23
 
24
- # Suppress Python 3.13 asyncio cleanup noise (Invalid file descriptor in BaseEventLoop.__del__)
25
- try:
26
- import asyncio
27
- _orig_close = asyncio.BaseEventLoop.close
28
- def _safe_close(self):
29
- try:
30
- _orig_close(self)
31
- except (ValueError, OSError):
32
- pass
33
- asyncio.BaseEventLoop.close = _safe_close
34
- except Exception:
35
- pass
36
-
37
  GLMOCR_BASE = os.path.dirname(glmocr.__file__)
38
  CONFIG_PATH = os.path.join(GLMOCR_BASE, "config.yaml")
39
  FORMATTER_PATH = os.path.join(GLMOCR_BASE, "postprocess", "result_formatter.py")
@@ -149,7 +149,7 @@ def extract_zone_text_pdf(pdf_path, page_num, y_start_frac, y_end_frac):
149
 
150
 
151
  def ocr_zone(image_path, y_start_frac, y_end_frac):
152
- """Run OCR on a horizontal band of the image. Skips MaaS if crop is too small (API returns 400)."""
153
  zone_name = "header" if y_end_frac < 0.5 else "footer"
154
  try:
155
  from PIL import Image
@@ -162,13 +162,20 @@ def ocr_zone(image_path, y_start_frac, y_end_frac):
162
  return ""
163
  crop = img.crop((0, y0, w, y1))
164
  cw, ch = crop.size
165
- pixels = cw * ch
166
- if ch < MIN_CROP_HEIGHT or pixels < MIN_CROP_PIXELS:
167
- log.info(
168
- "[%s] ocr_zone: skip (crop too small: %dx%d=%d pixels, need height>=%d and pixels>=%d)",
169
- zone_name, cw, ch, pixels, MIN_CROP_HEIGHT, MIN_CROP_PIXELS,
170
- )
171
- return ""
 
 
 
 
 
 
 
172
  fd, path = tempfile.mkstemp(suffix=".jpg")
173
  os.close(fd)
174
  try:
 
2
  GLM-OCR Hugging Face Space app with client-side header/footer fallback for MaaS.
3
  Works for every PDF and every image: uses API bboxes when available, else minimal band.
4
  """
5
+ # Patch asyncio first (before Gradio imports it) to suppress Python 3.13 cleanup noise
6
+ import asyncio
7
+ try:
8
+ _orig_close = asyncio.BaseEventLoop.close
9
+ def _safe_close(self):
10
+ try:
11
+ _orig_close(self)
12
+ except (ValueError, OSError):
13
+ pass
14
+ asyncio.BaseEventLoop.close = _safe_close
15
+ except Exception:
16
+ pass
17
+
18
  import logging
19
  import os
20
  import re
 
34
  )
35
  log = logging.getLogger("glmocr_app")
36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
  GLMOCR_BASE = os.path.dirname(glmocr.__file__)
38
  CONFIG_PATH = os.path.join(GLMOCR_BASE, "config.yaml")
39
  FORMATTER_PATH = os.path.join(GLMOCR_BASE, "postprocess", "result_formatter.py")
 
149
 
150
 
151
  def ocr_zone(image_path, y_start_frac, y_end_frac):
152
+ """Run OCR on a horizontal band. Pads small crops to meet API minimum size instead of skipping."""
153
  zone_name = "header" if y_end_frac < 0.5 else "footer"
154
  try:
155
  from PIL import Image
 
162
  return ""
163
  crop = img.crop((0, y0, w, y1))
164
  cw, ch = crop.size
165
+ # Pad to minimum size so MaaS accepts the image (avoids 400 on tiny strips)
166
+ if ch < MIN_CROP_HEIGHT or (cw * ch) < MIN_CROP_PIXELS:
167
+ need_h = max(ch, MIN_CROP_HEIGHT)
168
+ need_w = max(cw, 1)
169
+ if (need_w * need_h) < MIN_CROP_PIXELS:
170
+ need_w = max(need_w, (MIN_CROP_PIXELS + need_h - 1) // need_h)
171
+ canvas = Image.new("RGB", (need_w, need_h), (255, 255, 255))
172
+ if zone_name == "header":
173
+ canvas.paste(crop, (0, 0)) # crop at top
174
+ else:
175
+ canvas.paste(crop, (0, need_h - ch)) # crop at bottom
176
+ crop = canvas
177
+ cw, ch = crop.size
178
+ log.info("[%s] ocr_zone: padded to %dx%d for API", zone_name, cw, ch)
179
  fd, path = tempfile.mkstemp(suffix=".jpg")
180
  os.close(fd)
181
  try: