Создание штрих‑кода PDF417 занимает всего четыре строки кода на Python. Чтение его из фотографии телефона, сканирования с разрешением 200 DPI или посадочного талона, который провёл день в кармане, — вот где начинается настоящая работа, и именно здесь большинство интеграций PDF417 действительно терпят неудачу. В этой статье вы узнаете, как считывать штрих‑коды PDF417 в Python, когда исходное изображение несовершенно. Если вам интересна сторона генерации, то ранее опубликованный пошаговый материал о том, как генерировать штрих‑коды PDF417 с помощью Python охватывает создание базовых и пользовательских символов PDF417, включая управление строками и столбцами, а руководство по чтению штрих‑кодов на Python описывает универсальное сканирование различных символогий. Далее будет узко и глубоко рассматриваться распознавание PDF417.
Каждый фрагмент ниже был выполнен с использованием Aspose.BarCode for Python via .NET 26.7 на Linux с Python 3.12. Время выполнения и результаты чтения/пропусков измерены, а не оценены, а скрипт, который их создал, находится в конце, чтобы вы могли запустить его на своих собственных изображениях.
Что действительно нарушает распознавание PDF417
PDF417 — это многослойный символьный набор: строки кодовых слов, каждое кодовое слово построено из четырёх штрихов и четырёх пробелов, охватывающих 17 модулей. Эта структура содержит коррекцию ошибок Рида‑Соломона, поэтому порванный угол или пятно от кофе обычно можно восстановить. То, что невозможно восстановить, — это потеря самой сетки модулей.
Три вещи разрушают сетку, в приблизительном порядке того, как часто они встречаются в продакшене:
- Эффективная ширина модуля менее двух пикселей. Это основная причина сбоя. Это происходит из‑за уменьшения масштаба, расстояния до камеры и размытия, которое растягивает чернила одного модуля на соседние. Штрих‑код, сгенерированный при трёх пикселях на модуль и затем размытый, фактически является штрих‑кодом при одном пикселе на модуль.
- Перспектива и вращение. Штрих‑код, сфотографированный под углом, имеет строки, которые больше не параллельны сканирующим линиям. Детектор справляется с этим, но это требует прохода обнаружения, который пропускает самый быстрый предустановленный режим.
- Потеря контраста. Термобумага, которая выцвела, экран, сфотографированный под бликом, или скан с зафиксированной яркостью. Менее критично, чем кажется, как показывают цифры ниже.
Практический вывод состоит в том, что настройки распознавания являются механизмом восстановления, а не заменой качества захвата. Они позволяют восстановить средний диапазон качества изображения. Они не восстанавливают нижний диапазон.
Настройка считывателя PDF417 на Python
Установите библиотеку из PyPI:
pip install aspose-barcode-for-python-via-net
API распознавания находится в aspose.barcode.barcoderecognition. Для этой статьи важны два класса: BarCodeReader, который управляет обнаружением и декодированием, и QualitySettings, который контролирует, насколько усердно работает считыватель.
Чтение штрих‑кода PDF417 в Python
Минимальный рабочий пример чтения состоит из двух аргументов и цикла:
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 в Python.
Вывод на чистом изображении:
Code text: PASSENGER|KHAN/M|SEAT14C|LHE-DXB
Symbology: Pdf417
Reading quality: 100.0
Второй аргумент на практике не является необязательным. Оставьте его, и BarCodeReader переходит к DecodeType.ALL_SUPPORTED_TYPES, что запускает обнаружение более чем шести десятков символогий для каждой кандидатской области на изображении. В конвейере, работающем только с PDF417, это просто пустая трата ресурсов, и это открывает возможность ложного срабатывания линейной символогии внутри структуры строки PDF417. Укажите тип.
Если ваш ввод поступает в виде байтов из загрузки, а не из файла на диске, передайте поток и установите тайм‑аут, чтобы патологическое изображение не могло блокировать рабочий процесс:
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 и запустил каждый набор настроек против каждого варианта. Медиана трёх запусков:
| Source image | high_performance | normal_quality | high_quality | max_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 |
Из этой таблицы выводятся четыре вещи, и они более полезны, чем отдельные числа:
- Шум и низкий контраст не являются той проблемой, какой их считают. Reed‑Solomon плюс детектор поглотили сильный гауссовский шум и снижение контраста на 82 % в самом быстром пресете. Прекратите настраивать их.
- Поворот плюс размытие — это случай, который разделяет пресеты. Это также точный профиль захвата с handheld‑телефона, поэтому
high_performanceявляется неправильным значением по умолчанию для любого конвейера, полученного с мобильных устройств. max_qualityтребует в три раза больше времени, чемnormal_quality, и не читает ничего дополнительно. Он заслуживает место как путь второй попытки, а не как значение по умолчанию.- Как только сетка модуля исчезает, ни один пресет её не восстанавливает. Строка с сильным размытием — провал во всех случаях, и
max_qualityпотратил 180 мс, подтверждая это. Это проблема захвата, решаемая исправлением захвата: больше пикселей, лучшее фокусирование, больший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 в Python.
Измерено: промах за 12 мс без переопределения, чтение за 54 мс с ним. Одна настройка изменила результат, и он всё равно вернулся быстрее, чем предустановка max_quality.
Свойства, которые стоит знать:
| Свойство | Значения | Когда использовать |
|---|---|---|
deconvolution | FAST, NORMAL, SLOW | Размытие движения и снимки с расфокусировкой |
barcode_quality | HIGH, NORMAL, LOW | Дефекты печати, термическое выцветание, артефакты факса |
x_dimension | AUTO, SMALL, NORMAL, LARGE, USE_MINIMAL_X_DIMENSION | Плотные штрихкоды или фиксированный известный размер модуля |
minimal_x_dimension | float | В сочетании с USE_MINIMAL_X_DIMENSION задаёт нижний предел |
complex_background | AUTO, DISABLED, ENABLED | Штрихкод, напечатанный поверх графики или узорчатой формы |
inverse_image | AUTO, DISABLED, ENABLED | Штрихкоды белый‑на‑чёрном, скриншоты |
allow_incorrect_barcodes | bool | Только для диагностики, никогда в продакшн |
Последний из них заслуживает предупреждения. 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)]
Воссоздать макрос 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.

Страница 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, что будет мешать любому тестированию с обратным проходом. Бесплатная временная лицензия устраняет это в оценочной версии.
Бесплатные дополнительные ресурсы
- Параметры качества чтения штрихкодов и предустановки
- Особые случаи чтения штрихкодов
- Справочник API
- Бесплатные онлайн-инструменты для штрихкодов
Заключение
Чтение штрихкодов PDF417 в Python — это двухстрочная операция на чистых изображениях и инженерная задача на реальных. Вышеуказанные измерения указывают на простую стратегию: назовите ваш DecodeType, по умолчанию используйте normal_quality, попробуйте ещё раз с high_quality и включённой деконволюцией, и проверяйте каждый результат перед тем, как действовать. Сохраните дорогие пресеты для пути повторной попытки, и когда целый класс изображений не проходит ни при одной настройке, исправьте захват вместо считывателя. Вопросы приветствуются на форум бесплатной поддержки.
Часто задаваемые вопросы
Почему один и тот же штрих‑код PDF417 читается на одном изображении и не читается на другом?
Распознавание зависит от того, сколько пикселей занимает каждый модуль после захвата. Размытие, уменьшение масштаба и JPEG‑компрессия уменьшают эффективную ширину модуля, и как только модуль становится уже примерно двух чистых пикселей, ни один пресет не сможет его восстановить.Какой пресет распознавания следует использовать для PDF417?
Начните сnormal_quality, который является значением по умолчанию. Перейдите кhigh_qualityдля захватов с камеры и сканирований, аmax_qualityоставьте для повторных проходов, поскольку он работает в несколько раз медленнее и не даёт заметного прироста чтения.Действительно ли ограничение DecodeType только PDF417 ускоряет чтение?
Да. По умолчанию используетсяDecodeType.ALL_SUPPORTED_TYPES, который запускает детектор для каждой поддерживаемой символьной системы. Явное указание PDF417 исключает эту работу и также устраняет возможность ложного срабатывания от другой символьной системы.Может ли Aspose.BarCode читать сообщение Macro PDF417, разбитое на несколько изображений?
Да. Читайте каждый сегмент с помощьюDecodeType.MACRO_PDF417и используйтеmacro_pdf_417_file_id,macro_pdf_417_segment_idиmacro_pdf_417_segments_countв расширенном результате для последовательной сборки полезной нагрузки.Как понять, можно ли доверять декодированному результату?
Проверьтеreading_qualityиconfidenceв объектеBarCodeResult, а также используйте квадрантregion, чтобы убедиться, что штрих‑код найден в ожидаемом месте изображения.Можно ли читать PDF417 с фотографии водительского удостоверения или посадочного талона?
Можно, при условии, что захват выполнен в фокусе и штрих‑код не обрезан. Обрежьте область штрих‑кода перед чтением и отдавайте предпочтение PNG вместо JPEG для промежуточных файлов.
