распознавание bar-кодов
Модератор: Olej
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
распознавание bar-кодов
Автоматическое распознавание bar-кодов, bar-коды - это обобщённое название штрих кодов (линейных), QR кодов (2-мерных) ... и ещё кой каких того же типа (хотя меня лично на пока интересуют только QR коды).
Довольно много публикаций и программных пакетов для этого в последние времена.
Само изображение кода может попадать в систему самым разнообразным образом: как файл имидж-формата, записанный где-то в другом месте (по сети, с фотоаппарата-смартфона, со сканера...) или как непосредственно фрейм изображения, захваченный с WEB-камеры на USB.
Отрабатывать это лучше, думаю, на стационарном Linux, но потом бы заманчиво перенести и на одноплатные микрокомпьютеры, типа Orange Pi.
С большой вероятностью делать это лучше (проще, быстрее, наличие готового инструментария) на Python.
Довольно много публикаций и программных пакетов для этого в последние времена.
Само изображение кода может попадать в систему самым разнообразным образом: как файл имидж-формата, записанный где-то в другом месте (по сети, с фотоаппарата-смартфона, со сканера...) или как непосредственно фрейм изображения, захваченный с WEB-камеры на USB.
Отрабатывать это лучше, думаю, на стационарном Linux, но потом бы заманчиво перенести и на одноплатные микрокомпьютеры, типа Orange Pi.
С большой вероятностью делать это лучше (проще, быстрее, наличие готового инструментария) на Python.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: распознавание bar-кодов
Сама генерация (это не сильно и интересно) и чтение (декодирование) изображения QR кода - в чистом виде дело пустяшное (в том смысле, что есть множество Python пакетов от разных умельцев ... поспешили ).Olej писал(а): Довольно много публикаций и программных пакетов для этого в последние времена.
...
С большой вероятностью делать это лучше (проще, быстрее, наличие готового инструментария) на Python.
Но интерес состоит в том, что:
1. QR код нужно обнаружить, локализовать - он может быть частью какого-то крупного изображения, и местоположение егов изображении не фиксировано (нужно определить);
2. QR код может быть искажён:
- повёрнут на угол влево-вправо (не горизонтальный);
- снят под углом (не по нормали объектив) - то что называют искажения перспективы;
- какие-то ещё искажения... ?
- одновременно несколько из предыдущих видов;
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: распознавание bar-кодов
Тема QR кодов уже обсуждалась здесь в форуме и не раз:Olej писал(а): Сама генерация (это не сильно и интересно) и чтение (декодирование) изображения QR кода - в чистом виде дело пустяшное (в том смысле, что есть множество Python пакетов от разных умельцев ... поспешили ).
QR-код
ещё раз про QR-коды
Но это было а). давно и б). в потребительском смысле (как воспользоваться), а не в программистском.
Теперь это в разделе "Программирование"...
P.S. Пишу конспект своих действий по конкретной работе и для конкретного заказчика.
Может кому ещё попутно пригодится...
Кому не пригодится - просьба не беспокоить.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: распознавание bar-кодов
По структуре QR-кода вот более-менее внятное описание - QR-код (совсем просто, уровня "на пальцах").Olej писал(а): P.S. Пишу конспект своих действий по конкретной работе и для конкретного заказчика.
Откуда для своих целей мы можем почерпнуть следующие полезности:
1. закодировать в QR можно любую символьно-числовую информацию;
2. это важно:
3. структура QR кода весьма сложная:Максимальное количество символов, которые помещаются в один QR-код:
- цифры десятичной системы счисления — 7089;
- цифры десятичной системы счисления и буквы (латиница) — 4296;
- байты — 2953 (следовательно, около 2953 букв кириллицы в кодировке windows-1251 или около 1450 букв кириллицы в utf-8);
- иероглифы — 1817.
На QR-коде есть обязательные поля, они не несут закодированной информации, а содержат информацию для декодирования. Это:
- Поисковые узоры
- Выравнивающие узоры
- Полосы синхронизации
- Код маски и уровня коррекции
- Код версии (с 7-й версии)
4. ... да ещё с разночтениями многих несовместимых версий;
5. но влезать в это всё нет, в наших целях, никакого резона, поскольку есть в великом множестве кодеры-декодеры изображений QR а). онлайновые в Интернет (спешат наперегонки друг-другу) и б). библиотеки с программными API, в частности, во множестве на Python.
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: распознавание bar-кодов
Для моей задачи нужно генерировать в некотором количестве чистых QR, чтобы потом подвергать их искажениям и восстановлениям...Olej писал(а):5. но влезать в это всё нет, в наших целях, никакого резона, поскольку есть в великом множестве кодеры-декодеры изображений QR а). онлайновые в Интернет (спешат наперегонки друг-другу) и б). библиотеки с программными API, в частности, во множестве на Python.
Для генерации я воспользовался онлайн-генератором (но их великое множество) ГЕНЕРАТОР QR КОДОВ. Подготовил 2 тестовых QR с вот таким произвольным бессмысленно-русскоязычным (специально - проверка на вшивость с нелюбимым языком ) содержимым:
1-й тестовый QR код
В качестве онлайн-декодера (для проверки чистых QR) использую вот этот декодер Распознавание QR кода.2-й тестовый QR код: координаты угловых точек прямоугольника <x,y>
Указываю файлы, сгенерированные выше, и получаю:Выберите файл с QR кодом, который хотите расшифровать:
ОК, тестеры у меня уже готовы.QR код успешно распознан:
1-й тестовый QR код
QR код успешно распознан:
2-й тестовый QR код: координаты угловых точек прямоугольника <x,y>
- Вложения
-
- qr1.gif (2.19 КБ) 3352 просмотра
-
- qr2.gif (4.48 КБ) 3352 просмотра
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: распознавание bar-кодов
Из свежих меня заинтересовалаOlej писал(а): Довольно много публикаций и программных пакетов для этого в последние времена.
...
С большой вероятностью делать это лучше (проще, быстрее, наличие готового инструментария) на Python.
An OpenCV barcode and QR code scanner with ZBar
С той разницей, что: меня, пока, интересует не Rapsberry Pi (но это интересно на потом), а дистрибутивы Linux общего использования, в частности, RPM дистрибутивы...by Adrian Rosebrock on May 21, 2018 in Image Processing, Raspberry Pi, Tutorials
Статью на которую ссылается автор нужно отметить особо - Barcode and QR code Scanner using ZBar and OpenCVA few weeks ago Satya Mallick from the LearnOpenCV blog posted a really great tutorial on using the ZBar library to scan barcodes.
The instructions to install ZBar in today’s post are largely based on his instructions, but with a few updates, the largest one being related to how we install the Python zbar bindings themselves, ensuring we can:
- Use Python 3 (the official zbar Python bindings only support Python 2.7)
- Detect and localize exactly where in the image the barcode is.
Installing the necessary software is an easy 3-step process.
FEBRUARY 18, 2018 BY SATYA MALLICK 44 COMMENTS:
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: распознавание bar-кодов
Структура QR кода хорошо расписана здесь - Генерируем QR код сами:Olej писал(а): По структуре QR-кода вот более-менее внятное описание - QR-код (совсем просто, уровня "на пальцах").
Ничего не понятно? Мне тоже. Посмотрите на пример и всё станет ясно.
Всё оставшееся свободное пространство на холсте разбивается на столбики: каждые 2 модуля, не важно что находится в этих модулях, кроме вертикильной полосы синхронизации, которая просто пропускается. Заполнение начинается с правого нижнего угла, идёт в пределах столбика справа налево, снизу вверх. Если текущий модуль занят (например полосой синхронизации или выравнивающим узором), то он просто пропускается. Если достигнут верх столбика, то движение продолжается с верхнего правого угла столбика, который расположен левее, и идёт сверху вниз. Достигнув низа, движение продолжается от нижнего правого угла столбика, который расположен левее, и идёт снизу вверх. И так далее, пока всё свободное пространство не будет заполнено.
Это всё до уровня ручной генерации пикселей изображения...
Но в наши задачи, к счастью, такой уровень детализации не входит!
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: распознавание bar-кодов
Именно из-за этого + из-за того, что область новая, как составная часть вообще OpenCV и компьютерного зрения, и наличествует огромный зверинец пакетов и версий, и некоторые из них работают только с Python 2, а некоторые только с Python 3 ... - есть прямой резон потерять некоторое время, но установить виртуальные среды Python для установки и экспериментов с этими разноверсионными пакетами.Olej писал(а): Сама генерация (это не сильно и интересно) и чтение (декодирование) изображения QR кода - в чистом виде дело пустяшное (в том смысле, что есть множество Python пакетов от разных умельцев ... поспешили ).
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: распознавание bar-кодов
По мотивам, но не только это...Olej писал(а): Из свежих меня заинтересовала
An OpenCV barcode and QR code scanner with ZBar
- Распознавалка QR-кодов (повёрнутых, искажённых перспективой и т.д.), которая позволяет не только распознать QR, но и детерминировать искажение:
Код: Выделить всё
# -*- coding: utf-8 -*-
import numpy as np
import argparse
import imutils
from pyzbar import pyzbar
import cv2
import sys
import math
from common import *
ap = argparse.ArgumentParser() # construct the argument parse and parse the arguments
ap.add_argument( "-i", "--image", required=True, help="path to the image file" )
args = vars(ap.parse_args())
image = cv2.imread( args[ "image" ], cv2.IMREAD_LOAD_GDAL ) # load the image from disk
if image.ndim > 2:
image = cv2.cvtColor( image, cv2.COLOR_BGR2GRAY ) # convert image into grayscale
#thresh, n = thresh_opt( image, 70, 150, 10 )
thresh, n = thresh_opt( image, 50, 120, 10 ) # find optimal p4qr1.jpg
#print( '{} => {}'.format( thresh, n ) )
image = cv2.threshold( image, thresh, 255, cv2.THRESH_BINARY )[ 1 ]
barcodes = pyzbar.decode( image ) # find the barcodes in the image
n = len( barcodes )
print( '{} => {}'.format( thresh, n ) )
#print( barcodes[ 0 ].polygon )
image = cv2.bitwise_not( image ) # convert to monochrome
show( image, 2000 )
def angles( bar ):
def get_angl( p1, p2 ):
x = p1.x - p2.x
y = p1.y - p2.y
a = math.atan2( y, x ) * 180 / math.pi
if abs( y ) > abs( x ): a -= 90
else: a -= 180
if a > 180: a -= 360
if a < -180: a += 360
return a
poly = bar.polygon
return ( get_angl( poly[ 0 ], poly[ 3 ] ), get_angl( poly[ 1 ], poly[ 2 ] ) )
for angle in range( -45, 46, 5 ): # loop over the rotation angles
# rotated = imutils.rotate( image, angle )
rotated = imutils.rotate_bound( image, angle )
rotated = cv2.bitwise_not( rotated )
barcodes = pyzbar.decode( rotated ) # find the barcodes in the image
for barcode in barcodes:
qa = angles( barcode )
print( '{:+04d}: {}\t<{:.2f}|{:.2f}>°'.format( angle, barcode.polygon, qa[ 0 ], qa[ 1 ] ) )
if 0 == len( barcodes ):
print( '{:+04d}: .................'.format( angle ) )
key = show( rotated, 2000 )
if key == 27 or key == ord( 'q' ):
sys.exit()
Всего то ...
Код: Выделить всё
[olej@xenix barcode-scanner]$ python2 rotate_doc.py -i ../QR1/qr1.gif
50 -> 1
60 -> 1
70 -> 1
80 -> 1
90 -> 1
100 -> 1
110 -> 1
80 => 1
-045: [Point(x=32, y=156), Point(x=155, y=280), Point(x=279, y=156), Point(x=156, y=33)] <-44.77|-45.00>°
-040: [Point(x=33, y=146), Point(x=145, y=279), Point(x=278, y=167), Point(x=166, y=32)] <-40.60|-40.10>°
-035: [Point(x=32, y=132), Point(x=132, y=275), Point(x=275, y=175), Point(x=175, y=32)] <-34.97|-34.97>°
-030: [Point(x=31, y=119), Point(x=119, y=270), Point(x=270, y=183), Point(x=183, y=31)] <-30.07|-29.95>°
-025: [Point(x=30, y=104), Point(x=105, y=263), Point(x=262, y=189), Point(x=189, y=31)] <-24.66|-25.24>°
-020: [Point(x=30, y=90), Point(x=89, y=254), Point(x=253, y=194), Point(x=194, y=30)] <-20.10|-20.10>°
-015: [Point(x=28, y=73), Point(x=73, y=242), Point(x=242, y=196), Point(x=196, y=28)] <-15.00|-15.23>°
-010: [Point(x=27, y=57), Point(x=57, y=229), Point(x=229, y=199), Point(x=199, y=27)] <-9.89|-9.89>°
-005: [Point(x=25, y=40), Point(x=40, y=215), Point(x=215, y=199), Point(x=199, y=25)] <-4.93|-5.22>°
+000: [Point(x=23, y=23), Point(x=23, y=198), Point(x=199, y=199), Point(x=198, y=23)] <0.00|0.33>°
+005: [Point(x=25, y=199), Point(x=199, y=215), Point(x=215, y=40), Point(x=40, y=25)] <4.93|5.22>°
+010: [Point(x=27, y=199), Point(x=198, y=228), Point(x=229, y=57), Point(x=57, y=27)] <9.89|10.28>°
+015: [Point(x=28, y=196), Point(x=196, y=242), Point(x=242, y=73), Point(x=73, y=28)] <15.00|15.23>°
+020: [Point(x=30, y=194), Point(x=192, y=251), Point(x=254, y=89), Point(x=90, y=29)] <19.98|20.94>°
+025: [Point(x=31, y=189), Point(x=189, y=263), Point(x=263, y=105), Point(x=105, y=30)] <24.96|25.10>°
+030: [Point(x=31, y=183), Point(x=183, y=270), Point(x=270, y=119), Point(x=119, y=31)] <30.07|29.95>°
+035: [Point(x=32, y=175), Point(x=176, y=275), Point(x=275, y=132), Point(x=132, y=32)] <34.97|34.70>°
+040: [Point(x=32, y=166), Point(x=167, y=278), Point(x=279, y=145), Point(x=146, y=33)] <40.60|40.10>°
+045: [Point(x=33, y=156), Point(x=156, y=279), Point(x=280, y=155), Point(x=156, y=32)] <44.77|-45.00>°
- Вложения
-
- rotate_doc.py
- (2.14 КБ) 113 скачиваний
- Olej
- Писатель
- Сообщения: 21338
- Зарегистрирован: 24 сен 2011, 14:22
- Откуда: Харьков
- Контактная информация:
Re: распознавание bar-кодов
Да ... и используемые функции - common.py:Olej писал(а): Всего то ...
Код: Выделить всё
# -*- coding: utf-8 -*-
from pyzbar import pyzbar
import cv2
import imutils
def show( img, tout = 0 ):
frame = imutils.resize( img, width = 400 ) # resize it to have a maximum width of 400 pixels
cv2.imshow( '', frame ) # show the output image
return cv2.waitKey( tout ) & 0xFF # wait for key pressed
def thresh_opt( img, tb = 50, tf = 90, ts = 4 ):
nmax = 0;
for t in range( tb, tf, ts ):
mimg = cv2.threshold( img, t, 255, cv2.THRESH_BINARY )[ 1 ]
show( mimg, 1000 )
n = len( pyzbar.decode( mimg ) )
print( '{} -> {}'.format( t, n ) )
if n > nmax:
nmax = n
thr = t
continue
if n < nmax:
return ( thr + t - ts ) / 2 , nmax
return ( thr + t ) / 2 , nmax
- Вложения
-
- common.py
- (824 байт) 103 скачивания
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 8 гостей