تولید یک بارکد PDF417 تنها با چهار خط پایتون انجام می‌شود. خواندن آن از یک عکس گوشی، اسکن 200 DPI یا بلیط پروازی که یک روز در جیب کسی بوده است، جایی است که کار واقعی آغاز می‌شود و جایی که اکثر ادغام‌های PDF417 در واقع شکست می‌خورند. در این مقاله، خواهید آموخت که چگونه بارکدهای PDF417 را در پایتون بخوانید وقتی تصویر منبع ناقص است. اگر به جای این به سمت تولید علاقه‌مندید، راهنمای قبلی دربارهٔ تولید بارکدهای PDF417 با استفاده از پایتون به ایجاد نمادهای پایه و سفارشی PDF417، از جمله کنترل ردیف و ستون می‌پردازد، و راهنمای خواننده بارکد پایتون اسکن عمومی در میان سمبولولوژی‌ها را پوشش می‌دهد. آنچه در ادامه می‌آید، به صورت دقیق و عمیق به تشخیص PDF417 می‌پردازد.

هر قطعه کد زیر بر روی Aspose.BarCode for Python via .NET 26.7 در لینوکس با Python 3.12 اجرا شد. زمان‌بندی‌ها و نتایج خواندن/از دست رفتن به‌صورت اندازه‌گیری شده‌اند، نه تخمین زده شده، و اسکریپتی که آن‌ها را تولید کرده در انتها قرار دارد تا بتوانید آن را بر روی تصاویر خودتان دوباره اجرا کنید.

چه چیزی در واقع تشخیص PDF417 را خراب می‌کند

PDF417 یک نمادگذاری لایه‌ای است: ردیف‌هایی از کدواژه‌ها، هر کدواژه از چهار نوار و چهار فضای بین آن ساخته شده است که در مجموع ۱۷ ماژول را پوشش می‌دهد. این ساختار تصحیح خطای رید‑سولومون را به همراه دارد، بنابراین یک گوشه پاره یا لکه قهوه‌ای معمولاً قابل تحمل است. چیزی که قابل تحمل نیست، از دست دادن خود شبکه ماژول‌ها است.

سه چیز شبکه را از بین می‌برند، به ترتیب تقریبی فراوانی که در تولید ظاهر می‌شوند:

  • عرض مؤثر ماژول که به زیر دو پیکسل می‌افتد. این شکست غالب است. این اتفاق از طریق کاهش مقیاس، از طریق فاصله دوربین و از طریق تاری رخ می‌دهد که جوهر یک ماژول را به همسایگانش پخش می‌کند. یک بارکد که با سه پیکسل برای هر ماژول تولید شده و سپس تار می‌شود، عملاً یک بارکد با یک پیکسل برای هر ماژول است.
  • پرسپکتیو و چرخش. یک بارکد که از زاویه‌ای عکاسی شده باشد، ردیف‌هایی دارد که دیگر خطوط اسکن موازی نیستند. تشخیص‌دهنده این را مدیریت می‌کند، اما هزینه یک عبور تشخیص را دارد که پیش‌تنظیم سریع‌ترین آن را نادیده می‌گیرد.
  • فروپاشی کنتراست. کاغذ حرارتی که رنگ‌پریده است، صفحه‌ای که تحت تابش نور مستقیم عکاسی شده یا اسکن با روشنایی ثابت. کمتر از آنچه به نظر می‌رسد خطرناک است، همان‌طور که اعداد زیر نشان می‌دهند.

نتیجه عملی این است که تنظیمات تشخیص یک مکانیزم بازیابی هستند، نه جایگزینی برای کیفیت ضبط. آن‌ها نوار میانی کیفیت تصویر را برای شما باز می‌گردانند. آن‌ها بخش پایین را باز نمی‌گردانند.

راه‌اندازی خواننده PDF417 پایتون

کتابخانه را از PyPI نصب کنید:

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

API تشخیص در 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 تنظیم کنید تا یک تصویر پاتولوژیک نتواند یک worker را متوقف کند:

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 در پایتون

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 به‌همراه آشکارساز، نویز گوسی سنگین و کاهش ۸۲٪ کنتراست در سریع‌ترین پیش‌تنظیم را جذب کردند. برای این‌ها تنظیم را متوقف کنید.

  2. چرخش به‌همراه تاری موردی است که پیش‌تنظیم‌ها را از هم جدا می‌کند. همچنین این دقیقاً نمایهٔ یک ضبط با تلفن دستی است، به همین دلیل high_performance پیش‌فرض اشتباهی برای هر خط لوله منبع موبایل است.

  3. max_quality سه برابر زمان normal_quality هزینه دارد و هیچ اطلاعات اضافی نمی‌خواند. این گزینه به‌عنوان مسیر دومین تلاش ارزش دارد، نه به‌عنوان پیش‌فرض.

  4. هنگامی که شبکهٔ ماژول از بین می‌رود، هیچ پیش‌تنظیمی آن را بازیابی نمی‌کند. ردیف تاری سنگین در تمام موارد یک خطا است، و max_quality برای اثبات آن ۱۸۰ میلی‌ثانیه صرف کرد. این یک مشکل ضبط است که با رفع ضبط قابل حل است: پیکسل‌های بیشتر، فوکوس بهتر، x_dimension بزرگ‌تر در زمان تولید.

تنظیم QualitySettings برای خواندن بارکدهای PDF417 تار در Python

یک پیش‌تنظیم مجموعه‌ای از ویژگی‌های فردی است و می‌توانید از یک پیش‌تنظیم شروع کنید و یکی را بازنویسی کنید. این جایی است که مزایای واقعی برای یک نقص شناخته‌شده و قابل تکرار به‌دست می‌آید.

تصویر چرخیده و تار شده بالا یک نمایش خوب است. تحت high_performance این مورد از دست می‌رود. فعال‌سازی دی‌کانولوشن بر روی همان پیش‌تنظیم، متن زیر را می‌دهد:

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 تار در پایتون.

اندازه‌گیری شد: بدون بازنویسی ۱۲ ms زمان از دست رفت، با آن ۵۴ ms زمان خوانده شد. یک ویژگی نتیجه را معکوس کرد و هنوز نتیجه سریع‌تر از پیش‌تنظیم 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 در Python

یک رشتهٔ رمزگشایی‌شده به‌طور خودکار یک رشتهٔ صحیح نیست. سه فیلد در 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.

صفحه ۲.

صفحه ۲.

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 ترجیح دهید.

بیشتر بخوانید