rehan953 commited on
Commit
bcc62dd
·
verified ·
1 Parent(s): 5cc96b8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -17
app.py CHANGED
@@ -1,5 +1,10 @@
 
 
 
 
1
  import os
2
  import re
 
3
  import yaml
4
  import gradio as gr
5
 
@@ -9,14 +14,16 @@ GLMOCR_BASE = os.path.dirname(glmocr.__file__)
9
  CONFIG_PATH = os.path.join(GLMOCR_BASE, "config.yaml")
10
  FORMATTER_PATH = os.path.join(GLMOCR_BASE, "postprocess", "result_formatter.py")
11
 
12
- # ─── 1. Config: include headers and footers (remove from abandon lists) ───
 
 
 
 
13
  with open(CONFIG_PATH, "r") as f:
14
  config = yaml.safe_load(f)
15
 
16
  config["pipeline"]["maas"]["enabled"] = True
17
- api_key = os.environ.get("GLMOCR_MaaS_API_KEY") or os.environ.get("ZHIPU_API_KEY")
18
- if api_key:
19
- config["pipeline"]["maas"]["api_key"] = api_key
20
 
21
  to_remove = {"header", "footer"}
22
  for key in ("layout", "result_formatter"):
@@ -35,7 +42,9 @@ for key in ("layout", "result_formatter"):
35
  with open(CONFIG_PATH, "w") as f:
36
  yaml.dump(config, f, default_flow_style=False, sort_keys=False)
37
 
38
- # ─── 2. result_formatter: stop stripping header/footer in postprocess ───
 
 
39
  with open(FORMATTER_PATH, "r") as f:
40
  source = f.read()
41
  for label in ('"header"', "'header'", '"footer"', "'footer'", '"doc_header"', "'doc_header'", '"doc_footer"', "'doc_footer'"):
@@ -45,7 +54,81 @@ for label in ('"header"', "'header'", '"footer"', "'footer'", '"doc_header"', "'
45
  with open(FORMATTER_PATH, "w") as f:
46
  f.write(source)
47
 
48
- # ─── 3. Run OCR (no custom header/footer logic; pipeline returns full content) ───
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  def run_ocr(uploaded_file):
50
  if uploaded_file is None:
51
  return "Please upload a file."
@@ -61,34 +144,70 @@ def run_ocr(uploaded_file):
61
  page_images = []
62
  for i in range(len(doc)):
63
  pix = doc[i].get_pixmap(matrix=fitz.Matrix(1.5, 1.5), alpha=False)
64
- img_path = f"/tmp/maas_page_{i}.png"
65
  pix.save(img_path)
66
  page_images.append(img_path)
67
  doc.close()
68
  results = parse(page_images)
69
  else:
 
70
  results = parse(path)
71
 
72
  if not isinstance(results, list):
73
  results = [results]
74
 
75
- parts = []
76
- for r in results:
77
- md = getattr(r, "markdown_result", None) or ""
78
- if isinstance(md, str) and md.strip():
79
- parts.append(md.strip())
80
- final = "\n\n---\n\n".join(parts) if parts else "(No content)"
81
- return final
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  except Exception as e:
83
  import traceback
84
  return f"Error: {e}\n\n{traceback.format_exc()}"
85
 
86
- # ─── 4. UI ───
87
  with gr.Blocks(title="GLM-OCR") as demo:
88
- gr.Markdown("# GLM-OCR\nUpload a PDF or image. Headers and footers are included.")
89
  file_in = gr.File(label="Upload PDF or image", file_types=[".pdf", ".png", ".jpg", ".jpeg", ".tiff", ".bmp"])
90
  run_btn = gr.Button("Run OCR", variant="primary")
91
  out = gr.Textbox(lines=40, label="Output")
92
  run_btn.click(fn=run_ocr, inputs=file_in, outputs=out)
93
 
94
- demo.launch()
 
 
1
+ """
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 os
6
  import re
7
+ import tempfile
8
  import yaml
9
  import gradio as gr
10
 
 
14
  CONFIG_PATH = os.path.join(GLMOCR_BASE, "config.yaml")
15
  FORMATTER_PATH = os.path.join(GLMOCR_BASE, "postprocess", "result_formatter.py")
16
 
17
+ DEFAULT_ZONE_FRAC = float(os.environ.get("GLMOCR_DEFAULT_ZONE_FRAC", "0.08"))
18
+
19
+ # ---------------------------------------------------------------------------
20
+ # 1. Config: include headers/footers (remove from abandon lists)
21
+ # ---------------------------------------------------------------------------
22
  with open(CONFIG_PATH, "r") as f:
23
  config = yaml.safe_load(f)
24
 
25
  config["pipeline"]["maas"]["enabled"] = True
26
+ config["pipeline"]["maas"]["api_key"] = "4570c28bdea5493c9efae9dae68edc66.sGbA9DLlcX1GlvqV"
 
 
27
 
28
  to_remove = {"header", "footer"}
29
  for key in ("layout", "result_formatter"):
 
42
  with open(CONFIG_PATH, "w") as f:
43
  yaml.dump(config, f, default_flow_style=False, sort_keys=False)
44
 
45
+ # ---------------------------------------------------------------------------
46
+ # 2. result_formatter: stop stripping header/footer in postprocess
47
+ # ---------------------------------------------------------------------------
48
  with open(FORMATTER_PATH, "r") as f:
49
  source = f.read()
50
  for label in ('"header"', "'header'", '"footer"', "'footer'", '"doc_header"', "'doc_header'", '"doc_footer"', "'doc_footer'"):
 
54
  with open(FORMATTER_PATH, "w") as f:
55
  f.write(source)
56
 
57
+
58
+ def get_header_footer_zones(regions, norm_height=1000):
59
+ if not regions:
60
+ return None, None
61
+ y_tops, y_bottoms = [], []
62
+ for r in regions:
63
+ bbox = r.get("bbox_2d") if isinstance(r, dict) else getattr(r, "bbox_2d", None)
64
+ if bbox and len(bbox) >= 4:
65
+ y_tops.append(bbox[1])
66
+ y_bottoms.append(bbox[3])
67
+ if not y_tops:
68
+ return None, None
69
+ return min(y_tops) / norm_height, max(y_bottoms) / norm_height
70
+
71
+
72
+ def extract_zone_text_pdf(pdf_path, page_num, y_start_frac, y_end_frac):
73
+ try:
74
+ import pymupdf as fitz
75
+ doc = fitz.open(pdf_path)
76
+ page = doc[page_num]
77
+ h, w = page.rect.height, page.rect.width
78
+ rect = fitz.Rect(0, h * y_start_frac, w, h * y_end_frac)
79
+ text = page.get_text(clip=rect).strip()
80
+ doc.close()
81
+ return text
82
+ except Exception:
83
+ return ""
84
+
85
+
86
+ def ocr_zone(image_path, y_start_frac, y_end_frac):
87
+ try:
88
+ from PIL import Image
89
+ from glmocr import parse
90
+ img = Image.open(image_path).convert("RGB")
91
+ w, h = img.size
92
+ y0 = max(0, int(h * y_start_frac))
93
+ y1 = min(h, int(h * y_end_frac))
94
+ if y1 <= y0:
95
+ return ""
96
+ crop = img.crop((0, y0, w, y1))
97
+ fd, path = tempfile.mkstemp(suffix=".png")
98
+ os.close(fd)
99
+ crop.save(path)
100
+ try:
101
+ out = parse(path)
102
+ if not isinstance(out, list):
103
+ out = [out]
104
+ if out and getattr(out[0], "markdown_result", None):
105
+ return (out[0].markdown_result or "").strip()
106
+ finally:
107
+ try:
108
+ os.unlink(path)
109
+ except Exception:
110
+ pass
111
+ except Exception:
112
+ pass
113
+ return ""
114
+
115
+
116
+ def get_page_md_and_regions(page_result):
117
+ md = ""
118
+ if hasattr(page_result, "markdown_result") and page_result.markdown_result:
119
+ md = (page_result.markdown_result or "").strip()
120
+ regions = []
121
+ if hasattr(page_result, "json_result"):
122
+ jr = page_result.json_result
123
+ if isinstance(jr, list) and len(jr) > 0:
124
+ r = jr[0] if isinstance(jr[0], list) else jr
125
+ if isinstance(r, list):
126
+ regions = r
127
+ elif isinstance(r, dict) and "regions" in r:
128
+ regions = r.get("regions") or []
129
+ return md, regions
130
+
131
+
132
  def run_ocr(uploaded_file):
133
  if uploaded_file is None:
134
  return "Please upload a file."
 
144
  page_images = []
145
  for i in range(len(doc)):
146
  pix = doc[i].get_pixmap(matrix=fitz.Matrix(1.5, 1.5), alpha=False)
147
+ img_path = os.path.join(tempfile.gettempdir(), f"maas_page_{i}.png")
148
  pix.save(img_path)
149
  page_images.append(img_path)
150
  doc.close()
151
  results = parse(page_images)
152
  else:
153
+ page_images = [path]
154
  results = parse(path)
155
 
156
  if not isinstance(results, list):
157
  results = [results]
158
 
159
+ all_pages = []
160
+ for page_num, page_result in enumerate(results):
161
+ page_md, regions = get_page_md_and_regions(page_result)
162
+ header_end_frac, footer_start_frac = get_header_footer_zones(regions, 1000)
163
+
164
+ he = header_end_frac if header_end_frac is not None else DEFAULT_ZONE_FRAC
165
+ fs = footer_start_frac if footer_start_frac is not None else (1.0 - DEFAULT_ZONE_FRAC)
166
+ if he <= 0 and header_end_frac is not None:
167
+ he = 0
168
+ if fs >= 1.0 and footer_start_frac is not None:
169
+ fs = 1.0
170
+
171
+ parts = []
172
+
173
+ if he > 0 and page_num < len(page_images):
174
+ img_path = page_images[page_num]
175
+ hdr = ""
176
+ if is_pdf:
177
+ hdr = extract_zone_text_pdf(path, page_num, 0, he)
178
+ if not (hdr and hdr.strip()):
179
+ hdr = ocr_zone(img_path, 0, he)
180
+ if hdr and hdr.strip():
181
+ parts.append(hdr.strip())
182
+
183
+ if page_md:
184
+ parts.append(page_md)
185
+
186
+ if fs < 1.0 and page_num < len(page_images):
187
+ img_path = page_images[page_num]
188
+ ftr = ""
189
+ if is_pdf:
190
+ ftr = extract_zone_text_pdf(path, page_num, fs, 1.0)
191
+ if not (ftr and ftr.strip()):
192
+ ftr = ocr_zone(img_path, fs, 1.0)
193
+ if ftr and ftr.strip():
194
+ parts.append(ftr.strip())
195
+
196
+ if parts:
197
+ all_pages.append("\n\n".join(parts))
198
+
199
+ return "\n\n---\n\n".join(all_pages) if all_pages else "(No content)"
200
  except Exception as e:
201
  import traceback
202
  return f"Error: {e}\n\n{traceback.format_exc()}"
203
 
204
+
205
  with gr.Blocks(title="GLM-OCR") as demo:
206
+ gr.Markdown("# GLM-OCR\nUpload a PDF or image. Headers and footers included.")
207
  file_in = gr.File(label="Upload PDF or image", file_types=[".pdf", ".png", ".jpg", ".jpeg", ".tiff", ".bmp"])
208
  run_btn = gr.Button("Run OCR", variant="primary")
209
  out = gr.Textbox(lines=40, label="Output")
210
  run_btn.click(fn=run_ocr, inputs=file_in, outputs=out)
211
 
212
+ if __name__ == "__main__":
213
+ demo.launch()