• bitcoinBitcoin(BTC)$64,985.00-0.80%
  • ethereumEthereum(ETH)$1,883.92-2.00%
  • tetherTether(USDT)$1.000.00%
  • binancecoinBNB(BNB)$566.93-0.40%
  • usd-coinUSDC(USDC)$1.000.00%
  • rippleXRP(XRP)$1.11-2.40%
  • solanaSolana(SOL)$75.50-2.40%
  • tronTRON(TRX)$0.3314731.10%
  • Figure HelocFigure Heloc(FIGR_HELOC)$1.043.70%
  • whitebitWhiteBIT Coin(WBT)$56.59-1.00%
  • HyperliquidHyperliquid(HYPE)$58.34-0.50%
  • dogecoinDogecoin(DOGE)$0.069910-3.40%
  • USDSUSDS(USDS)$1.000.00%
  • RainRain(RAIN)$0.014115-2.10%
  • leo-tokenLEO Token(LEO)$9.60-1.20%
  • zcashZcash(ZEC)$500.56-1.70%
  • moneroMonero(XMR)$354.960.70%
  • chainlinkChainlink(LINK)$8.46-0.90%
  • stellarStellar(XLM)$0.182755-0.70%
  • cardanoCardano(ADA)$0.166571-3.90%
  • CantonCanton(CC)$0.1201160.40%
  • daiDai(DAI)$1.000.00%
  • bitcoin-cashBitcoin Cash(BCH)$210.39-2.30%
  • USD1USD1(USD1)$1.000.00%
  • the-open-networkGram (prev. Toncoin)(GRAM)$1.47-2.90%
  • Ethena USDeEthena USDe(USDE)$1.000.00%
  • litecoinLitecoin(LTC)$46.09-1.00%
  • Global DollarGlobal Dollar(USDG)$1.000.00%
  • hedera-hashgraphHedera(HBAR)$0.070703-5.00%
  • suiSui(SUI)$0.73-4.70%
  • Circle USYCCircle USYC(USYC)$1.130.00%
  • avalanche-2Avalanche(AVAX)$6.26-4.60%
  • crypto-com-chainCronos(CRO)$0.056970-1.10%
  • paypal-usdPayPal USD(PYUSD)$1.000.00%
  • BlackRock USD Institutional Digital Liquidity FundBlackRock USD Institutional Digital Liquidity Fund(BUIDL)$1.000.00%
  • tether-goldTether Gold(XAUT)$4,053.82-0.80%
  • nearNEAR Protocol(NEAR)$1.891.50%
  • shiba-inuShiba Inu(SHIB)$0.000004-1.40%
  • uniswapUniswap(UNI)$3.84-0.40%
  • Ondo US Dollar YieldOndo US Dollar Yield(USDY)$1.140.00%
  • OndoOndo(ONDO)$0.391866-2.40%
  • BittensorBittensor(TAO)$191.92-1.90%
  • World Liberty FinancialWorld Liberty Financial(WLFI)$0.057006-10.00%
  • pax-goldPAX Gold(PAXG)$4,050.12-0.90%
  • okbOKB(OKB)$82.27-0.40%
  • AsterAster(ASTER)$0.630.00%
  • HTX DAOHTX DAO(HTX)$0.0000020.20%
  • Ripple USDRipple USD(RLUSD)$1.000.00%
  • MemeCoreMemeCore(M)$1.172.30%
  • usddUSDD(USDD)$1.000.00%
TradePoint.io
  • Main
  • AI & Technology
  • Stock Charts
  • Market & News
  • Business
  • Finance Tips
  • Trade Tube
  • Blog
  • Shop
No Result
View All Result
TradePoint.io
No Result
View All Result

How to Build an End-to-End OCR Pipeline with Baidu’s Unlimited-OCR for High-Resolution Images and Multi-Page PDF Parsing

July 24, 2026
in AI & Technology
Reading Time: 8 mins read
A A
How to Build an End-to-End OCR Pipeline with Baidu’s Unlimited-OCR for High-Resolution Images and Multi-Page PDF Parsing
ShareShareShareShareShare

In this tutorial, we build a complete workflow for running Baidu’s Unlimited-OCR model on document images and multi-page PDFs. We configure the GPU environment, install the required dependencies, load the 3B-parameter vision-language model with automatic selection of bfloat16 or float16, and generate structured sample documents for testing. We then evaluate both the tiled Gundam inference mode and the faster Base mode for single-page OCR before extending the pipeline to multi-page PDF parsing with PyMuPDF and infer_multi(). Throughout the workflow, we preserve long-context generation settings, repetition controls, and structured output handling to process dense layouts, tables, paragraphs, and cross-page content in a reproducible end-to-end pipeline.

import subprocess, sys
def pip_install(*pkgs):
   subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", *pkgs])
print(">> Installing dependencies (1-2 min)...")
pip_install(
   "transformers==4.57.1",
   "Pillow",
   "matplotlib",
   "einops",
   "addict",
   "easydict",
   "pymupdf",
   "psutil",
   "accelerate",
)
print(">> Done.")
import os
import torch
from transformers import AutoModel, AutoTokenizer
assert torch.cuda.is_available(), (
   "No GPU detected! In Colab: Runtime -> Change runtime type -> GPU."
)
gpu_name = torch.cuda.get_device_name(0)
print(f">> GPU: {gpu_name}")
use_bf16 = torch.cuda.is_bf16_supported()
DTYPE = torch.bfloat16 if use_bf16 else torch.float16
print(f">> Using dtype: {DTYPE}")
MODEL_NAME = "baidu/Unlimited-OCR"
print(">> Downloading model (~6 GB for 3B params in BF16). First run takes a while...")
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME, trust_remote_code=True)
model = AutoModel.from_pretrained(
   MODEL_NAME,
   trust_remote_code=True,
   use_safetensors=True,
   torch_dtype=DTYPE,
)
model = model.eval().cuda()
print(">> Model loaded and moved to GPU.")

We install the required libraries and prepare the Google Colab environment for Unlimited-OCR inference. We verify that a CUDA-enabled GPU is available and automatically choose bfloat16 or float16 based on hardware support. We then load the tokenizer and the 3B-parameter model from Hugging Face, switch them to evaluation mode, and move them to the GPU.

YOU MAY ALSO LIKE

Alphabet Accelerates Its AI Investment

Mobileye CEO To Step Down After 27 Years

from PIL import Image, ImageDraw, ImageFont
import textwrap
os.makedirs("inputs", exist_ok=True)
os.makedirs("outputs/single_gundam", exist_ok=True)
os.makedirs("outputs/single_base", exist_ok=True)
os.makedirs("outputs/multi_page", exist_ok=True)
def load_font(size):
   for path in [
       "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
       "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
   ]:
       if os.path.exists(path):
           return ImageFont.truetype(path, size)
   return ImageFont.load_default()
def make_sample_page(path, page_no):
   W, H = 1240, 1754
   img = Image.new("RGB", (W, H), "white")
   d = ImageDraw.Draw(img)
   title_f, head_f, body_f = load_font(48), load_font(34), load_font(26)
   d.text((80, 70), f"Quarterly Operations Report — Page {page_no}",
          fill="black", font=title_f)
   d.line([(80, 145), (W - 80, 145)], fill="black", width=3)
   body = (
       "This document demonstrates Unlimited-OCR's one-shot long-horizon "
       "parsing. The model reads an entire page — headings, paragraphs, "
       "and tables — and emits structured text in a single decoding pass. "
       "Unlike classic OCR pipelines, no separate layout-analysis stage "
       "is required."
   )
   y = 190
   for line in textwrap.wrap(body, width=72):
       d.text((80, y), line, fill="black", font=body_f)
       y += 40
   y += 30
   d.text((80, y), f"Table {page_no}: Regional Revenue (USD, millions)",
          fill="black", font=head_f)
   y += 60
   rows = [
       ["Region",  "Q1",   "Q2",   "Q3"],
       ["North",   "12.4", "13.1", "15.0"],
       ["South",   "9.8",  "10.2", "11.7"],
       ["East",    "14.3", "13.9", "16.2"],
       ["West",    "11.1", "12.5", "12.9"],
   ]
   col_w, row_h, x0 = 260, 56, 80
   for r, row in enumerate(rows):
       for c, cell in enumerate(row):
           x = x0 + c * col_w
           d.rectangle([x, y, x + col_w, y + row_h], outline="black", width=2)
           d.text((x + 14, y + 12), cell, fill="black", font=body_f)
       y += row_h
   y += 50
   footer = (
       f"Note {page_no}: Figures are illustrative. Multi-page mode stitches "
       "context across pages, so cross-page references remain coherent."
   )
   for line in textwrap.wrap(footer, width=72):
       d.text((80, y), line, fill="black", font=body_f)
       y += 40
   img.save(path)
   return path
IMAGE_PATH = make_sample_page("inputs/sample_page_1.png", 1)
PAGE_2     = make_sample_page("inputs/sample_page_2.png", 2)
PAGE_3     = make_sample_page("inputs/sample_page_3.png", 3)
print(f">> Sample pages written: {IMAGE_PATH}, {PAGE_2}, {PAGE_3}")
import matplotlib.pyplot as plt
plt.figure(figsize=(6, 8))
plt.imshow(Image.open(IMAGE_PATH))
plt.axis("off")
plt.title("Input document (page 1)")
plt.show()

We create the required input and output directories and generate three realistic sample document pages with PIL. We add headings, paragraphs, tables, and footnotes to test the model on structured, layout-rich content. We also preview the first generated page with Matplotlib before sending it to the OCR pipeline.

print("\n" + "=" * 76)
print("STEP 4: Single image — GUNDAM mode (tiled, high detail)")
print("=" * 76)
model.infer(
   tokenizer,
   prompt="document parsing.",
   image_file=IMAGE_PATH,
   output_path="outputs/single_gundam",
   base_size=1024,
   image_size=640,
   crop_mode=True,
   max_length=32768,
   no_repeat_ngram_size=35,
   ngram_window=128,
   save_results=True,
)

We run single-image OCR using Gundam mode, which combines a global document view with tiled image crops. We enable crop_mode and use a smaller tile size to preserve fine text and improve recognition on dense document layouts. We also configure long-output generation and repetition controls to ensure the model produces stable, structured results.

print("\n" + "=" * 76)
print("STEP 5: Single image — BASE mode (single view, faster)")
print("=" * 76)
model.infer(
   tokenizer,
   prompt="document parsing.",
   image_file=IMAGE_PATH,
   output_path="outputs/single_base",
   base_size=1024,
   image_size=1024,
   crop_mode=False,
   max_length=32768,
   no_repeat_ngram_size=35,
   ngram_window=128,
   save_results=True,
)

We process the same document using Base mode with a single 1024-pixel image view. We turn off image cropping to reduce inference complexity and improve processing speed for clean, clearly printed pages. We retain the same output length and repetition-control settings to directly compare Base mode with Gundam mode.

print("\n" + "=" * 76)
print("STEP 6: Multi-page / PDF parsing")
print("=" * 76)
import tempfile
import fitz
def pdf_to_images(pdf_path, dpi=300):
   """Rasterize every PDF page to a PNG; return the list of image paths."""
   doc = fitz.open(pdf_path)
   tmp_dir = tempfile.mkdtemp(prefix="pdf_ocr_")
   mat = fitz.Matrix(dpi / 72, dpi / 72)
   paths = []
   for i, page in enumerate(doc):
       out = os.path.join(tmp_dir, f"page_{i + 1:04d}.png")
       page.get_pixmap(matrix=mat).save(out)
       paths.append(out)
   doc.close()
   return paths
SAMPLE_PDF = "inputs/sample_doc.pdf"
pdf = fitz.open()
for p in [IMAGE_PATH, PAGE_2, PAGE_3]:
   img_doc = fitz.open(p)
   rect = img_doc[0].rect
   pdf_bytes = img_doc.convert_to_pdf()
   img_pdf = fitz.open("pdf", pdf_bytes)
   page = pdf.new_page(width=rect.width, height=rect.height)
   page.show_pdf_page(rect, img_pdf, 0)
pdf.save(SAMPLE_PDF)
pdf.close()
print(f">> Built sample PDF: {SAMPLE_PDF}")
page_images = pdf_to_images(SAMPLE_PDF, dpi=300)
print(f">> Rasterized {len(page_images)} pages")
model.infer_multi(
   tokenizer,
   prompt="Multi page parsing.",
   image_files=page_images,
   output_path="outputs/multi_page",
   image_size=1024,
   max_length=32768,
   no_repeat_ngram_size=35,
   ngram_window=1024,
   save_results=True,
)

We create a three-page PDF from the generated document images and rasterize each page of the PDF into a high-resolution PNG using PyMuPDF. We pass the resulting page-image sequence to infer_multi() so that the model can parse the complete document in a single long-horizon inference operation. We also widen the n-gram repetition window to maintain stable decoding across multiple pages.

print("\n" + "=" * 76)
print("STEP 7: Saved outputs")
print("=" * 76)
TEXT_EXTS = {".txt", ".md", ".mmd", ".json"}
def show_outputs(root):
   print(f"\n--- {root} ---")
   if not os.path.isdir(root):
       print("  (no output directory found)")
       return
   for dirpath, _, files in os.walk(root):
       for fn in sorted(files):
           fp = os.path.join(dirpath, fn)
           size = os.path.getsize(fp)
           print(f"  {fp}  ({size:,} bytes)")
           if os.path.splitext(fn)[1].lower() in TEXT_EXTS:
               with open(fp, "r", encoding="utf-8", errors="replace") as f:
                   content = f.read()
               preview = content[:1500]
               print("  " + "-" * 60)
               print("\n".join("  | " + ln for ln in preview.splitlines()))
               if len(content) > 1500:
                   print(f"  | ... [{len(content) - 1500:,} more chars]")
               print("  " + "-" * 60)
for out_dir in ["outputs/single_gundam", "outputs/single_base", "outputs/multi_page"]:
   show_outputs(out_dir)
print("""
============================================================================
DONE — CHEAT SHEET
============================================================================
Single image, dense/small text .... infer(), gundam (640 + crop_mode=True)
Single image, clean print ......... infer(), base   (1024, crop_mode=False)
Multi-page or PDF ................. infer_multi(), image_size=1024,
                                    ngram_window=1024
Long documents .................... keep max_length=32768 and the
                                    no_repeat_ngram settings — they prevent
                                    degeneration on long outputs.
Your own files .................... upload via Colab sidebar, point
                                    image_file / pdf_to_images() at them.
============================================================================
""")

We inspect the output directories created by the single-page and multi-page inference runs. We list every generated file and display previews of supported text, Markdown, MMD, and JSON artifacts. We conclude the workflow with a concise reference summarizing the recommended inference modes for dense images, clean pages, and multi-page PDFs.

In conclusion, we completed a practical OCR pipeline that handles both high-detail single-page documents and long multi-page PDFs within Google Colab. We compared Gundam and Base inference modes, rasterized PDFs into model-ready page images, ran long-horizon document parsing, and inspected the generated text, Markdown, and auxiliary artifacts directly from the output directories. We also configured the workflow to adapt to different GPU capabilities while retaining the generation parameters required for stable long-document decoding. It provides us with a reusable foundation for applying Unlimited-OCR to reports, scanned forms, technical documents, tables, and other layout-rich content without relying on a separate traditional OCR and layout-analysis stack.


Check out the Full Code here. Also, feel free to follow us on Twitter and don’t forget to join our 150k+ML SubReddit and Subscribe to our Newsletter. Wait! are you on telegram? now you can join us on telegram as well.

Need to partner with us for promoting your GitHub Repo OR Hugging Face Page OR Product Release OR Webinar etc.? Connect with us


Sana Hassan, a consulting intern at Marktechpost and dual-degree student at IIT Madras, is passionate about applying technology and AI to address real-world challenges. With a keen interest in solving practical problems, he brings a fresh perspective to the intersection of AI and real-life solutions.

Credit: Source link

ShareTweetSendSharePin

Related Posts

Alphabet Accelerates Its AI Investment
AI & Technology

Alphabet Accelerates Its AI Investment

July 24, 2026
Mobileye CEO To Step Down After 27 Years
AI & Technology

Mobileye CEO To Step Down After 27 Years

July 24, 2026
Khosla Ventures In Talks For Its Biggest Fundraise Ever
AI & Technology

Khosla Ventures In Talks For Its Biggest Fundraise Ever

July 24, 2026
AI Spending Takes Center Stage in Big Tech Earnings | Bloomberg Tech 7/23/2026
AI & Technology

AI Spending Takes Center Stage in Big Tech Earnings | Bloomberg Tech 7/23/2026

July 24, 2026
Next Post
Apple Prepping iMac, MacBooks Overhaul to Meet AI Demand

Apple Prepping iMac, MacBooks Overhaul to Meet AI Demand

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Search

No Result
View All Result
Where Novak Djokovic gets his dance moves and who he calls the GOAT

Where Novak Djokovic gets his dance moves and who he calls the GOAT

July 23, 2026
New outbreak of explosive diarrhea parasite reported by FDA — with 72 cases and no known source

New outbreak of explosive diarrhea parasite reported by FDA — with 72 cases and no known source

July 22, 2026
4 more Ford workers fired over alleged snack theft after .95 cookie fiasco with wrongfully canned electrician

4 more Ford workers fired over alleged snack theft after $1.95 cookie fiasco with wrongfully canned electrician

July 21, 2026

About

Learn more

Our Services

Legal

Privacy Policy

Terms of Use

Bloggers

Learn more

Article Links

Contact

Advertise

Ask us anything

©2020- TradePoint.io - All rights reserved!

Tradepoint.io, being just a publishing and technology platform, is not a registered broker-dealer or investment adviser. So we do not provide investment advice. Rather, brokerage services are provided to clients of Tradepoint.io by independent SEC-registered broker-dealers and members of FINRA/SIPC. Every form of investing carries some risk and past performance is not a guarantee of future results. “Tradepoint.io“, “Instant Investing” and “My Trading Tools” are registered trademarks of Apperbuild, LLC.

This website is operated by Apperbuild, LLC. We have no link to any brokerage firm and we do not provide investment advice. Every information and resource we provide is solely for the education of our readers. © 2020 Apperbuild, LLC. All rights reserved.

No Result
View All Result
  • Main
  • AI & Technology
  • Stock Charts
  • Market & News
  • Business
  • Finance Tips
  • Trade Tube
  • Blog
  • Shop

© 2023 - TradePoint.io - All Rights Reserved!