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

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

Далее. Выбор наиболее четкой горизонтальной линии. Если этот штрихкод прочитан с мятого полиэтиленового пакета, он даже не будет прямоугольным, а полоски не будут прямыми - нужно выбрать горизонтальный фрагмент с наиболее подходящим для чтения куском. Тут, видимо, надо будет разбить на полосы по одному пикселю высотой и потом усреднить их с отбрасыванием "плохих" (деформированных) полос.
И только после всего этого уже все написанное.
Как-то так...
Можно узкой плоской, практический по диагонали, срезать штрих код, найти самый короткий штрих и в несколько итераций распознать код, пока он не совпадет с контрольной суммой. Это будет быстрее чем позиционировать код
unsigned
char*
Bits7 =
new
unsigned
char
[8];
выглядит что можно было и на стеке это дело оставить.
Крайне расточительно под нули и единицы выделять массив байт
Распознавание информации с изображения — действительно интересная и нетривиальная задача. На первый взгляд, штрихкод может казаться четким и читаемым, но при детальном анализе пиксельных данных часто возникают искажения, шумы и другие артефакты, усложняющие декодирование.
Вы взялись за масштабный проект, включающий предобработку изображения, поиск информативной области, коррекцию и непосредственно декодирование — а ведь даже интерпретация бинарной последовательности (например, "00010101110101001"
) уже представляет собой сложную подзадачу.
Возможно, вам будет полезно рассмотреть серию задач на распознавание азбуки Морзе, например, этот набор на Codewars. Анализ решений других участников может дать ценные идеи для обработки "зашумленного" сигнала в реальных условиях.
Также обратите внимание на избыточность в кодировании цифр. Например, 6- или 7-битное представление позволяет закодировать 64 и 128 значений соответственно, хотя для цифр требуется всего 10. Вероятно, такая избыточность заложена специально для устойчивости к искажениям.
Для повышения надежности распознавания можно рассмотреть алгоритмы сравнения последовательностей, такие как расстояние Левенштейна, которые помогают находить наиболее вероятное соответствие даже при наличии ошибок.
Именно устойчивость к искажениям является наиболее сложным аспктом чтения информации с изображений.
Еще похоже что в статье вы довольно мало прибегаете к библиотекам <numeric> и <algorithm> а они содержат немало полезных утилит преобразования данных. В частности функцию accumulate довольно удобно использовать для подсчета последовательных повторений в массиве. Если не использовать стандартные библиотеки, то возможно стоило бы перейти на чистый С.
Вы взялись за масштабный проект, включающий предобработку изображения, поиск информативной области, коррекцию и непосредственно декодирование — а ведь даже интерпретация бинарной последовательности (например, "00010101110101001") уже представляет собой сложную подзадачу.
Спасибо конечно за комментарий, но из всего сказанного я реализовал только декодирование в несколько этапов.
За подсказку функции accumulate отдельное спасибо. Надобно узнать что это за функция и для чего используется
Пишем сканер штрихкодов на c++