Русский
Русский
English
Статистика
Реклама

Штрихкод

Малоизвестные факты о штрихкодах загадочные цифры под штрихкодом

02.11.2020 16:19:26 | Автор: admin
Число зверя, штрихи смерти насколько все это реально? Можно ли зашить в штрихкод видеоролик или фото голой Эммы Уотсон? Бывают ли неправильные штрихкоды, и что вообще значит неправильный штрихкод?

В Клеверенсе мы разрабатываем платформу Mobile SMARTS для создания мобильных решений по учету маркированного товара и постоянно сталкиваемся с детскими ошибками в маркировке. Обычно они вызваны простым нежеланием людей хоть немного разбираться в теме.

Наша платформа тоже не идеальна, но кое-что в своём деле мы понимаем. Статья не к тому, что типа мы крутые и разбираемся, а все вокруг не крутые и не разбираются, нет. У каждого свои задачи, мы тоже часто лажаем. Просто тема набирает популярность и выходит в массы, а любые ошибки стоят денег.

Сначала для затравки расскажем про кассовый штрихкод, а затем про загадочный GS1 DataMatrix, который используется в проекте тотальной маркировки товаров.

Сама статья больше развлекательная, всё изложенное при желании легко гуглится, но может и побудить кого-то изучить тему глубже.


Загадочные цифры под штрихкодом


image

Цифры под штрихкодом что это такое? Знающие люди говорят, что тут всё просто: именно эти цифры зашиты в штрихкод. Девушка на кассе вбивает в программу цифры под штрихкодом и вуаля товар найден.

К сожалению, это заблуждение. Цифры под штрихкодом не зашиты в штрихкод. Для разговоров у камина сойдет, а для айтишника беда.

Это распространенное заблуждение приводит к тому, что когда встает задача распечатать штрихкод, человек гуглит бесплатный онлайн генератор штрихкода, пихает в поле эти самые цифры, и получает проблему на ровном месте.

Надписи под штрихкодом называются Human readable interpretation (HRI). Одно только название уже должно наводить на мысль, что тут не всё в порядке.

В самом мягком варианте вера в то, что цифры под штрихкодом повторяют содержимое штрихкода это примерно как верить в то, что название файла определяет его содержимое. Типа: Переименовала ваш файл в .doc, но он всё равно не открывается.

Рассмотрим подробнее, где тут собака зарыта.

Кассовый штрихкод



Пример про кассовый штрихкод для затравки. Он на самом деле не вызывает никаких проблем, потому что за 50 лет использования в софте и оборудовании были вставлены 1000 костылей, чтобы обойти все проблемы (ну почти). Зато он хорошо иллюстрирует вопрос.


Вот в этих двух штрихкодах (EAN-13) ниже, под которыми написано 4601200000003 и 0123456789128, в обоих нет штрихов для первой цифры. В первом штрихкоде нет штрихов для 4 (она закодирована другим способом), а во втором штрихкоде вообще в принципе нет лидирующего нуля, хотя он и напечатан под штрихкодом.

imageimage

Да-да, именно первой цифры, а не последней (чексуммы) как можно было бы подумать. Последняя цифра (чексумма) в полосках этих штрихкодов как раз-таки есть, иначе затея с чексуммой не будет работать.

Рассмотрим поближе, что тут происходит.

В первом приведенном штрихкоде (4601200000003) в начале идут две длинные полосочки, они кодируют начало штрихкода, далее идут штрихи и пропуски для цифры 6, затем про цифры 0, 1, 2, 0 и 0, две длинные полосочки в центре говорят про середину, затем пять одинаковых групп штрихов и пропусков кодируют 00000, далее идут штрихи и пропуски для цифры 3 и завершающие две длинные полоски про конец штрихкода. Итого, в штрихкоде есть штрихи только про 601200000003. Цифра 3 (последняя) в полосках штрихкода есть, а первой 4 нет! Откуда же взялась 4?

Дело в том, что 4 закодирована грязным хаком. Для неё не хватает места, и вообще всё это большой исторический казус.

Изначально такие кассовые штрихкоды появились в США, там они состоят из 12 цифр и называются UPC (Universal Product Code). Для переноса технологии в Европу и адаптации стандарта Европе нужны были дополнительные цифры, потому что американские 12 все уже были заняты.

image

Первым товаром, приобретенным по штрих-коду на этикетке, стал блок из 10 жевательных резинок Wrigley Juicy Fruit. Это произошло в супермаркете Marsh города Трой (Огайо) в четверг, 26 июня 1974 года в 8.01 утра. В историю вошли и имя покупателя, и имя кассира, открывших новую страницу розничной торговли. Теперь упаковка жвачки, которая тогда обошлась в 67 центов, вместе с чеком хранятся в музее американской истории Смитсоновского института.


Чтобы расширить емкость, можно было бы просто добавить еще немного штрихов и пропусков, но в те времена это серьезно ухудшало считываемость. Поэтому вместо того, чтобы просто увеличить штрихкод в ширину, был применен хак.

По американскому стандарту любая из цифр штрихкода может быть записана: а) обычными штрихами и пропусками; б) их зеркальным отражением; в) инверсией черного и белого; г) зеркальной инверсией. Всё это нужно для того, чтобы можно было печатать инверсные штрихкоды (белым по черному) и сканировать штрихкод вверх ногами (зеркальное отражение в случае штрихкода то же самое, что и поворот на 180).

В американском штрихкоде (который на 12 цифр) первые 6 цифр кодируются обычными штрихами, а вторые 6 цифр инвертированными штрихами (где черные штрихи заменены на белые полоски и наоборот). Это сделано для того, чтобы понимать, перевернут штрихкод или нет, нормально я его сканирую или вверх ногами (и затем декодировать цифры в правильном порядке, а не задом наперед).

В новом европейском штрихкоде (который на 13 цифр), первая цифра (например, 4) кодируется не штрихами, а путем перетасовывания способов кодирования следующих за ней 6 цифр из первого блока (второй блок из 6 оставили в покое).

Например, следующая за четверкой 6 выводится как обычно, штрихи следующего за ней 0 выводятся в обратном порядке (зеркально), следующие за ней 1 и 2 выводится снова в обычном виде, следующие два 0 снова зеркально. Общая длина штрихкода и число штрихов в результате этого трюка не меняется.

Для американского сканера такая белиберда не имеет смысла, а для Европы это тайный знак того, что в штрихкоде закодирована еще одна цифра! (да, мы всегда знали, что европейцы извращенцы).

Для всех цифр от 1 до 9 были придуманы такие правила тасовки способов кодирования. Для 0 ничего нет, т.е. 13-значный штрихкод с лидирующим нулем визуально ничем не отличается от 12-значного штрихкода без этого лишнего ноля (EAN-13 с лидирующим нулем эквивалентен UPC-А).

Из этого получается первый прикол, что если перед нами американский штрихкод (в котором варианты кодирования не перетасованы), то американский сканер читает 12 цифр, а условный европейский сканер может считать, что в нем есть лидирующий 0, и считывать лишний ноль (т.к. для кодирования ноля не предусмотрено никакой перетасовки, этого лидирующего нуля очевидно в принципе нигде нет в штрихкоде).

Конечно, мир давно глобализован, поэтому американский сканер и европейский сканер это просто условности. Сканер один и тот же, но у него есть настройка: нужно ли ему в принципе считывать EAN-13 (Европа) или читать только UPC-А (США), а если считывать EAN-13, то надо ли добавлять лишний ноль к американским штрихкодам UPC-А.

С этим связана одна распространенная проблема при внедрении штрихкодирования: когда в базе данных у компании либо нет нолей в начале штрихкодов, а сканер считывает с лишним нолем, либо наоборот, в базе данных есть ноль в начале, а сканер его не считывает (хотя, что там считывать, этого ноля в принципе в штрихкоде нет).

Казалось бы, сложно накосячить в использовании EAN-13/UPC. Тем не менее, люди делают следующие ошибки:

Сохраняют штрихкод в учетной системе без чексуммы (последнего знака).
Забывают обрабатывать присутствие/отсутствие лидирующего нуля при разработке алгоритма поиска по штрихкоду.
Требуют ввода 13 символов, а потом приходят сигареты с EAN-8 (с вводом маркировки табака станет неактуально, но пока так).
Не оставляют положенных широких белых полей справа и слева от штрихкода.

В наших программных продуктах, таких как Магазин 15 или Склад 15, построенных на платформе Mobile SMARTS, мы решаем эту проблему очень просто: сканер устройства всегда автоматически настраивается на возврат ноля, а поиск товара по базе данных производится два раза: и с нолем, и без ноля (чтобы уж точно найти товар).

Сканер мы стараемся настраивать программно, без участия человека. Если сканер нельзя настроить программно то это всегда проблема, потому что по умолчанию сканером может обрезаться не только 0 (который в начале), но еще и чексумма (которая в конце), тогда в программу придут не 13, а уже 11 символов, зачастую даже без указания типа штрихкода (такие замечательные сканеры тоже бывают).

В этом случае мы бессильны улучшить результат. 11 символов могли прийти от сканирования любого другого типа штрихкода, мы не можем считать все штрихкоды как EAN-13. Чтобы настроить сканер, человеку придется сканировать с листа настроечные штрихкоды или заходить в какие-нибудь меню, а всё это источники ошибок.

GS1 DataMatrix



Этот пример стал популярным благодаря введению обязательной маркировки товаров. История полна граблей, велосипедов и трупиков мелких животных, как сарай вашей бабушки.


Ну ладно, допустим с EAN-13 можно придраться и сказать, что первая цифра всё-таки есть в штрихкоде, просто она закодирована не совсем штрихами (хотя для лидирующего 0 это и не так).

Возьмем тогда другой пример, штрихкод GS1 DataMatrix "(21)abba01(01)04601200000003":

image

В этом штрихкоде внутри нет ни скобок, ни символа 0, ни буквы a, ни переноса строки.

Что тут происходит?

Во-первых, никакие скобки в штрихкод не кодируются, они печатаются только для удобства прочтения человеком. Это снова называется Human readable interpretation (HRI), привет, кожаный мешок.

Во-вторых, в штрихкоде есть специальные управляющие символы, которые должна расставить та программа, которая формирует данные для штрихкода. Не какая-то бесплатная opensource программа, написанная умными очкариками, а ваша программа, та самая, которую пишете Вы, мой друг. В этот раз символы, которые нужно вставить, не имеют отношения к коррекции и т.п., а размечают данные, которые нужно закодировать в штрихкод.

В самом начале в штрихкод вставляется управляющий символ, который называется FNC1 и имеет код 232, что соответствует либо странному печатаемому символу "" (ANSI), либо русской букве и (Windows-1251), смотря какую кодировку использовать. Этот символ говорит, что у нас не просто абы какой DataMatrix, а именно GS1 DataMatrix, данные в котором имеют определенный формат: массив данных из пар (код поля, значение поля).

Этот управляющий символ FNC1 попадает в самое начало штрихкода, но его нельзя передать в штрихкод в составе данных.

Кроме того, непечатаемые символы, вполне очевидно, нельзя копипастить в составе строки, хаха! Страдай, кожаный мешок!

Указание, нужен префикс или не нужен, обычно передают как отдельную настройку (галочку) в программу формирования штрихкода. Если передать префикс как часть данных, то получим либо ошибку, либо два префикса в штрихкоде (в зависимости от используемой программы).

Далее, поскольку в штрихкоде внутри нет скобок, то уже непонятно, где кончается одно поле и начинается другое, где тут номера полей. Без скобок получается 21abba010104601200000003 (тут 01 встречается три раза, ха-ха).

Где заканчивается 01 из значения поля (21) и начинается настоящее (01)?

Это решается следующим способом:

По стандарту GS1 поля имеют формат. Не абы что, а формат значения. Например, значение для (01) должно состоять из 14 цифр и баста (нельзя 13 цифр, нельзя 12 цифр, нельзя не цифры). А поле (21), наоборот, имеет переменную длину, разрешены цифры, латинские буквы обоих регистров, знаки препинания и даже (опачки!) скобки.

Если после значения для (21) штрихкод не закончился, и там еще что-то есть, то в данные вставляется разделитель (это может быть снова или FNC1, или непечатаемый символ GS с кодом 29).

А общее правило звучит так: спецсимвол GS не вставляется, только в случае если AI начинается с пары цифр из этой вот таблицы:

image

Для всех остальных полей GS1 (не из этой таблицы) в конце значения нужно вставлять GS.

Т.е., мы получим FNC121abba01GS0104601200000003 (только помним, что первый FNC1 мы не будем передавать в программу формирования штрихкода, а второй GS это не строка GS, а один символ с кодом 29).

Эти требования именно про данные, а не про штрихкод DataMatrix, потому что в штрихкод DataMatrix можно положить любые данные, они прекрасно закодируются и прочитаются. Тут речь о GS1 DataMatrix, который имеет определенный формат, и ваша программа должна соблюсти этот формат, прежде чем подавать данные в штрихкод.

Вообще говоря, в мире существуют программы печати штрихкодов, которым можно скармливать данные со скобками и они сами всё разрулят. Но это специализированный софт, который стоит денег, а не тот бестолковый и бесплатный онлайн-генератор штрихкодов, которым вы пользуетесь.

И наконец. То, как это будет напечатано и то, как это будет отсканировано, две большие разницы. То, как данные печатаются под штрихкодом, и как они передаются сканером это в чистом виде настройки принтера и сканера.

В нашем примере мы закодировали в штрихкод поля порядке: сначала (21), потом (01), а на изображении под штрихкодом распечаталось сначала (01), потом (21). Это снова называется Human readable interpretation (HRI), и порядок вывода в подписи соответствует правилу потому что так принято.

Сканер штрихкодов тоже имеет свои настройки, которые заставляют его переставлять поля, вставлять скобки и другие символы, переносить строки и т.п.

В большинстве случаев сканер прочитает наш штрихкод как 21abba01GS0104601200000003. Никакого лидирующего FNC1, никаких скобок, GS не печатаемый и не виден в Блокноте (нужно использовать хотя бы Notepad+).

И принтер, и сканер могут делать со штрихкодами что хотят: добавлять и убирать символы, менять их местами ради соответствия гайдлайну или для совместимости со сторонней программой.

Что еще интересно: в этом штрихкоде только 16 байт данных (на 24 символа без скобок).

Вот что тут происходит:

пары подряд идущих цифр кодируются одним байтом;
все отдельно стоящие цифры, не парные, а также все символы из таблицы ASCII (а это символы с кодами с 0 по 127, без русских букв, и печатаемые, и непечатаемые) кодируются в штрихкод как (значение байта символа)+1.

Т.е. чтобы закодировать a, нужно записать в штрихкод b, чтобы закодировать 1, нужно записать 2 и т.д., именно поэтому прямо в самом штрихкоде нет байта 97 (значение буквы a в ASCII).

Итого, в приведенном штрихкоде закодировано в байтах 232, 151, 98, 99, 99, 98, 131, 232, 131, 134, 190, 142, 130, 130, 130, 133. И это еще до кодов коррекции и паддинга!

Непонимание процесса кодирования приводит к тому, что, например, для начавшейся обязательной маркировки обуви люди печатают на принтер неправильно сформированные данные и получают неправильные штрихкоды, которые выглядят вполне нормально, читаются приложением Честный знак, но данные в них неверные, как минимум это не GS1 DataMatrix.

Штрихкоды неправильно напечатаны, неправильно читаются, и такая обувь не считается правильно промаркированной.

В своем софте Кировка мы боремся с этим следующим образом: для печати принимаем в качестве исходных данных любой мусор, пытаемся распарсить его как GS1 DataMatrix, разбираем на косточки. Если всё прошло удачно, то конвертируем в правильный формат, чтобы принтер это понял; а при сканировании перепроверяем данные от сканера, делая таким образом вывод о правильности печати.

Для этого нам, конечно, приходится работать на нативном уровне и со сканером мобильных устройств, и с принтерами, чтобы всё это было правильно ими интерпретировано, а мы собирали максимально полную информацию.

Выполним еще одно упражнение: посмотрим, какого размера должен быть штрихкод GS1 DataMatrix для хранения кода маркировки обуви и легпрома.

На сайте Честного знака написано, что код маркировки обуви должен содержать следующие поля (для легпрома те же требования):

Кода товара, 14 цифровых символов (GTIN).
Индивидуального серийного номера единицы товара, который генерируется оператором системы или участником оборота товаров, 13 символов (s/n).
Ключ проверки, предоставляемый оператором системы, 4 символа.
Код проверки, предоставляемый оператором системы, 88 символов.

Для каждого из этих полей в данных для штрихкода должен быть указан идентификатор применения GS1 (AI, application identifier).

image
Таблица codeword для DataMatrix.

image

Как видно, размер данных в теории может меняться в широких пределах от 68 до 118 байт. На практике разброс меньше, длина ближе к 118, потому что в серийном номере и в криптокоде мало цифр и много знаков препинания, включая скобки.

Согласно GS1 DataMatrix Guideline, такие данные укладываются в штрихкоды размером от 36х36 до 44х44 (колонок и строк битов, не миллиметров). В миллиметрах размер будет зависеть от разрешающей способности принтера (обычно это 203-600 dpi).

image
Таблица из GS1 DataMatrix Guideline

Пожалуй, достаточно.

А как же голая Эмма Уотсон? Рассмотрим в следующей статье.
Подробнее..

Неоконченная история QR-кода

21.03.2021 20:19:46 | Автор: admin

Мы встречаемся с ними всюду: на водосточных трубах жилых массивов и поручнях метро. В рекламных роликах крупных брендов и сервисах регистрации. Даже в видеоигре Alan Wake QR-коды, простите за каламбур, засветились в качестве пасхалок с дополнительным контентом.

Чуть ли не ежегодно возникают убийцы QR-кодов, а им самим предрекают скорую гибель. Но уже не одно десятилетие люди продолжают пользоваться этими черно-белыми квадратиками. Зачем? Почему? Кто их придумал? Попробуем разобраться под катом.

Япония издавна славится разного рода изобретениями, призванными сделать бизнес-процессы и производственные задачи как можно более компактными и эффективными. В начале 1990-х годов перед инженерами крупной машиностроительной компании Denso стояла нетривиальная задача: создать унифицированный штрих-код (или нечто подобное) для маркировки деталей и компонентного сканирования. На тот момент внутри компании были приняты более 10 кодов разного назначения, и сотрудники завода жаловались на то, что работа с кодами требует большой концентрации, а сами коды содержат чрезвычайно мало полезной информации.

При этом нельзя сказать, что проблема эта носила частный характер: по всей стране компании разрабатывали собственные варианты штрих-кодов, силясь впихнуть в них как можно больше данных.

Китайские шашки и японская смекалка

Масахиро Хара, сотрудник отдела разработки Denso Wave, в 1992 году взялся за решение этой задачи. Новые коды должны были отвечать следующим требованиям:

  • объем информации, которую возможно хранить в коде, должен существенно возрасти;

  • процесс считывания должен быть как можно более точным и быстрым;

  • сами коды должны быть устойчивы к пятнам от масла, грязи и прочим повреждениям;

  • считывающее устройство должно быть простым и дешевым.

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

Ключевое отличие QR-кода от традиционного штрихкода он распознается сканером как двумерное изображение. Для нормализации изображения при считывании и снижения вероятности ошибки код содержит несколько крупных квадратов в одном из углов, а также множество более мелких синхронизирующих точек, рассредоточенных по всей площади кода. Забавный момент: спецификация QR-кода описывает только сам принцип построения кода, но не формат данных, зашифрованных в нем. Это создает целое поле для экспериментов, которые не кончаются по сей день.

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

К 1994 году новый формат кода (Quick Response Code) был повсеместно внедрен на заводах производственной цепочки автоконцерна Toyota, но быстро перетек из цехов в другие бизнес-сферы. Масахиро Хара вспоминает, что вплоть до презентации нового формата кода он не был уверен, что его детище приживется в компании. Да, скорость считывания данных и надежность формата не вызывали сомнений, однако 2D-сканеры могли стать серьезным препятствием на пути внедрения технологии. Тем не менее код был воспринят и главами, и рядовыми сотрудниками корпорации очень тепло. В течение следующего месяца удалось успешно внедрить его в собственную Kanban-программу Toyota.

Не секрет, что японцы любят свои изобретения и не выпустят любимую игрушку из рук, пока не появится её более технологичный наследник. То же произошло с QR-кодами: с 2002-2003 года их стали применять в ресторанах для маркировки контейнеров, в делопроизводстве. Известны также случаи применения QR-кодов в школах, музеях и на кладбищах.

QR-коды захватывают мир

Простота и удобство кода понравились людям и за пределами Японии. К середине-концу 2000-х годов о японском изобретении узнал весь мир. При этом фраза-обозначение QR code является зарегистрированным товарным знаком, принадлежащим компании-изобретателю, однако использование самих кодов не облагается отчислениями.

Говорить о версиях QR-кодов можно достаточно долго: существуют и маленькие версии (21х21px), и более крупные 177х177px. Вот основные принятые во всем мире кодировки данных:

  • цифровая кодировка, до 7089 цифр;

  • алфавитно-цифровая кодировка, до 4296 символов (или до 2953 символов с поддержкой кириллицы);

  • байтовая кодировка, до 2953 байт;

  • кодировка кандзи, до 1817 иероглифов.

Кроме того, существуют и более экзотичные, практически не прижившиеся форматы: например, для описания графической и аудиоинформации.

Опустим технические моменты, лежащие в основе принципа QR-кода: этой информации и на Хабре, и за его пределами предостаточно. Гораздо интереснее сконцентрироваться на том, как эти коды используются вне рамок бизнес-задач.

Примечание: QR-коды ниже представлены исключительно для демонстрации технологии. Автор статьи не несет ответственности за их содержание сканируйте на свой страх и риск :)

Двумерный креатив

Игра с цветом

Современные смартфоны и считывающие устройства куда меньше зависят от четкости изображения кода, нежели их предшественники. Благодаря этому стало возможно раскрашивать QR-коды в разные цвета и интегрировать их в дизайн продуктов. Ниже мы приведем несколько вариантов кода, удачно вписанных в разноцветные изображения.

Игра с формой

Закругленные QR-коды, коды, в которые вписаны изображения и логотипы также не новость. Чтобы устройства могли разобрать нестандартные с точки зрения формы коды, применяется технология избыточного кодирования.

Особняком здесь стоят дизайнерские варианты QR-кодов: это не просто вписывание квадратика с изображением в поле кода, это целое произведение искусства. Ну, почти искусства.

Коды с нестандартной ориентацией в пространстве также не новы.

Кроме того, периодически можно встретить анимированые QR-коды, однако это, скорее, модная диковинка, нежели оправданное использование технологии.

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

Игры с применением

Открытки, футболки, бижутерия с памятными шифровками даже сюда добрались QR-коды.

Открытые выставки и уличные библиотеки используют QR-коды: чаще всего в них шифруются основные данные о художниках, писателях и музыкантах, а по сокращенной ссылке можно скачать копию того или иного произведения.

Ритейл не остался в стороне: в QR-кодах шифруются коды скидочных купонов и номера карт для программ лояльности. Впрочем, здесь у QR-кода есть сильные конкуренты, например, NFC-решения.

QR-коды все еще популярны среди рекламодателей: в кодах шифруются адреса сайтов и ссылки на скачивание приложений своеобразная попытка перевести пользователей из оффлайна в онлайн.

Сомнительное решение наручные часы, которые показывают время в зашифрованном варианте.

Туристические достопримечательности во многих городах снабжены не только соответствующими табличками, но и QR-кодами. Это позволяет, с одной стороны, сохранить аутентичность памятника, с другой снабдить его дополнительной информацией для иностранных туристов, которые не могут прочитать оригинальную надпись.

Японская виза здесь без комментариев. :)

Визитки для быстрого обмена контактами не обязательно иметь под рукой бумагу и ручку (или записную книжку на смартфоне). Достаточно считать код, и данные о бизнес-партнере автоматически появятся на устройстве.

Татуировки опять же, без комментариев. Главное, чтобы мастер ничего не напутал. Агент 47 шлет пламенный привет.

Архитектуру культура QR-кодов также не обошла стороной. Выполненные в QR-стиле здания вряд ли можно считать полнофункциональными носителями информации, скорее это дань моде.

Проект бизнес-центра в ОАЭПроект бизнес-центра в ОАЭ

Киса и Ося были тут: QR-коды используются также в так называемой психогеографии. Люди записывают свои мысли, ассоциации и воспоминания, связанные с разными местами, и распространяют их в виде QR-кодов.

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

Игры с содержанием

Пароли от гостиничного Wi-Fi, географические координаты, ссылки на меню это весьма традиционные варианты использования кода. Как насчет чего-то более интересного?

Сервис QRInfoPoint предлагает достаточно забавное решение для передачи музыки, фото или видео через QR-код. Задумка проста и элегантна: разумеется, вместить целый аудио-файл в код не получится, однако вполне возможно залить его на сервер (или воспользоваться уже существующей ссылкой, например, на YouTube), а в код интегрировать адрес html-странички с соответствующим тегом и атрибутом src, по которому будет загружена и проиграна композиция.

Симпатичные QR-коды использует Nintendo в играх серии Pokemon (и некоторых других) для передачи информации, обмена покемонами и многого другого.

Совершенно сумасшедший, но работающий QR-код. Опять же, в стилистике Nintendo.

Попытка зашифровать в QR-коде целую игру:

Убийцы и прочие родственники QR-кода

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

Приложение PhonoPaper позволяет зашифровать аудио до 10 секунд в изображении или произвести расшифровку.

Приложение Честный знак для проверки подлинности товаров и получения дополнительной информации по различным кодам.

Кроме того, с успехом выполняют задачи, возложенные маркетологами и любителями фана на QR, технологии дополненной реальности, NFC и биконы.

Clickable paper проект, нацеленный на получение дополнительной информации из печатных материалов.

Убийца QR-кодов SnapTag обведи логотип кружком, и дело в шляпе.

Это далеко не полный список технологий, чья задумка перекликается с идеей QR-кода. Но пока что почти тридцатилетняя технология не сдает позиций напротив, обрастает новыми формами и применениями, как в реальном бизнесе, так и в среде фан-сервисов. Возможно, мы еще им просто не наигрались.

Подробнее..

Штрих-код

16.05.2021 12:20:18 | Автор: admin
image

Редкие гуляющие в межсезонье 1948 года по пустынному флоридскому пляжу, которые могли наблюдать невысокого подвижного человека в очках, с очень живым лицом, что-то рисующего на прибрежном песке, и представить себе не могли, что на их глазах творится история.
Но тем не менее, это было именно так, ибо молодой человек был Норманом Вудлендом, а то, что он начертил на песке, мир когда-то узнает как шрих-код.

Сама идея создания универсального кода, в котором была бы зашифрована информация о товаре, была подслушана товарищем Вудленда, Бернаром Сильвером, причем подслушана буквально: он стал свидетелем разговора своего декана (Вудленд и Сильвер учились тогда в аспирантуре) с директором супермаркета, который спрашивал, способны ли ученые создать систему, позволяющую мгновенно регистрировать покупку и вести учет товара.
Декан от такой задачи отказался, а Вудленд и Сильвер буквально загорелись этой идеей: она показалась им вполне решаемой, а её будущее великолепным.

image

Супермаркет в США, 60-е г.г. Любой торговец скажет, что скорость оборота один из самых главных факторов успеха в торговле, а в розничной торговле на скорость оборота влияют быстрота заказа реализованного, быстрота выкладки товара и быстрота обработки покупок

В самом деле, торговле подобная система была нужна как воздух слишком уж огромное количество действий приходилось совершать торговому персоналу для учета товара.
Приемка товара, финансовая отчетность, рекламации, пополнение товарного запаса, анализ спроса все это велось тогда вручную, отсюда и бесконечно раздутые штаты бухгалтерии и грузчиков, продавцов и кассиров, постоянные сверки и переучеты, а значит дополнительная финансовая нагрузка на магазины того времени.

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

Вудленд и Сильвер, впрочем, быстро убедились, что их декан был прав: задача оказалась совсем не банальной.
Но задача уже полностью захватила молодых людей. В 1948-м Вудленд прерывает свою учебу в аспирантуре, которая мешает ему сосредоточится на решении целиком, и уезжает в Майами, к своему деду.
И там к нему в самом деле приходит решение: он вспоминает вдруг, как в свои бойскаутские времена он изучал азбуку Морзе. Песок пляжа, на котором он пробует изобразить точки и тире, наталкивает его на мысль о передаче содержания с помощью линий различной толщины.
Кодировку надо было как-то считывать, и Вудленд и Сильвер придумали использовать для этого технологию передачи звука в кино, придуманную за два десятка лет до них Лу де Форестом, которая заключалась в просвечивании разной интенсивности цвета, наносимого по краю кинопленки.
Уже в 1949 году друзья получили патент на свое изобретение (их код выглядел как яблоко, полоски расположены были по кругу), и

image

Одна из первых разработок Вудленда и Сильвера. Штрих-код здесь располагается по кругу, в этом авторы видели определенный плюс. Появившийся позже сканер изменил расположение полосок

Нет, мир не стал мгновенно счастливее: на этапе конструирования, уже работая в IBM, куда их пригласили как авторов приглянувшейся руководству компании перспективной идеи, изобретатели столкнулись с проблемой считывания кода, а точнее с проблемой создания адекватного устройства.
Их первый сканер представлял из себя устройство размером со стол, крышка которого была прозрачной, а под крышкой были мощные лампы. Получаемый сигнал передавался на осциллограф, который должен был фиксировать результат.
Первые испытания закончились пожаром: лампы раскалили крышку, бумага задымилась, но, тем не менее, первый результат был получен.
Увы, он не удовлетворил ни самих изобретателей, ни торговлю.

Прекрасная идея, как оказалось, несколько опередила время: проблема считывания кода выглядела нерешаемой, и тем более не решаемой была проблема обработки полученной информации. Эта задача возлагалась на ЭВМ, но ЭВМ тех лет были чрезвычайно громоздки и еще только учились решать задачи сложнее арифметических действий.

Казалось, на коммерческой реализации проекта был поставлен крест, в IBM официально закрыли проект, Вудленд и Сильвер продают свой патент в компанию RCA за скромные $15000.
RCA вцепляется в идею шрих-кода, и много лет экспериментирует с ней, пробуя заинтересовать им торговлю.
Они первые догадались применить для сканирования кода лазер: тонкий гелиево-неоный луч прекрасно подходил для распознавания кода.
У компании есть и первые, пусть и скромные, успехи: их кодом начинают (пусть и не без проблем) пользоваться при железнодорожных и морских перевозках.
В конце концов, их активность оказывается замеченной: в начале 70-х американский союз супермаркетов объявляет конкурс на лучший код.

image

Норман Вудленд, Джодж Лорер и Бернар Сильвер, создатели штрих-кода

Корпорация IBM мгновенно возвращается в игру задача кажется чрезвычайно привлекательной для использования потенциала компании.
Создается рабочая группа по руководством отличного инженера и прекрасного руководителя Джорджа Лорера. Вместе с математиком Дэвидом Савиром они приступают к решению.
Тут кто-то из ветеранов IBM вспоминает про двух талантливых ребят, занимавшихся у них этой проблемой в 50-е.
Сильвера к тому времени уже нет в живых, но Вудленд не растерял своих способностей, и он с азартом включается в работу.

Лорер находит ахиллесову пяту концентрического кода, и предлагает вместо него линейный: это очень упрощает процесс сканирования и резко повышает его качество, количество ошибок при считывании резко снижается. Однако решено добавлять еще и цифровой код, который позволял бы, в случае отказа системы, ввести код вручную, и добавил защитный код в конце полосы.
Можно сказать, что Лорер блестяще отшлифовал лучшие идеи, привнеся свои, и к тому же объединил в итоговом продукте все современные технические достижения.

В итоге именно простое и элегантное решение от IBM пришлось по вкусу американской торговле, и 3 апреля 1973 года считается рождением UPC (Universal Product Code).
В 1974 году состоялась первая продажа товара с отсканированным штрих-кодом.
Американская розница тут же предложила своим поставщикам наносить штрих-коды на упаковку, а производители скоро и сами оценили удобство такой маркировки, которая позволяла им четко отслеживать отгрузку и движение товара.

Как и все, пусть даже самые прекрасные изобретения, штрих-код распространяется не мгновенно: еще в 1979 году всего лишь 1% американских продавцов пользуется этой технологией, но уже в начале 80-х число пользователей превышает 90%, а к середине того же десятилетия в США уже не остается торговых точек, которые не использовали бы штрихкодирование.

image

США, середина 70-х, сканирование покупок на кассе. Надо сказать, в те годы это всё ещё большая экзотика

IBM, конечно, не останавливается только на кодировании, предлагая комплексное решение, которое и стало определяющим в успехе идеи: кассы, материалы и техника для нанесения кода, сканер (в разработке лазеров компания была одним из чрезвычайно заметных фигур) и, конечно же, компьютер и программы для учета.
Спрос и предложение движутся навстречу друг другу: американский ритейл заметил, что вложения в новые технологии первопроходцев окупились меньше чем за два года и выстроился в очередь за новой технологией, масштабирование же, в свою очередь, сильно снизило стоимость переоборудования.

Необходимость стандартизации приводит с созданию специального органа по предоставлению и классификации штрих-кода UCC.

image

Первый в мире продукт со штрих-кодом

Говорят (чего только не расскажут!), что жена Лорера каждый раз, приходя в магазин, с гордостью говорила кассирам и покупателям: Это штрих-код, его придумал мой муж!. Её, кажется, забавляло недоумение буквально всех, кому она говорила об этом мол, а что, когда-то были времена, когда штрих-кода не существовало?

Разумеется, такие времена были, и, может быть, кто-то из нас их даже сможет вспомнить: в СССР первая покупка товара со штрих-кодом состоялась в 1990 году, а сам штрих-код стал заметным (но даже тогда еще не всеобщим) явлением в нашей стране только к XXI веку.

В настоящее время у него появляются конкуренты: RFID, QR и несколько менее известные форматы.
Но при всем этом позиции штрих-кода выглядят незыблемыми: сегодня каждый день в мире сканируется более 6 млрд. штрих-кодов.

Александр Иванов, специально для блога VDSina



На правах рекламы


Воплощайте любые идеи и проекты с помощью наших VDS Windows или Linux. Сервер готов к работе через минуту после оплаты!

Подписывайтесь на наш чат в Telegram.

Подробнее..

Декомпилируем приложение xiaomi сканер и забираем результат сканирования

18.08.2020 12:17:00 | Автор: admin
У коллеги возникло предложение:
Напиши мне за банку чипсов распознавалку штрих-кодов на андроид, чтобы просто в файлики результаты писать и время, брату надо
В итоге оказалось не брату, да и не надо, и вообще банка чипсов это дорого
Из интереса пробежался по готовым решениям на js и android, и т.к. у меня смартфон xiaomi с готовым приложением сканером, подумал, почему бы не попробовать просто забирать результаты сканирования из него?
Ок, пробовал погуглить инфу об интентах или готовую инструкцию по получению данных из сканера, но тщетно.
Решено провести разведку манифеста приложения на наличие интентов.

  1. Находим и забираем APK с телефона.
    adb shell~:/pm list packages | grep scanner~:/pm path com.xiaomi.scannerexitpull /system/priv-app/MiuiScanner/MiuiScanner.apk
    
  2. Декомпилируем apk с помощью онлайн сервиса.
  3. Исследуем манифест.
    Находим первый попавшийся по смыслу экшн.
    AndroidManifest.xml

  4. Создаем новый android проект и пишем вызов сканера.
      val intent = Intent("miui.intent.action.scanbarcode")   startActivityForResult(intent, 1);
    
  5. Запускаем приложение, делаем вызов и
    запускается сканер и дает спокойно работать, но нужно получить результат, как? Видимо нужен корректный код запроса, или дополнительные данные в интенте. Анализируем декомпилированные исходники в части обработки интентов и попадается следующее.
    ScanActivity.java

    Судя по всему нужно добавить булево значение в интент.
  6. Ищем нужное имя ключа, которое лежит в EXTRA_INTENT_IS_BACKTO_THIRDAPP и находим isBackToThirdApp.
    AppUtils.java

  7. Переписываем код вызова сканера.
      val intent = Intent("miui.intent.action.scanbarcode")  intent.putExtra("isBackToThirdApp",true)  startActivityForResult(intent, 1);
    
  8. Забираем результат.
            super.onActivityResult(requestCode, resultCode, data)        if (resultCode==Activity.RESULT_OK){                result.setText(data?.extras?.getString("result"))        } 
    
  9. Короткое видео с примером работы приложения.
  10. Интерес удовлетворен, и теперь мы можем пользоваться результатами родного Xiaomi приложения и сосредоточиться на описании своей логики работы с результатами, поедая чипсы
Подробнее..

Мой штрихкод. Code128

14.06.2021 12:13:27 | Автор: admin

Однажды в процессе производственной деятельности у меня появилась необходимость генерации штрихкода по стандарту code128. Появилась в виду того, что имевшаяся в эксплуатации функция (хранимая процедура в базе Oracle) генерировала клёвый, полосатый штрихкод, который читался не во всех случаях. Разработчики в своё время оттестировали эту процедуру весьма некачественно, но перерабатывать уже не собирались т.к. проект был давно сдан, а потребности в считывании так и не появились.

Первая мысль поиск готовых библиотек. Навскидку определили критерии с pl/sql не связываемся, пусть это будет внешний сервис: возможно кусок на javascript для генерации прямо на страничке, либо обращение за картинкой к ближайшему серверу где имеется php. Беглый поиск в интернете показал что тема истоптана весьма плотно. Есть как наколенные поделки уровня лабораторки по программированию, так и мощные библиотеки для всех вариантов кодирования вплоть до qr-кодов. Варианты с JavaScript пришлось отбросить т.к. они во-первых практически все обфусканы (даже непонятно, то ли для сокращения объема, то ли стыдно исходники показать), во-вторых генерируют строку для отображения определенным шрифтом, наличие которого не всегда можно обеспечить на клиентском месте и требует дополнительных обработок для экранирования спецсимволов. Внимательное изучение библиотек и кусков кода на php тоже произвело тягостное впечатление на первый взгляд всё вроде бы правильно: и классы написаны на все случаи жизни, комментарии в наличии, украшательства типа выбора цвета и рамочек, примеры подготовлены. Начнёшь вникать хотят либо php самой распоследней версии (на боевых серверах не всегда это получается добыть), либо внутренняя логика не различима совсем, либо штрихкод на выходе получается длиннее ожидаемого. Вот последнее не дало покоя и подтолкнуло к собственной реализации.

Самое время пощупать теорию. Вернее мы с ней познакомились намного раньше, просто до последнего не хотелось ввязываться в дополнительное программирование. Исторические факты опустим, а вот очень хорошее техническое описание имеется на http://code128.narod.ru/ (в архиве это файл Descript.doc ) либо в Википедии. В принципе, это всё что нам потребуется для понимания и собственной реализации алгоритма (тут я немного лукавлю из любой готовой библиотеки нужно выдрать таблицы толщин штрихов, чтобы не вбивать их вручную). Ну и напишем всё это безобразие на php, заодно посмотрим пару прикольных моментов, про которые все забывают или стесняются использовать.

Теория гласит, что code128 позволяет закодировать (сюрпрайз!) 128 символов, при этом нам доступно 3 алфавита, между которыми можно переключаться по ходу дела. Наибольший практический интерес представляют алфавит B для буквенно-цифровых символов и алфавит С который используется для кодирования цифр, но с некоторой оптимизацией одним штриховым символом можно закодировать 2 исходных символа и получить более короткий штрихкод. Вот эта оптимизация пока не даётся ни одному php-разработчику максимум что я видел это попытка в начале кодирования определить состав строки и при наличии только цифр переключаться на алфавит С. В остальных библиотеках это банальная подстановка символов штрихкода по таблице.

Для начала осмотрим приборы и материалы в начале строки можем задать алфавит для кодирования, перед каждым символом можем переключить алфавит. Также мы на входе ограничены по длине строки - это очень хорошо и важно для нас. Имеем цель получить штрихкод. Точнее, самый короткий штрихкод.

Разберём пару примеров. Допустим у нас есть последовательность ABC12DE попробуем её закодировать разными методами, на примере изображены слева только алфавит B, справа - совместно B и С:

Наша попытка оптимизировать длину кода используя более короткий алфавит потерпела фиаско - мы получили дополнительные символы на переключениях алфавита и в результате штрихкод стал на 1 символ длиннее. Если хорошо подумать, то переключение на алфавит С выгодно при наличии 6 и более цифр подряд. Но есть ведь и граничные случаи цифры в конце последовательности, в начале, а есть еще вариант с нечетным количеством цифр и тогда надо пристально смотреть когда переключаться на алфавит С с первой цифры или со второй? В общем вариантов достаточно много, что в итоге у большинства отбивает желание оптимизировать длину кода, а делать всё одним алфавитом.

И вот тут нас озаряет, что работа с рекурсивной функцией избавит нас от рассмотрения всех этих условий и задача станет невероятно простой функция будет вызывать сама себя с тремя вариантами кодирования текущего символа и возвращать наиболее короткий (итоговый) вариант. Причём длина варианта включает в себя и символ переключения между алфавитами. Причин отказа от захода в ветку алгоритма совсем немного либо кончился входной поток, либо мы не можем закодировать символ(ы) данным алфавитом (например нет 2-х цифр для алфавита С). Так, как входной поток имеет ограничение по длине, то дерево не будет расти бесконечно! По тексту будем реализовывать только алфавит B и C - проще для понимания и потом объясню остальное :)

Сразу набросаем простейший класс который содержит сам текст, такие-же классы для рассмотрения вариантов по алфавиту B и С, длину последовательности. Делаем ему минимальный конструктор на входе строка для кодирования, режим кодирования, ссылки на потомков. В начале конструктора добавляем проверки, чтобы не прорабатывать данную ветку дерева:

<?phpclass code128 {    private $code = '';    private $leafB = NULL, $leafC = NULL;    public function __construct($text, $mode = 'B')    {if (strlen($text) == 0) return NULL;$this->mode = $mode;if ($mode == 'B') {    $this->code = substr($text, 0, 1);    $text = substr($text, 1);}else if ($mode == 'C') {    if (strlen($text) < 2) return NULL;    if (!is_numeric($text[0])) return NULL;    if (!is_numeric($text[1])) return NULL;    $this->code = substr($text, 0, 2);    $text = substr($text, 2);}else    return NULL;$this->leafB = new code128($text, 'B');$this->leafC = new code128($text, 'C');    }    public function draw()    {echo "Code [" . $this->code . "]\n";if ($this->leafB != NULL) $this->leafB->draw();if ($this->leafC != NULL) $this->leafC->draw();    }}    $n = new code128('s92317lsdfa4324', 'B');    $n->draw();?>

и сразу ловим конкретный косяк куча "пустых" объектов. И это не смотря на то что мы явно отказались создаваться и вроде как железно возвращаем NULL! В общем сразу надо понять, что в php объект создаётся в любом случае. Полагаю что также и в остальных объектно-ориентированных языках. И все эти условия надо проверять перед созданием объекта. Следовательно правильный конструктор будет выглядеть примерно так:

    public function __construct($text, $mode = 'B')    {$this->mode = $mode;if ($mode == 'B') {    $this->code = substr($text, 0, 1);    $text = substr($text, 1);}else if ($mode == 'C') {    $this->code = substr($text, 0, 2);    $text = substr($text, 2);}if(strlen($text)>0) $this->leafB = new code128($text, 'B');if(strlen($text)>1)    if(is_numeric($text[0]) && is_numeric($text[1])) $this->leafC = new code128($text, 'C');    }

Не считая того, что мы избавились от пустых объектов, код получился даже немного короче чем прототип. Дальше начнём немного оптимизировать - добавим небольшой трюк: вместо того чтобы делать кучу проверок является ли последовательность символами, цифрами, их количество и т.д. просто смотрим в таблице наличие такого индекса в алфавите. Я уже писал что таблицу можно добыть в любой библиотеке реализующей кодирование code128? В общем напоминаю ещё раз, и готовый кусочек кода, который мне уже нравится, приведен ниже:

if($mode == 'B') list($this->code, $text) = sscanf($text, '%c%s');if($mode == 'C') list($this->code, $text) = sscanf($text, '%2d%s');if(strlen($text)>0)    if(array_key_exists(substr($text, 0, 1), $symCode)) $this->leafB = new code128($text, 'B', $this);if(strlen($text)>1)    if(array_key_exists(substr($text, 0, 2), $symCode)) $this->leafC = new code128($text, 'C', $this);

$symCode - это алфавиты, которые я загнал в файл tables.php и включаю его через require в начале исходника. Формат простой - символ алфавита => код штрихкода.

$symCode = array(/*alphabet Balphabet C */' ' => 0,'00' => 0,'!' => 1,'01' => 1,'"' => 2,'02' => 2,'#' => 3,'03' => 3,'$' => 4,'04' => 4,'%' => 5,'05' => 5,'&' => 6,'06' => 6,

Дерево строится, но результата пока не видно. Следующим этапом необходимо определить самую короткую ветку: Первый вариант - заводим в классе счётчик и увеличиваем его при каждом переходе на ветку. Как только достигнем дна (конца исходного текста), на концах дерева будет указан размер финального кода. Второй вариант конечные веточки ставят себе размер 1, а дальше родитель решает какой из потомков имеет код короче и ставит себе размер на 1 или 2 больше. Почему на 2? Надо учитывать накладные расходы на переключение алфавита. Кстати и в первом варианте это тоже надо учитывать. В итоге в корне дерева будет длина самой короткой последовательности. Чем хорош первый вариант? Получение итоговой последовательности практически мгновенное возвращаешься по папе к корню дерева. Ну и недостаток чтобы найти самую короткую ветку надо сделать полный обход дерева. Второй вариант длина самой короткой последовательности известна и находится в одном месте, но получение последовательности чуток посложнее, хотя и не требует полного обхода. Попробуем проработать первый вариант доделать надо совсем немного, просто родитель после создания потомков должен выбрать самого короткого потомка и сохранить ссылку на конечный элемент ветки. Выразился невероятно коряво, но Вы посмотрите код - там ещё страшнее :)

require 'tables.php';class code128 {    private $code = NULL;    private $text = '';    private $mode = 'Auto';    private $len = 1;    private $leafB = NULL, $leafC = NULL, $parent = NULL, $minCode = NULL;    public function __construct($text, $mode = 'Auto', $parent = NULL)    {global $symCode;$this->parent = $parent;$this->text = $text;$this->mode = $mode;if($parent != NULL) {    $this->len = $this->parent->len + 1;    if($this->parent->mode != $mode) $this->len++;     }    if($mode == 'B') list($this->code, $text) = sscanf($text, '%c%s');    if($mode == 'C') list($this->code, $text) = sscanf($text, '%2d%s');    if(strlen($text)>0)       if(array_key_exists(substr($text, 0, 1), $symCode)) $this->leafB = new code128($text, 'B', $this);    if(strlen($text)>1)       if(array_key_exists(substr($text, 0, 2), $symCode)) $this->leafC = new code128($text, 'C', $this);    if($this->leafB == NULL && $this->leafC == NULL) $this->minCode = $this;    else {       $this->minCode = ($this->leafB != NULL) ? $this->leafB->minCode : $this->leafC->minCode;       if($this->leafC != NULL)        if($this->minCode->len > $this->leafC->minCode->len) $this->minCode = $this->leafC->minCode;    }    return $this;     }

Итак, худо-бедно мы нашли самый короткий путь (штрихкод). Надо его вывести для начала на экран. Делаем в два этапа: сначала от потомка возвращаемся к родителю. Итоговые символы, включая переключение между алфавитами, пушим (push) в массив. Да, в PHP есть такая функция, и она позволяет нам сделать из массива довольно удобный стэк.

 private function getCode() {$stack = array();$p = $this->minCode;while($p != NULL) {    array_push($stack, $p->code);    if($p->parent != NULL) {if($p->parent->mode == 'Auto') { array_push($stack, 'Start'.$p->mode); break;}if($p->mode != $p->parent->mode) array_push($stack, 'Code'.$p->mode);    }    $p = $p->parent;}return $stack;  }

Когда потребуется вывести строку используем array_pop. Таким образом, мы по прежнему используем данный массив как стэк и легко выводим информацию в обратном порядке. Попутно готовим дополнительную обвязку для нашего штрихкода старт/стоп/контрольная сумма.

Финал совсем близко - я уже устал писать, Вы устали читать. Предлагаю пробежаться весьма бегло. Само рисование сделано в виде SVG. Для данной задачи весьма удобно нет необходимости кодировать размеры изображения, они будут задаваться тэгами на страничке. Кроме того, рендеринг и масштабирование осуществляется конечным устройством, что обеспечит необходимое качество в dpi соответствующее устройству вывода.

  private function printPattern($code, $posX, $res, $height)  {for($i = 0; $i < strlen($code); $i++) {    $w = $res*intval($code[$i]);    if(!($i%2))echo "  <rect x='$posX' y='0' width='$w' height='$height' fill='#0'/>\n";    $posX += $w;}return $posX;   }   public function printSVG($resolution=1, $height=50)   {global $symCode;global $barPattern;$s = $this->getCode();$pos = 1;$offset = $resolution*11;$width = ((count($s) + 4)*11 + 2)*$resolution;echo "<svg xmlns='http://www.w3.org/2000/svg' width='$width' height='$height'>\n";$start = $symCode[array_pop($s)];$checksum = $start;$offset = $this->printPattern($barPattern[$start], $offset, $resolution, $height);while(!empty($s)) {    $code = $symCode[array_pop($s)];    $offset = $this->printPattern($barPattern[$code], $offset, $resolution, $height);    $checksum += $code*$pos;    $pos++;}$offset = $this->printPattern($barPattern[$checksum%103], $offset, $resolution, $height);$offset = $this->printPattern($barPattern[$symCode['Stop']], $offset, $resolution, $height);echo "</svg>\n";    }

Появился глобальный массив $barPattern. Искать в файле tables.php рядом с $symCode. Кусочек приведу. Там всё просто - для заданного кода выходного символа чередуются толщины черных и белых штрихов:

$barPattern = array('212222',/* 0 */'222122',/* 1 */'222221',/* 2 */'121223',/* 3 */'121322',/* 4 */

Как этим пользоваться? В файл с классом в конец добавим пару строк:

    header('Content-Type: image/svg+xml');    echo "<?xml version='1.0' encoding='UTF-8' standalone='no'?>\n\n";    $n = new code128(html_entity_decode($_SERVER["QUERY_STRING"]));    $n->printSVG();

попробовать можно сразу, вставив в html-страничку примерно вот такой тэг:

<img src="barcode128.php?ad32324adsFAE13413ldsFf">

Ну и напоследок. Реализованы только алфавиты B и С. Уложился примерно в 100 строчек, не считая таблиц перекодировки. Реализовать алфавит А можно аналогичным способом просто дописав конструктор и таблицу с алфавитами, только желательно учесть один хитрый код, позволяющий кратковременно переключиться на один символ другого алфавита. Самому дописать у меня нет ни желания, ни времени, ни прочих мотиваций. (Полу)готовый проект вероятно пополнит кладбище штрихкодировщиков на гитхабе - если у кого есть желание продолжить проект - пишите, не стесняйтесь.

Подробнее..
Категории: Php , Штрихкод , Code128

Зачем нужна еще одна система распознавания баркода?

29.01.2021 18:07:40 | Автор: admin

В сегодняшней статье на Хабре мы расскажем про очередную задачу распознавания. Рассмотрим проблему распознавания штрихкодов, которая очень актуальна в связи с непрерывным развитием системы маркировки и системы оплаты товаров по QR-коду в 2021 году.

Штрихкод, или баркод, безусловно, является важным изобретением человечества, которое изменило течение нашей жизни. В одной из своих статей на Хабре мы ужерассказывали, как эволюционировал этот способ кодирования информации.

Сегодня не будем углубляться в техническую часть, а рассмотрим существующие проблемы при внедрении технологии распознавания баркодов. Действительно, откуда могут возникнуть проблемы, если штрихкодирование это такой особый способ кодирования данных, который как раз призван обеспечить быстрое и беспроблемное считывание данных машиной? Все алгоритмы декодирования баркодов разжёваны до самых мелочей. Задача декодирования баркодов отлично решается без использования каких-либо нейронных сетей и прочих страшилок нашего века. Кажется, что технология распознавания баркодов это тот космодром, с которого должны взлетать в счастливое будущее большое количество opensource-библиотек.

Оказывается, дело обстоит не совсем так. Первый звоночек о негодности всего бесплатного для решения задачи распознавания баркодов мы получили в виде очередного запроса от давнего клиента одного коммерческого банка (из топ-10), технологичности которого могут позавидовать многие. Коллеги продемонстрировали, что популярные бесплатные библиотеки категорически не справляются даже с QR-кодами. Про коды типа AZTEC даже говорить не приходится (этот вид баркодов, который встречается на платежках, визуально похож на QR-код, но при этом кардинально отличается от него по сложности декодирования).

Мы немного погрузились в задачу и очень быстро поняли, что практически все библиотеки сдали свои позиции на полпути, еще не дойдя даже непосредственно до распознавания. Ведь наибольшую трудность в задаче представляют точная локализация и ориентация распознаваемого штрихкода. На первый взгляд кажется, что задача должна решиться в два счета, так как у многих штрихкодов в структуре присутствуют специальные черно-белые квадратные мишени для локализации. Но мы-то с вами знаем, что задача цветовой константности, решение которой как раз и позволяет понять, какие объекты каким образом окрашены, совсем непроста. Да и мишени, кстати, не всегда черно-белые и даже не всегда квадратные (дизайнерские решения, эксплуатирующие разные цвета и форму, очень мешают задаче распознавания баркода).

Чтобы окончательно проникнуться сложностью задачи распознавания штрихкодов, представьте, какие артефакты возникают при движении камеры, фотографировании в темноте со вспышкой, пересъемке штрихкода с монитора, попытке распознать заламинированный штрихкод. А еще представьте, как выглядит штрихкод с огромным количеством данных внутри (можно даже не представлять, а просто взять квитанцию оплаты, например, за детский садик).

Кстати говоря, мы уже провели первый этап исследований задачи поиска штрихкода на изображении. Ознакомиться с нашими статьями в 2020 году по тематике можноздесьиздесь.

Есть еще одна причина, почему мы не остались в стороне от решения проблемы распознавания штрихкодов. В нашей стране семимильными шагами развивается технология оплаты по QR-кодам (в подтверждение моих слов смотрите, например, материал на vc.ruздесь,здесьиздесь). БудучиучастникамиГлобального договора ООН и ярыми приверженцами ответственного ИИ, мы просто не могли допустить, чтобы рынок не оценил всех преимуществ оплаты по QR из-за фактической неспособности имеющихся бесплатных библиотек распознавания. И не будем забывать про набирающую обороты Систему маркировки и прослеживаемости товаров. Все это натолкнуло нас на создание модуля распознавания штрихкодовSmart Code Engine.

Чтобы проверить эффективность получившегося решения, мы самостоятельно создали небольшой набор фотографий QR-кодов. Единственное требование фотографировать баркоды необходимо так, как это делают обычные пользователи. Ниже приводим примеры изображений из нашего датасета.

Как видите, изображения далеки от идеальных. Мы сравнили качество работы Smart Code Engine с двумя популярными opensource-решениями:OpenCV 4.5.1(библиотека компьютерного зрения с открытым исходным кодом, которую часто применяют при создании системы с ИИ) иZxing(библиотека с открытым исходным кодом для распознавания баркодов). В таблице ниже представлены результаты:

Продукт

Smart Code Engine

OpenCV 4.5.1

Zxing

Качество распознавания

99%

56%

81%

Как трактовать эти числа? Достаточно просто:

  • OpenCV серьезно проигрывает Zxing по качеству декодирования;

  • Smart Code Engine обеспечивает в 19 раз меньше ошибок, чем Zxing (с OpenCV даже и смысла сравнивать нет).

Возникает вопрос: А на чем ошибаются рассмотренные системы? Проведем анализ ошибок только для Smart Code Engine и Zxing. Ниже представлено единственное изображение, на котором ошиблось Smart Code Engine.

Действительно, непростой случай для систем машинного зрения (блики, геометрические искажения, сложный фон). Что же, будем работать дальше и повышать качество распознавания. Кстати, ZXing тоже не справился с этим изображением.

А вот несколько примеров, на чем ошибается ZXing. Тоже не самые простые случаи (серьезные проективные искажения, высокая плотность, сложный фон).

На сегодняшний день Smart Code Engine обеспечивает качественное распознавание одно- и двумерных штрих-кодов из различных счетов и квитанций, включая счета за коммунальные и государственные услуги, налоговых документов и счетов, а также билетов, чеков, счетов-фактур, ценников, плакатов и объявлений. Модуль чтения QR-кодов способен читать инвертированные коды, а также устойчив к любой ориентации. Текущая версия Smart Code Engine поддерживает распознавание QR Code, AZTEC, PDF 417, Data Matrix, codabar, CODE_39, CODE_93, CODE_128, EAN_8, EAN_13, ITF, UPC_A, UPC_E.

Smart Code Engine уже внедрен в мобильные приложения Тинькофф Банка, Рокетбанка, СДМ-Банка, Банка Санкт-Петербург. Мы уверены, это только начало.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru