Время на прочтение
Aspose QR Code Сканер — это бесплатное онлайн-приложение для чтения QR-кодов с изображения или камеры вашего мобильного телефона. Он способен находить и считывать несколько штрих-кодов на изображении. Наш сложный алгоритм позволяет считывать даже поврежденные штрих-коды. Сканер QR-кодов поддерживает множество различных форматов ввода (PNG, JPEG, BMP, GIF).
Это бесплатное приложение предоставлено Aspose.BarCode
Также посмотрите наш Cloud API
Введение
Эта статья — первая в цикле статей, в котором мы разберемся с тем, как qr-код устроен, и напишем простенький Qr-детектор и дешифровщик, а также свой собственный генератор qr-кодов.
Использовать мы будем python вместе с opencv и numpy. Учитывая, что opencv — кросс-язычная библиотека, а также то, что работа с изображением/текстурой в разных решениях выглядят примерно одинаково, то я думаю, что вы без труда сможете перевести алгоритм, который будет здесь написан, на любой нужный вам язык
В первую очередь мы будем рассматривать полноразмерный qr-код, Micro-qr возможно будет рассмотрен после завершения работы над полноразмерным qr
Также, хочу отметить, что готовый класс QrCodeDetector уже имеется внутри opencv. Возможно, вам не нужно изобретать велосипед 🙂
Как долго действует QR-код?
Срок действия QR-кода не истекает. Рассматривайте QR-код как контейнер, в котором хранится информация, которая была помещена в него. Лист бумаги с QR-кодом может испачкаться и повредиться, жесткий диск, на котором хранится цифровое изображение вашего QR-кода, может сломаться. Но хотя QR-код читается, он содержит те же данные, с которыми изначально был закодирован. Но вместо самой информации QR-код может кодировать URL-адрес, ведущий на страницу с некоторой конкретной информацией. Срок действия этой ссылки может истечь, страница исчезла или информация на странице может измениться или стать неактуальной. В этом случае вы можете сказать, что QR-код «истек».
Содержат ли QR-коды личную информацию? В безопасности ли мои данные?
QR-коды содержат именно ту информацию, которую их просят закодировать. Если у вас есть лист бумаги с напечатанным QR-кодом, он не содержит дополнительной информации. Однако если вы сфотографируете QR-код на смартфон, ничто не мешает вашему телефону прикрепить к фотографии какие-либо личные данные, такие как ваше имя, адрес или любую другую информацию, которую он может получить от вашего телефона. Если у вас есть личный паспорт/сертификат вакцины, он может содержать некоторые личные данные, которые вы, возможно, захотите сохранить в тайне. Но, скорее всего, нет. QR-код в сертификате вакцины обычно содержит только ссылку на внешнюю страницу, а данные на этой странице обычно анонимизируются. Посетите веб-сайт местных органов власти или вы можете проверить, что закодировано в вашем QR-коде, с помощью сканера Aspose.Barcode
Какую информацию я могу закодировать в штрих-код?
Обычно это буквы и цифры. Некоторые штрих-коды позволяют также использовать определенный набор специальных символов или все символы ASCII. Информация, закодированная в штрих коде, обычно представляет собой некоторое описание предмета, на котором этот размещен штрих-код.
Насколько маленьким может быть штрих-код?
Штрих-код может быть достаточно маленьким. Например, 1×1 см для двухмерного штрих-кода. Но в штрих-код меньшего размера можно закодировать меньше информации. И вам также предется использовать принтер с более высоким разрешением.
Сколько данных может содержать штрих-код?
Обычно это около 25 символов для 1D штрихкода и около 2000 для 2D. Конечно, чем больше символов вы закодируете, тем крупнее будет штрих-код. Штрих-код 1D может стать непрактично широким, если кодирует более чем из 15 символов.
Иногда возникают такие ситуации, когда нужно прочитать QR код, а смартфона под рукой нет. Что же делать? В голову приходит лишь попробовать прочитать вручную. Если кто-нибудь сталкивался с такими ситуациями или кому просто интересно как же читается QR код машинами, то данная статья поможет вам разобраться в этой проблеме.
В статье рассмотрены базовые особенности QR кодов и методика дешифрирования информации без использования вычислительных машин.
Иллюстраций: 14, символов: 8 510.
Для тех, кто не в курсе что такое QR код, есть неплохая статья в английской Wikipedia. Также можно почитать тематический блог на Хабре и несколько хороших статей по смежной тематике, которые можно найти поиском.
Решение задачи непосредственного чтения информации с QR-картинки рассмотрим на примере двух кодов. Информация была закодирована в online-генераторе QR Coder.ru.
Чтобы понять, как извлечь данные из кода, нужно разобраться в алгоритме. Существует несколько стандартов в семействе QR кодов, с их базовыми принципами можно ознакомиться в спецификациях. Кратко поясню: данные, которые необходимо закодировать, разбиваются на блоки в зависимости от режима кодирования. К разбитым по блокам данным прибавляется заголовок, указывающий на режим и количество блоков. Существуют и такие режимы, в которых используется более сложная структура размещения информации. Данные режимы рассматривать не будем ввиду того, что извлекать вручную из них информацию нецелесообразно. Однако, основываясь на тех принципах, которые описаны ниже, можно адаптироваться и к этим режимам.
На случай некорректного чтения данных, в QR применяются специальные коды, которые способны исправить недочёты при чтении. Это так называемые коды Рида-Соломона. Принцип вычисления кодов, а также исправление ошибок в блоках информации рассматривать не будем, это тема отдельной статьи. Корректирующие ошибки коды Рида-Соломона (RS) записываются после всех информационных данных. Это очень упрощает задачу непосредственного чтения информации: можно просто считать данные, не трогая коды. Как показывает практика, обычно бОльшую часть QR -матрицы занимают корректирующие RS-коды.
По стандарту, данные с RS-кодами перед записью в картинку «перемешиваются». Для этих целей используют специальные маски. Существует 8 алгоритмов, среди которых выбирается наилучший. Критерии выбора основаны на системе штрафов, о которых можно также почитать в спецификации.
«Перемешанные» данные записываются в особой последовательности на шаблонную картинку, куда добавляется техническая информация для декодирующих устройств. Исходя из описанного алгоритма, можно выделить схему извлечения данных из QR кода:
Здесь зелёным фломастером подчёркнуты пункты, которые нужно будет выполнить при непосредственном чтении кода. Остальные пункты можно опустить ввиду того, что считывание производит человек.
ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ
Как уже говорилось, интерес представляют только первые 5 бит. Из которых 2 бита показывают уровень коррекции ошибок, а остальные 3 бита показывают какая маска из доступных 8 применяется к данным. В рассматриваемых QR кодах системная информация содержит:
Сканер Aspose. BarCode
Спецификация
BS ISO/IEC 18004:2006. Information technology. Automatic identification and data capture techniques. QR Code 2005 bar code symbology specification. London: BSI. 2007. p. 126. ISBN 978-0-580-67368-9.
P.S. Соблюдайте правила ресурса и условия Creative Commons Attribution 3.0 Unported (CC BY 3.0)
P.P.S. Если ошибся блогом, то подскажите куда — перенесу.
Шаг 0. QR код
Взглянув на картинки, можно заметить несколько отчётливых областей. Эти области используются для детектирования QR кода. Эти данные не представляют интереса с точки зрения записанной информации, но их нужно вычеркнуть или просто запомнить их расположение, чтобы они не мешали. Всё остальное поле кода несёт уже полезную информацию. Её можно разбить на две части: системная информация и данные. Также существует информация о версии кода. От версии кода зависит максимальный объём данных, которые могут быть записаны в код. При повышении версии – добавляются специальные блоки, например как здесь:
По ним можно сориентироваться и понять какая версия QR перед вами. Коды высоких версий обычно также нецелесообразно считывать вручную.
Размещение системной информации показано на рисунке:
Системная информация дублируется, что позволяет значительно понизить вероятность возникновения ошибок при детектировании кода и считывании. Системная информация – это 15 бит данных, среди которых первые 5 — это полезная информация, а остальные 10 — это BCH(15,5) код, который позволяет исправлять ошибки в системных данных. К классу BCH кодов относят и RS коды. Обратите внимание, что на рисунке две полоски по 15 бит не пересекаются.
Шаг 4. Применение маски к заголовку
После извлечения 4-х бит, описывающих режим, необходимо к ним применить маску.
В нашем случае для двух кодов используются разные маски. Маска определяется выражением, приведённым в таблице выше. Если данное выражение сводится к TRUE (верное) для бита с координатами (i,j), то бит инвертируется, иначе всё остаётся без изменений. Начало координат в левом верхнем углу (0,0). Взглянув на выражения, можно заметить в них закономерности. Для рассматриваемых QR кодов, маски будут выглядеть так:
Обнаружение
Очевидно, что прежде, чем дешифровать qr-код, нужно для начала его обнаружить на картинке. Как же это делают наши смартфоны? Всё очень просто, специально для этого на Qr-коде есть вот эти три квадратика:
Как отсканировать штрих код
Загрузите изображение, выберите тип штрих кода и нажмите на кнопку “Сканировать штрих код”.
Приложение работает на любой платформе, включая Windows, Mac, Android и iOS. Все файлы обрабатываются на наших серверах, установка стороннего ПО не требуется.
Работает на Aspose.BarCode. Все файлы обрабатываются библиотеками Aspose, которые используются многими компаниями из списка Fortune 100 в 114 странах.
Популярные типы штрих кодов
Так же вы можете сканировать многие другие типы символик.
Шаг 3. Чтение заголовка данных
Чтобы понять с какими данными предстоит иметь дело, необходимо изначально прочитать 4-х битный заголовок, который содержит в себе информацию о режиме. Специфика чтения данных изображена на картинке:
Список возможных режимов:
Шаг 2. Маска для системной информации
Кроме уже озвученных схем защиты системной информации, вдобавок, используется статическая маска, которая применяется к любой системной информации. Она имеет вид: 101010000010010. Так как имеет интерес только первые 5 бит, то маску можно сократить и легко запомнить: 10101 (десять — сто один). После применения операции «исключающего или» (xor) получаем информацию.
Возможные уровни коррекции ошибок:
Шаг 5. Чтение данных
После получения данных о режиме можно приступать к чтению информации. Надо оговорить, что наиболее интересно считывать числовые и буквенно-числовые данные, так как они легко интерпретируются. Но также не стоит бояться 8-битных. Это может быть также легко интерпретируемая информация. Например, многие онлайн генераторы QR текст кодируют в этом режиме, используя ASCII. Ещё одна причина, почему следует изначально прочитать режим, это то, что от него зависит количество пакетов данных. Которая также зависит и от версии кода. Для версий с первой по девятую длины блоков для более читабельных режимов:
Первый блок после указателя режима — это количество символов. Для числового режима количество закодировано в 10 следующих битах, а для 8-битного режима в 8 битах (прошу прощения за тавтологию).
На рисунке видно, все 4 пакета представляют собой коды ASCII латинских букв, образующие слово «habr»
Естественно наилучшим способом остаётся достать телефон из кармана и, наведя камеру на QR-картинку, считать всю информацию. Однако в экстренных случаях может пригодиться и описанная методика. Конечно, в голове не удержишь все указатели режимов и типов масок, а также ASCII символы, но популярные комбинации запомнить (хотя бы те, что рассмотрены в статье) под силу.
Пишем код
Как уже было сказано выше, использовать мы будем opencv и numpy. Импортируем эти библиотеки:
import cv2 as cv
import numpy as np
В первую очередь нам нужно найти первый чёрный пиксель на изображении, которое является трёхмерным массивом вида:
Поэтому мы проходимся по массиву, пока не найдем элемент, значение которого меньше 50. (черный цвет = 0, но на изображении могут быть помехи, так что мы просто ищем тёмные пиксели):
Кстати, ради дебага я использую режим чтения cv.IMREAD_COLOR, по существу он здесь совершенно не нужен, так что я советую заменить его на cv.IMREAD_GRAYSCALE
Мы нашли черный пиксель, теперь нам нужно проверить, что он является частью квадрата:
Здесь в функции get_square_length мы сначала ищем длину квадрата, проходя по нему до сюда:
А затем при помощи функции _is_black_point проверяем два региона:
Мы проверяем именно два региона, а не две точки, т.к., как уже было сказано ранее, существует погрешность при работе с изображением
Также, стоит проверить наличие вот этого маленького квадратика внутри:
Для этого в наш класс пишем еще одну функцию:
Теперь похожим образом нужно проверить оставшиеся два квадрата, для этого дописываем нашу detect функцию:
По итогу мы получаем следующий код:
Заключение
В этой статье мы написали простенький qr-детектор, который обнаруживает qr-код на белом фоне. В следующих статьях мы научимся обнаруживать qr-код на более сложных изображениях, после чего переводить его в понимаемы нами (человеками) формат
Код всех частей этого цикла можно найти в этом репозитории
Если вам необходимо получить полную информацию о qr-кодах, не ожидая выхода всех частей этого цикла, советую ознакомиться с данной документацией: ISO/IEC JTC 1/SC 31 N (arscreatio.com). Сущность qr-кода не сильно изменилась со времен его создания, поэтому не смотрите на то, что документация 2004 года
*нашел вариант на русском из нашего ГОСТ-а: ГОСТ Р ИСО/МЭК 18004-2015. Информационные технологии. Технологии автоматической идентификации и сбора данных. Спецификация символики штрихового кода QR Code (internet-law.ru)
Также, для быстрого понимания основных принципов чтения qr-кода, советую обратить внимание на эту статью.