У меня проблема с результатами обучения YOLOv8 (от Ultralytics), в частности с рисованием меток (а не прогнозов). У меня есть набор данных спутниковых изображений, где есть (сегментация) полигоны на крыше здания, и мы хотим, чтобы модель прогнозировала сегментацию крыш зданий. Проблема в том, что вывод YOLOv8 для построения меток выглядит странно. У меня есть данные в виде многоугольников только в формате JSON, и я извлек/создал bbox из многоугольников (поскольку YOLO требует координаты bbox в метках), а затем поместил метки в структуру YOLO. Боюсь, что я что-то упускаю при обработке данных, однако моя собственная визуализация верна и отлично показывает метки.
Мои визуализации:
Визуализации YOLO (различное изображение, но одна и та же проблема на всех изображениях):
Исходные полигоны в файле json выглядят примерно так:
"polygon": [[0.6005, 0.0844], [0.432, 0.3742], [0.2131, 0.2514], [0.3691, 0.0], [0.4462, 0.0]]
текстовый файл этикетки YOLO выглядит следующим образом:
{label_clss}{x_center}{y_center}{bbox_width}{bbox_height}{polygon_coord}
3 0.4068 0.1871 0.3874 0.3742 0.6005 0.0844 0.4320 0.3742 0.2131 0.2514 0.3691 0.0000 0.4462 0.0000
1 0.2420 0.2840 0.0817 0.0602 0.2161 0.2539 0.2012 0.2784 0.2693 0.3141 0.2829 0.2921
3 0.4968 0.5071 0.3422 0.3051 0.4035 0.3587 0.3257 0.4908 0.4726 0.5833 0.4476 0.6200 0.5621 0.6597 0.6679 0.4923 0.4484 0.3546 0.4329 0.3777
функция, которую я использовал для получения bbox из полигонов:
def get_bounding_box(polygon):
# Extract x and y coordinates separately
x_coords = [point[0] for point in polygon]
y_coords = [point[1] for point in polygon]
# Determine the bounding box corners
min_x, max_x = min(x_coords), max(x_coords)
min_y, max_y = min(y_coords), max(y_coords)
# Calculate center, width, and height
x_center = (min_x + max_x) / 2
y_center = (min_y + max_y) / 2
width = max_x - min_x
height = max_y - min_y
return x_center, y_center, width, height
Это метод, который я использую для создания txt-файлов YOLO:
def export_yolo_labels(json_data, folder_path = "yolo_labels"):
os.makedirs(folder_path, exist_ok=True)
for anno in json_data:
img_size = (anno["image_size"]["width"],anno["image_size"]["height"])
img_name = anno["image_name"]
label_name = f"{img_name.replace('.png', '.txt')}"
file = open(os.path.join(folder_path,label_name), "a")
for label in anno["labels"]:
label_class = label["label_class"]
polygon = label["polygon"]
x_center, y_center, bbox_width, bbox_height = get_bounding_box(polygon)
flat_polygon = flatten_polygon(polygon)
yolo_text_format = f"{label_class} {x_center:.4f} {y_center:.4f} {bbox_width:.4f} {bbox_height:.4f} {flat_polygon}"
file.write(yolo_text_format + '\n')
file.close()
я что-то пропустил? В чем может быть проблема? как это решить? Спасибо!
Этикетки имеют правильный формат YOLOv8.
Для задачи сегментации объектов требуемый формат маркировки для Yolov8 следующий (https://docs.ultralytics.com/datasets/segment/#ultralytics-yolo-format):
<class-index> <x1> <y1> <x2> <y2> ... <xn> <yn>
Вам необходимо сохранить нормализованные координаты сегмента {label_clss}{polygon_coord}
и избавиться от лишней части bbox {x_center}{y_center}{bbox_width}{bbox_height}
, так как она нужна только для задачи обнаружения объектов. В случае сегментации объекта программный код yolov8 легко вычислит координаты bbox на основе предоставленных координат сегмента.
Подозреваю, что в вашем случае модель принимает координаты bbox в метке как часть сегмента и отображает этот искаженный результат.
Большое спасибо за ваш ответ. Все верно, после удаления координат bbox все заработало. Я хочу упомянуть (возможно, это кому-то поможет), что я использую веса йоло для сегментации, например
yolov8x-seg.pt