Почему повреждённый QR-код всё ещё читается
Код Рида-Соломона исправляет часть ошибок QR-кода. Уровень H даёт запас около 30% кодовых слов, но не любой трети картинки.

Код Рида-Соломона исправляет часть ошибок QR-кода. Уровень H даёт запас около 30% кодовых слов, но не любой трети картинки.

Дальше вы научитесь отличать повреждение картинки от ошибки кодового слова, поймёте пределы уровней L, M, Q и H и проведёте безопасный тест на копиях кода из генератора eCalc.
В статье вы узнаете:
QR-код состоит из модулей, маленьких чёрных и белых квадратов. Версия 1 содержит матрицу 21 на 21 модуль. Каждая следующая версия добавляет по четыре модуля к стороне, а версия 40 доходит до 177 на 177. Однако далеко не каждая клетка хранит кусочек ссылки.
Модуль является одной клеткой видимой матрицы. Кодовое слово является группой из 8 бит в закодированном потоке. При размещении потока каждый бит занимает свой модуль данных, поэтому восемь соседних по потоку клеток образуют одно кодовое слово.
Поисковые квадраты задают положение. Три крупных узора по углам помогают найти код, определить его поворот и оценить размер сетки. Белые разделители вокруг них не дают соседним клеткам слиться с маяками. Линии синхронизации показывают шаг модулей, а метки выравнивания помогают исправить перспективу и изгиб.
Служебные области объясняют, как читать матрицу. В них записаны уровень коррекции, номер маски и, начиная с версии 7, номер версии. Маска равномернее распределяет чёрные и белые клетки, чтобы длинная полоса или случайный узор не мешали распознаванию. Сама маска ошибок не исправляет.
Свободные места получают данные и проверочные слова. Закодированный поток укладывается змейкой по два столбца, пропуская служебные области. Часть кодовых слов несёт исходное сообщение, часть нужна для коррекции. Для камеры все они выглядят обычными клетками, но декодер обращается с ними по-разному.
Снаружи матрицу окружает тихая зона, чистое поле шириной не меньше четырёх модулей со всех сторон. Она помогает отделить QR-код от текста, рамки и рисунка упаковки. Это пространство не входит в данные, поэтому Рид-Соломон не может «восстановить» обрезанный край или убрать соседнюю надпись.
Получается два разных запаса прочности. Сначала камера должна найти три маяка, построить сетку и уверенно решить, где чёрное, а где белое. Только после этого программа получает кодовые слова и может исправлять их. Если первый этап не состоялся, до математики дело не дойдёт.
Почему инженеры выбрали именно такую конструкцию и как заводская метка стала международным форматом, рассказано отдельно в истории создания QR-кода. Здесь важнее следующий вопрос: что происходит после того, как камера всё-таки прочитала сетку с ошибками.
Ирвинг Рид и Густав Соломон опубликовали метод кодирования в 1960 году. Их работа описывала, как превратить сообщение в набор математически связанных значений, по которым можно восстановить несколько ошибочных символов [Reed, Solomon, 1960]. QR-код применяет эту идею к восьмибитным кодовым словам.
При создании QR-кода данные рассматриваются как коэффициенты многочлена в конечном поле из 256 значений. Число 256 появляется не для красоты: восемь бит дают ровно 256 комбинаций от 0 до 255. Кодировщик делит подготовленный многочлен на специальный порождающий многочлен и сохраняет остаток в виде проверочных кодовых слов.
Декодер выполняет обратную проверку. Если считанная последовательность не согласуется с контрольными значениями, алгоритм вычисляет, в каких кодовых словах появились ошибки и какими должны быть исходные значения. Он не угадывает знакомую ссылку и не ищет похожую картинку в базе. Связь между всеми словами блока даёт достаточно уравнений для восстановления.
Проверочные кодовые слова ≥ 2 × неизвестные ошибки
Это правило относится к одному блоку и к ошибкам, положение которых заранее неизвестно, как обычно бывает после съёмки камерой. Десять проверочных слов позволяют исправить до пяти ошибочных слов в том же блоке. Шестая ошибка может оказаться лишней, даже если большая часть QR-кода выглядит идеально.
Кодовое слово и видимая площадь связаны непрямо. Если пятно изменило три модуля одного восьмибитного слова, для Рида-Соломона это одна ошибочная единица. Если восемь пылинок задели по одному модулю в восьми разных словах, ошибок уже восемь. Площадь чёрной краски может быть меньше, а математического ущерба больше.
В QR-кодах старших версий поток делят на несколько блоков. Для каждого блока создают собственные проверочные слова, а готовые слова перемежают: по очереди берут первое слово разных блоков, затем второе и так далее. Поэтому локальная царапина часто распределяет ошибки между несколькими блоками, вместо того чтобы уничтожить длинный непрерывный кусок одного. Но перемежение даёт шанс, а не гарантию: конкретный блок всё равно может исчерпать свой предел.
Фраза «информация продублирована» удобна, но неточна. Внутри нет второй полной копии адреса. Есть исходные и проверочные значения, которые работают вместе. За этот запас приходится платить местом, и четыре уровня коррекции выбирают разный обмен между ёмкостью и устойчивостью.
Обычный QR-код предлагает четыре уровня. Проценты являются приблизительной долей ошибочных кодовых слов от их общего числа, которую формат рассчитывает восстановить при подходящих условиях. Они не обозначают долю символов ссылки, чёрных модулей или пикселей изображения.
| Уровень | Примерный запас | Практический смысл |
|---|---|---|
| L, Low | 7% кодовых слов | Больше данных, меньше запаса |
| M, Medium | 15% кодовых слов | Обычный компромисс |
| Q, Quartile | 25% кодовых слов | Больше защиты для сложной среды |
| H, High | 30% кодовых слов | Самая сильная штатная коррекция |
Возьмём учебный пример уровня Q. Пусть есть 100 исходных кодовых слов и 100 проверочных. Всего получится 200 слов. Сто проверочных дают возможность исправить до 50 неизвестных ошибок, а 50 от общего числа 200 составляют 25%. Поэтому обещание формулируют как 25% всех кодовых слов, хотя относительно ста исходных слов число выглядит как 50%.
Уровень H не добавляет волшебную стойкость к геометрии. Он выделяет больше ёмкости под проверочные слова, поэтому в тот же размер матрицы помещается меньше данных. Если сообщение уже не помещается, генератор выбирает более высокую версию с большим числом модулей.
При неизменном размере печати более высокая версия делает каждую клетку мельче. Значит, повышение уровня может потребовать увеличить сам квадрат. Иначе дополнительная математика получит менее чёткое изображение: принтер размажет тонкие модули, камера смешает соседние клетки, а блик накроет сразу несколько рядов.
Актуальная редакция ISO/IEC 18004:2024 описывает форматы символа, размеры, правила коррекции и эталонный алгоритм декодирования. Уровень является частью этого контракта: сканер читает его из служебной области и понимает, сколько проверочных слов ожидать.
Генератор QR-кода eCalc сейчас создаёт символы с уровнем M, то есть с ориентиром примерно на 15% ошибочных кодовых слов. Он автоматически выбирает подходящую версию для введённой ссылки или текста и оставляет тихую зону в четыре модуля.
30% не являются разрешением закрыть треть картинки. Число относится к кодовым словам при удачном распознавании сетки. Оно не защищает тихую зону, не обещает пережить потерю поискового квадрата и не учитывает автоматически размер печати, размытие, блик, изгиб или перегрузку отдельного блока.
Представим один QR-код и несколько его копий. На каждой закрасим квадрат одинаковой площади, но в новом месте. Число пикселей останется прежним, а результат будет отличаться, потому что повреждение попадёт в разные части процесса.
Пятно рядом с внешним краем может нарушить тихую зону. Камера увидит рамку, текст или соседний узор как продолжение матрицы и не выделит код из фона. Внутри не испорчено ни одного кодового слова, но считывание уже стало хуже.
Пятно на поисковом квадрате мешает найти положение и поворот. Три маяка имеют некоторый запас к неполным линиям и не обязаны исчезать от одной царапины. Однако потеря узнаваемой структуры способна остановить чтение раньше, чем декодер соберёт данные.
Пятно в поле данных меняет модули исходных и проверочных слов. Здесь Рид-Соломон может помочь. Итог зависит от того, сколько кодовых слов стало ошибочными, как они распределились между блоками и удалось ли камере правильно оценить границы клеток под пятном.
Рассеянная пыль иногда выглядит безобиднее сплошной кляксы, но может задеть по одному модулю во множестве разных слов. Локальный дефект, наоборот, часто выигрывает от перемежения. Универсального победителя нет: компактная клякса на маяке хуже россыпи точек в данных, а такая же клякса в удачной области может исправиться полностью.
Камера читает не площадь краски, а значения клеток. Маленькая точка у края модуля может не изменить его итоговый цвет. Та же точка в центре миниатюрной клетки перевернёт считанный бит. При слабом фокусе граница расплывается сразу на несколько модулей, хотя на исходном файле ни один из них не повреждён.
Поэтому физический размер важен не меньше уровня. Короткая ссылка обычно даёт менее плотную матрицу. При квадрате шириной 40 мм её модули крупнее, чем у длинного адреса с рекламными параметрами. Крупный модуль получает больше точек принтера и пикселей камеры, лучше переживает расстояние, дрожание руки и шероховатую бумагу.
Логотип в центре является контролируемым повреждением, а не специальной функцией любого QR-кода. Даже при уровне H нельзя отдать ему ровно 30% площади и считать работу законченной. Логотип закрывает конкретные модули, может попасть на служебную область, а его белая подложка меняет рисунок сильнее прозрачного знака. Единственная честная проверка проходит на готовом размере, материале и способе печати.
Блик, тень и складка добавляют ещё одну неприятность: они меняются вместе с углом камеры. Код, который один раз прочитался на экране, может не сработать на глянцевой наклейке у окна. Запас коррекции помогает после распознавания, но не превращает плохую фотографию в хорошую. Форма размытия помогает отличить слабый фокус от движения и ошибок оптики.
Простой эксперимент показывает границы лучше абстрактного обещания. Он не сертифицирует код для производства, зато быстро объясняет, почему место дефекта важнее красивого процента.
Для печати дополнительно сократите адрес, сохраните четыре модуля чистого поля, сделайте тёмные клетки заметно темнее фона и не уменьшайте квадрат ради экономии пары миллиметров. Если ссылка длинная, сначала уберите необязательные параметры. Меньшая версия часто приносит больше реальной надёжности, чем сложное украшение.
Если QR-код размещается на бутылке, ткани, металле или глянцевой упаковке, тестируйте именно этот материал. Изгиб меняет геометрию, фактура рвёт края модулей, металл даёт блики, а ткань растягивает сетку. Чистый PNG на мониторе таких проблем не показывает.
Главный вывод можно применить сразу: проценты L, M, Q и H описывают запас математического кода, а не разрешённую площадь кляксы. Создайте контрольный QR-код, повредите несколько копий по-разному и выберите вариант, который остаётся читаемым с запасом. Телефон в руках полезнее линейки, которой пытаются отмерить «безопасные 30%».
Напишите своё мнение, комментарий или предложение.