Штрих-код — это метод представления данных в визуальной и машиночитаемой форме, он состоит из полос и пробелов. Сегодня мы видим штрих-коды повсюду, чаще всего на продуктах в супермаркетах.
Штрих-коды можно считывать с помощью оптического сканера штрих-кода, но здесь, для начала, напишем скрипт Python для считывания и декодирования штрих-кодов с рисунков, где они изображены.
Не столь часто используемый, но, как мне кажется, более ценный QR-кодએ — тип матричного штрих-кода, который представляет собой машиночитаемую оптическую этикетку, которая содержит информацию об элементе, к которому она прикреплена.
Для начала я расскажу вам, как считывать и декодировать штрих-коды, а также находить их на изображении. Потом вы узнаете, как сгенерировать и прочитать QR-коды в Python с помощью библиотек
Для выполнения описанных здесь упражнений необходимо установить нужные нам зависимости:
pip3 install opencv-python qrcode pyzbar numpy
Как сделать считыватель штрих-кода на Python
Как только зависимости будут установлены, откройте новый файл Python и импортируйте то, что нужно для считывателя:
from pyzbar import pyzbar import cv2
У меня есть несколько изображений для тестирования, вы можете использовать любое изображение из Интернета или своего собственного диска, но вы можете получить мои тестовые изображения в
Я разбил всю функциональность по функциям и первая функция, которую мы обсудим, следующая:
def decode(image): # decodes all barcodes from an image decoded_objects = pyzbar.decode(image) for obj in decoded_objects: # draw the barcode print(f"Обнаружен штрих-код:\n{obj}") image = draw_barcode(obj, image) # print barcode type & data print("Тип:", obj.type) print("Данные:", obj.data) print() return image
Функция decode()
принимает изображение в виде массива numpy и использует pyzbar.decode()
, который отвечает за декодирование всех штрих-кодов из одного изображения и возвращает кучу полезной информации о каждом обнаруженном штрих-коде.
Затем мы перебираем все обнаруженные штрих-коды, рисуем прямоугольник вокруг штрих-кода и печатаем тип и данные штрих-кода. Чтобы прояснить ситуацию, вот как каждый объект выглядел, если мы его распечатали:
Decoded(data=b'43770929851162', type='I25', rect=Rect(left=62, top=0, width=694, height=180), polygon=[Point(x=62, y=1), Point(x=62, y=179), Point(x=756, y=180), Point(x=756, y=0)])
Таким образом, функция pyzbar.decode()
возвращает данные, содержащие штрих-код, тип штрих-кода, а также точки расположения в виде прямоугольника и многоугольника.
Это подводит нас к следующей функции, которую мы использовали, draw_barcode()
:
def draw_barcode(decoded, image): # n_points = len(decoded.polygon) # for i in range(n_points): # image = cv2.line(image, decoded.polygon[i], decoded.polygon[(i+1) % n_points], color=(0, 255, 0), thickness=5) # раскомментируйте выше и закомментируйте ниже, если хотите нарисовать многоугольник, а не прямоугольник image = cv2.rectangle(image, (decoded.rect.left, decoded.rect.top), (decoded.rect.left + decoded.rect.width, decoded.rect.top + decoded.rect.height), color=(0, 255, 0), thickness=5) return image
Эта функция берет декодированный объект, который мы только что видели, и само изображение, она рисует прямоугольник вокруг штрих-кода с помощью функции cv2.rectangle()
, или вы можете раскомментировать другую версию функции; рисование многоугольника с помощью функции cv2.line()
, выбор за вами. Я предпочел прямоугольную версию.
Ну наконец то, он возвращает изображение, содержащее нарисованные штрих-коды. Теперь давайте воспользуемся этими функциями для наших примеров изображений:
if __name__ == "__main__": from glob import glob barcodes = glob("barcode*.png") for barcode_file in barcodes: # загружаем изображение в opencv img = cv2.imread(barcode_file) # декодировать обнаруженные штрих-коды и получить изображение # нарисованный img = decode(img) # показать изображение cv2.imshow("img", img) cv2.waitKey(0)
В моем текущем каталоге у меня есть barcode1.png, barcode2.png и barcode3.png, которые являются примерами изображений отсканированного штрих-кода. Я использовал glob
, чтобы получить все эти изображения в виде списка и перебирать их.
В каждый файл мы загружаем его с помощью функции cv2.imread()
и используем ранее обсуждавшуюся функцию decode()
для декодирования штрих-кодов, а затем показываем фактическое изображение.
Обратите внимание, что скрипт также обнаружит QR-коды, и это нормально, но для получения более точных результатов читайте вторую часть этой заметки.
Когда я запускаю сценарий, он показывает каждое изображение и печатает его тип и данные, нажмите любую клавишу, и вы получите следующее изображение, вот мой результат:
================== RESTART: D:\PHYTON\qrcode\barcode_reader.py ================= Обнаружен штрих-код: Decoded(data=b'0036000291452', type='EAN13', rect=Rect(left=124, top=58, width=965, height=812), polygon=[Point(x=124, y=59), Point(x=124, y=869), Point(x=621, y=870), Point(x=1089, y=870), Point(x=1089, y=58)]) Тип: EAN13 Данные: b'0036000291452' Обнаружен штрих-код: Decoded(data=b'Wikipedia', type='CODE128', rect=Rect(left=593, top=4, width=0, height=294), polygon=[Point(x=593, y=4), Point(x=593, y=298)]) Тип: CODE128 Данные: b'Wikipedia' Обнаружен штрих-код: Decoded(data=b'43770929851162', type='I25', rect=Rect(left=62, top=0, width=694, height=180), polygon=[Point(x=62, y=1), Point(x=62, y=179), Point(x=756, y=180), Point(x=756, y=0)]) Тип: I25 Данные: b'43770929851162' >>>
Вот последнее показанное изображение:
Это здорово, теперь у вас есть отличный инструмент для создания собственного сканера штрих-кода на Python. Я знаю, что вы все хотите читать прямо с камеры и подготовил код для считывания и обнаружения штрих-кода с камеры в реальном времени. Вот он:
from pyzbar import pyzbar import cv2 def draw_barcode(decoded, image): # n_points = len(decoded.polygon) # for i in range(n_points): # image = cv2.line(image, decoded.polygon[i], decoded.polygon[(i+1) % n_points], color=(0, 255, 0), thickness=5) image = cv2.rectangle(image, (decoded.rect.left, decoded.rect.top), (decoded.rect.left + decoded.rect.width, decoded.rect.top + decoded.rect.height), color=(0, 255, 0), thickness=5) return image def decode(image): # decodes all barcodes from an image decoded_objects = pyzbar.decode(image) for obj in decoded_objects: # draw the barcode image = draw_barcode(obj, image) # print barcode type & data print("Type:", obj.type) print("Data:", obj.data) print() return image if __name__ == "__main__": cap = cv2.VideoCapture(0) while True: # read the frame from the camera _, frame = cap.read() # decode detected barcodes & get the image # that is drawn frame, decoded_objects = decode(frame) # show the image in the window cv2.imshow("frame", frame) if cv2.waitKey(1) == ord("q"): break
Вы также можете добавить какой-то звуковой сигнал при обнаружении каждого штрих-кода, так же, как в супермаркетах, ознакомьтесь с руководством по воспроизведению звуков, которые могут помочь вам в этом.
Для получения более подробной информации приглашаю вас почитать
Как сгенерировать и прочитать QR-код в Python
Пришло время узнать, как сгенерировать и прочитать QR-коды в Python с помощью библиотек
Создание QR-кода
Во-первых, давайте начнем с создания QR-кодов, это в целом очень просто при наличии библиотеки
import qrcode # пример данных data = "https://waksoft.susu.ru" # имя выходного файла filename = "waksoft.susu.ru.png" # генерировать qr-код img = qrcode.make(data) # сохранить img в файл img.save(filename)
Это сгенерирует новый файл изображения в текущем каталоге с именем «waksoft.susu.ru.png», который содержит изображение QR-кода указанных данных (в данном случае URL этого веб-сайта), будет выглядеть примерно так:
Вы также можете использовать эту библиотеку для полного управления генерацией QR-кода с помощью класса qrcode.QRCode()
, в котором вы можете создать экземпляр и указать размер, цвет заливки, задний цвет и исправление ошибок, например:
import qrcode import numpy as np # данные для кодирования data = "https://waksoft.susu.ru" # создать экземпляр объекта QRCode qr = qrcode.QRCode(version=1, box_size=10, border=4) # добавить данные в QR-код qr.add_data(data) # компилируем данные в массив QR-кода qr.make() # распечатать форму изображения print("The shape of the QR image:", np.array(qr.get_matrix()).shape) # переносим массив в реальное изображение img = qr.make_image(fill_color="white", back_color="black") # сохраняем в файл img.save("waksoft.susu.ru_inversed.png")
Итак, при создании класса QRCode
мы указываем параметр версии, который представляет собой целое число от 1 до 40, которое контролирует размер изображения QR-кода (1 — маленький, матрица 21×21, 40 — матрица 185×185), но это будет перезаписано, когда данные не соответствуют указанному вами размеру. В нашем случае он автоматически масштабируется до версии 3.
Параметр box_size
управляет количеством пикселей в каждом прямоугольнике QR-кода, тогда как граница определяет, сколько прямоугольников должно иметь толщину.
Затем мы добавляем данные с помощью метода qr.add_data()
, компилируем их в массив с помощью метода qr.make()
, а затем создаем фактическое изображение с помощью метода qr.make_image()
. Мы указали белый цвет как fill_color
и черный как back_color
, что является полной противоположностью QR-коду по умолчанию, посмотрите:
И форма изображения действительно увеличена, а не 21×21:
>>> ================= RESTART: D:/PHYTON/qrcode/qr-code-inversed.py ================ The shape of the QR image: (33, 33) >>>
Читаем QR-код
Есть много инструментов, считывающих QR-код. Однако для этого мы будем использовать библиотеку
Хорошо, откройте новый файл Python и следуйте за мной, давайте прочитаем только что сгенерированное изображение:
import cv2 # читать изображение QRCODE img = cv2.imread("waksoft.susu.ru.png")
К счастью для нас, OpenCV уже имеет встроенный детектор QR-кода:
# инициализируем детектор QRCode cv2 detector = cv2.QRCodeDetector()
У нас есть изображение и детектор, давайте обнаружим и расшифруем эти данные:
# обнаружить и декодировать data, bbox, straight_qrcode = detector.detectAndDecode(img)
Функция detectAndDecode()
принимает изображение в качестве входных данных и декодирует его, чтобы вернуть кортеж из 3 значений: данные, декодированные из QR-кода, выходной массив вершин найденного четырехугольника QR-кода и выходное изображение, содержащее исправленный и преобразованный в двоичную форму QR-код.
Здесь нам просто нужны данные и bbox
, который поможет нарисовать четырехугольник на изображении, и данные будут выведены на консоль!
Давай сделаем это:
# if there is a QR code if bbox is not None: print(f"QRCode data:\n{data}") # отображаем изображение с линиями # длина ограничивающей рамки n_lines = len (bbox) for i in range(n_lines): # рисуем все линии point1 = tuple(bbox[i][0]) point2 = tuple(bbox[(i+1) % n_lines][0]) cv2.line(img, point1, point2, color=(255, 0, 0), thickness=2)
Функция cv2.line()
рисует отрезок линии, соединяющий две точки, мы получаем эти точки из массива bbox
, который ранее был декодирован с помощью detectAndDecode()
. Мы указали синий цвет ((255, 0, 0)
, поскольку OpenCV использует цвета BGR) и толщину 2
.
Наконец, давайте покажем изображение и выйдем при нажатии клавиши:
# отобразить результат cv2.imshow("img", img) cv2.waitKey(0) cv2.destroyAllWindows()
После запуска распечатываются декодированные данные:
QRCode data: https://waksoft.susu.ru
И показано следующее изображение:
Как видите, синие линии нарисованы точно в границах QR-кода. Отлично, мы закончили с этим скриптом, попробуйте запустить его с другими данными и посмотрите свои результаты!
Обратите внимание, что это идеально подходит для QR-кодов, а не для штрих-кодов.
Если вы хотите обнаруживать и декодировать QR-коды в реальном времени с помощью веб-камеры (и я уверен, что вы это делаете), вот код для этого:
import cv2 https://pypi.org/project/qrcode/ cap = cv2.VideoCapture(0) # инициализируем детектор QRCode cv2 detector = cv2.QRCodeDetector() while True: _, img = cap.read() # обнаружить и декодировать data, bbox, _ = detector.detectAndDecode(img) # проверяем, есть ли на изображении QRCode if bbox is not None: # отображаем изображение с линиями for i in range(len(bbox)): # рисуем все линии cv2.line(img, tuple(bbox[i][0]), tuple(bbox[(i+1) % len(bbox)][0]), color=(255, 0, 0), thickness=2) if data: print("[+] QR Code detected, data:", data) # отобразить результат cv2.imshow("img", img) if cv2.waitKey(1) == ord("q"): break cap.release() cv2.destroyAllWindows()
Отлично, я закончил и теперь вы можете интегрировать его в свои собственные приложения!
Почитайте
Источники вдохновения
С Python прочитаем любые штрих- и QR‑коды, опубликовано К ВВ, лицензия — Creative Commons Attribution-NonCommercial 4.0 International.
Респект и уважуха