Как визуализировать данные MQTT с помощью OpenCV-Python

Вопрос или проблема

Мне удалось извлечь часть данных из JSON-загрузки из mqtt [BCID и Местоположение]. Моя проблема заключается в том, как это визуализировать? Я продолжаю получать ошибки, такие как «недопустимая аппаратная инструкция», «cv2.error: Неизвестное исключение C++ из кода OpenCV» и т. д.

  • Мои характеристики: MacOS Big Sur Version 11.7.10
#визуализировать местоположение
#ПРЕВРАЩЕНО В ПИКСЕЛИ!
import cv2
from pathlib import Path
import uuid
import ssl
import json
from dotenv import dotenv_values
from paho.mqtt.client import Client
from paho.mqtt.enums import CallbackAPIVersion
import numpy as np

IMAGE_SIZE = 1080  # Размер изображения (1080x1080)

class Visualizer:
    def visualize():    
        print()

class MQTTClient:
    """MQTTClient"""

    def __init__(self, broker_url: str, port: int, topics: dict, **kwargs):
        self.broker_url = broker_url
        self.port = port
        self.topics = topics

        self.client = Client(
            CallbackAPIVersion.VERSION2, f"visualizer-{str(uuid.uuid4()).split('-')[4]}"
        )
        self.client.tls_set(
            ca_certs=None,
            certfile=None,
            keyfile=None,
            cert_reqs=ssl.CERT_NONE,
            tls_version=ssl.PROTOCOL_TLSv1_2,
        )
        if {"broker_user", "broker_pass"}.issubset(kwargs):
            self.client.username_pw_set(kwargs["broker_user"], kwargs["broker_pass"])
        self.client.on_connect = self.on_connect
        self.client.on_message = self.on_message

    def start(self):
        """Подключается к брокеру и создает фоновый поток для ожидания сообщений."""
        self.client.connect(self.broker_url, port=self.port, keepalive=60)
        self.client.subscribe([(topic, 0) for topic in self.topics])
        self.client.loop_start()

    def on_connect(self, client, userdata, connect_flags, reason_code, properties):
        """Обратный вызов при подключении к брокеру."""
        if reason_code == 0:
            print(f"Подключение к брокеру MQTT успешно: {self.broker_url}")
        else:
            print(f"Ошибка при подключении к брокеру MQTT: {reason_code}")

    def on_message(self, client, userdata, msg):
        """Обратный вызов при получении сообщения."""

        data = json.loads(msg.payload.decode("utf-8"))
        location = data['outputs'][0]['location']

        pixel_coordinates = convert_to_pixels(location)

        print(f"BCID: {data['outputs'][0]['bcid']} Координаты пикселей: {pixel_coordinates}")

def convert_to_pixels(location):
    """
    Преобразовать нормализованные координаты местоположения в пиксельные координаты.

    Args:
    location (list): Нормализованные координаты [xmin, ymin, xmax, ymax].

    Returns:
    list: Пиксельные координаты в изображении 1080x1080 [xmin_px, ymin_px, xmax_px, ymax_px].
    """
    # Масштабировать и преобразовать нормализованные координаты в пиксельные координаты 1080x1080
    # Нормализованный диапазон предполагается как [-1.0, 1.0]
    xmin, ymin, xmax, ymax = location

    # Отображение нормализованных координат [-1.0, 1.0] на [0, IMAGE_SIZE]
    xmin_px = int((xmin + 1) * IMAGE_SIZE / 2)
    ymin_px = int((ymin + 1) * IMAGE_SIZE / 2)
    xmax_px = int((xmax + 1) * IMAGE_SIZE / 2)
    ymax_px = int((ymax + 1) * IMAGE_SIZE / 2)

    return [xmin_px, ymin_px, xmax_px, ymax_px]

CONFIG = dotenv_values(Path.cwd() / ".env")
BROKER_URL = CONFIG["MQTT_BROKER"]
BROKER_USER = CONFIG["MQTT_USER"] if "MQTT_USER" in CONFIG else ""
BROKER_PASS = CONFIG["MQTT_PASS"] if "MQTT_PASS" in CONFIG else ""
PORT = 8883

TOPICS = ["/viana/+/ze_all_tracks"]

def main():
    client = MQTTClient(BROKER_URL, PORT, TOPICS)
    client.start()
    input()

if __name__ == "__main__":
    main()

Я пробовал множество способов визуализировать данные, многие из них не поддерживают мою ОС. Я пытался использовать XQuartz, но это также оказалось неэффективным и неподдерживаемым согласно моему терминалу. Я также пробовал matplotlib, но это тоже не работает.

Ответ или решение

Для визуализации данных MQTT с использованием OpenCV на Python, приведем полное решение вашей проблемы, включая советы по устранению возможных ошибок. Мы будем использовать OpenCV, чтобы нарисовать прямоугольник на изображении, основываясь на координатах, полученных из MQTT-сообщений.

Шаг 1: Устранение ошибок OpenCV

Похоже, что вы сталкиваетесь с ошибками, связанными с OpenCV. Убедитесь, что у вас установлена последняя стабильная версия OpenCV, совместимая с вашей операционной системой. Вы можете установить его с помощью следующей команды:

pip install opencv-python

Шаг 2: Создание функции для визуализации данных

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

class Visualizer:
    def __init__(self):
        # Создаем пустое черное изображение 1080x1080
        self.image = np.zeros((IMAGE_SIZE, IMAGE_SIZE, 3), dtype=np.uint8)

    def visualize(self, pixel_coordinates):
        """Визуализируем данные на изображении"""
        xmin_px, ymin_px, xmax_px, ymax_px = pixel_coordinates

        # Рисуем прямоугольник на изображении
        cv2.rectangle(self.image, 
                      (xmin_px, ymin_px), 
                      (xmax_px, ymax_px), 
                      (0, 255, 0), # Цвет прямоугольника (зеленый)
                      2) # Толщина прямоугольника

        # Отображаем изображение
        cv2.imshow("Visualization", self.image)
        cv2.waitKey(1)  # Обновляем окно

Шаг 3: Обновление класса MQTTClient

Теперь мы обновим класс MQTTClient, чтобы интегрировать Visualizer и вызывать его функцию визуализации при получении сообщения:

class MQTTClient:
    def __init__(self, broker_url: str, port: int, topics: dict, **kwargs):
        # ... [остальной код как прежде] ...
        self.visualizer = Visualizer()

    def on_message(self, client, userdata, msg):
        data = json.loads(msg.payload.decode("utf-8"))
        location = data['outputs'][0]['location']

        pixel_coordinates = convert_to_pixels(location)

        print(f"BCID: {data['outputs'][0]['bcid']} Pixel Coordinates: {pixel_coordinates}")
        self.visualizer.visualize(pixel_coordinates)  # вызов функции визуализации

Шаг 4: Тестирование

После завершения изменения кода запустите скрипт. При поступлении новых данных вы увидите обновляющееся окно OpenCV с прямоугольниками, визуализирующими границы объектов на изображении.

Замечания и рекомендации

  1. Закрытие окна: Не забудьте добавить логику для закрытия окна OpenCV (например, с помощью cv2.destroyAllWindows()), когда вы завершаете выполнение программы.

  2. Проверка данных: Убедитесь, что данные, которые вы получаете через MQTT, правильно форматированы и существуют. Это поможет избежать ошибок на этапе анализа JSON.

  3. Использование Matplotlib: Если вы также хотите попробовать Matplotlib, вы можете заменить cv2.imshow на Matplotlib, но OpenCV обычно более оптимален для обновления изображений в режиме реального времени.

Заключение

Теперь у вас есть полное решение для визуализации данных MQTT с использованием OpenCV на Python. Простое обновление вашего кода с учетом вышеприведенных шагов должно устранить ошибки и обеспечить визуализацию данных. Если возникнут дополнительные вопросы, не стесняйтесь задавать их!

Оцените материал
Добавить комментарий

Капча загружается...