في هذا البرنامج التعليمي، نقوم ببناء سير عمل كامل للتشغيل بايدو غير محدود التعرف الضوئي على الحروف نموذج على صور المستندات وملفات PDF متعددة الصفحات. نقوم بتكوين بيئة GPU، وتثبيت التبعيات المطلوبة، وتحميل نموذج لغة الرؤية ذو المعلمة 3B مع التحديد التلقائي لـ bfloat16 أو float16، وإنشاء مستندات عينة منظمة للاختبار. نقوم بعد ذلك بتقييم كل من وضع استدلال Gundam المتجانب والوضع الأساسي الأسرع للتعرف الضوئي على الحروف لصفحة واحدة قبل توسيع المسار إلى تحليل PDF متعدد الصفحات باستخدام PyMuPDF وinfer_multi(). طوال سير العمل، نحافظ على إعدادات إنشاء السياق الطويل، وعناصر التحكم في التكرار، ومعالجة المخرجات المنظمة لمعالجة التخطيطات الكثيفة، والجداول، والفقرات، والمحتوى عبر الصفحات في مسار متكامل قابل للتكرار.

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.")

نقوم بتثبيت المكتبات المطلوبة وإعداد بيئة Google Colab لاستدلال OCR غير المحدود. نحن نتحقق من توفر وحدة معالجة الرسومات التي تدعم CUDA ونختار تلقائيًا bfloat16 أو float16 بناءً على دعم الأجهزة. نقوم بعد ذلك بتحميل الرمز المميز ونموذج المعلمة 3B من Hugging Face، وتحويلهما إلى وضع التقييم، ونقلهما إلى وحدة معالجة الرسومات.

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()

نقوم بإنشاء أدلة الإدخال والإخراج المطلوبة وإنشاء ثلاث صفحات مستندات نموذجية واقعية باستخدام PIL. نضيف عناوين وفقرات وجداول وحواشي سفلية لاختبار النموذج على محتوى منظم وغني بالتخطيط. نقوم أيضًا بمعاينة الصفحة الأولى التي تم إنشاؤها باستخدام Matplotlib قبل إرسالها إلى خط أنابيب OCR.

print("\n" + "=" * 76)
print("STEP 4: Single image — GUNDAM mode (tiled, high detail)")
print("=" * 76)
model.infer(
   tokenizer,
   prompt="<image>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,
)

نقوم بتشغيل تقنية التعرف الضوئي على الحروف (OCR) لصورة واحدة باستخدام وضع Gundam، الذي يجمع بين عرض المستند الشامل واقتصاص الصور المتجانبة. نقوم بتمكين وضع الاقتصاص واستخدام حجم مربع أصغر للحفاظ على النص الدقيق وتحسين التعرف على تخطيطات المستندات الكثيفة. نقوم أيضًا بتكوين عناصر التحكم في توليد المخرجات الطويلة والتكرار لضمان أن النموذج ينتج نتائج مستقرة ومنظمة.

print("\n" + "=" * 76)
print("STEP 5: Single image — BASE mode (single view, faster)")
print("=" * 76)
model.infer(
   tokenizer,
   prompt="<image>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,
)

نقوم بمعالجة نفس المستند باستخدام الوضع الأساسي مع عرض صورة واحد بدقة 1024 بكسل. نقوم بإيقاف تشغيل اقتصاص الصور لتقليل تعقيد الاستدلال وتحسين سرعة المعالجة للحصول على صفحات نظيفة ومطبوعة بوضوح. نحن نحتفظ بنفس طول الإخراج وإعدادات التحكم في التكرار لمقارنة الوضع الأساسي مباشرةً مع وضع Gundam.

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="<image>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,
)

نقوم بإنشاء ملف PDF من ثلاث صفحات من صور المستندات التي تم إنشاؤها ونقوم بتنقيط كل صفحة من ملف PDF إلى ملف PNG عالي الدقة باستخدام PyMuPDF. نقوم بتمرير تسلسل صورة الصفحة الناتج إلى infer_multi()‎ حتى يتمكن النموذج من تحليل المستند الكامل في عملية استدلال واحدة طويلة الأفق. نقوم أيضًا بتوسيع نافذة تكرار n-gram للحفاظ على فك التشفير المستقر عبر صفحات متعددة.

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.
============================================================================
""")

نقوم بفحص أدلة الإخراج التي تم إنشاؤها بواسطة عمليات الاستدلال ذات الصفحة الواحدة والمتعددة الصفحات. نقوم بإدراج كل ملف تم إنشاؤه ونعرض معاينات للنصوص المدعومة وعناصر Markdown وMMD وJSON. نختتم سير العمل بمرجع موجز يلخص أوضاع الاستدلال الموصى بها للصور الكثيفة والصفحات النظيفة وملفات PDF متعددة الصفحات.

في الختام، لقد أكملنا عملية التعرف الضوئي على الحروف (OCR) التي تتعامل مع المستندات عالية التفاصيل ذات الصفحة الواحدة وملفات PDF الطويلة متعددة الصفحات داخل Google Colab. قمنا بمقارنة أوضاع الاستدلال Gundam وBase، وقمنا بتحويل ملفات PDF النقطية إلى صور صفحة جاهزة للنموذج، وقمنا بتشغيل تحليل المستند طويل الأفق، وفحصنا النص الذي تم إنشاؤه، وMarkdown، والعناصر المساعدة مباشرة من أدلة الإخراج. قمنا أيضًا بتكوين سير العمل للتكيف مع إمكانيات وحدة معالجة الرسومات المختلفة مع الاحتفاظ بمعلمات الإنشاء المطلوبة لفك تشفير المستندات الطويلة بشكل مستقر. فهو يوفر لنا أساسًا قابلاً لإعادة الاستخدام لتطبيق Unlimited-OCR على التقارير والنماذج الممسوحة ضوئيًا والمستندات الفنية والجداول والمحتويات الأخرى الغنية بالتخطيط دون الاعتماد على حزمة OCR تقليدية منفصلة وتحليل التخطيط.


تحقق من الرمز الكامل هنا أيضًا، لا تتردد في متابعتنا على تغريدÂ ولا تنسى الانضمام إلينا 150 ألف + مل§ والاشتراك في النشرة الإخبارية لدينا. انتظر! هل أنت على برقية؟ الآن يمكنك الانضمام إلينا على التليجرام أيضًا.

هل تحتاج إلى الشراكة معنا للترويج لصفحة GitHub Repo أو صفحة الوجه المعانقة أو إصدار المنتج أو الندوة عبر الويب وما إلى ذلك؟ تواصل معنا


سناء حسن، مستشارة متدربة في Marktechpost وطالبة بدرجة مزدوجة في IIT Madras، شغوفة بتطبيق التكنولوجيا والذكاء الاصطناعي لمواجهة تحديات العالم الحقيقي. ومع اهتمامه الشديد بحل المشكلات العملية، فهو يقدم منظورًا جديدًا للتقاطع بين الذكاء الاصطناعي وحلول الحياة الواقعية.


اكتشاف المزيد من كحيل | أخبار التقنية

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

شاركها.
اترك تعليقاً

اكتشاف المزيد من كحيل | أخبار التقنية

اشترك الآن للاستمرار في القراءة والحصول على حق الوصول إلى الأرشيف الكامل.

متابعة القراءة