如果两个 COCO 格式的数据集具有 相同的类别名称和类别 ID,那么可以合并它们,但需要确保:

  1. 图像 ID 不能重复

    COCO 格式中,每个图像都有唯一的 "id",合并时要确保 ID 不冲突,否则会导致错误。
  2. 标注(annotations)的 ID 不能重复

    COCO 数据集的 "annotations" 里的 每个标注 也有唯一的 "id",合并时要重新编号。
  3. 类别(categories)一致

    既然类别名称和 ID 一样,就不用修改 "categories" 部分,只要保留其中一个数据集的类别信息即可。
import json
import os

path = 'D:/bop/ycbv/train_real/coco_annotations/'
entries = os.listdir(path)
entries.sort()

# 读取第一个 JSON 作为主文件
with open(path + entries[0], 'r') as f:
    main = json.load(f)

# 遍历并合并其他 JSON 文件
for entry in entries[1:]:
    with open(path + entry, 'r') as f:
        file = json.load(f)

    main['images'].extend(file['images'])
    main['annotations'].extend(file['annotations'])

# 重新编号 image_id 和 annotation_id
for i in range(len(main['images'])):
    main['images'][i]['id'] = i + 1
for i in range(len(main['annotations'])):
    main['annotations'][i]['id'] = i + 1

# 记录 image_id 变化的位置
sameID = []
for i in range(len(main['annotations'])):
    if i == 0 or main['annotations'][i]['image_id'] != main['annotations'][i - 1]['image_id']:
        sameID.append(main['annotations'][i]['id'])

# 生成新的 image_id 映射
newList = []
c = 1
for i in range(len(sameID) - 1):
    newList.extend([c] * (sameID[i + 1] - sameID[i]))  # 赋予同样的 image_id
    c += 1

# **动态填充 newList,避免索引越界**
if len(newList) < len(main['annotations']):
    newList.extend([newList[-1]] * (len(main['annotations']) - len(newList)))

# 替换 annotations 里的 image_id
for i in range(len(main['annotations'])):
    main['annotations'][i]['image_id'] = newList[i]

# 保存合并后的 JSON 文件
output_path = os.path.join(path, 'merged_data.json')
with open(output_path, 'w') as outfile:
    json.dump(main, outfile, indent=4)

print(f"合并完成,输出文件: {output_path}")

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐