ROS (Robot İşletim Sistemi) hızlı başlangıç kılavuzu#
Bu kılavuz, RGB görüntülerinde, derinlik görüntülerinde ve nokta bulutlarında gerçek zamanlı nesne algılama ve segmentasyon yapmak için Ultralytics YOLO modelini ROS1 (rospy) veya ROS2 (rclpy) ile nasıl entegre edeceğini gösterir.
YOLO'yu ROS ile kurma bölümüne geç, ardından RGB görüntüleri, derinlik görüntüleri veya nokta bulutları ile çalış.
ROS nedir?#
Robot İşletim Sistemi (ROS), robotik araştırmalarında ve endüstride yaygın biçimde kullanılan açık kaynaklı bir çerçevedir. ROS, geliştiricilerin robot uygulamaları oluşturmasına yardımcı olan kütüphane ve araçlar sunar. ROS çeşitli robotik platformlarla çalışacak şekilde tasarlanmıştır; bu da onu robotik alanında çalışanlar için esnek ve güçlü bir araç hâline getirir. Kısa bir tanıtım için Open Robotics'in üç dakikalık ROS Tanıtımı videosunu izle.
ROS'un Temel Özellikleri#
-
Modüler Mimari: ROS, geliştiricilerin düğümler adı verilen daha küçük ve yeniden kullanılabilir bileşenleri birleştirerek karmaşık sistemler oluşturmasına olanak tanıyan modüler bir mimariye sahiptir. Her düğüm genellikle belirli bir işlevi yerine getirir ve düğümler birbirleriyle konular veya hizmetler üzerinden mesaj alışverişinde bulunur.
-
İletişim Ara Katmanı: ROS, süreçler arası iletişimi ve dağıtık hesaplamayı destekleyen sağlam bir iletişim altyapısı sunar. Bu, veri akışları (konular) için yayınla-abone ol modeli ve hizmet çağrıları için istek-yanıt modeliyle sağlanır.
-
Donanım Soyutlaması: ROS, donanım üzerinde bir soyutlama katmanı sunarak geliştiricilerin cihazdan bağımsız kod yazmasını sağlar. Böylece aynı kod farklı donanım yapılandırmalarında kullanılabilir ve entegrasyon ile deneme süreçleri kolaylaşır.
-
Araçlar ve Yardımcı Programlar: ROS; görselleştirme, hata ayıklama ve simülasyon için zengin bir araç ve yardımcı program kümesiyle birlikte gelir. Örneğin RViz sensör verilerini ve robotun durum bilgilerini görselleştirmek için, Gazebo ise algoritmaları ve robot tasarımlarını test etmek için güçlü bir simülasyon ortamı sunar.
-
Geniş Ekosistem: ROS ekosistemi geniştir ve sürekli büyümektedir; gezinme, manipülasyon, algılama ve daha fazlası dâhil olmak üzere farklı robotik uygulamalar için çok sayıda paket sunar. Topluluk, bu paketlerin geliştirilmesine ve bakımına etkin biçimde katkıda bulunur.
ROS Sürümlerinin Gelişimi
2007'de geliştirilmeye başlanmasından bu yana ROS, ROS 1 ve ROS 2 olarak ayrılarak birden çok sürümle gelişti. Aşağıdaki mevcut örneklerde ROS1 Noetic kullanılıyor; ROS2 Kullanımı bölümündeki yalın bağdaştırıcılar, güncel ROS2 sürümleri için karşılık gelen rclpy arayüzlerini gösteriyor.
ROS 1 ve ROS 2#
ROS 1, robotik geliştirme için sağlam bir temel sunarken ROS 2, eksikliklerini şu özellikleri sunarak giderir:
- Gerçek Zamanlı Performans: Gerçek zamanlı sistemler ve belirleyici davranış için geliştirilmiş destek.
- Güvenlik: Çeşitli ortamlarda güvenli ve güvenilir çalışma için geliştirilmiş güvenlik özellikleri.
- Ölçeklenebilirlik: Çok robotlu sistemler ve büyük ölçekli dağıtımlar için daha iyi destek.
- Platformlar Arası Destek: Windows ve macOS dahil olmak üzere Linux dışındaki çeşitli işletim sistemleriyle genişletilmiş uyumluluk.
- Esnek İletişim: Süreçler arası daha esnek ve verimli iletişim için DDS kullanımı.
ROS Mesajları ve Konuları#
ROS'ta düğümler arasındaki iletişim mesajlar ve konular aracılığıyla sağlanır. Mesaj, düğümler arasında aktarılan bilgileri tanımlayan bir veri yapısıdır; konu ise mesajların gönderilip alındığı adlandırılmış bir kanaldır. Düğümler bir konuya mesaj yayımlayabilir veya bir konudaki mesajlara abone olabilir ve böylece birbirleriyle iletişim kurabilir. Bu yayınla-abone ol modeli, düğümler arasında eş zamansız iletişim ve gevşek bağlılık sağlar. Robotik bir sistemdeki her sensör veya eyleyici genellikle verileri bir konuya yayımlar; diğer düğümler bu verileri işleme veya kontrol amacıyla kullanabilir. Bu kılavuzda Image, Depth ve PointCloud mesajlarına ve kamera konularına odaklanacağız.
Ultralytics YOLO'yu ROS ile Kurma#
ROS1 örnekleri, bu ROS ortamı kullanılarak test edildi; bu ortam, ROSbot ROS deposunun bir çatalıdır. Aynı YOLO ve NumPy işleme adımları ROS2'de de geçerlidir; yalnızca düğüm yaşam döngüsü ve mesaj dönüştürme işlemleri farklıdır.
Bağımlılıkların Kurulumu#
ROS ortamının yanı sıra aşağıdaki bağımlılıkları yüklemen gerekir:
-
ROS NumPy paketi: ROS Image mesajları ile NumPy dizileri arasında hızlı dönüşüm için gereklidir.
pip install ros_numpy -
Ultralytics paketi:
pip install ultralytics
ROS2 Kullanımı#
ROS2, rospy yerine rclpy kullanır ve ros_numpy görüntü dönüştürme işlemini cv_bridge ile yapar. Aşağıdaki düğüm, aşağıda gösterilen RGB algılama akışının ROS2'deki eksiksiz karşılığıdır; modelleri bir kez örnekleyip geri çağrımlar arasında yeniden kullan.
import cv_bridge
import rclpy
from rclpy.node import Node
from rclpy.qos import qos_profile_sensor_data
from sensor_msgs.msg import Image
from ultralytics import YOLO
class UltralyticsNode(Node):
"""Run YOLO detection on ROS2 image messages."""
def __init__(self):
"""Initialize the ROS2 node, model, and image interfaces."""
super().__init__("ultralytics")
self.bridge = cv_bridge.CvBridge()
self.model = YOLO("yolo26m.pt")
self.publisher = self.create_publisher(Image, "/ultralytics/detection/image", 5)
self.create_subscription(Image, "/camera/color/image_raw", self.callback, qos_profile_sensor_data)
def callback(self, message):
"""Publish the annotated camera frame."""
image = self.bridge.imgmsg_to_cv2(message, desired_encoding="bgr8")
annotated = self.model(image)[0].plot(show=False)
self.publisher.publish(self.bridge.cv2_to_imgmsg(annotated, encoding="bgr8"))
def main(args=None):
"""Start the ROS2 node."""
rclpy.init(args=args)
node = UltralyticsNode()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == "__main__":
main()Derinlik görüntüleri için aşağıdaki derinlik işleme kodunu yeniden kullan ve yalnızca mesaj alma ve dönüştürme işlemlerini değiştir:
self.create_subscription(Image, "/camera/color/image_raw", self.rgb_callback, qos_profile_sensor_data)
self.create_subscription(Image, "/camera/depth/image_raw", self.depth_callback, qos_profile_sensor_data)
def rgb_callback(self, message):
self.rgb_image = self.bridge.imgmsg_to_cv2(message, desired_encoding="bgr8")
def depth_callback(self, message):
depth_image = self.bridge.imgmsg_to_cv2(message, desired_encoding="passthrough")
# Aşağıdaki derinlik örneğindeki NumPy maskesini ve mesafe hesaplamasını uygula.Nokta bulutları için ROS2 sensor_msgs_py.point_cloud2 sağlar; düzenli bulutu bir kez dönüştür, ardından aşağıdaki NumPy bölümleme ve 3B eşleme adımlarını yeniden kullan:
from sensor_msgs_py import point_cloud2
points = point_cloud2.read_points_numpy(message, field_names=("x", "y", "z", "rgb"))
points = points.reshape(message.height, message.width, 4)Ultralytics'i ROS sensor_msgs/Image ile kullan#
sensor_msgs/Image mesaj türü, ROS'ta görüntü verilerini temsil etmek için yaygın olarak kullanılır. Kodlama, yükseklik, genişlik ve piksel verileri için alanlar içerir; bu da onu kameralar veya diğer sensörler tarafından yakalanan görüntüleri aktarmaya uygun kılar. Image mesajları, görsel algılama, nesne algılama ve navigasyon gibi görevlerde robotik uygulamalarda yaygın olarak kullanılır.
Görüntülerin Adım Adım Kullanımı#
Aşağıdaki kod parçacığı, Ultralytics YOLO paketinin ROS ile nasıl kullanılacağını gösterir. Bu örnekte bir kamera konusuna abone oluyor, gelen görüntüyü YOLO ile işliyor ve algılanan nesneleri algılama ve bölütleme için yeni konulara yayımlıyoruz.
Önce gerekli kitaplıkları içe aktar ve iki modeli örnekle: biri bölütleme, diğeri algılama için. ROS ana sistemiyle iletişimi etkinleştirmek için ultralytics adlı bir ROS düğümü başlat. Kararlı bir bağlantı sağlamak için kısa bir bekleme ekliyoruz; böylece düğüme devam etmeden önce bağlantıyı kurması için yeterli zaman tanıyoruz.
import time
import rospy
from ultralytics import YOLO
detection_model = YOLO("yolo26m.pt")
segmentation_model = YOLO("yolo26m-seg.pt")
rospy.init_node("ultralytics")
time.sleep(1)İki ROS konusu başlat: biri algılama, diğeri bölütleme için. Bu konular, açıklama eklenmiş görüntüleri yayımlamak ve daha ileri işlemler için erişilebilir kılmak amacıyla kullanılacak. Düğümler arasındaki iletişim sensor_msgs/Image mesajlarıyla sağlanır.
from sensor_msgs.msg import Image
det_image_pub = rospy.Publisher("/ultralytics/detection/image", Image, queue_size=5)
seg_image_pub = rospy.Publisher("/ultralytics/segmentation/image", Image, queue_size=5)Son olarak, /camera/color/image_raw konusundaki mesajları dinleyen ve her yeni mesaj için bir geri çağırım işlevi çağıran bir abone oluştur. Bu geri çağırım işlevi sensor_msgs/Image türündeki mesajları alır, ros_numpy kullanarak bunları bir NumPy dizisine dönüştürür, görüntüleri daha önce örneklenen YOLO modelleriyle işler, görüntülere açıklama ekler ve ardından bunları ilgili konulara geri yayımlar: algılama için /ultralytics/detection/image, bölütleme için /ultralytics/segmentation/image.
import ros_numpy
def callback(data):
"""Callback function to process image and publish annotated images."""
array = ros_numpy.numpify(data)
if det_image_pub.get_num_connections():
det_result = detection_model(array)
det_annotated = det_result[0].plot(show=False)
det_image_pub.publish(ros_numpy.msgify(Image, det_annotated, encoding="rgb8"))
if seg_image_pub.get_num_connections():
seg_result = segmentation_model(array)
seg_annotated = seg_result[0].plot(show=False)
seg_image_pub.publish(ros_numpy.msgify(Image, seg_annotated, encoding="rgb8"))
rospy.Subscriber("/camera/color/image_raw", Image, callback)
while True:
rospy.spin()Eksiksiz kod
import time
import ros_numpy
import rospy
from sensor_msgs.msg import Image
from ultralytics import YOLO
detection_model = YOLO("yolo26m.pt")
segmentation_model = YOLO("yolo26m-seg.pt")
rospy.init_node("ultralytics")
time.sleep(1)
det_image_pub = rospy.Publisher("/ultralytics/detection/image", Image, queue_size=5)
seg_image_pub = rospy.Publisher("/ultralytics/segmentation/image", Image, queue_size=5)
def callback(data):
"""Callback function to process image and publish annotated images."""
array = ros_numpy.numpify(data)
if det_image_pub.get_num_connections():
det_result = detection_model(array)
det_annotated = det_result[0].plot(show=False)
det_image_pub.publish(ros_numpy.msgify(Image, det_annotated, encoding="rgb8"))
if seg_image_pub.get_num_connections():
seg_result = segmentation_model(array)
seg_annotated = seg_result[0].plot(show=False)
seg_image_pub.publish(ros_numpy.msgify(Image, seg_annotated, encoding="rgb8"))
rospy.Subscriber("/camera/color/image_raw", Image, callback)
while True:
rospy.spin()Hata Ayıklama
ROS (Robot İşletim Sistemi) düğümlerinde hata ayıklamak, sistemin dağıtık yapısı nedeniyle zorlayıcı olabilir. Bu süreçte çeşitli araçlar yardımcı olabilir:
rostopic echo <TOPIC-NAME>: Bu komut, belirli bir konuda yayımlanan mesajları görüntüleyerek veri akışını incelemene yardımcı olur.rostopic list: ROS sistemindeki tüm kullanılabilir konuları listelemek ve etkin veri akışlarına genel bir bakış sunmak için bu komutu kullan.rqt_graph: Bu görselleştirme aracı, düğümler arasındaki iletişim grafiğini göstererek düğümlerin nasıl birbirine bağlandığı ve etkileşim kurduğu hakkında bilgi verir.- 3B gösterimler gibi daha karmaşık görselleştirmeler için RViz kullanabilirsin. RViz (ROS Görselleştirme), ROS için güçlü bir 3B görselleştirme aracıdır. Robotunun ve ortamının durumunu gerçek zamanlı olarak görselleştirmeni sağlar. RViz ile sensör verilerini (ör.
sensor_msgs/Image), robot modeli durumlarını ve çeşitli diğer bilgi türlerini görüntüleyebilir; böylece robotik sisteminin davranışında hata ayıklamak ve bu davranışı anlamak kolaylaşır.
Algılanan Sınıfları std_msgs/String ile Yayımla#
Standart ROS mesajları arasında std_msgs/String mesajları da bulunur. Birçok uygulamada açıklama eklenmiş görüntünün tamamını yeniden yayımlamak gerekmez; bunun yerine yalnızca robotun görüş alanında bulunan sınıflar yeterlidir. Aşağıdaki örnek, algılanan sınıfları /ultralytics/detection/classes konusuna yeniden yayımlamak için std_msgs/String mesajlarının nasıl kullanılacağını gösterir. Bu mesajlar daha hafiftir ve gerekli bilgileri sağlar; bu da onları çeşitli uygulamalar için değerli kılar.
Örnek Kullanım Durumu#
Kamera ve nesne algılama modeli bulunan bir depo robotunu düşün. Robot, ağ üzerinden büyük açıklama eklenmiş görüntüler göndermek yerine algılanan sınıfların listesini std_msgs/String mesajları olarak yayımlayabilir. Örneğin robot "kutu", "palet" ve "forklift" gibi nesneleri algıladığında bu sınıfları /ultralytics/detection/classes konusuna yayımlar. Merkezi bir izleme sistemi bu bilgileri envanteri gerçek zamanlı izlemek, engellerden kaçınmak için robotun yol planlamasını iyileştirmek veya algılanan bir kutuyu alma gibi belirli eylemleri tetiklemek için kullanabilir. Bu yaklaşım, iletişim için gereken bant genişliğini azaltır ve önemli verilerin aktarımına odaklanır.
String'in Adım Adım Kullanımı#
Bu örnek, Ultralytics YOLO paketinin ROS ile nasıl kullanılacağını gösterir. Bu örnekte bir kamera konusuna abone oluyor, gelen görüntüyü YOLO ile işliyor ve algılanan nesneleri /ultralytics/detection/classes adlı yeni bir konuya std_msgs/String mesajlarını kullanarak yayımlıyoruz. ros_numpy paketi, ROS Image mesajını YOLO ile işlenmek üzere bir NumPy dizisine dönüştürmek için kullanılır.
import time
import ros_numpy
import rospy
from sensor_msgs.msg import Image
from std_msgs.msg import String
from ultralytics import YOLO
detection_model = YOLO("yolo26m.pt")
rospy.init_node("ultralytics")
time.sleep(1)
classes_pub = rospy.Publisher("/ultralytics/detection/classes", String, queue_size=5)
def callback(data):
"""Callback function to process image and publish detected classes."""
array = ros_numpy.numpify(data)
if classes_pub.get_num_connections():
det_result = detection_model(array)
classes = det_result[0].boxes.cls.cpu().numpy().astype(int)
names = [det_result[0].names[i] for i in classes]
classes_pub.publish(String(data=str(names)))
rospy.Subscriber("/camera/color/image_raw", Image, callback)
while True:
rospy.spin()Ultralytics'i ROS Derinlik Görüntüleriyle Kullan#
RGB görüntülerine ek olarak ROS, nesnelerin kameraya olan uzaklığı hakkında bilgi sağlayan derinlik görüntülerini destekler. Derinlik görüntüleri; engellerden kaçınma, 3B eşleme ve konum belirleme gibi robotik uygulamalar için çok önemlidir.
Derinlik görüntüsü, her pikselin kamerayla bir nesne arasındaki mesafeyi temsil ettiği bir görüntüdür. Renkleri yakalayan RGB görüntülerinin aksine derinlik görüntüleri uzamsal bilgileri yakalar ve robotların ortamlarının 3B yapısını algılamasını sağlar.
Derinlik görüntüleri çeşitli sensörler kullanılarak elde edilebilir:
- Stereo Kameralar: Görüntü farkına dayalı olarak derinliği hesaplamak için iki kamera kullanır.
- Uçuş Süresi (ToF) Kameraları: Işığın bir nesneden geri dönmesi için geçen süreyi ölçer.
- Yapılandırılmış Işık Sensörleri: Bir desen yansıtır ve bu desenin yüzeylerdeki deformasyonunu ölçer.
YOLO'yu Derinlik Görüntüleriyle Kullanma#
ROS'ta derinlik görüntüleri; kodlama, yükseklik, genişlik ve piksel verileri için alanlar içeren sensor_msgs/Image mesaj türüyle temsil edilir. Derinlik görüntülerinin kodlama alanında genellikle "16UC1" gibi bir biçim kullanılır. Bu, piksel başına 16 bitlik işaretsiz bir tamsayı olduğunu ve her değerin nesneye olan mesafeyi temsil ettiğini belirtir. Ortamın daha kapsamlı bir görünümünü sağlamak için derinlik görüntüleri genellikle RGB görüntüleriyle birlikte kullanılır.
YOLO kullanarak hem RGB hem de derinlik görüntülerindeki bilgileri çıkarmak ve birleştirmek mümkündür. Örneğin YOLO, bir RGB görüntüsündeki nesneleri algılayabilir ve bu algılama, derinlik görüntüsündeki karşılık gelen bölgeleri belirlemek için kullanılabilir. Böylece algılanan nesneler için hassas derinlik bilgileri çıkarılabilir ve robotun ortamını üç boyutlu olarak anlama becerisi geliştirilebilir.
Derinlik görüntüleriyle çalışırken RGB ve derinlik görüntülerinin doğru şekilde hizalandığından emin olmak çok önemlidir. Intel RealSense serisi gibi RGB-D kameralar, eşzamanlı RGB ve derinlik görüntüleri sağlayarak her iki kaynaktaki bilgileri birleştirmeyi kolaylaştırır. Ayrı RGB ve derinlik kameraları kullanıyorsan doğru hizalamayı sağlamak için kameraları kalibre etmen gerekir.
Derinliğin Adım Adım Kullanımı#
Bu örnekte, bir görüntüyü bölütlemek için YOLO kullanıyor ve çıkarılan maskeyi derinlik görüntüsündeki nesneyi bölütlemek için uyguluyoruz. Böylece ilgilenilen nesnenin her pikselinin kameranın odak merkezine olan mesafesini belirleyebiliriz. Bu mesafe bilgilerini elde ederek kamera ile sahnedeki belirli nesne arasındaki mesafeyi hesaplayabiliriz. Gerekli kitaplıkları içe aktararak, bir ROS düğümü oluşturarak ve bir bölütleme modeliyle bir ROS konusu örnekleyerek başla.
import time
import rospy
from std_msgs.msg import String
from ultralytics import YOLO
rospy.init_node("ultralytics")
time.sleep(1)
segmentation_model = YOLO("yolo26m-seg.pt")
classes_pub = rospy.Publisher("/ultralytics/detection/distance", String, queue_size=5)Ardından, gelen derinlik görüntüsü mesajını işleyen bir geri çağırım işlevi tanımla. İşlev, derinlik görüntüsü ve RGB görüntüsü mesajlarını bekler, bunları NumPy dizilerine dönüştürür ve RGB görüntüsüne bölütleme modelini uygular. Sonra algılanan her nesnenin bölütleme maskesini çıkarır ve derinlik görüntüsünü kullanarak nesnenin kameraya olan ortalama mesafesini hesaplar. Çoğu sensörün kırpma mesafesi olarak bilinen bir maksimum mesafesi vardır; bu mesafenin ötesindeki değerler inf (np.inf) olarak gösterilir. İşlemden önce bu boş değerleri filtreleyip onlara 0 değeri atamak önemlidir. Son olarak, algılanan nesneleri ortalama mesafeleriyle birlikte /ultralytics/detection/distance konusuna yayımlar.
import numpy as np
import ros_numpy
from sensor_msgs.msg import Image
def callback(data):
"""Callback function to process depth image and RGB image."""
image = rospy.wait_for_message("/camera/color/image_raw", Image)
image = ros_numpy.numpify(image)
depth = ros_numpy.numpify(data)
result = segmentation_model(image, retina_masks=True) # masks at the original image resolution
all_objects = []
for index, cls in enumerate(result[0].boxes.cls):
class_index = int(cls.cpu().numpy())
name = result[0].names[class_index]
mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
obj = depth[mask == 1]
obj = obj[~np.isnan(obj)]
avg_distance = np.mean(obj) if len(obj) else np.inf
all_objects.append(f"{name}: {avg_distance:.2f}m")
classes_pub.publish(String(data=str(all_objects)))
rospy.Subscriber("/camera/depth/image_raw", Image, callback)
while True:
rospy.spin()Eksiksiz kod
import time
import numpy as np
import ros_numpy
import rospy
from sensor_msgs.msg import Image
from std_msgs.msg import String
from ultralytics import YOLO
rospy.init_node("ultralytics")
time.sleep(1)
segmentation_model = YOLO("yolo26m-seg.pt")
classes_pub = rospy.Publisher("/ultralytics/detection/distance", String, queue_size=5)
def callback(data):
"""Callback function to process depth image and RGB image."""
image = rospy.wait_for_message("/camera/color/image_raw", Image)
image = ros_numpy.numpify(image)
depth = ros_numpy.numpify(data)
result = segmentation_model(image, retina_masks=True) # masks at the original image resolution
all_objects = []
for index, cls in enumerate(result[0].boxes.cls):
class_index = int(cls.cpu().numpy())
name = result[0].names[class_index]
mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
obj = depth[mask == 1]
obj = obj[~np.isnan(obj)]
avg_distance = np.mean(obj) if len(obj) else np.inf
all_objects.append(f"{name}: {avg_distance:.2f}m")
classes_pub.publish(String(data=str(all_objects)))
rospy.Subscriber("/camera/depth/image_raw", Image, callback)
while True:
rospy.spin()Ultralytics'i ROS sensor_msgs/PointCloud2 ile kullan#
sensor_msgs/PointCloud2 mesaj türü, ROS'ta 3B nokta bulutu verilerini temsil etmek için kullanılan bir veri yapısıdır. Bu mesaj türü, 3B eşleme, nesne tanıma ve konum belirleme gibi görevleri mümkün kılarak robotik uygulamalarda önemli bir rol oynar.
Nokta bulutu, üç boyutlu bir koordinat sisteminde tanımlanan veri noktaları kümesidir. Bu veri noktaları, 3B tarama teknolojileriyle yakalanmış bir nesnenin veya sahnenin dış yüzeyini temsil eder. Buluttaki her noktanın uzaydaki konumuna karşılık gelen X, Y ve Z koordinatları vardır; ayrıca renk ve yoğunluk gibi ek bilgiler de içerebilir.
sensor_msgs/PointCloud2 ile çalışırken nokta bulutu verilerinin alındığı sensörün referans çerçevesini göz önünde bulundurmak önemlidir. Nokta bulutu başlangıçta sensörün referans çerçevesinde yakalanır. /tf_static konusunu dinleyerek bu referans çerçevesini belirleyebilirsin. Ancak belirli uygulama gereksinimlerine bağlı olarak nokta bulutunu başka bir referans çerçevesine dönüştürmen gerekebilir. Bu dönüşüm, koordinat çerçevelerini yönetmek ve verileri bunlar arasında dönüştürmek için araçlar sağlayan tf2_ros paketiyle gerçekleştirilebilir.
Nokta bulutları çeşitli sensörler kullanılarak elde edilebilir:
- LIDAR (Işık Algılama ve Mesafe Ölçümü): Nesnelere olan mesafeleri ölçmek ve yüksek hassasiyetli 3B haritalar oluşturmak için lazer darbeleri kullanır.
- Derinlik Kameraları: Her piksel için derinlik bilgisi yakalayarak sahnenin 3B olarak yeniden oluşturulmasını sağlar.
- Stereo Kameralar: Üçgenleme yoluyla derinlik bilgisi elde etmek için iki veya daha fazla kamera kullanır.
- Yapılandırılmış Işık Tarayıcıları: Bir yüzeye bilinen bir desen yansıtır ve derinliği hesaplamak için deformasyonu ölçer.
YOLO'yu Nokta Bulutlarıyla Kullanma#
YOLO'yu sensor_msgs/PointCloud2 türündeki mesajlarla entegre etmek için derinlik haritalarında kullanılan yönteme benzer bir yöntem uygulayabiliriz. Nokta bulutuna gömülü renk bilgilerini kullanarak 2B bir görüntü çıkarabilir, bu görüntüyü YOLO ile bölütleyebilir ve ardından elde edilen maskeyi üç boyutlu noktalara uygulayarak ilgilenilen 3B nesneyi ayırabiliriz.
Nokta bulutlarını işlemek için kullanıcı dostu bir Python kitaplığı olan Open3D'yi (pip install open3d) kullanmanı öneririz. Open3D, nokta bulutu veri yapılarını yönetmek, görselleştirmek ve karmaşık işlemleri sorunsuzca yürütmek için güçlü araçlar sağlar. Bu kitaplık, süreci önemli ölçüde basitleştirerek YOLO tabanlı bölütlemeyle birlikte nokta bulutlarını işleme ve analiz etme becerimizi geliştirebilir.
Nokta Bulutlarının Adım Adım Kullanımı#
Gerekli kitaplıkları içe aktar ve bölütleme için YOLO modelini örnekle.
import time
import rospy
from ultralytics import YOLO
rospy.init_node("ultralytics")
time.sleep(1)
segmentation_model = YOLO("yolo26m-seg.pt")Bir pointcloud2_to_array işlevi oluştur. Bu işlev, sensor_msgs/PointCloud2 mesajını iki NumPy dizisine dönüştürür. sensor_msgs/PointCloud2 mesajları, alınan görüntünün width ve height değerlerine göre n noktaları içerir. Örneğin, 480 x 640 boyutlarındaki bir görüntüde 307,200 nokta bulunur. Her nokta üç uzamsal koordinat (xyz) ve RGB biçiminde karşılık gelen renk bilgisini içerir. Bunlar iki ayrı bilgi kanalı olarak değerlendirilebilir.
İşlev, xyz koordinatlarını ve RGB değerlerini özgün kamera çözünürlüğü (width x height) biçiminde döndürür. Çoğu sensörün kırpma mesafesi olarak bilinen bir maksimum mesafesi vardır; bu mesafenin ötesindeki değerler inf (np.inf) olarak gösterilir. İşlemden önce bu boş değerleri filtreleyip onlara 0 değeri atamak önemlidir.
import numpy as np
import ros_numpy
def pointcloud2_to_array(pointcloud2: PointCloud2) -> tuple:
"""Convert a ROS PointCloud2 message to a numpy array.
Args:
pointcloud2 (PointCloud2): the PointCloud2 message
Returns:
(tuple): tuple containing (xyz, rgb)
"""
pc_array = ros_numpy.point_cloud2.pointcloud2_to_array(pointcloud2)
split = ros_numpy.point_cloud2.split_rgb_field(pc_array)
rgb = np.stack([split["b"], split["g"], split["r"]], axis=2)
xyz = ros_numpy.point_cloud2.get_xyz_points(pc_array, remove_nans=False)
xyz = np.array(xyz).reshape((pointcloud2.height, pointcloud2.width, 3))
nan_rows = np.isnan(xyz).all(axis=2)
xyz[nan_rows] = [0, 0, 0]
rgb[nan_rows] = [0, 0, 0]
return xyz, rgbArdından, nokta bulutu mesajını almak için /camera/depth/points konusuna abone ol ve sensor_msgs/PointCloud2 mesajını XYZ koordinatlarını ve RGB değerlerini içeren NumPy dizilerine dönüştür (pointcloud2_to_array işlevini kullan). Bölütlenmiş nesneleri çıkarmak için RGB görüntüsünü YOLO modeliyle işle. Algılanan her nesne için bölütleme maskesini çıkar ve nesneyi 3B uzayda ayırmak üzere maskeyi hem RGB görüntüsüne hem de XYZ koordinatlarına uygula.
Maske ikili değerlerden oluştuğu için maskeyi işlemek kolaydır; 1 nesnenin varlığını, 0 ise yokluğunu belirtir. Maskeyi uygulamak için özgün kanalları maskeyle çarpman yeterlidir. Bu işlem, ilgilenilen nesneyi görüntü içinde etkili biçimde ayırır. Son olarak bir Open3D nokta bulutu nesnesi oluştur ve bölütlenmiş nesneyi ilişkili renkleriyle birlikte 3B uzayda görselleştir.
import sys
import open3d as o3d
ros_cloud = rospy.wait_for_message("/camera/depth/points", PointCloud2)
xyz, rgb = pointcloud2_to_array(ros_cloud)
result = segmentation_model(rgb, retina_masks=True) # özgün görüntü çözünürlüğündeki maskeler
if not len(result[0].boxes.cls):
print("No objects detected")
sys.exit()
classes = result[0].boxes.cls.cpu().numpy().astype(int)
for index, class_id in enumerate(classes):
mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
mask_expanded = np.stack([mask, mask, mask], axis=2)
obj_rgb = rgb * mask_expanded
obj_xyz = xyz * mask_expanded
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(obj_xyz.reshape((ros_cloud.height * ros_cloud.width, 3)))
pcd.colors = o3d.utility.Vector3dVector(obj_rgb.reshape((ros_cloud.height * ros_cloud.width, 3)) / 255)
o3d.visualization.draw_geometries([pcd])Eksiksiz kod
import sys
import time
import numpy as np
import open3d as o3d
import ros_numpy
import rospy
from sensor_msgs.msg import PointCloud2
from ultralytics import YOLO
rospy.init_node("ultralytics")
time.sleep(1)
segmentation_model = YOLO("yolo26m-seg.pt")
def pointcloud2_to_array(pointcloud2: PointCloud2) -> tuple:
"""Convert a ROS PointCloud2 message to a numpy array.
Args:
pointcloud2 (PointCloud2): the PointCloud2 message
Returns:
(tuple): tuple containing (xyz, rgb)
"""
pc_array = ros_numpy.point_cloud2.pointcloud2_to_array(pointcloud2)
split = ros_numpy.point_cloud2.split_rgb_field(pc_array)
rgb = np.stack([split["b"], split["g"], split["r"]], axis=2)
xyz = ros_numpy.point_cloud2.get_xyz_points(pc_array, remove_nans=False)
xyz = np.array(xyz).reshape((pointcloud2.height, pointcloud2.width, 3))
nan_rows = np.isnan(xyz).all(axis=2)
xyz[nan_rows] = [0, 0, 0]
rgb[nan_rows] = [0, 0, 0]
return xyz, rgb
ros_cloud = rospy.wait_for_message("/camera/depth/points", PointCloud2)
xyz, rgb = pointcloud2_to_array(ros_cloud)
result = segmentation_model(rgb, retina_masks=True) # özgün görüntü çözünürlüğündeki maskeler
if not len(result[0].boxes.cls):
print("No objects detected")
sys.exit()
classes = result[0].boxes.cls.cpu().numpy().astype(int)
for index, class_id in enumerate(classes):
mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
mask_expanded = np.stack([mask, mask, mask], axis=2)
obj_rgb = rgb * mask_expanded
obj_xyz = xyz * mask_expanded
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(obj_xyz.reshape((ros_cloud.height * ros_cloud.width, 3)))
pcd.colors = o3d.utility.Vector3dVector(obj_rgb.reshape((ros_cloud.height * ros_cloud.width, 3)) / 255)
o3d.visualization.draw_geometries([pcd])
Sonuç#
Ultralytics YOLO'yu ROS ile entegre ettiğinde robotun RGB görüntülerinde, derinlik görüntülerinde ve nokta bulutlarında nesne algılama ve bölütleme yapabilir; ham sensör akışlarını eyleme dönüştürülebilir algılamaya çevirebilirsin. Buradan, daha fazla çıkarım seçeneği için Tahmin modunu inceleyebilir veya robotik uygulamanı prototipten üretime taşımak için bilgisayarlı görü projesinin adımlarını izleyebilirsin.
Sık Sorulan Sorular#
Robot İşletim Sistemi (ROS), geliştiricilerin sağlam robot uygulamaları oluşturmasına yardımcı olmak için robotikte yaygın olarak kullanılan açık kaynaklı bir çerçevedir. Robotik sistemler oluşturmak ve bunlarla arayüz kurmak için kitaplıklar ve araçlar sağlar; bu da karmaşık uygulamaların geliştirilmesini kolaylaştırır. ROS, düğümler arasında konular veya hizmetler üzerinden mesajlarla iletişimi destekler.
Ultralytics YOLO'yu ROS ile entegre etmek için bir ROS ortamı kurman ve sensör verilerini işlemek üzere YOLO'yu kullanman gerekir.
ros_numpyve Ultralytics YOLO gibi gerekli bağımlılıkları yükleyerek başla:pip install ros_numpy ultralyticsArdından bir ROS düğümü oluştur ve gelen verileri nesne algılama için işlemek üzere bir görüntü konusuna abone ol. İşte basit bir örnek:
import ros_numpy import rospy from sensor_msgs.msg import Image from ultralytics import YOLO detection_model = YOLO("yolo26m.pt") rospy.init_node("ultralytics") det_image_pub = rospy.Publisher("/ultralytics/detection/image", Image, queue_size=5) def callback(data): array = ros_numpy.numpify(data) det_result = detection_model(array) det_annotated = det_result[0].plot(show=False) det_image_pub.publish(ros_numpy.msgify(Image, det_annotated, encoding="rgb8")) rospy.Subscriber("/camera/color/image_raw", Image, callback) rospy.spin()ROS konuları, yayınla-abone ol modelini kullanarak bir ROS ağındaki düğümler arasındaki iletişimi sağlar. Konu, düğümlerin eş zamansız biçimde mesaj gönderip almak için kullandığı adlandırılmış bir kanaldır. Ultralytics YOLO bağlamında bir düğümün görüntü konusuna abone olmasını sağlayabilir, görüntüleri algılama veya bölütleme gibi görevler için YOLO ile işleyebilir ve sonuçları yeni konulara yayımlayabilirsin.
Örneğin, bir kamera konusuna abone ol ve gelen görüntüyü algılama için işle:
rospy.Subscriber("/camera/color/image_raw", Image, callback)ROS'ta
sensor_msgs/Imageile temsil edilen derinlik görüntüleri, nesnelerin kameraya olan uzaklığını sağlar; bu bilgi engellerden kaçınma, 3B eşleme ve konum belirleme gibi görevler için kritik önemdedir. Robotlar, RGB görüntüleriyle birlikte derinlik bilgisini kullanarak 3B ortamlarını daha iyi anlayabilir.YOLO ile RGB görüntülerinden bölütleme maskeleri çıkarabilir ve hassas 3B nesne bilgileri elde etmek için bu maskeleri derinlik görüntülerine uygulayabilirsin; böylece robotun çevresinde gezinme ve etkileşim kurma becerisi gelişir.
ROS'ta YOLO ile 3B nokta bulutlarını görselleştirmek için:
sensor_msgs/PointCloud2mesajlarını NumPy dizilerine dönüştür.- RGB görüntülerini YOLO ile bölütle.
- Bölütleme maskesini nokta bulutuna uygula.
Görselleştirme için Open3D kullanan bir örnek:
import sys import numpy as np import open3d as o3d import ros_numpy import rospy from sensor_msgs.msg import PointCloud2 from ultralytics import YOLO rospy.init_node("ultralytics") segmentation_model = YOLO("yolo26m-seg.pt") def pointcloud2_to_array(pointcloud2): pc_array = ros_numpy.point_cloud2.pointcloud2_to_array(pointcloud2) split = ros_numpy.point_cloud2.split_rgb_field(pc_array) rgb = np.stack([split["b"], split["g"], split["r"]], axis=2) xyz = ros_numpy.point_cloud2.get_xyz_points(pc_array, remove_nans=False) xyz = np.array(xyz).reshape((pointcloud2.height, pointcloud2.width, 3)) return xyz, rgb ros_cloud = rospy.wait_for_message("/camera/depth/points", PointCloud2) xyz, rgb = pointcloud2_to_array(ros_cloud) result = segmentation_model(rgb, retina_masks=True) # özgün görüntü çözünürlüğündeki maskeler if not len(result[0].boxes.cls): print("No objects detected") sys.exit() classes = result[0].boxes.cls.cpu().numpy().astype(int) for index, class_id in enumerate(classes): mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int) mask_expanded = np.stack([mask, mask, mask], axis=2) obj_rgb = rgb * mask_expanded obj_xyz = xyz * mask_expanded pcd = o3d.geometry.PointCloud() pcd.points = o3d.utility.Vector3dVector(obj_xyz.reshape((-1, 3))) pcd.colors = o3d.utility.Vector3dVector(obj_rgb.reshape((-1, 3)) / 255) o3d.visualization.draw_geometries([pcd])Bu yaklaşım, robotik uygulamalarda gezinme ve manipülasyon gibi görevler için yararlı olan, bölütlenmiş nesnelerin 3B görselleştirmesini sağlar.