# Распознавание QR-кода через подписку на топик

{% hint style="danger" %}
Вся информация ниже взята из первоисточника: <https://clover.coex.tech/ru/camera.html>
{% endhint %}

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-MdsHIbKvaFeQbZFFzrV%2F-MdsL5Rah5f9CQNkLHPC%2FcpHCNgz2298.jpg?alt=media\&token=b0e1ddf2-cd5c-41c1-a2bf-91233ab9fa83)

{% hint style="warning" %}
Для создания текстового файла используем команду **nano**
{% endhint %}

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-MdsHIbKvaFeQbZFFzrV%2F-MdsLfdh0MF572swTvNp%2F_y2JS1pcEPQ.jpg?alt=media\&token=762711a9-338d-43cd-a465-4e0b4468f6a8)

{% hint style="warning" %}
Официальный гитбук расположен по адресу: <https://clover.coex.tech/ru/>
{% endhint %}

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-MdsHIbKvaFeQbZFFzrV%2F-MdsMG9xrRVBE-EbMWQF%2FVNHZC-BYR0I.jpg?alt=media\&token=5ac4c6e7-8172-4906-94b1-779829c939d6)

{% hint style="warning" %}
Для быстрого копирования можно использовать комбинацию клавиш: CTRL+SHIFT+C (копировать) и   CTRL+SHIFT+V (вставка)
{% endhint %}

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me1OAZsOS8V1Ji3rB6X%2F-Me1QhhW7lon2sgn-nFZ%2Fimage.png?alt=media\&token=dbf63617-603b-4eb5-94ed-ff061e5c01be)

Давайте разберем построчно этот скрипт, поскольку, именно от него мы и будем отталкиваться при распознавании 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*

{% hint style="info" %}
Подробнее про вышеперечисленные фрагменты кода можно изучить по ссылке: <https://clover.coex.tech/ru/ros.html>
{% endhint %}

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

**cv\_image = bridge.imgmsg\_to\_cv2(data, 'bgr8')** - захватываем изображение с камеры и кладем это изображение в переменную cv\_image

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

Отлично! Мы разобрали каждую строчку этого скрипта, теперь давайте добавим в конце кода строчку с выводом сообщения на экран с информацией о расшифрованном qr-коде.

Для этого добавьте в конец кода (во внутрь функции image\_callback) данную строчку:&#x20;

```python
print(barcodes)
```

{% hint style="info" %}
Данная программа будет работать только тогда, когда мы к камере поднесём изображение с QR-кодом
{% endhint %}

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me1UbMFaWZb7ZkImKyj%2F-Me1WS7pcVp2RD2mDPd-%2Fimage.png?alt=media\&token=676ca7ba-2d7c-428e-af90-2bd1c7b200c4)

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

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

{% content-ref url="../programmirovanie-poleta/sozdanie-avtonomnoi-programmy-programmy" %}
[sozdanie-avtonomnoi-programmy-programmy](https://lahmeneffa.gitbook.io/docs-tkuik/programmirovanie-poletov/programmirovanie-poleta/sozdanie-avtonomnoi-programmy-programmy)
{% endcontent-ref %}

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

```python
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()

```

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

```python
from clover import srv
from std_srvs.srv import Trigger

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

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

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me1X23QHkLd4luXTVwB%2F-Me1ZVRTE72tinqhdo0W%2Fimage.png?alt=media\&token=5597daf9-1c2d-4bb2-80d8-1b90af89fdb6)

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

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

{% hint style="warning" %}
Для запуску файла используйте команду python qr.py. Где qr.py - это название файла, который необходимо запустить
{% endhint %}

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

Также, нам необходимо выводить изображение qr-кода в топик  [web\_video\_server](https://clover.coex.tech/ru/web_video_server.html).

Для всего этого необходимо создать Publisher (публицист), publish (публикация) и Subscriber (подписчик). Благодаря этим трем методам происходит обмен данными между нодами.&#x20;

Publisher создает топик с именем, который мы укажем.&#x20;

publish этот топик опубликует и он будет нам виден.&#x20;

Subscriber подписывается на publish, благодаря чему, он обменивается информацией с Publisher. Таким образом, результат распознавания, можно вывести на картинку с камеры в реальном времени.&#x20;

{% hint style="warning" %}
Подробнее по ссылке: <https://clover.coex.tech/ru/ros.html>
{% endhint %}

Возьмем необходимые строчки из официального гитбука и вставим в наш код:

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me1_FqAWBlpj_pT5wNJ%2F-Me1eX7NJwAnBZpbN7kO%2Fimage.png?alt=media\&token=5f1baebd-383b-4925-8e85-1aa1df42178a)

Получаем:

```python
image_sub = rospy.Subscriber('main_camera/image_raw', Image, image_callback)
image_pub = rospy.Publisher('~debug', Image)
image_pub.publish(bridge.cv2_to_imgmsg(cv_image, 'bgr8'))
```

Подписчика (Subscriber) вставляем в то место, где хотим вызвать нашу функцию по распознаванию QR-кода. К примеру, добавим его в место, когда квадрокоптер уже прилетел на точку с изображением и завис над ним.&#x20;

Публициста (Publisher) добавим в начало нашей программы, после объявление ноды с уникальным именем.&#x20;

Публикацию (publish) добавляем во внутрь нашей функции, где происходит обработка изображения с QR-кодом.

Итого, наш код примет вид:

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me534xAt8CVm2lQRIOo%2F-Me54Uqa3HwimSp3O6Oo%2Fimage.png?alt=media\&token=4641df6e-c4e8-416a-ad2b-b8a728768d6b)

Сохраните и выйдите из редактора.

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

Перед тем как запустить этот код давайте откроем браузер "Firefox Web Browser", он расположен на рабочем столе виртуальной машины:

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me534xAt8CVm2lQRIOo%2F-Me557CZ4u9rlniirDGE%2Fimage.png?alt=media\&token=a12447cd-f55a-4d5d-bab2-512956cc8296)

Теперь в поисковой строке пропищите данную строчку, которая обеспечит локальное подключение к вашему виртуальному квадрокоптеру:

```python
http://localhost
```

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me55AoEknuRjYF93Rrh%2F-Me55az7Yzf17oVmUfeZ%2Fimage.png?alt=media\&token=57b85200-f676-4c15-b8a0-151d04eba4d8)

Подробнее про каждую ссылку, представленной на этом web-сервисе, вы можете найти по ссылке ниже:

{% content-ref url="../programmirovanie-poleta/untitled-2" %}
[untitled-2](https://lahmeneffa.gitbook.io/docs-tkuik/programmirovanie-poletov/programmirovanie-poleta/untitled-2)
{% endcontent-ref %}

Откройте второй топик "View image topics".&#x20;

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me55AoEknuRjYF93Rrh%2F-Me568R2rZqailbYj3KG%2Fimage.png?alt=media\&token=49dc6b8e-958e-4a4f-83c7-7252de5c0591)

Перед вами все существующие топики, которые связаны с просмотром и обработкой изображения с камеры. Когда мы запустим программу, то появится еще один топик, который мы прописали в программе. Напомню, что наименование топика мы задаем в Publisher.&#x20;

{% hint style="warning" %}
Данный web-сервис не будет отображаться, если у вас не запущен симулятор Gazebo.
{% endhint %}

Теперь, когда у вас запущен браузер с web-сервисом, запущен симулятор Gazebo, мы можем запустить наш код.

{% hint style="warning" %}
Для запуску файла используйте команду python qr.py. Где qr.py - это название файла, который необходимо запустить
{% endhint %}

&#x20;После запуска должно произойти следующее: у вас сначала появится ваш топик, открыв, который вы увидите белый экран.&#x20;

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me579Ct-ONtToM7lfUw%2F-Me57FMNUuN4sxCj509d%2Fimage.png?alt=media\&token=ba5847ac-92ac-4a14-b44e-10d05b3aa9e9)

&#x20;Как только, квадракоптер увидит QR-код, тогда на экран: сразу появиться его изображение.&#x20;

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me579Ct-ONtToM7lfUw%2F-Me57OELXY7Ecu-TMvIP%2Fimage.png?alt=media\&token=86e11551-c208-4693-a096-b2d6eef7200e)

После завершения полета, в симуляторе отразиться информация зашифрованная в QR-коде. Эта информация повторяется несколько раз, поскольку он делает обработку изображения несколько раз в секунду:&#x20;

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me579Ct-ONtToM7lfUw%2F-Me57UKZWUDvD0DBKiaq%2Fimage.png?alt=media\&token=fb1fd8eb-ca7a-42b6-baa4-77fe684f4ada)

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

```python
[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)])]
```

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

{% hint style="success" %}
Подробнее про массивы в python можно ознакомиться по ссылке: <https://pythonru.com/uroki/massivy-uroki-po-python-dlja-nachinajushhih>
{% endhint %}

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

```python
print(barcodes[0])
```

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me5BaTkqFee21vswRE1%2F-Me5C6JV0xjzFnJ4Stj8%2Fimage.png?alt=media\&token=274bf379-40e9-4ae8-a9a7-503b6fe3ab87)

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me5BaTkqFee21vswRE1%2F-Me5CM-n7XdHkBoJaoy9%2Fimage.png?alt=media\&token=707a2106-6192-4c7f-927f-ed70b9de1187)

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

{% hint style="success" %}
Подробнее про кортежи в python по ссылке: <https://pythonworld.ru/tipy-dannyx-v-python/kortezhi-tuple.html>
{% endhint %}

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

```python
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-кода.&#x20;

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

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

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

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

```python
 print(barcodes[0].data)
```

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me5GpHujgls08hUjP2z%2F-Me5HafvguU8N6yiSIOm%2Fimage.png?alt=media\&token=5c3d76b3-cef5-4de6-896d-2930d3f4e373)

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

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

```python
print(barcodes[0].type)
```

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-Me5IPbhAnVQtMCQSKOQ%2F-Me5JlF0AbpJq9li7vnK%2Fimage.png?alt=media\&token=586c89b2-269e-4217-a68d-bc5a6dd1fcdb)

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

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

```python
 print(barcodes[0].polygon)
```

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-MeBb2rh1kkVUctEv1Yp%2F-MeBbqBlSw0BRw36JNbW%2Fimage.png?alt=media\&token=a8c87aef-b7d9-4a37-bf6a-67edaa17902b)

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

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

![](https://2176758188-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MdqITQbWJUL8n4CbfRn%2F-MeBb2rh1kkVUctEv1Yp%2F-MeBfWIaVKFSWpoT6ZgL%2Fimage.png?alt=media\&token=354c4852-a6cf-490b-8b3d-9d15ed4680a2)

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

1. **Вывести в терминал только значение ширины (width) QR кода в пикселях.**
2. **Вписать в QR код окружность красного цвета.**
3. **Вывести в терминал только координаты левого верхнего угла QR кода в пикселях.**


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lahmeneffa.gitbook.io/docs-tkuik/programmirovanie-poletov/raspoznavanie-qr-kodov/raspoznavanie-qr-koda-s-zakhvatom-odnogo-kadra.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
