Распознавание QR-кода

Процесс декодирования изображения QR-кода алгоритмами компьютерного зрения: поиск позиционных маркеров с паттерном 1:1:3:1:1, определение версии и маски, чтение модулей и исправление ошибок по алгоритму Рида-Соломона.

Распознавание QR-кода — многошаговый алгоритмический процесс, в котором камера или программный декодер преобразует сырое изображение в исходные данные. Сначала кадр переводится в чёрно-белое (бинаризация) с адаптивным порогом, чтобы компенсировать неравномерное освещение. Затем детектор ищет характерную последовательность тёмных и светлых полос в соотношении 1:1:3:1:1 — именно так выглядит любой горизонтальный или вертикальный срез позиционного маркера. После нахождения трёх finder patterns алгоритм вычисляет перспективное преобразование и восстанавливает прямоугольную сетку модулей.

Восстановив сетку, декодер считывает 15-битный блок формат-информации рядом с позиционными маркерами: в нём закодированы уровень коррекции ошибок (L/M/Q/H) и номер маски. Маска снимается операцией XOR, после чего модули данных читаются зигзагообразными столбцами справа налево. Полученные кодовые слова передаются в алгоритм Рида-Соломона, который исправляет повреждённые байты в пределах допустимого уровня коррекции. На выходе — поток байтов в кодировке указанного сегмента (числовой, буквенно-цифровой, байтовый или кандзи). Весь цикл на современном смартфоне занимает 50–200 мс. Проверить скорость и надёжность распознавания можно через сканер QR онлайн.

Этапы декодирования

  • Захват кадра: камера фиксирует изображение с достаточным разрешением — минимум 10 пикселей на модуль QR-кода для надёжного чтения.
  • Бинаризация: каждый пиксель переводится в 0 или 1 по адаптивному порогу; глобальный порог ненадёжен при неравномерном освещении.
  • Поиск позиционных маркеров: строки сканируются на паттерн 1:1:3:1:1 по горизонтали, затем перпендикулярно через найденную точку — по вертикали; трёхкратное совпадение фиксирует центр finder pattern.
  • Коррекция перспективы: по координатам трёх маркеров строится проективное преобразование, выравнивающее матрицу независимо от угла съёмки до ±45°.
  • Чтение формат-информации: 15-битный блок вблизи маркеров содержит EC level и номер маски — без этих данных декодирование невозможно.
  • Снятие маскирования: XOR всей области данных с выбранным паттерном маски устраняет нежелательные области сплошного цвета, которые мешали бы поиску маркеров.
  • Декодирование с RS-исправлением: кодовые слова данных и коррекции передаются в декодер Рида-Соломона; исправленные байты интерпретируются согласно режиму кодирования сегмента.

Что мешает распознать

Главные враги сканирования — низкая контрастность и блики. При освещении менее 50 люкс или при попадании зайчика прямо на маркер адаптивная бинаризация даёт ошибки, и паттерн 1:1:3:1:1 не обнаруживается. Физические повреждения кода безопасны в пределах допустимого уровня коррекции: при уровне H (30%) код читается даже с крупным логотипом поверх, но при повреждении >30% декодер не восстановит данные. Нарушение quiet zone — светлого поля шириной минимум 4 модуля по периметру — приводит к тому, что сканер не отделяет матрицу от фона. Подробнее о том, как совместить дизайн и читаемость, — в материале дизайн и сканирование QR.

Геометрические искажения критичны при экстремальных углах съёмки (свыше 50–60° от нормали): алгоритм перспективной коррекции перестаёт точно восстанавливать сетку, и модули на границе матрицы читаются с ошибками. Дрожание камеры размывает границы модулей — особенно в кодах Version 10+ с мелкими модулями. Недостаточное разрешение (менее 5–6 пикселей на модуль) приводит к тому, что граница «тёмный–светлый» не детектируется. О технических характеристиках сканера QR — в соответствующем разделе глоссария.

Частые вопросы

Почему один и тот же QR читается одними сканерами, но не читается другими?

Разные приложения используют разные библиотеки декодирования с разным качеством алгоритмов бинаризации и поиска маркеров. Лучшие декодеры (ZXing, ZBar, Dynamsoft, Scandit) применяют адаптивную локальную бинаризацию по методу Оцу или Брэдли, которая корректно обрабатывает неравномерное освещение. Слабые декодеры используют глобальный порог и теряют паттерн 1:1:3:1:1 в тенях. Дополнительный фактор — способность к коррекции геометрических искажений: продвинутые сканеры применяют полноценное проективное преобразование с маркерами выравнивания, тогда как упрощённые ограничиваются аффинным. Если код не читается встроенной камерой, попробуйте специализированное приложение или онлайн-сканер — они, как правило, используют более точные алгоритмы и работают на полном разрешении кадра без предварительного сжатия превью.

Влияет ли цвет QR-кода на скорость и надёжность распознавания?

Напрямую — нет, если контраст достаточен. Стандарт ISO/IEC 18004 требует, чтобы тёмные модули были темнее светлых минимум на 40% по яркостному каналу (Y в цветовом пространстве YCbCr). Это означает, что синие модули на белом фоне читаются так же надёжно, как чёрные — при условии соблюдения порога. Проблемы начинаются при инверсии (светлый код на тёмном фоне): часть сканеров не поддерживает инвертированные QR и не находит паттерн 1:1:3:1:1, ожидая тёмные маркеры на светлом фоне. Золото, серебро и металлические цвета опасны бликами — зеркальное отражение источника света перекрывает модули и нарушает бинаризацию. Для максимальной надёжности на любом устройстве оптимален классический чёрный на белом с запасом контраста.

Как QR-декодер работает при частичном перекрытии кода?

Декодер справляется с перекрытием благодаря коррекции ошибок Рида-Соломона — при условии, что не перекрыты позиционные маркеры и формат-информация. Маркеры необходимы для построения сетки: без хотя бы двух из трёх finder patterns алгоритм не может вычислить перспективное преобразование. Формат-информация дублируется в двух местах матрицы, что повышает отказоустойчивость. Если оба блока повреждены, декодер не узнает маску и EC level и не сможет интерпретировать данные. При корректно работающей коррекции ошибок уровня H (30%) перекрытие до 30% площади модулей данных не вызывает сбоев. Именно поэтому логотипы помещают в центр кода — вдали от маркеров и блоков формат-информации.