### 将 YOLO 格式数据集转换为 COCO 格式的实现
YOLO 和 COCO 是两种常见的目标检测数据集格式,它们之间的主要区别在于标注文件的结构和存储方式。以下是将 YOLO 格式数据集转换为 COCO 格式的具体方法。
#### 1. 数据准备
在开始转换之前,需要准备好以下内容:
- **YOLO 格式的标签文件**:这些是以 `.txt` 文件形式存在的标注文件,位于 `labels/` 文件夹下。
- **图像文件路径列表**:用于构建 COCO 的 `images` 字段。
- **类别名称列表**:定义了数据集中包含的目标类别的名称。
#### 2. 转换逻辑
COCO 格式的标注文件是一个 JSON 文件,其基本结构如下:
```json
{
"info": {},
"licenses": [],
"categories": [
{"id": 0, "name": "class_1"},
{"id": 1, "name": "class_2"}
],
"images": [
{"id": 0, "file_name": "image_1.jpg", "width": 640, "height": 480},
{"id": 1, "file_name": "image_2.jpg", "width": 640, "height": 480}
],
"annotations": [
{
"id": 0,
"image_id": 0,
"category_id": 0,
"bbox": [x_min, y_min, width, height],
"area": area_of_bbox,
"iscrowd": 0
}
]
}
```
为了完成转换,需执行以下几个操作:
- 构建 `categories` 部分,基于类别名称列表生成对应的 ID 映射关系[^1]。
- 解析每张图片的信息并填充到 `images` 列表中。
- 对于每个标注文件解析边界框坐标,并将其从相对位置 (YOLO 格式) 转换为绝对像素位置 (COCO 格式),最后填入 `annotations` 中。
#### 3. Python 实现脚本
下面提供了一个完整的 Python 脚本来完成上述任务:
```python
import os
import json
from PIL import Image
def convert_yolo_to_coco(yolo_labels_dir, images_dir, output_json_path, class_names):
"""
Convert YOLO format dataset to COCO format.
:param yolo_labels_dir: Path to the directory containing .txt label files in YOLO format.
:param images_dir: Path to the directory containing image files.
:param output_json_path: Output path for saving the resulting COCO-format JSON file.
:param class_names: List of class names corresponding to indices used in labels.
"""
# Initialize COCO structure
coco_data = {
"info": {},
"licenses": [],
"categories": [{"id": idx, "name": name} for idx, name in enumerate(class_names)],
"images": [],
"annotations": []
}
annotation_id_counter = 0
# Process each image and its associated label file
for img_idx, filename in enumerate(os.listdir(images_dir)):
if not filename.lower().endswith(('.png', '.jpg', '.jpeg')):
continue
img_path = os.path.join(images_dir, filename)
img = Image.open(img_path)
w, h = img.size
# Add image entry
coco_image_entry = {
"id": img_idx,
"file_name": filename,
"width": w,
"height": h
}
coco_data["images"].append(coco_image_entry)
# Load corresponding label file
label_filename = f"{os.path.splitext(filename)[0]}.txt"
label_filepath = os.path.join(yolo_labels_dir, label_filename)
if not os.path.exists(label_filepath):
continue
with open(label_filepath, 'r') as lbl_f:
lines = lbl_f.readlines()
for line in lines:
parts = list(map(float, line.strip().split()))
cls_id, xc_norm, yc_norm, w_norm, h_norm = map(int, parts[:1]) + parts[1:]
# Convert normalized coordinates back to absolute values
x_center = xc_norm * w
y_center = yc_norm * h
box_w = w_norm * w
box_h = h_norm * h
x_min = int(x_center - box_w / 2)
y_min = int(y_center - box_h / 2)
# Create annotation entry
annotation_entry = {
"id": annotation_id_counter,
"image_id": img_idx,
"category_id": cls_id,
"bbox": [x_min, y_min, box_w, box_h],
"area": box_w * box_h,
"iscrowd": 0
}
coco_data["annotations"].append(annotation_entry)
annotation_id_counter += 1
# Save result to a JSON file
with open(output_json_path, 'w') as out_f:
json.dump(coco_data, out_f)
if __name__ == "__main__":
yolo_labels_directory = "/path/to/yolo/labels/"
images_directory = "/path/to/images/"
output_json_file = "/path/to/output/coco_format.json"
classes_list = ["cat", "dog"] # Replace this with your actual class names.
convert_yolo_to_coco(
yolo_labels_dir=yolo_labels_directory,
images_dir=images_directory,
output_json_path=output_json_file,
class_names=classes_list
)
```
此代码实现了从 YOLO 格式向 COCO 格式的转换过程[^2]。它通过遍历所有的图片及其关联的标注文件来提取必要的信息,并按照 COCO 的标准格式重组数据。
---