{"id":14291,"url":"\/distributions\/14291\/click?bit=1&hash=257d5375fbb462be671b713a7a4184bd5d4f9c6ce46e0d204104db0e88eadadd","hash":"257d5375fbb462be671b713a7a4184bd5d4f9c6ce46e0d204104db0e88eadadd","title":"\u0420\u0435\u043a\u043b\u0430\u043c\u0430 \u043d\u0430 Ozon \u0434\u043b\u044f \u0442\u0435\u0445, \u043a\u0442\u043e \u043d\u0438\u0447\u0435\u0433\u043e \u0442\u0430\u043c \u043d\u0435 \u043f\u0440\u043e\u0434\u0430\u0451\u0442","buttonText":"","imageUuid":""}

Computer Vision в помощь декодирования QR-кода на Python

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

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

Но для начала краткая истории появления QR-кода. QR-код (Quick response code – код быстрого реагирования) был разработан Масахиро Хара в японской компании Denso-Wave в 1994г. Несмотря на то что код был разработан для упрощения работы сотрудников на производстве за счет простоты и удобства он получил распространение во многих сферах деятельности человека.

В первой части статьи я расскажу, как сгенерировать свой QR-код. Во второй части будет рассказано как считать и декодировать QR-код.

Первым делом установим все необходимые библиотеки.

pip install pyzbar qrcode opencv-python glob

pyzbar - декодирование QR-кодов;

qrcode - создание QR-кодов;

opencv-python - работа с изображениями;

glob - считывание всех файлов в указанной папке.

Как сгенерировать QR-код

Создать собственный QR-код легче, чем может показаться.

import qrcode qr = qrcode.QRCode() qr.add_data('https://yandex.ru') img = qr.make_image() img.save('ya.png')

Результат работы кода.

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

В таком простом исполнении параметры создания QR-кода будут выставлены автоматически, но можно создать и по своим параметрам.

qr = qrcode.QRCode( version = 3, box_size = 10, border = 2, error_correction = qrcode.constants.ERROR_CORRECT_Q ) qr.add_data('https://yandex.ru') img = qr.make_image(back_color='yellow', fill_color='black') img.save('ya2.png')

Тот же самый адрес сайта, но QR-код уже отличается.

Параметр version может быть от 1 до 40, от 21х21 до 177х177 пикселей, не учитывая поля.

Параметр box_size отвечает за количество пикселей в каждом квадрате QR-кода.

Параметр border создает границу вокруг QR-кода.

Параметр Error_correction служит для восстановления кода, если код повредился и плохо читаем.

Каждый уровень указывает на процент данных для восстановления.

В методе make_image() добавил параметр back_color, отвечающий за цвет фона и fill_color- за цвет QR-кода.

Добавим логотип в наш QR-код. Раз у нас ссылка ведет на сайт yandex.ru, то и логотип будем использовать от Яндекса.

from PIL import Image logo = Image.open('yandex_logo.png') qr = qrcode.QRCode( version = 3, box_size = 10, border = 2, error_correction = qrcode.constants.ERROR_CORRECT_H ) pos = ( (img.size[0] - logo.size[0]) // 2, (img.size[1] - logo.size[1]) // 2, ) qr.add_data('https://yandex.ru') img = qr.make_image().convert('RGB') # конвертируем в RGB чтобы логотип был цветным img.paste(logo, pos) img.save('yandex_qr_logo.png')

Вставляя логотип, мы повреждаем часть QR-кода, но из-за того, что мы добавили 30% на восстановление при ошибках, код считывается без проблем.

Перейдем ко второй части и попробуем декодировать зашифрованные данные кода.

Как декодировать QR-код

Импортируем установленные библиотеки.

Также я буду использовать библиотеку glob. Glob создает список файлов по указанному пути и мы поочередно их считываем.

from pyzbar import pyzbar import cv2 from glob import glob

Чтобы показать, как работает библиотека, считаем 1 чек и посмотрим, какой результат она выдаст.

filename = 'receipts/1.jpg' img = cv2.imread(filename) # Считываем файл с изображением qrcodes = pyzbar.decode(img) # Создается список найденных кодов print(qrcodes)

pyzbar.decode() принимает изображение с QR-кодом и декодирует его, выдавая параметры самого QR-кода и обнаруженные данные.

[Decoded(data=b't=20170221T095900&s=30.00&fn=99990789659&i=501&fp=4189225230&n=1', type='QRCODE', rect=Rect(left=111, top=462, width=159, height=159), polygon= [Point(x=111, y=462), Point(x=112, y=619), Point(x=270, y=621), Point(x=268, y=462)])]

Для тестирования я взял несколько чеков, для тестового решения можно взять любые QR-коды, которые вы сможете найти.

Для упрощения работы все операции с изображением я вывел в отдельную функцию.

def getQr(filename): all_data = [] img = cv2.imread(filename) # Считываем файл с изображением qrcodes = pyzbar.decode(img) # Создается список найденных кодов for qrcode in qrcodes: qrcodeData = qrcode.data.decode('utf-8') if qrcode.type == 'QRCODE' and 'fn=' in qrcodeData: # проверяем тип кода и проверяем вхождение строки 'fn=' all_data.append(qrcodeData.split('&')) return all_data

В основном коде дополнительно импортировал библиотеку pandas для создания датафрейма.

# данные чеков которые я буду собирать в отдельную таблицу # t — timestamp, время, когда осуществлена покупка # s — сумма чека # fn —номер фискального накопителя # fd — номер фискального документа # fp — информация для проверки ФД # n — номер чека import pandas as pd df_good = pd.DataFrame() # Удачно считанные данные df_bad = pd.DataFrame() # список не распознанных кодов for filename in glob('receipts/*.jpg'): # Считываем тип файлов только jpg data = getQr(filename) if data != []: for cell in data: # если на изображении больше 1 кода df_good = df_good.append(pd.DataFrame([cell])) else: df_bad = df_bad.append(pd.DataFrame([filename])) if len(df_good) != 0: df_good.columns = ['t', 's', 'fn', 'fd', 'fp', 'number'] df_good.reset_index(drop=True, inplace=True) if len(df_bad) != 0: df_bad.columns = ['filename'] df_bad.reset_index(drop=True, inplace=True) data - сами данные которые мне нужны; type - тип кода, меня интересовал тип 'QRCODE'; rect - координаты QR-кода на изображении; polygon – координаты точек(углов) QR-кода.

Посмотрим удачно считанные коды.

А вот название файлов не найденных, либо не считанных кодов.

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

Как вы уже увидели в создании и декодировании QR-кодов нет ничего сложного. Я показал лишь основу, которую вы можете модернизировать, добавляя дополнительные библиотеки или встраивая в другие программы. Это еще один пример того, как Computer Vision облегчает жизнь и работу людей.

0
Комментарии
-3 комментариев
Раскрывать всегда