Das Erzeugen eines PDF417‑Barcodes erfordert vier Zeilen Python. Das Auslesen eines solchen aus einem Foto vom Handy, einem 200 DPI‑Scan oder einer Bordkarte, die einen Tag in jemandes Tasche verbracht hat, ist der Punkt, an dem die eigentliche Arbeit beginnt, und wo die meisten PDF417‑Integrationen tatsächlich scheitern. In diesem Artikel erfahren Sie, wie Sie PDF417‑Barcodes in Python lesen, wenn das Quellbild nicht perfekt ist. Wenn Sie stattdessen die Erzeugungsseite suchen, behandelt der frühere Leitfaden, wie man PDF417‑Barcodes mit Python erzeugt erstellt, das Erstellen von grundlegenden und benutzerdefinierten PDF417‑Symbolen, einschließlich Zeilen‑ und Spaltensteuerung, und der Python‑Barcode‑Reader‑Leitfaden behandelt das allgemeine Scannen über verschiedene Symbolarten hinweg. Was hier folgt, geht eng und tief auf die PDF417‑Erkennung ein.

Jeder untenstehende Codeabschnitt wurde mit Aspose.BarCode for Python via .NET 26.7 unter Linux mit Python 3.12 ausgeführt. Die Zeiten sowie die Lese‑/Fehlergebnisse sind gemessen, nicht geschätzt, und das Skript, das sie erzeugt hat, befindet sich am Ende, sodass Sie es mit Ihren eigenen Bildern erneut ausführen können.

Was tatsächlich die PDF417‑Erkennung beeinträchtigt

PDF417 ist eine gestapelte Symbolik: Reihen von Codewörtern, wobei jedes Codewort aus vier Balken und vier Leerzeichen besteht, die 17 Module umfassen. Diese Struktur enthält Reed‑Solomon-Fehlerkorrektur, sodass eine gerissene Ecke oder ein Kaffeefleck in der Regel überlebbar ist. Was nicht überlebbar ist, ist der Verlust des Modulrasters selbst.

Drei Dinge zerstören das Raster, in grober Reihenfolge ihrer Häufigkeit in der Produktion:

  • Effektive Modulbreite unter zwei Pixel fallend. Dies ist das dominierende Versagen. Es tritt durch Herunterskalieren, durch Kameradistanz und durch Unschärfe auf, die die Tinte eines Moduls über seine Nachbarn verteilt. Ein Barcode, der mit drei Pixeln pro Modul erzeugt und dann unscharf gemacht wird, ist funktional ein Barcode mit einem Pixel pro Modul.
  • Perspektive und Drehung. Ein Barcode, der aus einem Winkel fotografiert wird, hat Reihen, die nicht mehr parallel zu den Scanlinien sind. Der Detektor verarbeitet dies, aber es kostet einen Detektionsdurchlauf, den das schnellste Preset überspringt.
  • Kontrastzusammenbruch. Thermopapier, das verblasst ist, ein Bildschirm, der unter Blendung fotografiert wurde, oder ein Scan mit festgelegter Helligkeit. Weniger fatal, als es aussieht, wie die untenstehenden Zahlen zeigen.

Die praktische Konsequenz ist, dass Erkennungseinstellungen ein Wiederherstellungsmechanismus und kein Ersatz für die Aufnahmequalität sind. Sie holen die mittlere Qualitätsstufe des Bildes zurück. Die untere Stufe wird nicht zurückgeholt.

Einrichten des Python PDF417 Readers

Installieren Sie die Bibliothek von PyPI:

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

Die Erkennungs‑API befindet sich in aspose.barcode.barcoderecognition. Zwei Klassen sind für diesen Artikel wichtig: BarCodeReader, der die Erkennung und Dekodierung steuert, und QualitySettings, die festlegt, wie intensiv der Leser arbeitet.

PDF417-Barcode in Python lesen

Der minimal funktionsfähige Lesevorgang besteht aus zwei Argumenten und einer Schleife:

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)
Lesen Sie einen PDF417-Barcode in Python.

Lesen Sie einen PDF417-Barcode in Python.

Ausgabe auf einem sauberen Bild:

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

Das zweite Argument ist in der Praxis nicht optional. Lassen Sie es weg und BarCodeReader greift auf DecodeType.ALL_SUPPORTED_TYPES zurück, was die Erkennung von mehr als sechzig Symbolen für jede Kandidatenregion im Bild ausführt. In einer reinen PDF417‑Pipeline ist das reine Verschwendung und öffnet die Tür zu einem linearen Symbol‑False‑Positive innerhalb der PDF417‑Zeilenstruktur. Nennen Sie den Typ.

Wenn Ihre Eingabe als Bytes von einem Upload und nicht als Datei auf der Festplatte ankommt, übergeben Sie einen Stream und setzen Sie ein Timeout, damit ein pathologisches Bild keinen Worker blockieren kann:

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

Vergleichen Sie die PDF417‑Erkennungsqualitäts‑Einstellungen in Python

QualitySettings liefert vier Presets, die es zu kennen gilt. Das Zuweisen eines Presets an den Reader erfolgt in einer einzigen Zeile:

reader = rec.BarCodeReader("scan.png", rec.DecodeType.PDF417)
reader.quality_settings = rec.QualitySettings.high_quality
VorgabeZweckKosten
high_performanceSaubere, maschinell erzeugte BilderSchnellste, überspringt Wiederherstellungsdurchläufe
normal_qualityStandard. Regelmäßige Scans und ExporteAusgewogen
high_qualityKameraaufnahmen, degradierte ScansMäßig
max_qualityErneuter Durchlauf bei Bildern, die bereits fehlgeschlagen sindLangsamste bei weitem

Um herauszufinden, was diese Beschreibungen in der Praxis bedeuten, habe ich ein PDF417 mit drei Pixeln pro Modul erzeugt, es auf sechs Arten mit Pillow verschlechtert und jede Voreinstellung gegen jede Variante ausgeführt. Median von drei Durchläufen:

Quellbildhigh_performancenormal_qualityhigh_qualitymax_quality
Saubergelesen, 35 msgelesen, 50 msgelesen, 45 msgelesen, 106 ms
Um 12° gedreht, unscharfverpasst, 15 msgelesen, 74 msgelesen, 67 msgelesen, 157 ms
Gaußsches Rauschen (σ 40)gelesen, 31 msgelesen, 49 msgelesen, 52 msgelesen, 123 ms
Halbe Auflösunggelesen, 22 msgelesen, 37 msgelesen, 35 msgelesen, 86 ms
Niedriger Kontrastgelesen, 24 msgelesen, 38 msgelesen, 43 msgelesen, 112 ms
Starke Unschärfe (σ 2.2)verpasst, 5 msverpasst, 25 msverpasst, 85 msverpasst, 180 ms

Vier Dinge ergeben sich aus dieser Tabelle, und sie sind nützlicher als die einzelnen Zahlen:

  1. Rauschen und geringer Kontrast sind nicht das Problem, das die Leute denken. Reed‑Solomon plus der Detektor absorbierten starkes Gaußsches Rauschen und eine 82 %ige Kontrastreduktion beim schnellsten Preset. Stoppen Sie das Tuning dafür.
  2. Rotation plus Unschärfe ist der Fall, der die Presets trennt. Es ist auch das genaue Profil einer Aufnahme mit einem Handheld‑Telefon, weshalb high_performance die falsche Vorgabe für jede mobil‑bezogene Pipeline ist.
  3. max_quality kostet das Dreifache der Zeit von normal_quality und liest nichts zusätzlich. Es verdient seinen Platz als Zweitversuch‑Pfad, nicht als Vorgabe.
  4. Sobald das Modulraster weg ist, stellt kein Preset es wieder her. Die Zeile mit starker Unschärfe ist überall ein Fehlgriff, und max_quality verbrachte 180 ms, um das zu beweisen. Das ist ein Aufnahmeproblem mit einer Aufnahme‑Lösung: mehr Pixel, besserer Fokus, größerer x_dimension zur Erzeugungszeit.

QualitySettings anpassen, um unscharfe PDF417-Barcodes in Python zu lesen

Ein Preset ist ein Bündel einzelner Eigenschaften, und Sie können von einem Preset ausgehen und eines überschreiben. Hier liegen die echten Vorteile für einen bekannten, wiederholbaren Defekt.

Das oben rotierte und verschwommene Bild ist eine gute Demonstration. Unter high_performance fehlt es. Aktivieren Sie die Deconvolution über dieselbe Voreinstellung und es lautet:

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)
Stellen Sie QualitySettings ein, um unscharfe PDF417-Barcodes in Python zu lesen.

Stellen Sie QualitySettings ein, um unscharfe PDF417-Barcodes in Python zu lesen.

Gemessen: Miss in 12 ms ohne die Überschreibung, Lesen in 54 ms damit. Eine Eigenschaft drehte das Ergebnis um, und das Ergebnis kam immer noch schneller zurück als das max_quality‑Preset es getan hätte.

Die Eigenschaften, die es zu kennen gilt:

EigenschaftWerteWann es zu verwenden ist
deconvolutionFAST, NORMAL, SLOWBewegungsunschärfe und unscharfe Aufnahmen
barcode_qualityHIGH, NORMAL, LOWDruckfehler, thermisches Verblassen, Fax-Artefakte
x_dimensionAUTO, SMALL, NORMAL, LARGE, USE_MINIMAL_X_DIMENSIONDichte Barcodes oder eine feste, bekannte Modulgröße
minimal_x_dimensionfloatZusammen mit USE_MINIMAL_X_DIMENSION verwenden, um eine Untergrenze festzulegen
complex_backgroundAUTO, DISABLED, ENABLEDBarcode, der über Kunstwerken oder einem gemusterten Formular gedruckt wird
inverse_imageAUTO, DISABLED, ENABLEDWeiße‑auf‑schwarze Barcodes, Bildschirmaufnahmen
allow_incorrect_barcodesboolNur für Diagnosen, niemals in der Produktion

Das Letzte verdient eine Warnung. allow_incorrect_barcodes gibt Symbole zurück, die die Prüfsummenvalidierung nicht bestanden haben. Es ist ein Debugging‑Hilfsmittel, um die Frage zu beantworten „hat der Detektor hier überhaupt etwas gefunden?“. Das Ausliefern bedeutet, dekodierte Zeichenketten zu liefern, die falsch sind, anstatt zu fehlen, was eindeutig schlechter ist als ein Fehlen.

Eine Stufungsstrategie, die in der Produktion gut funktioniert: Versuchen Sie zuerst normal_quality und bei einem Fehlschlag einmal mit high_quality plus deconvolution = SLOW erneut. Sie zahlen den teuren Pfad nur für die Bilder, die ihn benötigen.

Validieren der PDF417-Dekodierungsergebnisse in Python

Ein dekodierter String ist nicht automatisch ein korrekter String. Drei Felder in BarCodeResult helfen:

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

Zusammenführen eines Macro PDF417, das über mehrere Bilder verteilt ist

Macro PDF417 teilt eine logische Nachricht über mehrere Symbole auf, was sich in Versandlisten und mehrseitigen Dokumenten zeigt. Die Segmentmetadaten überleben die Rundreise, sodass die Wiederzusammenstellung deterministisch ist:

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

Seite 1.

Seite 2.

Seite 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

Beachten Sie, dass macro_pdf_417_file_id ein Integer und kein String ist, sowohl auf der Erstellungs‑ als auch auf der Erkennungsseite. Das gleiche Objekt stellt außerdem macro_pdf_417_file_name, macro_pdf_417_sender, macro_pdf_417_addressee, macro_pdf_417_time_stamp und macro_pdf_417_checksum bereit, wenn der Encoder sie befüllt hat.

Benchmark PDF417-Erkennung mit Ihren eigenen Bildern

Die Auswahl des Presets sollte eine Messung sein, nicht ein Schätzwert. Zeigen Sie dies auf einen Ordner mit repräsentativen Aufnahmen aus Ihrer tatsächlichen Pipeline, und es wird Ihnen sagen, welches Preset seine Kosten rechtfertigt:

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

Führen Sie es einmal gegen fünfzig echte Aufnahmen aus und die voreingestellte Debatte endet.

Praktische Richtlinien

  • Beschränken Sie DecodeType auf PDF417, es sei denn, Sie erwarten tatsächlich gemischte Symbologien. Verwenden Sie MACRO_PDF417, COMPACT_PDF417 oder MICRO_PDF417, wenn Sie die Variante kennen.
  • Zuschneiden, bevor Sie dekodieren. Das Übergeben eines kompletten A4-Scans, wenn der Barcode nur 5 % davon einnimmt, verschwendet Erkennungszeit und erzeugt falsche Positive.
  • Behalten Sie Zwischendateien verlustfrei. PNG oder TIFF. JPEG-Ringing bei niedrigen Qualitätsstufen greift genau die Balkenkanten an, die der Decoder benötigt.
  • Stufen Sie Ihre Wiederholungsversuche an, anstatt standardmäßig die langsamste Voreinstellung zu verwenden.
  • Beheben Sie die Erzeugung, bevor Sie die Erkennung abstimmen. Wenn Sie den Encoder steuern, kostet das Erhöhen von x_dimension nichts und löst mehr Fehlinterpretationen als jede Lesereinstellung. Der PDF417-Generierungsartikel behandelt diese Parameter.
  • Setzen Sie timeout bei jedem Reader, der benutzerbereitgestellte Bilder verarbeitet.

Kostenlose Lizenz erhalten

Die Evaluierungs‑Build fügt Wasserzeichen zum decodierten Text für Symbolsysteme außer Code 39 hinzu, was jede Round‑Trip‑Prüfung beeinträchtigen kann. Eine kostenlose temporäre Lizenz entfernt das für die Evaluation.

Kostenlose zusätzliche Ressourcen

Fazit

Das Lesen von PDF417‑Barcodes in Python ist bei sauberen Bildern ein zweizeiliger Vorgang und bei realen Bildern ein technisches Problem. Die obigen Messungen deuten auf eine einfache Vorgehensweise hin: Benennen Sie Ihren DecodeType, verwenden Sie standardmäßig normal_quality, versuchen Sie es einmal mit high_quality und aktivierter Deconvolution, und validieren Sie jedes Ergebnis, bevor Sie es verwenden. Speichern Sie die aufwändigen Voreinstellungen für den Wiederholungsweg, und wenn eine ganze Klasse von Bildern bei jeder Einstellung fehlschlägt, beheben Sie die Aufnahme statt den Leser. Fragen sind willkommen im kostenlosen Support‑Forum.

Häufig gestellte Fragen

  1. Warum wird derselbe PDF417‑Barcode in einem Bild gelesen und in einem anderen nicht?
    Die Erkennung hängt davon ab, wie viele Pixel jedes Modul nach der Aufnahme einnimmt. Unschärfe, Verkleinerung und JPEG‑Kompression verkleinern die effektive Modulbreite, und sobald ein Modul unter etwa zwei saubere Pixel fällt, kann kein Preset es wiederherstellen.

  2. Welches Erkennungs‑Preset sollte ich für PDF417 verwenden?
    Beginnen Sie mit normal_quality, dem Standardwert. Wechseln Sie zu high_quality für Aufnahmen mit der Kamera und Scans und reservieren Sie max_quality für Wiederholungsdurchläufe, da es mehrere Male langsamer ist, ohne wesentlich mehr zu lesen.

  3. Beschleunigt das Einschränken von DecodeType auf PDF417 tatsächlich das Lesen?
    Ja. Der Standardwert ist DecodeType.ALL_SUPPORTED_TYPES, der den Detektor für jede unterstützte Symbolik ausführt. Das explizite Angeben von PDF417 entfernt diese Arbeit und eliminiert zudem die Möglichkeit eines Fehlalarms durch eine andere Symbolik.

  4. Kann Aspose.BarCode eine Macro‑PDF417‑Nachricht lesen, die über mehrere Bilder verteilt ist?
    Ja. Lesen Sie jedes Segment mit DecodeType.MACRO_PDF417 und verwenden Sie macro_pdf_417_file_id, macro_pdf_417_segment_id und macro_pdf_417_segments_count im erweiterten Ergebnis, um die Nutzdaten in der richtigen Reihenfolge zusammenzusetzen.

  5. Wie erkenne ich, ob ein dekodiertes Ergebnis vertrauenswürdig ist?
    Prüfen Sie reading_quality und confidence im BarCodeResult und verwenden Sie das region‑Quadrilat, um zu bestätigen, dass der Barcode an der erwarteten Stelle im Bild gefunden wurde.

  6. Kann es PDF417 von einem Foto eines Führerscheins oder einer Bordkarte lesen?
    Ja, sofern die Aufnahme scharf ist und der Barcode nicht abgeschnitten wurde. Schneiden Sie den Barcode‑Bereich vor dem Lesen zu und bevorzugen Sie PNG gegenüber JPEG für Zwischendateien.

Mehr lesen