2. Visión artificial de ROS: acoplamiento de imagen ROS (imgmsg) y opencv (cv2)

Referencia: Gu Yue College y práctica de desarrollo de robots ROS

Objetivo : realizar el sistema ROS para leer la imagen de la cámara, los datos de imagen leídos por ROS se convierten en la imagen en opencv, opencv procesa la imagen recibida y finalmente la devuelve al sistema ROS para la salida visual.

Instale la biblioteca opencv y los paquetes de interfaz relacionados

Dado que uso la versión ROS-Melodic, roscore solo se puede ejecutar en python2, y la parte de visión debe ejecutarse en python3, por lo que el paquete se instala en dos pythons. (Operación importante, porque otras bibliotecas relacionadas con la visión, como pytorch, requieren python3. Si el entorno predeterminado es python2 y el paquete correspondiente no está instalado en python3, se informará un error de dependencia faltante).

(1 mensaje) Modificación de ROS: el sistema ubuntu cambia la versión predeterminada de python (operación importante ) 1001.2014.3001.5501 El método específico para cambiar la versión de python se encuentra en el artículo anterior.

sudo apt-get install ros-melodic-vision-opencv libopencv-dev ros-melodic-vision-opencv python-opencv

Descarga el código fuente correspondiente y ponlo en el src del espacio de trabajo

guyueclass/planning&perception/robot_vision_beginner/robot_vision en principal guyuehome/guyueclass (github.com) https://github.com/guyuehome/guyueclass/tree/main/planning%26perception/robot_vision_beginner/robot_vision este código fuente de la práctica de desarrollo de robots Guyue Academy y ROS .

código en ejecución

El primero es usb_cam.launch

<launch>

  <node name="usb_cam" pkg="usb_cam" type="usb_cam_node" output="screen" >
    <param name="video_device" value="/dev/video0" />
    <param name="image_width" value="640" />
    <param name="image_height" value="480" />
    <param name="pixel_format" value="yuyv" />
    <param name="camera_frame_id" value="usb_cam" />
    <param name="io_method" value="mmap"/>
  </node>

</launch>

 Cree un nodo y luego sirva como editor, la información de la imagen de la cámara, los parámetros deben corresponder a los parámetros de la cámara, o no se informará un error.

Seguido por cv_bridge_test.py

 Entre ellos, la declaración de la versión de python debe modificarse, porque la versión de python predeterminada de la versión molodic es python2, pero ahora todos los algoritmos visuales se usan en python3, lo que tiene un significado práctico en python3.

Declaración modificada:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import rospy
import cv2
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image

class image_converter:
    def __init__(self):    
        # 创建cv_bridge,声明图像的发布者和订阅者
        self.image_pub = rospy.Publisher("cv_bridge_image", Image, queue_size=1)
        self.bridge = CvBridge()
        self.image_sub = rospy.Subscriber("/usb_cam/image_raw", Image, self.callback)

    def callback(self,data):
        # 使用cv_bridge将ROS的图像数据转换成OpenCV的图像格式
        try:
            cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
        except CvBridgeError as e:
            print(e)

        # 在opencv的显示窗口中绘制一个圆,作为标记
        (rows,cols,channels) = cv_image.shape
        if cols > 60 and rows > 60 :
            cv2.circle(cv_image, (60, 60), 30, (0,0,255), -1)

        # 显示Opencv格式的图像
        cv2.imshow("Image window", cv_image)
        cv2.waitKey(3)

        # 再将opencv格式额数据转换成ros image格式的数据发布
        try:
            self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))
        except CvBridgeError as e:
            print(e)

if __name__ == '__main__':
    try:
        # 初始化ros节点
        rospy.init_node("cv_bridge_test")
        rospy.loginfo("Starting cv_bridge_test node")
        image_converter()
        rospy.spin()
    except KeyboardInterrupt:
        print("Shutting down cv_bridge_test node.")
        cv2.destroyAllWindows()

De acuerdo con el gráfico de cálculo final generado por rqt_graph, /usb_cam es el nodo publicador generado por el archivo de inicio, y /cv_bridge_test es el nodo cv_bridge_test inicializado bajo if __name__ == '__main__': como suscriptor.

import cv2
from cv_bridge import CvBridge, CvBridgeError
from sensor_msgs.msg import Image

cv2 - biblioteca opencv

cv_bridge——Convierta la imagen ROS (imgmsg) y la imagen opencv (cv2) llamando a la API en esta función.

sensor_msgs.msg——tipo de datos del sensor, donde el tipo de datos de Imagen se importa aquí.

        self.image_pub = rospy.Publisher("cv_bridge_image", Image, queue_size=1)
        self.bridge = CvBridge()
        self.image_sub = rospy.Subscriber("/usb_cam/image_raw", Image, self.callback)

Según el gráfico de cálculo anterior:

El primero es el suscriptor, cuya función es recibir la información de la imagen original publicada por usb_cam , el nombre del tema /usb_cam/image_raw , el nombre del tema no se puede cambiar aquí, porque en la comunicación del tema, los nombres del tema del editor y el suscriptor debe ser el mismo para comunicarse.

El segundo es el editor. Tenga en cuenta que este editor no es el mismo que el suscriptor anterior, porque los nombres de los temas de los dos son diferentes, lo que significa que los dos no pueden comunicarse sobre el tema. Entre ellos, el tema cv_bridge_image publicado por el editor tiene un tipo de dato de Imagen , que se puede observar a través del comando rqt_image_view .

self.bridge = CvBridge() define un identificador y luego puede llamar de manera flexible a las interfaces de conversión relacionadas.

    def callback(self,data):
        # 使用cv_bridge将ROS的图像数据转换成OpenCV的图像格式
        try:
            cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
        except CvBridgeError as e:
            print(e)

        # 在opencv的显示窗口中绘制一个圆,作为标记
        (rows,cols,channels) = cv_image.shape
        if cols > 60 and rows > 60 :
            cv2.circle(cv_image, (60, 60), 30, (0,0,255), -1)

        # 显示Opencv格式的图像
        cv2.imshow("Image window", cv_image)
        cv2.waitKey(3)

        # 再将opencv格式额数据转换成ros image格式的数据发布
        try:
            self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))
        except CvBridgeError as e:
            print(e)

Esta es la función de devolución de llamada, que es el parámetro del suscriptor de comunicación de tema, y ​​la función de devolución de llamada se llama a través del último parámetro.

self.image_sub = rospy.Subscriber("/usb_cam/image_raw", Image, self.callback)

 Al mismo tiempo, en la función principal, el giro retrocede sin parar para lograr el propósito de la suscripción cíclica sin parar.

rospy.spin()

En la función de devolución de llamada:

En el primer paso, la información de la imagen original de ROS se convierte en información de imagen en opencv.

cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")

El segundo paso, procesamiento de imágenes en opencv.

        # 在opencv的显示窗口中绘制一个圆,作为标记
        (rows,cols,channels) = cv_image.shape
        if cols > 60 and rows > 60 :
            cv2.circle(cv_image, (60, 60), 30, (0,0,255), -1)

        # 显示Opencv格式的图像
        cv2.imshow("Image window", cv_image)
        cv2.waitKey(3)

En el tercer paso, la imagen procesada por opencv se vuelve a convertir en información de imagen ROS y se libera al mismo tiempo.La información de imagen liberada se puede ver a través de comandos ROS.

self.image_pub.publish(self.bridge.cv2_to_imgmsg(cv_image, "bgr8"))

El análisis está completo, ejecute el código

roslaunch robot_vision usb_cam.launch
rosrun robot_vision cv_bridge_test.py
rqt_image_view

Si la segunda parte es la versión ROS-melodic, definitivamente reportará un error, por supuesto, se puede solucionar modificando la declaración de la versión de python y ejecutando python2, pero ahora python2 ha sido eliminado, incluso si se ejecuta con éxito, no tiene sentido.

icono-predeterminado.png?t=M85BError de ROS : error de cv_bridge en el método ROS-Melodic .

resultado de la operación:

Esta es la salida de imagen por opencv .

 Esta es la imagen convertida y publicada, donde el nombre del tema es cv_bridge_image , que es rastreable y lógico en el código.

 Esta es la imagen sin procesar, el nombre del tema es /usb_cam/image_raw y el mensaje de tipo de datos de imagen que el suscriptor recibe en el código. (rqt_image_view)

 Este es el gráfico de cálculo (rqt_graph), en el que solo se ven dos nodos

Supongo que te gusta

Origin blog.csdn.net/wzfafabga/article/details/127237869
Recomendado
Clasificación