إنشاء رمز شريطي PDF417 يتطلب أربع أسطر من بايثون. قراءة هذا الرمز من صورة هاتف، أو مسح بدقة 200 DPI، أو بطاقة صعود قضت يومًا في جيب شخص ما هو المكان الذي يبدأ فيه العمل الحقيقي، وهو المكان الذي تفشل فيه معظم تكاملات PDF417 فعليًا. في هذه المقالة، ستتعلم كيفية قراءة رموز PDF417 الشريطية باستخدام بايثون عندما تكون صورة المصدر غير مثالية. إذا كنت تبحث عن جانب الإنشاء بدلاً من ذلك، فإن الدليل السابق حول كيفية إنشاء رموز PDF417 باستخدام بايثون يغطي إنشاء رموز PDF417 الأساسية والمخصصة، بما في ذلك التحكم في الصفوف والأعمدة، ودليل قارئ الباركود بايثون يغطي المسح العام عبر الأنواع المختلفة من الرموز. ما يلي هنا يركز بشكل ضيق وعميق على التعرف على PDF417.

تم تشغيل كل مقطع أدناه ضد Aspose.BarCode for Python via .NET 26.7 على Linux مع Python 3.12. تم قياس أوقات التنفيذ ونتائج القراءة/الفشل، وليس تقديرها، والسكريبت الذي أنتجها موجود في النهاية حتى يمكنك إعادة تشغيله على صورك الخاصة.

ما الذي يعيق فعليًا التعرف على PDF417

PDF417 هو ترميز مكدس: صفوف من كلمات الشيفرة، كل كلمة شيفرة مبنية من أربعة أشرطة وأربعة مسافات تمتد عبر 17 وحدة. يحمل هذا الهيكل تصحيح الأخطاء Reed‑Solomon، لذا فإن الزاوية الممزقة أو بقعة القهوة عادةً ما تكون قابلة للنجاة. ما لا يمكن النجاة منه هو فقدان شبكة الوحدات نفسها.

ثلاثة أشياء تدمر الشبكة، بترتيب تقريبي حسب مدى ظهورها في الإنتاج:

  • انخفاض عرض الوحدة الفعلي إلى أقل من بكسلين. هذا هو الفشل السائد. يحدث ذلك من خلال تقليل الحجم، أو من خلال مسافة الكاميرا، أو من خلال الضبابية التي تنشر حبر الوحدة عبر جيرانها. الباركود المولد بثلاث بكسلات لكل وحدة ثم تم تشويهه هو عمليًا باركود ببيكسل واحد لكل وحدة.
  • المنظور والدوران. الباركود المصور بزاوية يحتوي على صفوف لم تعد خطوط مسح موازية. المكتشف يتعامل مع ذلك، لكنه يتطلب تمريرة كشف تتخطاها الإعدادات الأسرع.
  • انهيار التباين. الورق الحراري الذي تلاشى، أو الشاشة المصورة تحت الوهج، أو المسح الضوئي مع تثبيت السطوع. أقل فتكًا مما يبدو، كما تُظهر الأرقام أدناه.

العاقبة العملية هي أن إعدادات التعرف هي آلية استرداد، ليست بديلاً عن جودة الالتقاط. إنها تعيد لك شريحة الجودة المتوسطة للصورة. ولا تعيد لك الشريحة السفلية.

إعداد قارئ PDF417 للبايثون

قم بتثبيت المكتبة من PyPI:

pip install aspose-barcode-for-python-via-net

توجد واجهة برمجة تطبيقات التعرف في aspose.barcode.barcoderecognition. فئتان مهمتان لهذه المقالة: BarCodeReader، التي تدير الكشف والترميز، وQualitySettings، التي تتحكم في مدى صعوبة محاولة القارئ.

قراءة رمز PDF417 الشريطي في بايثون

الحد الأدنى للقراءة القابلة للتنفيذ هو معاملان وحلقة:

from aspose.barcode import barcoderecognition as rec

reader = rec.BarCodeReader("clean.png", rec.DecodeType.PDF417)

for result in reader.read_bar_codes():
    print("Code text:", result.code_text)
    print("Symbology:", result.code_type_name)
    print("Reading quality:", result.reading_quality)
قراءة باركود PDF417 في بايثون.

قراءة باركود PDF417 في بايثون.

الإخراج على صورة نظيفة:

Code text: PASSENGER|KHAN/M|SEAT14C|LHE-DXB
Symbology: Pdf417
Reading quality: 100.0

المعامل الثاني ليس اختياريًا في الممارسة العملية. اتركه خارجًا وسيتراجع BarCodeReader إلى DecodeType.ALL_SUPPORTED_TYPES، والذي يجري الكشف لأكثر من ستين رموزًا مقابل كل منطقة مرشحة في الصورة. في خط معالجة يقتصر على PDF417 فقط، هذا إهدار تام، كما يفتح الباب أمام نتيجة إيجابية كاذبة لرمز خطي داخل بنية صف PDF417. حدد النوع.

إذا وصل الإدخال كـ بايتات من عملية تحميل بدلاً من ملف على القرص، مرّر stream واضع timeout حتى لا تتمكن صورة غير طبيعية من إيقاف العامل.

import io
from aspose.barcode import barcoderecognition as rec

def decode_pdf417(image_bytes, timeout_ms=2000):
    reader = rec.BarCodeReader(io.BytesIO(image_bytes), rec.DecodeType.PDF417)
    reader.timeout = timeout_ms
    return [r.code_text for r in reader.read_bar_codes()]

مقارنة إعدادات جودة التعرف على PDF417 في Python

QualitySettings يأتي بأربع إعدادات مسبقة تستحق المعرفة. تعيين واحدة للقارئ يتم بسطر واحد:

reader = rec.BarCodeReader("scan.png", rec.DecodeType.PDF417)
reader.quality_settings = rec.QualitySettings.high_quality
الإعداد المسبقمخصص لـالتكلفة
high_performanceصور نظيفة، تم إنشاؤها آليًاالأسرع، يتخطى عمليات الاسترداد
normal_qualityافتراضي. مسح وتصدير عاديمتوازن
high_qualityالتقاطات الكاميرا، مسحات متدهورةمتوسط
max_qualityإعادة محاولة على الصور التي فشلت بالفعلالأبطأ بفارق كبير

للتعرف على ما تعنيه تلك الأوصاف عمليًا، قمت بإنشاء PDF417 بمعدل ثلاث بكسلات لكل وحدة، وقمت بتدهوره بست طرق باستخدام Pillow، وشغلت كل إعداد مسبق ضد كل نسخة. المتوسط من ثلاث تجارب:

صورة المصدرhigh_performancenormal_qualityhigh_qualitymax_quality
نظيفةقراءة، 35 msقراءة، 50 msقراءة، 45 msقراءة، 106 ms
دوران 12°, مشوشفشل، 15 msقراءة، 74 msقراءة، 67 msقراءة، 157 ms
ضوضاء غاوسية (σ 40)قراءة، 31 msقراءة، 49 msقراءة، 52 msقراءة، 123 ms
نصف الدقةقراءة، 22 msقراءة، 37 msقراءة، 35 msقراءة، 86 ms
تباين منخفضقراءة، 24 msقراءة، 38 msقراءة، 43 msقراءة، 112 ms
تشويش شديد (σ 2.2)فشل، 5 msفشل، 25 msفشل، 85 msفشل، 180 ms

أربعة أشياء تخرج من هذا الجدول، وهي أكثر فائدة من الأرقام الفردية:

  1. الضوضاء وانخفاض التباين ليسا المشكلة التي يعتقد الناس أنها كذلك. Reed‑Solomon بالإضافة إلى الكاشف استوعبا ضوضاء غاوسية ثقيلة وانخفاض التباين بنسبة 82 % في أسرع إعداد مسبق. توقف عن ضبط هذه الإعدادات.
  2. الدوران مع الضبابية هو الحالة التي تميز الإعدادات المسبقة. وهو أيضًا الملف التعريفي الدقيق لالتقاط هاتف محمول، ولهذا السبب high_performance هو الإعداد الافتراضي الخاطئ لأي خط أنابيب مصدره الهاتف المحمول.
  3. max_quality يكلف ثلاثة أضعاف وقت normal_quality ولا يقرأ أي شيء إضافي. إنه يستحق مكانه كمسار محاولة ثانية، وليس كإعداد افتراضي.
  4. بمجرد اختفاء شبكة الوحدة، لا يمكن لأي إعداد مسبق استعادتها. صف الضبابية الثقيلة هو فشل شامل، وقد استغرق max_quality 180 مللي ثانية لإثبات ذلك. هذه مشكلة في الالتقاط مع حل للالتقاط: مزيد من البكسلات، تركيز أفضل، x_dimension أكبر عند وقت الإنشاء.

ضبط QualitySettings لقراءة الباركود PDF417 الضبابي في Python

الإعداد المسبق هو مجموعة من الخصائص الفردية، ويمكنك البدء من إعداد مسبق وتجاوز أحدها. هنا تكمن الفوائد الحقيقية لعيب معروف وقابل للتكرار.

الصورة المدورة والمطمّهة أعلاه تُظهر مثالًا جيدًا. تحت high_performance هي مفقودة. فعّل deconvolution فوق نفس الإعداد المسبق وستظهر:

from aspose.barcode import barcoderecognition as rec

reader = rec.BarCodeReader("rotated.png", rec.DecodeType.PDF417)

quality = rec.QualitySettings.high_performance
quality.deconvolution = rec.DeconvolutionMode.NORMAL
reader.quality_settings = quality

for result in reader.read_bar_codes():
    print(result.code_text)
ضبط QualitySettings لقراءة رموز PDF417 الضبابية في بايثون.

ضبط QualitySettings لقراءة رموز PDF417 الضبابية في بايثون.

تم القياس: فشل في 12 مللي ثانية بدون التجاوز، تم القراءة في 54 مللي ثانية معه. خاصية واحدة غيرت النتيجة، ولا يزال الناتج يعود أسرع مما كان سيحدث مع إعداد max_quality.

الخصائص التي تستحق المعرفة:

الخاصيةالقيممتى تستخدمه
deconvolutionFAST, NORMAL, SLOWضبابية الحركة واللقطات غير المركزة
barcode_qualityHIGH, NORMAL, LOWعيوب الطباعة، تلاشي حراري، تشوهات الفاكس
x_dimensionAUTO, SMALL, NORMAL, LARGE, USE_MINIMAL_X_DIMENSIONباركودات كثيفة، أو حجم وحدة ثابت معروف
minimal_x_dimensionfloatاستخدم مع USE_MINIMAL_X_DIMENSION لتحديد حد أدنى
complex_backgroundAUTO, DISABLED, ENABLEDباركود مطبوع فوق عمل فني أو نموذج بنقوش
inverse_imageAUTO, DISABLED, ENABLEDباركود أبيض على خلفية سوداء، لقطات شاشة
allow_incorrect_barcodesboolللتشخيص فقط، لا للإنتاج

الأخير يستحق تحذيراً. allow_incorrect_barcodes يُعيد الرموز التي فشلت في التحقق من صحة المجموع الاختباري. إنها أداة تصحيح للمساعدة في الإجابة على “هل اكتشف الكاشف شيئًا هنا؟” شحنها يعني شحن سلاسل مُفسَّرة خاطئة بدلاً من عدم وجودها، وهو أسوأ من مجرد فقدان.

استراتيجية تصنيف تعمل بشكل جيد في بيئة الإنتاج: جرب normal_quality أولاً، وعند الفشل أعد المحاولة مرة واحدة باستخدام high_quality بالإضافة إلى deconvolution = SLOW. تدفع المسار المكلف فقط للصور التي تحتاجه.

تحقق من نتائج فك ترميز PDF417 في بايثون

السلسلة المفكوكة ليست بالضرورة سلسلة صحيحة تلقائيًا. ثلاثة حقول في BarCodeResult تساعد:

for result in reader.read_bar_codes():
    print("Text:", result.code_text)
    print("Reading quality:", result.reading_quality)
    print("Confidence:", result.confidence)
    print("Region:", [(p.x, p.y) for p in result.region.points])
Text: PASSENGER|KHAN/M|SEAT14C|LHE-DXB
Reading quality: 100.0
Confidence: 100
Region: [(7, 6), (261, 7), (261, 276), (7, 277)]

إعادة تجميع Macro PDF417 المقسمة عبر الصور

Macro PDF417 يقسم رسالة منطقية واحدة عبر عدة رموز، وهو ما يظهر في قوائم الشحن والوثائق متعددة الصفحات. تبقى بيانات التعريف للقطعة صالحة بعد الجولة الكاملة، وبالتالي تكون عملية إعادة التجميع حتمية:

from aspose.barcode import barcoderecognition as rec

segments = {}
total = None

for path in ["page1.png", "page2.png"]:
    reader = rec.BarCodeReader(path, rec.DecodeType.MACRO_PDF417)
    for result in reader.read_bar_codes():
        meta = result.extended.pdf417
        segments[meta.macro_pdf_417_segment_id] = result.code_text
        total = meta.macro_pdf_417_segments_count
        print(f"{path}: segment {meta.macro_pdf_417_segment_id + 1} of {total}, "
              f"file id {meta.macro_pdf_417_file_id}")

if total and len(segments) == total:
    payload = "".join(segments[i] for i in sorted(segments))
    print("Reassembled:", payload)
else:
    print("Incomplete: missing segments")
الصفحة 1.

الصفحة 1.

الصفحة 2.

الصفحة 2.

Output:

Data\pdf417\page1.png: segment 1 of 2, file id 42
Data\pdf417\page2.png: segment 2 of 2, file id 42
Reassembled: SEGMENT-A-DATASEGMENT-B-DATA

لاحظ أن macro_pdf_417_file_id هو عدد صحيح، وليس سلسلة، في كل من جانب الإنشاء والتعرف. كما أن نفس الكائن يعرض أيضًا macro_pdf_417_file_name وmacro_pdf_417_sender وmacro_pdf_417_addressee وmacro_pdf_417_time_stamp وmacro_pdf_417_checksum عندما يملأها المشفر.

قياس أداء التعرف على PDF417 على صورك الخاصة

اختيار الإعداد يجب أن يكون قياسًا، وليس تخمينًا. وجهه إلى مجلد يحتوي على لقطات تمثيلية من خط الأنابيب الفعلي الخاص بك وسيخبرك أي إعداد يبرر تكلفته:

import time, statistics, pathlib
from aspose.barcode import barcoderecognition as rec

PRESETS = ["high_performance", "normal_quality", "high_quality", "max_quality"]

def probe(path, preset, reps=3):
    times, found = [], False
    for _ in range(reps):
        reader = rec.BarCodeReader(str(path), rec.DecodeType.PDF417)
        reader.quality_settings = getattr(rec.QualitySettings, preset)
        start = time.perf_counter()
        results = list(reader.read_bar_codes())
        times.append((time.perf_counter() - start) * 1000)
        found = found or bool(results)
    return found, statistics.median(times)

for image in sorted(pathlib.Path("samples").glob("*.png")):
    row = []
    for preset in PRESETS:
        found, ms = probe(image, preset)
        row.append(f"{preset}: {'read' if found else 'miss'} {ms:.0f}ms")
    print(f"{image.name:28} " + " | ".join(row))
clean.png                    high_performance: read 32ms | normal_quality: read 48ms | high_quality: read 51ms | max_quality: read 130ms
faded_thermal.png            high_performance: read 26ms | normal_quality: read 43ms | high_quality: read 46ms | max_quality: read 144ms
half_resolution.png          high_performance: read 27ms | normal_quality: read 41ms | high_quality: read 41ms | max_quality: read 89ms
heavy_blur.png               high_performance: miss 7ms | normal_quality: miss 24ms | high_quality: miss 69ms | max_quality: miss 180ms
noisy_scan.png               high_performance: read 26ms | normal_quality: read 42ms | high_quality: read 47ms | max_quality: read 116ms
Page1.png                    high_performance: read 21ms | normal_quality: read 34ms | high_quality: read 38ms | max_quality: read 90ms
Page2.png                    high_performance: read 21ms | normal_quality: read 33ms | high_quality: read 38ms | max_quality: read 89ms
rotated.png                  high_performance: miss 16ms | normal_quality: read 43ms | high_quality: read 57ms | max_quality: read 147ms

قم بتشغيله مرة واحدة ضد خمسين لقطة حقيقية وسينتهي النقاش المسبق.

إرشادات عملية

  • قصر DecodeType على PDF417 ما لم تكن تتوقع حقًا رموزًا مختلطة. استخدم MACRO_PDF417، COMPACT_PDF417 أو MICRO_PDF417 عندما تعرف المتغير.
  • قم بالقص قبل فك الترميز. تمرير مسح كامل بحجم A4 عندما يشغل الباركود 5 ٪ منه يضيع وقت الكشف ويضيف سطحًا من الإيجابيات الزائفة.
  • احتفظ بالملفات الوسيطة بدون فقدان. PNG أو TIFF. تشويه JPEG عند إعدادات جودة منخفضة يهاجم بالضبط حواف الخط التي يحتاجها المفكك.
  • رتب محاولاتك بدلاً من الاعتماد على الإعداد المسبق الأبطأ.
  • قم بإصلاح الإنشاء قبل ضبط التعرف. إذا كنت تتحكم في المشفر، رفع x_dimension لا يكلف شيئًا ويحل المزيد من الأخطاء مقارنة بأي إعداد للقارئ. تغطي مقالة إنشاء PDF417 تلك المعلمات.
  • حدد timeout على أي قارئ يتعامل مع صور مقدمة من المستخدم.

احصل على ترخيص مجاني

إصدار التقييم يضيف علامة مائية على النص المفكوك للرموز غير Code 39، مما سيؤثر على أي اختبار ذهابًا وإيابًا تقوم به. ترخيص مؤقت مجاني يزيل ذلك في التقييم.

موارد إضافية مجانية

الخلاصة

قراءة الباركود PDF417 في بايثون هي عملية من سطرين على الصور النظيفة ومشكلة هندسية على الصور الحقيقية. تشير القياسات أعلاه إلى موقف بسيط: عيّن DecodeType الخاص بك، واجعل القيمة الافتراضية normal_quality، وأعد المحاولة مرة واحدة باستخدام high_quality وتمكين إلغاء التشويش، وتحقق من كل نتيجة قبل اتخاذ أي إجراء. احفظ الإعدادات المكلفة للمسار الاحتياطي، وعندما تفشل فئة كاملة من الصور في جميع الإعدادات، قم بإصلاح عملية الالتقاط بدلاً من القارئ. الأسئلة مرحب بها في منتدى الدعم المجاني.

الأسئلة المتكررة

  1. لماذا يتم قراءة نفس رمز PDF417 في صورة واحدة ويفشل في أخرى؟
    يعتمد التعرف على عدد البكسلات التي يشغلها كل وحدة بعد الالتقاط. الضبابية، تصغير الحجم، وضغط JPEG كلها تقلص عرض الوحدة الفعّال، ومتى ما انخفض عرض الوحدة إلى أقل من حوالي بكسلين نظيفين، لن يتمكن أي إعداد مسبق من استعادتها.

  2. أي إعداد مسبق للتعرف يجب أن أستخدمه لـ PDF417؟
    ابدأ بـ normal_quality، وهو الإعداد الافتراضي. انتقل إلى high_quality لالتقاطات الكاميرا والمسح، واحتفظ بـ max_quality لمرات إعادة المحاولة لأنه أبطأ عدة مرات دون أن يقرأ المزيد بشكل ملحوظ.

  3. هل تقييد DecodeType إلى PDF417 يجعل القراءة أسرع فعليًا؟
    نعم. الإعداد الافتراضي هو DecodeType.ALL_SUPPORTED_TYPES، الذي يشغّل الكاشف لكل الرموز المدعومة. تحديد PDF417 صراحةً يزيل هذا العمل ويزيل أيضًا احتمال الحصول على نتيجة إيجابية كاذبة من رمز آخر.

  4. هل يمكن لـ Aspose.BarCode قراءة رسالة Macro PDF417 مقسمة عبر عدة صور؟
    نعم. اقرأ كل جزء باستخدام DecodeType.MACRO_PDF417 واستخدم macro_pdf_417_file_id و macro_pdf_417_segment_id و macro_pdf_417_segments_count في النتيجة الموسعة لإعادة تجميع الحمولة بالترتيب.

  5. كيف يمكنني معرفة ما إذا كانت النتيجة المفكوكة موثوقة؟
    تحقق من reading_quality و confidence في BarCodeResult، واستخدم رباعية region لتأكيد أن الرمز الشريطي تم العثور عليه في الموقع المتوقع داخل الصورة.

  6. هل يمكنه قراءة PDF417 من صورة رخصة قيادة أو بطاقة صعود؟
    يمكنه ذلك، بشرط أن يكون الالتقاط واضحًا وأن الرمز الشريطي غير مقطوع. قص إلى منطقة الرمز الشريطي قبل القراءة، ويفضل استخدام PNG بدلاً من JPEG للملفات الوسيطة.

اقرأ المزيد