2. Vision artificielle ROS - Ancrage d'images ROS (imgmsg) et opencv (cv2)

Référence : Gu Yue College et pratique de développement de robots ROS

Objectif : Pour réaliser le système ROS pour lire l'image de la caméra, les données d'image lues par ROS sont converties en image dans opencv, opencv traite l'image reçue, et la renvoie finalement au système ROS pour une sortie visuelle.

Installez la bibliothèque opencv et les packages d'interface associés

Depuis que j'utilise la version ROS-Melodic, roscore ne peut être exécuté qu'en python2, et la partie vision doit être exécutée en python3, donc le paquet est installé dans deux pythons. (Opération importante, car d'autres bibliothèques liées à la vision, telles que pytorch, nécessitent python3. Si l'environnement par défaut est python2 et que le package correspondant n'est pas installé dans python3, une erreur de dépendance manquante sera signalée.)

(1 message) Modification ROS : le système ubuntu modifie la version python par défaut (opération importante ) 1001.2014.3001.5501 La méthode spécifique de changement de version python se trouve dans l'article ci-dessus.

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

Téléchargez le code source correspondant et mettez-le dans le src de l'espace de travail

guyueclass/planning&perception/robot_vision_beginner/robot_vision at main guyuehome/guyueclass (github.com) https://github.com/guyuehome/guyueclass/tree/main/planning%26perception/robot_vision_beginner/robot_vision this Guyue Academy and ROS robot development practice code source .

code d'exécution

Le premier est 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>

 Créez un nœud, puis servez d'éditeur, les informations d'image de la caméra, les paramètres doivent correspondre aux paramètres de la caméra, sinon une erreur ne sera pas signalée.

Suivi par cv_bridge_test.py

 Parmi eux, la déclaration de version python doit être modifiée, car la version python par défaut de la version molodic est python2, mais maintenant les algorithmes visuels sont tous utilisés dans python3, ce qui a une signification pratique dans python3.

Déclaration modifiée :

#!/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()

Selon le graphe de calcul final généré par rqt_graph, /usb_cam est le nœud éditeur généré par le fichier de lancement, et /cv_bridge_test est le nœud cv_bridge_test initialisé sous if __name__ == '__main__' : en tant qu'abonné.

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

cv2 - bibliothèque opencv

cv_bridge——Convertissez l'image ROS (imgmsg) et l'image opencv (cv2) en appelant l'api dans cette fonction.

sensor_msgs.msg —— type de données du capteur, où le type de données de l'image Image est importé ici.

        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)

D'après le graphique de calcul ci-dessus :

Le premier est l'abonné, dont le rôle est de recevoir les informations d'image originales publiées par usb_cam , le nom du sujet /usb_cam/image_raw , le nom du sujet ne peut pas être modifié ici, car dans la communication du sujet, les noms des sujets de l'éditeur et de l'abonné doit être le même pour communiquer.

Le second est l'éditeur. Notez que cet éditeur n'est pas le même que l'abonné ci-dessus, car les noms de sujet des deux sont différents, ce qui signifie que les deux ne peuvent pas communiquer sur le sujet. Parmi eux, le sujet cv_bridge_image publié par l'éditeur a un type de données Image , qui peut être observé via la commande rqt_image_view .

self.bridge = CvBridge() définit un handle, puis peut appeler de manière flexible les interfaces de conversion associées.

    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)

Il s'agit de la fonction de rappel, qui est le paramètre de l'abonné de communication du sujet, et la fonction de rappel est appelée via le dernier paramètre.

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

 Dans le même temps, dans la fonction principale, le spin revient sans arrêt pour atteindre l'objectif d'abonnement cyclique sans arrêt.

rospy.spin()

Dans la fonction de rappel :

Dans la première étape, les informations d'image d'origine ROS sont converties en informations d'image dans opencv.

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

La deuxième étape, le traitement d'image 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)

Dans la troisième étape, l'image traitée par opencv est reconvertie en informations d'image ROS et publiée en même temps. Les informations d'image publiées peuvent être visualisées via les commandes ROS.

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

L'analyse est terminée, exécutez le code

roslaunch robot_vision usb_cam.launch
rosrun robot_vision cv_bridge_test.py
rqt_image_view

Si la deuxième partie est la version ROS-melodic, elle signalera certainement une erreur.Bien sûr, cela peut être résolu en modifiant la déclaration de version de python et en l'exécutant avec python2, mais maintenant python2 a été éliminé, même s'il s'exécute avec succès, il n'a pas de sens.

icon-default.png?t=M85BErreur ROS : erreur cv_bridge dans la méthode ROS-Melodic .

résultat de l'opération :

Ceci est l'image sortie par opencv .

 Il s'agit de l'image convertie et publiée, où le nom du sujet est cv_bridge_image , qui est traçable et logique dans le code.

 Il s'agit de l'image brute, le nom du sujet est /usb_cam/image_raw et le message de type de données d'image que l'abonné reçoit dans le code. (rqt_image_view)

 Il s'agit du graphe de calcul (rqt_graph), dans lequel seuls deux nœuds sont visibles

Je suppose que tu aimes

Origine blog.csdn.net/wzfafabga/article/details/127237869
conseillé
Classement