Vytvoření PDF417 čárového kódu vyžaduje čtyři řádky Pythonu. Čtení takového kódu z fotografie z telefonu, skenu s 200 DPI nebo palubní vstupenky, která strávila den v kapse někoho, je místo, kde začíná skutečná práce, a kde většina integrací PDF417 ve skutečnosti selhává. V tomto článku se naučíte, jak číst PDF417 čárové kódy v Pythonu, když je zdrojový obrázek nedokonalý. Pokud hledáte spíše generování, dřívější průvodce, jak generovat PDF417 čárové kódy pomocí Pythonu pokrývá vytváření základních a vlastních PDF417 symbolů, včetně řízení řádků a sloupců, a průvodce čtečkou čárových kódů v Pythonu pokrývá obecné skenování napříč symbologií. Následující část se zaměřuje úzce a hluboce na rozpoznávání PDF417.

Každý úryvek níže byl spuštěn proti Aspose.BarCode for Python via .NET 26.7 na Linuxu s Pythonem 3.12. Časy a výsledky čtení/špatných čtení jsou měřeny, nikoli odhadovány, a skript, který je vytvořil, je na konci, takže jej můžete znovu spustit na svých vlastních obrázcích.

Co ve skutečnosti narušuje rozpoznávání PDF417

PDF417 je vrstvená symbologie: řádky kódových slov, každé kódové slovo je vytvořeno ze čtyř pruhů a čtyř mezer, které zabírají 17 modulů. Tato struktura obsahuje korekci chyb Reed‑Solomon, takže roztrhaný roh nebo skvrna od kávy jsou obvykle přežitelné. Co není přežitelné, je ztráta samotné mřížky modulů.

Tři věci ničí mřížku, přibližně v pořadí, jak často se v produkci objevují:

  • Efektivní šířka modulu klesající pod dva pixely. Jedná se o hlavní selhání. K tomu dochází při zmenšování, při vzdálenosti kamery a při rozostření, které rozprostře inkoust jednoho modulu na jeho sousedy. Čárový kód vygenerovaný při třech pixelech na modul a poté rozostřený je funkčně čárový kód při jednom pixelu na modul.
  • Perspektiva a rotace. Čárový kód vyfocený pod úhlem má řádky, které již nejsou rovnoběžné se skenovacími čarami. Detektor to zvládne, ale vyžaduje to průchod detekcí, který nejrychlejší předvolba vynechává.
  • Kolaps kontrastu. Termální papír, který vybledl, obrazovka pořízená pod odleskem nebo sken s nastaveným jasem. Méně fatální, než to vypadá, jak ukazují níže uvedená čísla.

Praktickým důsledkem je, že nastavení rozpoznávání jsou mechanismus obnovy, nikoli náhrada za kvalitu zachycení. Vrací vám zpět střední pásmo kvality obrazu. Nevrací vám však spodní pásmo.

Nastavení čtečky PDF417 v Pythonu

Nainstalujte knihovnu z PyPI:

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

API pro rozpoznávání se nachází v aspose.barcode.barcoderecognition. Pro tento článek jsou důležité dvě třídy: BarCodeReader, která řídí detekci a dekódování, a QualitySettings, která určuje, jak moc se čtečce snaží.

Načtení PDF417 čárového kódu v Pythonu

Minimální použitelné čtení jsou dva argumenty a smyčka:

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)
Načíst čárový kód PDF417 v Pythonu.

Načíst čárový kód PDF417 v Pythonu.

Výstup na čistém obrázku:

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

Druhý argument není v praxi volitelný. Vynechejte jej a BarCodeReader se vrátí k DecodeType.ALL_SUPPORTED_TYPES, což spustí detekci více než šedesáti symbolů proti každému kandidátnímu regionu na obrázku. V pipeline pouze pro PDF417 je to čistá ztráta a otevírá to dveře pro falešně pozitivní lineární symbol v rámci struktury řádku PDF417. Uveďte typ.

Pokud váš vstup přichází jako bajty z nahrání místo souboru na disku, předávejte proud a nastavte časový limit, aby se patologický obrázek nemohl zaseknout pracovníka.

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

Porovnat nastavení kvality rozpoznávání PDF417 v Pythonu

QualitySettings nabízí čtyři předvolby, které stojí za to znát. Přiřazení jedné čteči je jediný řádek:

reader = rec.BarCodeReader("scan.png", rec.DecodeType.PDF417)
reader.quality_settings = rec.QualitySettings.high_quality
PresetIntended forCost
high_performanceČisté, strojově generované obrázkyNejrychlejší, vynechává opravy
normal_qualityVýchozí. Běžné skeny a exportyVyvážený
high_qualityZáběry z kamery, degradované skenyStřední
max_qualityOpakovaný průchod na obrázcích, které již selhalyNejpomalejší o velký rozdíl

Abych zjistil, co tyto popisy v praxi znamenají, vygeneroval jsem PDF417 se třemi pixely na modul, degradoval jej šesti způsoby pomocí Pillow a spustil každý přednastavený režim proti každé variantě. Medián ze tří běhů:

Zdrojový obrázekhigh_performancenormal_qualityhigh_qualitymax_quality
Čistýčtení, 35 msčtení, 50 msčtení, 45 msčtení, 106 ms
Otočený o 12°, rozmazanýneúspěch, 15 msčtení, 74 msčtení, 67 msčtení, 157 ms
Gaussovský šum (σ 40)čtení, 31 msčtení, 49 msčtení, 52 msčtení, 123 ms
Poloviční rozlišeníčtení, 22 msčtení, 37 msčtení, 35 msčtení, 86 ms
Nízký kontrastčtení, 24 msčtení, 38 msčtení, 43 msčtení, 112 ms
Silné rozmazání (σ 2.2)neúspěch, 5 msneúspěch, 25 msneúspěch, 85 msneúspěch, 180 ms

Ze této tabulky vyplývají čtyři věci a jsou užitečnější než jednotlivá čísla:

  1. Šum a nízký kontrast nejsou problém, jak si lidé myslí. Reed‑Solomon plus detektor absorbovaly silný gaussovský šum a snížení kontrastu o 82 % na nejrychlejším přednastavení. Přestaňte je ladit.
  2. Rotace plus rozmazání je případ, který odlišuje přednastavení. Je to také přesný profil zachycení z mobilního telefonu, což je důvod, proč high_performance je špatná výchozí hodnota pro jakýkoli pipeline pocházející z mobilu.
  3. max_quality stojí třikrát více času než normal_quality a nepřináší žádné další výhody. Zaslouží si místo jako cesta pro druhý pokus, ne jako výchozí.
  4. Jakmile je mřížka modulu pryč, žádné přednastavení ji neobnoví. Řádek s těžkým rozmazáním selhává ve všech případech a max_quality strávil 180 ms jeho dokazováním. Jedná se o problém zachycení s opravou zachycení: více pixelů, lepší ostrost, větší x_dimension v čase generování.

Ladění QualitySettings pro čtení rozmazaných čárových kódů PDF417 v Pythonu

Předvolba je balík jednotlivých vlastností a můžete začít s předvolbou a přepsat ji. Právě zde jsou skutečné výhody pro známý, opakovatelný defekt.

Výše otočený a rozmazaný obrázek je dobrým demonstračním příkladem. Pod high_performance to chybí. Povolte dekonvoluci na stejném přednastavení a zobrazí se:

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)
Nastavte QualitySettings pro čtení rozmazaných čárových kódů PDF417 v Pythonu.

Nastavte QualitySettings pro čtení rozmazaných čárových kódů PDF417 v Pythonu.

Měřeno: miss za 12 ms bez přepsání, čtení za 54 ms s ním. Jedna vlastnost změnila výsledek a výsledek byl stále rychlejší, než by byl při přednastavení max_quality.

Vlastnosti, které stojí za to znát:

VlastnostHodnotyKdy jej použít
deconvolutionFAST, NORMAL, SLOWRozmazání pohybu a snímky mimo ostrost
barcode_qualityHIGH, NORMAL, LOWTiskové vady, tepelný vyblednutí, faxové artefakty
x_dimensionAUTO, SMALL, NORMAL, LARGE, USE_MINIMAL_X_DIMENSIONHusté čárové kódy nebo pevná známá velikost modulu
minimal_x_dimensionfloatPoužijte spolu s USE_MINIMAL_X_DIMENSION k nastavení minimální hodnoty
complex_backgroundAUTO, DISABLED, ENABLEDČárový kód tištěný přes grafiku nebo vzorovaný formulář
inverse_imageAUTO, DISABLED, ENABLEDBílý na černém čárový kód, snímky obrazovky
allow_incorrect_barcodesboolPouze pro diagnostiku, nikdy pro produkci

Poslední z nich si zaslouží varování. allow_incorrect_barcodes vrací symboly, které neprošly kontrolou součtu. Jedná se o ladící pomůcku pro odpověď na otázku „detektor vůbec něco našel?“ Vydání toho znamená odeslání dekódovaných řetězců, které jsou špatné místo toho, aby chyběly, což je výrazně horší než jen vynechání.

Strategie vrstvení, která dobře funguje v produkci: nejprve vyzkoušejte normal_quality a při neúspěchu zkuste jednou high_quality plus deconvolution = SLOW. Nákladnou cestu platíte jen pro obrázky, které ji potřebují.

Ověření výsledků dekódování PDF417 v Pythonu

Dekódovaný řetězec není automaticky správný řetězec. Tři pole v BarCodeResult pomáhají:

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

Znovu sestavit makro PDF417 rozdělené na více obrázků

Macro PDF417 rozděluje jednu logickou zprávu na několik symbolů, což se objevuje v přepravních manifestech a vícestránkových dokumentech. Metadata segmentu přežívají během celého cyklu, takže opětovné sestavení je deterministické:

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

Strana 1.

Stránka 2.

Stránka 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

Všimněte si, že macro_pdf_417_file_id je celé číslo, nikoli řetězec, jak na straně generování, tak na straně rozpoznávání. Ten samý objekt také poskytuje macro_pdf_417_file_name, macro_pdf_417_sender, macro_pdf_417_addressee, macro_pdf_417_time_stamp a macro_pdf_417_checksum, pokud je enkodér naplnil.

Benchmark rozpoznávání PDF417 na vlastních obrázcích

Výběr předvolby by měl být měřením, ne odhadem. Ukazujte to na složku s reprezentativními zachyceními z vašeho skutečného pipeline a řekne vám, která předvolba si zaslouží svou cenu:

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

Spusťte to jednou proti padesáti skutečným zachycením a přednastavená debata končí.

Praktické pokyny

  • Omezte DecodeType na PDF417, pokud opravdu neočekáváte smíšené symboliky. Použijte MACRO_PDF417, COMPACT_PDF417 nebo MICRO_PDF417, když znáte variantu.
  • Ořízněte před dekódováním. Předání celého skenu A4, když čárový kód zabírá jen 5 % plochy, zbytečně prodlužuje čas detekce a přidává falešně pozitivní plochu.
  • Uchovávejte mezisouborů bezztrátově. PNG nebo TIFF. JPEG s nízkou kvalitou vytváří artefakty přesně na okrajích čáry, které dekodér potřebuje.
  • Rozvrhněte své pokusy místo toho, abyste se spolehli na nejpomalejší předvolbu.
  • Opravte generování před laděním rozpoznávání. Pokud řídíte enkodér, zvýšení x_dimension nic nestojí a řeší více chyb než jakékoli nastavení čtečky. Článek o generování PDF417 (Článek o generování PDF417) popisuje tyto parametry.
  • Nastavte timeout u každého čtečky, která pracuje s obrázky dodanými uživatelem.

Získejte bezplatnou licenci

Vyhodnocovací verze vkládá vodoznak do dekódovaného textu pro symbologie jiné než Code 39, což bude rušit jakékoli testování round‑trip, které provádíte. Bezplatná dočasná licence to pro vyhodnocování odstraní.

Bezplatné další zdroje

Závěr

Čtení čárových kódů PDF417 v Pythonu je dvouřádková operace na čistých obrázcích a inženýrský problém na reálných. Výše uvedená měření ukazují na jednoduchý přístup: pojmenujte svůj DecodeType, výchozí nastavení normal_quality, jednou zopakujte s high_quality a povolenou dekonvolucí a ověřte každý výsledek, než s ním něco uděláte. Uložte nákladné předvolby pro cestu opakování a když celá třída obrázků selže při každém nastavení, opravte zachycení místo čtečky. Otázky jsou vítány na bezplatném fóru podpory.

Často kladené otázky

  1. Proč se stejný PDF417 čárový kód načte na jednom obrázku a na jiném selže?
    Rozpoznávání závisí na tom, kolik pixelů každý modul zabírá po zachycení. Rozmazání, zmenšení rozlišení a JPEG komprese všechny zmenšují efektivní šířku modulu a jakmile modul klesne pod přibližně dva čisté pixely, žádné přednastavení jej neobnoví.

  2. Jaké přednastavení rozpoznávání mám pro PDF417 použít?
    Začněte s normal_quality, což je výchozí nastavení. Přepněte na high_quality pro snímky z kamery a skeny a max_quality si nechte na opakované průchody, protože je několikanásobně pomalejší a nepřináší podstatně více výsledků.

  3. Zda omezení DecodeType na PDF417 skutečně zrychlí čtení?
    Ano. Výchozí hodnota je DecodeType.ALL_SUPPORTED_TYPES, která spouští detektor pro každou podporovanou symbologii. Výslovné určení PDF417 toto zpracování odstraní a také eliminuje možnost falešného pozitivního výsledku z jiné symbologie.

  4. Dokáže Aspose.BarCode přečíst zprávu Macro PDF417 rozdělenou do několika obrázků?
    Ano. Přečtěte každý segment pomocí DecodeType.MACRO_PDF417 a použijte macro_pdf_417_file_id, macro_pdf_417_segment_id a macro_pdf_417_segments_count v rozšířeném výsledku k sestavení payloadu v správném pořadí.

  5. Jak zjistím, zda lze dekódovaný výsledek důvěřovat?
    Zkontrolujte reading_quality a confidence v objektu BarCodeResult a použijte čtyřúhelník region k potvrzení, že čárový kód byl nalezen na očekávaném místě v obrázku.

  6. Dokáže číst PDF417 z fotografie řidičského průkazu nebo palubní vstupenky?
    Ano, pokud je zachycení zaostřené a čárový kód není oříznutý. Před čtením ořízněte oblast čárového kódu a pro mezisouboru upřednostněte PNG před JPEG.

Číst dál