Att generera en PDF417‑streckkod kräver fyra rader Python. Att läsa tillbaka en sådan från ett foto på telefonen, en 200 DPI‑skanning eller ett boardingkort som har tillbringat en dag i någons ficka är där det verkliga arbetet börjar, och det är där de flesta PDF417‑integrationer faktiskt misslyckas. I den här artikeln kommer du att lära dig hur du läser PDF417‑streckkoder i Python när källbilden är bristfällig. Om du istället är intresserad av genereringssidan, täcker den tidigare genomgången om hur man genererar PDF417‑streckkoder med Python skapandet av grundläggande och anpassade PDF417‑symboler, inklusive rad‑ och kolumnkontroll, och Python‑streckkodsläsarguiden täcker allmän scanning över olika symboler. Det som följer här går på djupet och smalt på PDF417‑igenkänning.

Varje kodsnutt nedan kördes mot Aspose.BarCode for Python via .NET 26.7 på Linux med Python 3.12. Tiderna och läs-/missresultaten är mätta, inte uppskattade, och skriptet som skapade dem finns i slutet så att du kan köra om det på dina egna bilder.

Vad som faktiskt stör PDF417-igenkänning

PDF417 är en staplad symbologi: rader av kodord, där varje kodord byggs av fyra streck och fyra mellanslag som sträcker sig över 17 moduler. Den strukturen innehåller Reed‑Solomon‑felkorrigering, så ett slitet hörn eller en kaffefläck är vanligtvis överlevande. Vad som inte är överlevande är att förlora själva modulgittret.

Tre saker förstör rutnätet, i ungefärlig ordning efter hur ofta de dyker upp i produktion:

  • Effektiv modulbredd som faller under två pixlar. Detta är det dominerande felet. Det sker genom nedskalning, genom kamerans avstånd och genom oskärpa, som sprider en moduls bläck över dess grannar. En streckkod som genereras med tre pixlar per modul och sedan oskärpas är i praktiken en streckkod med en pixel per modul.
  • Perspektiv och rotation. En streckkod som fotograferas i en vinkel har rader som inte längre är parallella skanningslinjer. Detektorn hanterar detta, men det kräver ett detekteringspass som det snabbaste förinställningen hoppar över.
  • Kontrastkollaps. Termiskt papper som har bleknat, en skärm fotograferad under bländning eller en skanning med ljusstyrkan låst. Mindre allvarligt än det ser ut, som siffrorna nedan visar.

Den praktiska konsekvensen är att igenkänningsinställningarna är en återhämtningsmekanism, inte en ersättning för fångstkvalitet. De köper tillbaka den mellersta delen av bildkvaliteten. De köper inte tillbaka den lägsta.

Ställ in Python PDF417-läsaren

Installera biblioteket från PyPI:

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

Recognition‑API:t finns i aspose.barcode.barcoderecognition. Två klasser är relevanta för den här artikeln: BarCodeReader, som driver detektering och avkodning, och QualitySettings, som styr hur hårt läsaren försöker.

Läs en PDF417‑streckkod i Python

Den minsta livskraftiga läsningen är två argument och en loop:

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)
Läs en PDF417-streckkod i Python.

Läs en PDF417-streckkod i Python.

Utdata på en ren bild:

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

Det andra argumentet är i praktiken inte valfritt. Utelämna det så återgår BarCodeReader till DecodeType.ALL_SUPPORTED_TYPES, vilket kör detektering för mer än sextio symboler mot varje kandidatregion i bilden. På en pipeline som bara hanterar PDF417 är det ren slöseri, och det öppnar dörren för ett falskt positivt resultat för en linjär symbolik inom PDF417‑radstrukturen. Ange typen.

Om ditt indata kommer som bytes från en uppladdning snarare än en fil på disk, skicka en ström och ange en tidsgräns så att en patologisk bild inte kan stoppa en arbetare:

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

Jämför PDF417 igenkänningskvalitetsinställningar i Python

QualitySettings levereras med fyra förinställningar som är värda att känna till. Att tilldela en till läsaren är en enda rad:

reader = rec.BarCodeReader("scan.png", rec.DecodeType.PDF417)
reader.quality_settings = rec.QualitySettings.high_quality
FörinställningAvsedd förKostnad
high_performanceRena, maskin-genererade bilderSnabbast, hoppar över återhämtningspass
normal_qualityStandard. Vanliga skanningar och exportBalanserad
high_qualityKamerabilder, försämrade skanningarMåttlig
max_qualityOmförsökspass på bilder som redan misslyckatsLångsammast med stor marginal

För att ta reda på vad de beskrivningarna betyder i praktiken genererade jag en PDF417 med tre pixlar per modul, försämrade den på sex sätt med Pillow och körde varje förinställning mot varje variant. Median av tre körningar:

Källa bildhigh_performancenormal_qualityhigh_qualitymax_quality
Renläst, 35 msläst, 50 msläst, 45 msläst, 106 ms
Roterad 12°, suddigmiss, 15 msläst, 74 msläst, 67 msläst, 157 ms
Gaussiskt brus (σ 40)läst, 31 msläst, 49 msläst, 52 msläst, 123 ms
Halv upplösningläst, 22 msläst, 37 msläst, 35 msläst, 86 ms
Låg kontrastläst, 24 msläst, 38 msläst, 43 msläst, 112 ms
Stark oskärpa (σ 2.2)miss, 5 msmiss, 25 msmiss, 85 msmiss, 180 ms

Fyra saker faller ut ur den här tabellen, och de är mer användbara än de enskilda siffrorna:

  1. Brus och låg kontrast är inte det problem som folk tror att de är. Reed-Solomon plus detektorn absorberade tungt Gaussiskt brus och en 82 % kontrastminskning på den snabbaste förinställningen. Sluta finjustera för dessa.
  2. Rotation plus suddighet är fallet som skiljer förinställningarna åt. Det är också den exakta profilen för en handhållen telefonupptagning, vilket är anledningen till att high_performance är fel standard för någon mobilkälla pipeline.
  3. max_quality kostade tre gånger så lång tid som normal_quality och läste inget extra. Den förtjänar sin plats som en andra‑försök‑väg, inte som standard.
  4. När modulgittret är borta återställer ingen förinställning det. Den tunga suddighetsraden är ett misslyckande över hela linjen, och max_quality spenderade 180 ms på att bevisa det. Det är ett fångstproblem med en fångstlösning: fler pixlar, bättre fokus, större x_dimension vid genereringstid.

Justera QualitySettings för att läsa suddiga PDF417-streckkoder i Python

En förinställning är ett paket av enskilda egenskaper, och du kan börja med en förinställning och åsidosätta en. Det är här de verkliga vinsterna finns för ett känt, upprepningsbart fel.

Den roterade‑och‑suddiga bilden ovan är en bra demonstration. Under high_performance missar den. Aktivera dekonvolution ovanpå samma förinställning så läser den:

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)
Justera QualitySettings för att läsa suddiga PDF417-streckkoder i Python.

Justera QualitySettings för att läsa suddiga PDF417-streckkoder i Python.

Mätt: miss i 12 ms utan överskrivning, läst i 54 ms med den. En egenskap vände resultatet, och resultatet kom fortfarande tillbaka snabbare än vad max_quality‑förinställningen skulle ha gjort.

Egenskaperna som är värda att känna till:

EgenskapVärdenNär du bör använda den
deconvolutionFAST, NORMAL, SLOWRörelseoskärpa och bilder med fel fokus
barcode_qualityHIGH, NORMAL, LOWUtskriftsdefekter, termisk blekning, faxartefakter
x_dimensionAUTO, SMALL, NORMAL, LARGE, USE_MINIMAL_X_DIMENSIONTäta streckkoder, eller en fast känd modulstorlek
minimal_x_dimensionfloatKombinera med USE_MINIMAL_X_DIMENSION för att ange ett minimum
complex_backgroundAUTO, DISABLED, ENABLEDStreckkod tryckt över grafik eller ett mönstrat formulär
inverse_imageAUTO, DISABLED, ENABLEDVitt‑på‑svart streckkoder, skärmbilder
allow_incorrect_barcodesboolEndast för diagnostik, aldrig i produktion

Den sista förtjänar en varning. allow_incorrect_barcodes returnerar symboler som misslyckades med kontrollsummavalidering. Det är ett felsökningshjälpmedel för att besvara “hittade detektorn ens något här?” Att leverera det betyder att leverera avkodade strängar som är felaktiga snarare än frånvarande, vilket är strikt sämre än ett miss.

En nivåstrategi som fungerar bra i produktion: prova normal_quality först, och vid ett missförsök försök en gång till med high_quality plus deconvolution = SLOW. Du betalar den dyra vägen endast för de bilder som behöver det.

Validera PDF417‑avkodningsresultat i Python

En avkodad sträng är inte automatiskt en korrekt sträng. Tre fält på BarCodeResult hjälper:

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

Sätt ihop ett Macro PDF417 som är uppdelat över bilder

Macro PDF417 delar upp ett logiskt meddelande över flera symboler, vilket visas i fraktmanifest och flersidiga dokument. Segmentmetadata överlever rundresan, så återmontering är deterministisk:

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

Sida 1.

Sida 2.

Sida 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

Observera att macro_pdf_417_file_id är ett heltal, inte en sträng, både på genererings- och igenkänningssidan. Samma objekt exponerar också macro_pdf_417_file_name, macro_pdf_417_sender, macro_pdf_417_addressee, macro_pdf_417_time_stamp och macro_pdf_417_checksum när kodaren har fyllt i dem.

Benchmark PDF417-igenkänning på dina egna bilder

Förinställningsvalet bör vara en mätning, inte en gissning. Peka detta på en mapp med representativa fångster från din faktiska pipeline så kommer den att berätta vilken förinställning som förtjänar sin kostnad:

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

Kör det en gång mot femtio riktiga inspelningar och den förinställda debatten avslutas.

Praktiska riktlinjer

  • Begränsa DecodeType till PDF417 om du inte verkligen förväntar dig blandade symbologier. Använd MACRO_PDF417, COMPACT_PDF417 eller MICRO_PDF417 när du känner till varianten.
  • Beskär innan du avkodar. Att skicka en hel A4‑skanning när streckkoden bara upptar 5 % av den slösar bort upptäcktstid och ger falska positiva resultat.
  • Behåll mellanliggande filer förlustfritt. PNG eller TIFF. JPEG‑ringning vid låg kvalitet angriper exakt de streckkantskanter som avkodaren behöver.
  • Dela upp dina omförsök istället för att alltid använda den långsammaste förinställningen.
  • Fixa genereringen innan du finjusterar igenkänningen. Om du styr kodaren, kostar det inget att öka x_dimension och löser fler missar än någon läsarinställning. Artikeln om PDF417‑generering (PDF417‑genereringsartikel) täcker dessa parametrar.
  • Ange timeout på alla läsare som hanterar användargenererade bilder.

Få en gratis licens

Utvärderingsversionen vattenmärker avkodad text för symbologier förutom Code 39, vilket kan störa all rundresetestning du utför. En gratis tillfällig licens tar bort detta för utvärdering.

Gratis ytterligare resurser

Slutsats

Att läsa PDF417‑streckkoder i Python är en två‑radig operation på rena bilder och ett ingenjörsproblem på riktiga bilder. Mätningarna ovan pekar på en enkel strategi: namnge din DecodeType, standardvärdet normal_quality, försök igen en gång med high_quality och dekonvolution aktiverad, och validera varje resultat innan du agerar på det. Spara de dyra förinställningarna för återförsökspåret, och när en hel klass av bilder misslyckas med varje inställning, fixa inspelningen istället för läsaren. Frågor är välkomna på det gratis supportforumet.

FAQs

  1. Varför läses samma PDF417-streckkod i en bild men misslyckas i en annan?
    Upptäckten beror på hur många pixlar varje modul upptar efter inspelning. Oskärpa, nedskalning och JPEG‑komprimering minskar alla den effektiva modulbredden, och när en modul faller under ungefär två rena pixlar kan ingen förinställning återställa den.

  2. Vilken igenkänningsförinställning bör jag använda för PDF417?
    Börja med normal_quality, som är standard. Byt till high_quality för kamerainspelningar och skanningar, och reservera max_quality för omförsök eftersom den är flera gånger långsammare utan att läsa avsevärt mer.

  3. Gör det att begränsa DecodeType till PDF417 faktiskt läsningen snabbare?
    Ja. Standardvärdet är DecodeType.ALL_SUPPORTED_TYPES, vilket kör detektorn för varje stödd symbolik. Att explicit ange PDF417 tar bort det arbetet och eliminerar även risken för falskt positivt resultat från en annan symbolik.

  4. Kan Aspose.BarCode läsa ett Macro PDF417-meddelande som är uppdelat över flera bilder?
    Ja. Läs varje segment med DecodeType.MACRO_PDF417 och använd macro_pdf_417_file_id, macro_pdf_417_segment_id och macro_pdf_417_segments_count i det utökade resultatet för att återmontera nyttolasten i rätt ordning.

  5. Hur vet jag om ett avkodat resultat är pålitligt?
    Kontrollera reading_quality och confidence på BarCodeResult, och använd region‑fyrkanten för att bekräfta att streckkoden hittades där du förväntade dig den i bilden.

  6. Kan den läsa PDF417 från ett foto av ett körkort eller boardingpass?
    Den kan, förutsatt att inspelningen är i fokus och att streckkoden inte är avklippt. Beskär till streckkodsområdet innan läsning, och föredra PNG framför JPEG för mellanfiler.

Läs mer