Надпись "Откройте камерой" мешала прочитать QR-код
Когда QR-код не распознаётся, первое желание - увеличить изображение. Однако этот способ помогает далеко не всегда. Иногда крупная версия читается хуже уменьшенной, особенно если рядом с кодом размещены декоративные элементы или поясняющая надпись.
Именно такая ситуация возникла с одним SVG-файлом. В варианте шириной 640 пикселей QR-код не открывался, а после уменьшения до 320 пикселей внезапно начинал распознаваться. При этом сам QR оставался тем же: менялся только масштаб отображения. На первый взгляд изображение выглядело безупречно - белое поле, квадратный код и подпись "ОТКРОЙТЕ КАМЕРОЙ" снизу. Но для алгоритма эта надпись оказалась не безобидной подсказкой, а дополнительным набором контрастных элементов.
Воспроизвести проблему и проследить её причины помог разбор, опубликованный в материале о том, [почему QR-код не распознаётся из-за подписи](https://habr.com/ru/articles/1080454/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1080454). Эксперимент проводился в Chromium 153.0.8010.36: браузер растеризовал SVG, после чего библиотека jsQR 1.4.0 получала готовый массив RGBA-пикселей. Камера смартфона и печать в рамках проверки не использовались.
Для сравнения изображение передали другому декодеру - @zxing/library 0.21.3. Он корректно прочитал контакт даже в версии шириной 640 пикселей. Это показало, что проблема связана не с повреждёнными данными QR и не с самим изображением как таковым. Нужно было выяснить, на каком именно этапе ошибается jsQR.
Работа распознавателя состоит из нескольких стадий. Сначала цветные пиксели преобразуются в чёрно-белое представление, затем алгоритм ищет сам код, определяет его геометрию, извлекает матрицу модулей и только после этого декодирует содержимое. Если функция возвращает `null`, это ещё не означает, что испорчены данные: сбой мог произойти уже на этапе поиска ориентиров.
В трёх углах QR-кода находятся крупные вложенные квадраты - поисковые паттерны. По ним программа понимает, где расположен код, каков его масштаб и под каким углом он находится. Человек без труда отличает эти элементы от подписи, но алгоритм видит лишь последовательности тёмных и светлых пикселей.
При визуализации координат, выбранных локатором jsQR, выяснилось, что две точки действительно попали в настоящие угловые паттерны: примерно в позиции (525, 137) и (115, 546,5). Третья точка оказалась в координатах (386, 638,5) - прямо в строке "ОТКРОЙТЕ КАМЕРОЙ". Настоящий верхний левый ориентир в итоговую тройку не вошёл.
После этого декодер построил геометрию уже на основе ошибочных данных. Вместо реальной сетки размером 57×57 модулей он оценил сторону примерно в 81, а после повторного центрирования - в 83 модуля. Иными словами, программа анализировала не ту сетку, поэтому обсуждать коррекцию ошибок на этом этапе было бессмысленно: до правильной матрицы она просто не добралась.
Чтобы проверить гипотезу, из готового растра удалили только нижнюю полосу с текстом, не обрезая изображение и не меняя положение QR-кода. Распознавание сразу восстановилось. В прямоугольнике размером 500×500 пикселей, содержащем сам код и его защитное поле, не изменился ни один пиксель во всех четырёх каналах. Следовательно, исправление не улучшило качество QR - оно лишь убрало ложные ориентиры за пределами кода.
Дополнительный тест дал тот же результат. Если удалить верхнюю декоративную область, но оставить надпись, QR по-прежнему не читается. Значит, проблема не в любом оформлении вокруг изображения, а конкретно в контрастной строке снизу.
Удаление одного небольшого фрагмента размером 24×24 пикселя также не помогло. После этого локатор нашёл другой похожий участок той же надписи - примерно в точке (314,5, 638,5) - и снова выбрал неправильную геометрию. Получился своеобразный "запасной" ложный ориентир: пока в строке оставались похожие комбинации полос, алгоритм мог принимать их за элемент QR-кода.
Была проведена и независимая проверка. В полный исходный растр передали правильные координаты угловых ориентиров, найденные на исправленной версии. После обхода этапа поиска декодер успешно вернул исходный контакт. Это подтвердило: данные внутри QR оставались доступными, а ошибка возникала именно при обнаружении и позиционировании кода.
Причина связана с принципом работы локатора. Он ищет последовательности чёрных и белых полос, характерные для углового паттерна QR. При прохождении линии через центр такого элемента ширины участков должны примерно соответствовать пропорции 1:1:3:1:1. Алгоритм сравнивает найденные комбинации с этим шаблоном в разных направлениях и оценивает степень совпадения. Чем меньше значение ошибки, тем более подходящим считается кандидат. Это не процент уверенности, а мера отклонения от ожидаемого профиля.
Крупные буквы в подписи содержали достаточно резкие переходы между чёрным и белым, чтобы частично напоминать поисковый шаблон. На увеличенной версии надпись занимала больше пикселей, а её контуры становились более устойчивыми для анализа. После уменьшения изображения тонкие элементы текста частично сглаживались и переставали выглядеть как убедительные ориентиры. Поэтому меньшая картинка неожиданно оказалась удобнее для распознавания.
Практический вывод прост: если QR-код плохо читается, важно не только [как увеличить читаемость QR-кода](https://habr.com/ru/articles/1080454/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1080454), но и что находится рядом с ним. Контрастные надписи, логотипы, рамки и декоративные узоры могут конкурировать с настоящими поисковыми паттернами. Иногда полезнее убрать подпись, увеличить свободное белое поле или проверить изображение в меньшем масштабе.
Пользователю, который пытается понять, как открыть QR-код камерой, обычно достаточно навести объектив на квадрат. Но для разработчика генератора важно обеспечить достаточную "тишину" вокруг кода: оставить светлую зону, не размещать рядом крупные чёрные символы и не накладывать текст на защитное поле. Особенно это актуально для SVG, где итоговая растеризация зависит от масштаба и браузера.
Если QR уже сохранён в виде картинки, возникает вопрос, как прочитать QR-код с изображения. В этом случае можно воспользоваться системной галереей, приложением камеры или сервисом, работающим как сканер QR-кодов онлайн. Однако разные декодеры используют разные алгоритмы поиска, поэтому результат может отличаться: один инструмент распознает код без проблем, а другой остановится на ложном кандидате.
Перед тем как искать, почему камера не распознает QR-код, стоит проверить несколько вещей: нет ли бликов, достаточно ли контраста, не обрезано ли белое поле, не наклонено ли изображение и не мешают ли посторонние элементы. Иногда помогает не увеличение, а уменьшение картинки, удаление подписи или повторное сохранение изображения с корректной растеризацией.
Таким образом, неисправность находилась не в содержимом контакта и не в механизме коррекции ошибок. Алгоритм просто выбрал неправильные три ориентира, приняв фрагменты текста за часть QR-кода. Исправление экспорта, сохранившее надпись визуально, устранило проблему благодаря изменению её растеризации. Для создателей QR-графики это хороший пример того, что понятная человеку подпись может стать неоднозначным сигналом для компьютерного зрения.


