透過 rqt_image_view,已經成功看到 TurtleBot3 相機的視角。不過現在看到影像的是我,真正要做視覺追蹤的是程式。
所以今天的問題是:
Python 要怎麼取得 /camera/image_raw 裡面的影像?
前面已經知道,相機影像會透過 ROS2 的 Topic 傳送,而 /camera/image_raw 使用的 Message Type 是:
sensor_msgs/msg/Image
但如果之後想用 OpenCV 做影像處理,還不能直接把這個 ROS2 Image 拿來使用,中間還需要經過轉換。
ROS2 Image 不能直接拿給 OpenCV,兩者的資料形式不同,因此需要一個中間的轉換工具。
ROS2 傳來的是:
sensor_msgs/msg/Image
而在 Python 中,OpenCV 處理的影像通常會以 NumPy 陣列表示:
numpy.ndarray
可以先把流程理解成:
ROS2 Image
sensor_msgs/msg/Image
↓
cv_bridge
↓
OpenCV Image
numpy.ndarray
| 項目 | ROS2 | OpenCV |
|---|---|---|
| 影像形式 | sensor_msgs/msg/Image |
numpy.ndarray |
| 主要用途 | ROS2 節點之間傳送影像 | Python 進行影像處理 |
| 中間轉換 | cv_bridge |
— |
cv_bridge 可以先想成 ROS2 Image 與 OpenCV 之間的翻譯員。ROS2 接收到的是自己的 Image Message,而 OpenCV 需要的是可以直接進行影像運算的格式,因此需要先透過 cv_bridge 轉換。
from cv_bridge import CvBridge
bridge = CvBridge()
接收到影像訊息後,可以再轉成 OpenCV 可以使用的影像:
cv_image = bridge.imgmsg_to_cv2(
msg,
desired_encoding='bgr8'
)
這裡的 bgr8 是 OpenCV 常使用的彩色影像格式,代表影像使用 B、G、R 三個色彩通道,每個通道使用 8 bit。
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import Image
from cv_bridge import CvBridge
import cv2
class CameraSubscriber(Node):
def __init__(self):
super().__init__('camera_subscriber')
self.bridge = CvBridge()
self.subscription = self.create_subscription(
Image,
'/camera/image_raw',
self.image_callback,
10
)
def image_callback(self, msg):
image = self.bridge.imgmsg_to_cv2(
msg,
desired_encoding='bgr8'
)
cv2.imshow('Camera', image)
cv2.waitKey(1)
def main():
rclpy.init()
node = CameraSubscriber()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if name == 'main':
main()
流程大致可以先拆成三個主要步驟:
create_subscription()
↓
訂閱 /camera/image_raw
image_callback()
↓
收到新的影像訊息時執行
imgmsg_to_cv2()
↓
ROS2 Image → OpenCV Image
前面介紹 Subscriber 時,我把它理解成負責「接收資料」的一方。
Subscriber 並不是自己一直跑去問:「有新照片嗎」,而是當 /camera/image_raw 有新的影像訊息送過來時,ROS2 就會執行我們設定好的 image_callback()。
這時候新的影像訊息 msg 就會一起傳進 Callback,再透過 cv_bridge 轉換成 OpenCV 可以使用的影像格式。
因此,影像處理的流程就從 Day 4 原本的:
Camera → Topic → rqt_image_view
變成:
Camera → Topic → Python Subscriber → cv_bridge → OpenCV
也就是說,現在不只是我們可以看到機器人的相機畫面,Python 程式也開始取得影像資料。不過現在的程式還只是把畫面接進 OpenCV,還沒有真的去分析畫面裡有什麼。
接下來就可以開始對影像做一些簡單的處理。
下一篇,我想先從 顏色目標偵測與 HSV 色彩空間開始,讓程式第一次嘗試從畫面中找到指定的東西。