Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -2,6 +2,7 @@ import gradio as gr
|
|
| 2 |
import yaml
|
| 3 |
import re
|
| 4 |
import os
|
|
|
|
| 5 |
|
| 6 |
import glmocr
|
| 7 |
GLMOCR_BASE = os.path.dirname(glmocr.__file__)
|
|
@@ -49,8 +50,6 @@ print("β
result_formatter.py fixed")
|
|
| 49 |
ABANDON = set(config["pipeline"]["result_formatter"]["abandon"])
|
| 50 |
|
| 51 |
# ββ STEP 3: Extract header/footer from PDF text layer βββββββββ
|
| 52 |
-
# The MaaS API only returns 'text' and 'table' labels.
|
| 53 |
-
# Headers and footers are extracted directly from the PDF using PyMuPDF.
|
| 54 |
def extract_pdf_headers(path):
|
| 55 |
import fitz
|
| 56 |
page_headers = []
|
|
@@ -67,21 +66,13 @@ def extract_pdf_headers(path):
|
|
| 67 |
return page_headers
|
| 68 |
|
| 69 |
# ββ STEP 4: Parse one page result into regions list βββββββββββ
|
| 70 |
-
# result from parse() is a LIST of PipelineResult objects (one per page)
|
| 71 |
-
# Each PipelineResult has:
|
| 72 |
-
# .json_result β list of region dicts with 'label' and 'content'
|
| 73 |
-
# .markdown_result β plain markdown string
|
| 74 |
def get_page_regions(page_result):
|
| 75 |
-
# Try json_result first (structured regions)
|
| 76 |
if hasattr(page_result, "json_result"):
|
| 77 |
jr = page_result.json_result
|
| 78 |
if isinstance(jr, list) and len(jr) > 0:
|
| 79 |
-
# json_result is a list of lists (one list per page image)
|
| 80 |
-
# since we pass one image per call, take index 0
|
| 81 |
regions = jr[0] if isinstance(jr[0], list) else jr
|
| 82 |
if isinstance(regions, list):
|
| 83 |
return regions, "json"
|
| 84 |
-
# Fallback to markdown_result
|
| 85 |
if hasattr(page_result, "markdown_result"):
|
| 86 |
md = page_result.markdown_result
|
| 87 |
if md and isinstance(md, str) and md.strip():
|
|
@@ -109,7 +100,6 @@ def run_ocr(uploaded_file):
|
|
| 109 |
pix.save(img_path)
|
| 110 |
page_images.append(img_path)
|
| 111 |
doc.close()
|
| 112 |
-
# parse() returns a LIST β one PipelineResult per page
|
| 113 |
results = parse(page_images)
|
| 114 |
if not isinstance(results, list):
|
| 115 |
results = [results]
|
|
@@ -121,27 +111,35 @@ def run_ocr(uploaded_file):
|
|
| 121 |
|
| 122 |
total_headers = 0
|
| 123 |
total_footers = 0
|
| 124 |
-
|
| 125 |
-
all_summary
|
| 126 |
|
| 127 |
for page_num, page_result in enumerate(results):
|
| 128 |
-
|
| 129 |
-
|
| 130 |
|
| 131 |
-
# Inject header
|
| 132 |
if pdf_headers and page_num < len(pdf_headers):
|
| 133 |
hdr = pdf_headers[page_num]["header"]
|
| 134 |
ftr = pdf_headers[page_num]["footer"]
|
| 135 |
if hdr:
|
| 136 |
total_headers += 1
|
| 137 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
page_summary.append("π΅ HEADER: " + hdr[:100])
|
| 139 |
if ftr:
|
| 140 |
total_footers += 1
|
| 141 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 142 |
page_summary.append("π’ FOOTER: " + ftr[:100])
|
| 143 |
|
| 144 |
-
# Get regions from
|
| 145 |
data, dtype = get_page_regions(page_result)
|
| 146 |
|
| 147 |
if dtype == "json":
|
|
@@ -157,27 +155,49 @@ def run_ocr(uploaded_file):
|
|
| 157 |
if label == "header":
|
| 158 |
total_headers += 1
|
| 159 |
page_summary.append("π΅ HEADER (API): " + content[:100])
|
| 160 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 161 |
elif label == "footer":
|
| 162 |
total_footers += 1
|
| 163 |
page_summary.append("π’ FOOTER (API): " + content[:100])
|
| 164 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 165 |
else:
|
| 166 |
page_summary.append("[" + label + "]: " + content[:100])
|
| 167 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 168 |
|
| 169 |
elif dtype == "raw":
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 173 |
|
| 174 |
else:
|
| 175 |
page_summary.append("[empty page]")
|
| 176 |
|
| 177 |
-
|
|
|
|
|
|
|
|
|
|
| 178 |
all_summary.extend(page_summary)
|
| 179 |
all_summary.append("")
|
| 180 |
|
|
|
|
|
|
|
|
|
|
| 181 |
summary = (
|
| 182 |
"Total pages : " + str(len(results)) + "\n"
|
| 183 |
+ "Headers found : " + str(total_headers) + "\n"
|
|
@@ -186,18 +206,18 @@ def run_ocr(uploaded_file):
|
|
| 186 |
+ "\n".join(all_summary)
|
| 187 |
)
|
| 188 |
|
| 189 |
-
|
| 190 |
-
return markdown, summary
|
| 191 |
|
| 192 |
except Exception as e:
|
| 193 |
import traceback
|
| 194 |
return "Error: " + str(e) + "\n\n" + traceback.format_exc(), "Failed."
|
| 195 |
|
| 196 |
# ββ STEP 6: Gradio UI βββββββββββββββββββββββββββββββββββββββββ
|
| 197 |
-
with gr.Blocks(title="GLM-OCR β MaaS (
|
| 198 |
gr.Markdown("""
|
| 199 |
# π GLM-OCR β Zhipu MaaS
|
| 200 |
-
Upload PDF or image.
|
|
|
|
| 201 |
Multi-page PDFs fully supported.
|
| 202 |
""")
|
| 203 |
|
|
@@ -209,7 +229,7 @@ with gr.Blocks(title="GLM-OCR β MaaS (Header & Footer)") as demo:
|
|
| 209 |
|
| 210 |
with gr.Row():
|
| 211 |
with gr.Column():
|
| 212 |
-
gr.Markdown("### π
|
| 213 |
markdown_out = gr.Textbox(lines=30, label="")
|
| 214 |
with gr.Column():
|
| 215 |
gr.Markdown("### ποΈ Detected Regions")
|
|
|
|
| 2 |
import yaml
|
| 3 |
import re
|
| 4 |
import os
|
| 5 |
+
import json
|
| 6 |
|
| 7 |
import glmocr
|
| 8 |
GLMOCR_BASE = os.path.dirname(glmocr.__file__)
|
|
|
|
| 50 |
ABANDON = set(config["pipeline"]["result_formatter"]["abandon"])
|
| 51 |
|
| 52 |
# ββ STEP 3: Extract header/footer from PDF text layer βββββββββ
|
|
|
|
|
|
|
| 53 |
def extract_pdf_headers(path):
|
| 54 |
import fitz
|
| 55 |
page_headers = []
|
|
|
|
| 66 |
return page_headers
|
| 67 |
|
| 68 |
# ββ STEP 4: Parse one page result into regions list βββββββββββ
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
def get_page_regions(page_result):
|
|
|
|
| 70 |
if hasattr(page_result, "json_result"):
|
| 71 |
jr = page_result.json_result
|
| 72 |
if isinstance(jr, list) and len(jr) > 0:
|
|
|
|
|
|
|
| 73 |
regions = jr[0] if isinstance(jr[0], list) else jr
|
| 74 |
if isinstance(regions, list):
|
| 75 |
return regions, "json"
|
|
|
|
| 76 |
if hasattr(page_result, "markdown_result"):
|
| 77 |
md = page_result.markdown_result
|
| 78 |
if md and isinstance(md, str) and md.strip():
|
|
|
|
| 100 |
pix.save(img_path)
|
| 101 |
page_images.append(img_path)
|
| 102 |
doc.close()
|
|
|
|
| 103 |
results = parse(page_images)
|
| 104 |
if not isinstance(results, list):
|
| 105 |
results = [results]
|
|
|
|
| 111 |
|
| 112 |
total_headers = 0
|
| 113 |
total_footers = 0
|
| 114 |
+
all_pages_json = [] # final JSON output β list of pages
|
| 115 |
+
all_summary = []
|
| 116 |
|
| 117 |
for page_num, page_result in enumerate(results):
|
| 118 |
+
page_summary = [f"ββ PAGE {page_num + 1} of {len(results)} ββ"]
|
| 119 |
+
page_regions = [] # JSON regions for this page
|
| 120 |
|
| 121 |
+
# Inject header from PDF text layer
|
| 122 |
if pdf_headers and page_num < len(pdf_headers):
|
| 123 |
hdr = pdf_headers[page_num]["header"]
|
| 124 |
ftr = pdf_headers[page_num]["footer"]
|
| 125 |
if hdr:
|
| 126 |
total_headers += 1
|
| 127 |
+
page_regions.append({
|
| 128 |
+
"label": "header",
|
| 129 |
+
"content": hdr,
|
| 130 |
+
"source": "pdf_text_layer"
|
| 131 |
+
})
|
| 132 |
page_summary.append("π΅ HEADER: " + hdr[:100])
|
| 133 |
if ftr:
|
| 134 |
total_footers += 1
|
| 135 |
+
page_regions.append({
|
| 136 |
+
"label": "footer",
|
| 137 |
+
"content": ftr,
|
| 138 |
+
"source": "pdf_text_layer"
|
| 139 |
+
})
|
| 140 |
page_summary.append("π’ FOOTER: " + ftr[:100])
|
| 141 |
|
| 142 |
+
# Get regions from API result
|
| 143 |
data, dtype = get_page_regions(page_result)
|
| 144 |
|
| 145 |
if dtype == "json":
|
|
|
|
| 155 |
if label == "header":
|
| 156 |
total_headers += 1
|
| 157 |
page_summary.append("π΅ HEADER (API): " + content[:100])
|
| 158 |
+
page_regions.append({
|
| 159 |
+
"label": "header",
|
| 160 |
+
"content": content,
|
| 161 |
+
"source": "api"
|
| 162 |
+
})
|
| 163 |
elif label == "footer":
|
| 164 |
total_footers += 1
|
| 165 |
page_summary.append("π’ FOOTER (API): " + content[:100])
|
| 166 |
+
page_regions.append({
|
| 167 |
+
"label": "footer",
|
| 168 |
+
"content": content,
|
| 169 |
+
"source": "api"
|
| 170 |
+
})
|
| 171 |
else:
|
| 172 |
page_summary.append("[" + label + "]: " + content[:100])
|
| 173 |
+
page_regions.append({
|
| 174 |
+
"label": label,
|
| 175 |
+
"content": content,
|
| 176 |
+
"source": "api"
|
| 177 |
+
})
|
| 178 |
|
| 179 |
elif dtype == "raw":
|
| 180 |
+
# Wrap raw markdown as a single text region
|
| 181 |
+
page_regions.append({
|
| 182 |
+
"label": "text",
|
| 183 |
+
"content": data,
|
| 184 |
+
"source": "api_raw"
|
| 185 |
+
})
|
| 186 |
+
page_summary.append("[raw markdown β " + str(len(data)) + " chars]")
|
| 187 |
|
| 188 |
else:
|
| 189 |
page_summary.append("[empty page]")
|
| 190 |
|
| 191 |
+
all_pages_json.append({
|
| 192 |
+
"page": page_num + 1,
|
| 193 |
+
"regions": page_regions
|
| 194 |
+
})
|
| 195 |
all_summary.extend(page_summary)
|
| 196 |
all_summary.append("")
|
| 197 |
|
| 198 |
+
# Format final JSON output
|
| 199 |
+
final_json = json.dumps(all_pages_json, indent=2, ensure_ascii=False)
|
| 200 |
+
|
| 201 |
summary = (
|
| 202 |
"Total pages : " + str(len(results)) + "\n"
|
| 203 |
+ "Headers found : " + str(total_headers) + "\n"
|
|
|
|
| 206 |
+ "\n".join(all_summary)
|
| 207 |
)
|
| 208 |
|
| 209 |
+
return final_json, summary
|
|
|
|
| 210 |
|
| 211 |
except Exception as e:
|
| 212 |
import traceback
|
| 213 |
return "Error: " + str(e) + "\n\n" + traceback.format_exc(), "Failed."
|
| 214 |
|
| 215 |
# ββ STEP 6: Gradio UI βββββββββββββββββββββββββββββββββββββββββ
|
| 216 |
+
with gr.Blocks(title="GLM-OCR β MaaS (JSON Output)") as demo:
|
| 217 |
gr.Markdown("""
|
| 218 |
# π GLM-OCR β Zhipu MaaS
|
| 219 |
+
Upload PDF or image. Output is **JSON format** with all regions.
|
| 220 |
+
Headers π΅ and Footers π’ included in every page.
|
| 221 |
Multi-page PDFs fully supported.
|
| 222 |
""")
|
| 223 |
|
|
|
|
| 229 |
|
| 230 |
with gr.Row():
|
| 231 |
with gr.Column():
|
| 232 |
+
gr.Markdown("### π JSON Output")
|
| 233 |
markdown_out = gr.Textbox(lines=30, label="")
|
| 234 |
with gr.Column():
|
| 235 |
gr.Markdown("### ποΈ Detected Regions")
|