YOLOv8+ROS目标检测:识别类别带时间写入TXT失败求助
YOLOv8+ROS目标检测:识别类别与时间写入TXT文件失败问题处理
我正在用YOLOv8结合ROS开展目标检测任务,基础功能正常,但实现将检测框内识别到的类别名称搭配检测时间写入TXT文件时功能失效。我尝试了自己的代码实现但无法推进,目前正在查阅Ultralytics官方文档。以下是我的代码及TXT文件的错误输出:
原代码
#!/usr/bin/env python3 from ultralytics import YOLO import rospy from sensor_msgs.msg import Image from cv_bridge import CvBridge import cv2 import os import datetime model = YOLO('yolov8n.pt') # 创建存储识别标签的文件 label_file = open("labels.txt", "w") def start_node(): rospy.init_node('detect_pump') rospy.loginfo('detect_pump node started') rospy.Subscriber("/image", Image, process_image) rospy.spin() def process_image(msg): bridge = CvBridge() orig = bridge.imgmsg_to_cv2(msg, "bgr8") image = orig results = model(orig, verbose=True, imgsz=640) resultado= model.predict(source="0") cv2.imshow('IMAGEM RECEBIDA', orig) cv2.waitKey(1) res_plotted = results[0].plot() cv2.imshow("result", res_plotted) cv2.waitKey(1) # 获取当前时间 current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 将识别到的标签拼接成字符串 labels_str = "\n".join(results.names) # 将标签和时间写入文件 label_file.write(f"Data/Hora: {current_time}\n") label_file.write(f"Labels: \n{labels_str}\n\n") if __name__ == '__main__': try: start_node() except rospy.ROSInterruptException: pass # 使用完毕后关闭文件 label_file.close()
当前错误输出
Data/Hora: 2023-10-14 17:08:30 Resultados: [ultralytics.yolo.engine.results.Results object with attributes: boxes: ultralytics.yolo.engine.results.Boxes object keypoints: None keys: ['boxes'] masks: None names: {0: 'person', 1: 'bicycle', 2: 'car', 3: 'motorcycle', 4: 'airplane', 5: 'bus', 6: 'train', 7: 'truck', 8: 'boat', 9: 'traffic light', 10: 'fire hydrant', 11: 'stop sign', 12: 'parking meter', 13: 'bench', 14: 'bird', 15: 'cat', 16: 'dog', 17: 'horse', 18: 'sheep', 19: 'cow', 20: 'elephant', 21: 'bear', 22: 'zebra', 23: 'giraffe', 24: 'backpack', 25: 'umbrella', 26: 'handbag', 27: 'tie', 28: 'suitcase', 29: 'frisbee', 30: 'skis', 31: 'snowboard', 32: 'sports ball', 33: 'kite', 34: 'baseball bat', 35: 'baseball glove', 36: 'skateboard', 37: 'surfboard', 38: 'tennis racket', 39: 'bottle', 40: 'wine glass', 41: 'cup', 42: 'fork', 43: 'knife', 44: 'spoon', 45: 'bowl', 46: 'banana', 47: 'apple', 48: 'sandwich', 49: 'orange', 50: 'broccoli', 51: 'carrot', 52: 'hot dog', 53: 'pizza', 54: 'donut', 55: 'cake', 56: 'chair', 57: 'couch', 58: 'potted plant', 59: 'bed', 60: 'dining table', 61: 'toilet', 62: 'tv', 63: 'laptop', 64: 'mouse', 65: 'remote', 66: 'keyboard', 67: 'cell phone', 68: 'microwave', 69: 'oven', 70: 'toaster', 71: 'sink', 72: 'refrigerator', 73: 'book', 74: 'clock', 75: 'vase', 76: 'scissors', 77: 'teddy bear', 78: 'hair drier', 79: 'toothbrush'} orig_img: array([[[253, 238, 255], [253, 238, 255], [253, 238, 255], ..., [191, 213, 146], [191, 222, 129], [191, 222, 129]], [[253, 238, 255], [253, 238, 255], [253, 238, 255], ..., [191, 213, 146], [191, 222, 129], [191, 222, 129]], [[253, 241, 255], [253, 241, 255], [253, 241, 255], ..., [192, 209, 156], [192, 216, 142], [192, 216, 142]], ..., [[131, 118, 154], [131, 118, 154], [130, 117, 153], ..., [ 22, 26, 32], [ 20, 25, 28], [ 19, 24, 27]], [[131, 118, 156], [130, 117, 155], [129, 116, 154], ..., [ 24, 28, 34], [ 22, 27, 30], [ 21, 26, 29]], [[131, 118, 156], [130, 117, 155], [128, 115, 153], ..., [ 25, 29, 35], [ 23, 28, 31], [ 22, 27, 30]]], dtype=uint8) orig_shape: (640, 480) path: 'image0.jpg' probs: None save_dir: None speed: {'preprocess': 3.4890174865722656, 'inference': 41.97049140930176, 'postprocess': 2.0608901977539062}]
问题分析
- 类别获取错误:
results.names是模型包含的全量类别字典,不是当前帧实际识别到的类别,导致输出所有80个COCO类别而非检测框内的目标。 - 冗余推理操作:代码中同时执行了
model(orig)(处理ROS图像)和model.predict(source="0")(调用本地摄像头),后者完全多余,会浪费计算资源且干扰结果。 - 文件操作不规范:全局以写入模式("w")打开文件,每次运行会清空历史记录;且未及时刷新缓冲区,ROS节点运行时可能导致内容无法实时写入磁盘。
修正后的代码
#!/usr/bin/env python3 from ultralytics import YOLO import rospy from sensor_msgs.msg import Image from cv_bridge import CvBridge import cv2 import datetime model = YOLO('yolov8n.pt') def start_node(): rospy.init_node('detect_pump') rospy.loginfo('detect_pump node started') rospy.Subscriber("/image", Image, process_image) rospy.spin() def process_image(msg): bridge = CvBridge() orig = bridge.imgmsg_to_cv2(msg, "bgr8") # 仅对ROS传入的图像执行推理 results = model(orig, verbose=True, imgsz=640) cv2.imshow('IMAGEM RECEBIDA', orig) cv2.waitKey(1) res_plotted = results[0].plot() cv2.imshow("result", res_plotted) cv2.waitKey(1) # 获取当前时间 current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") # 提取当前帧识别到的类别名称 detected_classes = [] # 获取所有检测框的类别ID class_ids = results[0].boxes.cls.cpu().numpy() names = results[0].names for cls_id in class_ids: detected_classes.append(names[int(cls_id)]) # 去重并拼接成字符串(避免同一类别多次出现) unique_classes = list(set(detected_classes)) labels_str = "\n".join(unique_classes) # 以追加模式打开文件,确保历史记录不丢失,写入后立即刷新 with open("labels.txt", "a", encoding="utf-8") as label_file: label_file.write(f"Data/Hora: {current_time}\n") label_file.write(f"Labels: \n{labels_str}\n\n") label_file.flush() if __name__ == '__main__': try: start_node() except rospy.ROSInterruptException: pass
修正说明
- 移除了多余的
model.predict(source="0")调用,仅处理ROS订阅到的图像 - 通过
results[0].boxes.cls获取当前帧检测框的类别ID,再映射为类别名称,确保只输出实际识别到的目标 - 使用
with语句管理文件,自动处理打开/关闭,以追加模式("a")写入避免覆盖历史数据,每次写入后调用flush()确保内容实时写入磁盘 - 对识别到的类别做了去重处理,避免同一帧内同一类别多次出现重复记录
内容的提问来源于stack exchange,提问作者BrunoCCoelho
相关产品推荐
相关产品推荐

