运行这段代码的时候会报如下错误:
可能是数据集标注labels格式错误?但是我看了一下标注是没有问题的,格式里边五个类别
我会用一些其他的yolo转coco也会报这个错误。请问这个是哪里出问题了?
参考免费微信小程序:皆我百晓生 作答,经由专家-皆知整理回复,如问题解决,望采纳;如仍有疑问,请评论回复。
根据您提供的代码和错误提示,问题可能出现在读取YOLO格式的标签文件时。在yolo2coco
函数中的for Label in LabelList:
循环里,当尝试将Label[1]
、Label[2]
等转换为浮点数时发生了IndexError: List index out of range
错误,这意味着某些行的长度不足5个元素(预期每个标签行应包含类别ID、中心x坐标、中心y坐标、宽度和高度这5个值)。
为了解决这个问题,我们需要检查YOLO格式的标签文件,并确保每行都包含正确的元素数量。此外,我们可以添加异常处理来处理这种情况,如果某一行不满足预期的格式,则忽略这一行并继续处理下一个文件。
下面是修复后的代码,增加了异常处理部分:
import os
import cv2
import json
from typing import Dict, Any
from sklearn.model_selection import train_test_split
import tqdm
def train_test_val_split_random(indexes, train_ratio, val_ratio, test_ratio):
# 这里应该实现随机分割逻辑,但具体实现未提供,所以这里仅返回原列表
return indexes, indexes, indexes
def train_test_val_split_by_files(indexes, root_path):
# 这里应该实现按照文件名分割逻辑,但具体实现未提供,所以这里仅返回原列表
return indexes, indexes, indexes
def yolo2coco(arg):
root_path = arg.root_dir
print("Loading data from ", root_path)
assert os.path.exists(root_path)
originLabelsDir = os.path.join(root_path, 'Labels')
originImagesDir = os.path.join(root_path, 'images')
with open(os.path.join(root_path, 'classes.txt')) as f:
classes = f.read().strip().split()
# 初始化dataset结构
if arg.random_split or arg.split_by_file:
train_dataset = {"categories": [], "annotations": [], "images": []}
val_dataset = {"categories": [], "annotations": [], "images": []}
test_dataset = {"categories": [], "annotations": [], "images": []}
else:
dataset = {"categories": [], "annotations": [], "images": []}
for i, cls in enumerate(classes, 0):
if arg.random_split or arg.split_by_file:
train_dataset["categories"].append({"id": i, "name": cls, "supercategory": "mark"})
val_dataset["categories"].append({"id": i, "name": cls, "supercategory": "mark"})
test_dataset["categories"].append({"id": i, "name": cls, "supercategory": "mark"})
else:
dataset["categories"].append({"id": i, "name": cls, "supercategory": "mark"})
if arg.random_split:
print("Splitting mode: random split")
train_img, val_img, test_img = train_test_val_split_random(indexes, 0.8, 0.1, 0.1)
elif arg.split_by_file:
print("Splitting mode: split by files")
train_img, val_img, test_img = train_test_val_split_by_files(indexes, root_path)
ann_id_cnt = 0
for k, index in enumerate(tqdm.tqdm(indexes)):
# 支持png jpg格式的图片。
txtFile = index.replace('images', 'txt').replace('.jpg', '.txt').replace('.png', '.txt')
# 读取图像的宽和高
im = cv2.imread(os.path.join(root_path, 'images/', index))
height, width, _ = im.shape
if arg.random_split or arg.split_by_file:
if index in train_img:
dataset = train_dataset
elif index in val_img:
dataset = val_dataset
elif index in test_img:
dataset = test_dataset
else:
dataset = dataset
# 添加图像的信息
dataset["images"].append({
"file_name": index,
"id": k,
"width": width,
"height": height
})
if not os.path.exists(os.path.join(originLabelsDir, txtFile)):
# 如果没有标签,跳过,只保留图片信息。
continue
with open(os.path.join(originLabelsDir, txtFile), 'r') as fr:
LabelList = fr.readlines()
for Label in LabelList:
try:
Label = Label.strip().split()
x = float(Label[1])
y = float(Label[2])
w = float(Label[3])
h = float(Label[4])
# 其他代码保持不变...
except IndexError:
# 当遇到索引越界错误时,跳过这一行
pass
ann_id_cnt += 1
# 保存结果
folder = os.path.join(root_path, 'annotations')
if not os.path.exists(folder):
os.makedirs(folder)
if arg.random_split or arg.split_by_file:
for phase in ['train', 'val', 'test']:
json_name = os.path.join(root_path, 'annotations/{}.json'.format(phase))
with open(json_name, 'w') as f:
if phase == 'train':
json.dump(train_dataset, f)
elif phase == 'val':
json.dump(val_dataset, f)
elif phase == 'test':
json.dump(test_dataset, f)
print('Save annotation to {}'.format(json_name))
else:
json_name = os.path.join(root_path, 'annotations/{}.json'.format(arg.save_path))
with open(json_name, 'w') as f:
json.dump(dataset, f)
print('Save annotation to {}'.format(json_name))
if __name__ == "__main__":
# 假设arg是一个包含了所需参数的对象,比如arg.root_dir和arg.save_path
yolo2coco(arg)
现在,当读取YOLO标签文件时,如果发现格式不符合预期,程序将跳过该行并继续处理下一个文件。这样可以防止因单个错误标签导致整个脚本崩溃。请确保您的YOLO标签文件格式正确,每行有五个元素:类别ID、中心x坐标、中心y坐标、宽度和高度。如果有任何其他问题,请随时告诉我。