Распознавание QR-кода с захватом одного кадра

Вся информация ниже взята из первоисточника: https://clover.coex.tech/ru/camera.html

  1. Откроем терминал и создадим пустой файл с расширением .py

Для создания текстового файла используем команду nano

2. Возьмем из официального гитбука шаблон по распознаванию qr-кода:

Официальный гитбук расположен по адресу: https://clover.coex.tech/ru/

3. Скопируем его содержимое в наш файл:

Для быстрого копирования можно использовать комбинацию клавиш: CTRL+SHIFT+C (копировать) и CTRL+SHIFT+V (вставка)

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

Давайте разберем построчно этот скрипт, поскольку, именно от него мы и будем отталкиваться при распознавании qr-кодов.

import rospy from pyzbar import pyzbar from cv_bridge import CvBridge from sensor_msgs.msg import Image

В этом блоке идет импорт, необходимых для нашей программы библиотек.

bridge = CvBridge() - вызов ROS-сервиса

rospy.init_node('barcode_test') - инициализация ноды с уникальным именем barcode_test

Подробнее про вышеперечисленные фрагменты кода можно изучить по ссылке: https://clover.coex.tech/ru/ros.html

def image_callback(data): - объявляем процедуру (функцию) с именем image_callback и задаем для нее единственный параметр data

cv_image = bridge.imgmsg_to_cv2(data, 'bgr8') - захватываем изображение с камеры и кладем это изображение в переменную cv_image

barcodes = pyzbar.decode(cv_image) - расшифровка изображения, на котором есть qr-код. В результате получиться массив с именем barcodes (список элементов)

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

Эту строчку подставляем в это место вместо data:

ИТОГО, получим:

Давайте добавим в конце кода строчку с выводом сообщения на экран с информацией о расшифрованном qr-коде.

Для этого добавьте в конец кода (во внутрь функции image_callback) данную строчку:

print(barcodes)

Данная программа будет работать только тогда, когда мы к камере поднесём изображение с QR-кодом

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

Я выдели красным маркером место взлета. Расстояние до каждого соседнего объекта - 1 метр. Видно, что ближайший QR-код находится на расстояние 1 метр по оси Y. Совершим полет в эту точку и зависнем на высоте не более 1 метра.

Если забыли как это делать, можно освежить память по ссылке ниже:

Создание автономной программы программы

Фрагмент с полетом должен выглядеть примерно так:

navigate(x=0, y=0, z=1.5, speed=0.5, frame_id='body', auto_arm=True)
rospy.sleep(4)
navigate(x=0, y=1, z=1, speed=0.5, frame_id='aruco_map')
rospy.sleep(4)


land()

Не забудьте, чтобы эти строчки могли работать необходимо добавить импорт необходимых библиотек и вызов соответствующих сервисов:

from clover import srv
from std_srvs.srv import Trigger

navigate = rospy.ServiceProxy('navigate', srv.Navigate)

land = rospy.ServiceProxy('land', Trigger)

Итоговый код примет вид:

Сохраним и запустим данный файл.

Для того, чтобы выйти из редактора с сохранением всех изменений нажмите последовательно следующие клавиши: ctrl+x, затем Y, после чего нажмите клавишу Enter.

Для запуску файла используйте команду python qr.py. Где qr.py - это название файла, который необходимо запустить

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

Давайте добавим строчку вызова функции:

image_callback()

В результате получим следующее:

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

image_callback()
image_callback()
image_callback()

В результате получим:

Отлично, мы прочитали наш QR-код. Причем мы его прочитали ровно столько раз, сколько мы и хотели.

Если у вас на экране ошибка, то решение можно увидеть по ссылке ниже:

Полет по точкам, используя координаты из QR-кода

Все выражение в квадратных скобках — это массив:

[Decoded(data='2.5 1.5 1 1 0 4', type='QRCODE', rect=Rect(left=133, top=92, width=45, height=48), polygon=[Point(x=133, y=92), Point(x=133, y=140), Point(x=178, y=139), Point(x=178, y=93)])]

Внутри массива перечислен один элемент. Этот элемент имеется индекс ноль.

Подробнее про массивы в python можно ознакомиться по ссылке: https://pythonru.com/uroki/massivy-uroki-po-python-dlja-nachinajushhih

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

print(barcodes[0])

Наш код примет следующий вид:

Сохраним и запустим код. В результате в терминал выведется сообщение:

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

Подробнее про кортежи в python по ссылке: https://pythonworld.ru/tipy-dannyx-v-python/kortezhi-tuple.html

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

data='2.5 1.5 1 1 0 4', 
type='QRCODE', 
rect=Rect(left=114, top=85, width=85, height=88), 
polygon=[Point(x=114, y=85), Point(x=114, y=173), Point(x=199, y=173), Point(x=199, y=85)])

В элементе кортежа data хранится зашифрованный текст QR-кода.

В элементе кортежа type хранится тип зашифрованного изображения.

В элементе кортежа rect хранится кортеж с именем Rect. В кортеже Rect хранятся геометрические размеры изображения в пикселях.

В элементе кортежа polygon имеется массив с именем Point. В этом массиве отображены координаты углов изображения в пикселях.

Давайте выведем в терминал только зашифрованный текст QR-кода. Следовательно, наша строчка с выводом на экран примет вид:

 print(barcodes[0].data)

В результате получим:

Отлично, теперь только текст, который зашифрован в QR-коде.

Теперь давайте выведем только тип зашифрованного изображения, для этого укажем имя элемента кортежа type:

print(barcodes[0].type)

В результате получим:

Отлично, теперь получился только тип зашифрованного изображения.

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

 print(barcodes[0].polygon)

В результате получим массив с 4-мя элементами:

Нумерация элементов начинается с нуля. Элемент под номером ноль - это координаты левого нижнего угла изображения; номер 1 - координаты левого верхнего угла; 2 - правый верхний; 3- правый нижний.

Выведем в терминал координаты правого нижнего угла изображения:

ЗАДАНИЯ НА САМОСТОЯТЕЛЬНУЮ РАБОТУ:

  1. Измените код, чтобы появился топик в web-сервисе

  2. Вызовите функцию распознавания QR-кода 10 раз, используйте при этом цикл.

Last updated