yolo格式转换成coco格式

# 说明:
'''
1)military_object.names文件内容如下:
label1
label2
label3
2)此训练针对矩形框的标注
3)代码中很多键值都是自己造的,因为训练用不到这些(比如mask的训练),仅仅只是为了跟coco格式保持一致
'''

import os
import json
import cv2
import random
import time

# coco格式最后储存位置
coco_format_save_path = '../datasets/military/annotations/instances_val_military.json'
# 类别文件,一行一个类
yolo_format_classes_path = '../datasets/military/annotations/military_object.names'
# yolo格式的注释文件
yolo_format_annotation_path = '../datasets/military/annotations/military_val_yolo.txt'
# 根据自己的数据集写类别。举个例子:
# categories_dict = [{'supercategory': 'None', 'id': 1, 'name': 'w3'},{'supercategory': 'None', 'id': 2, 'name': 'h3'}]

# 我有类别文件,本着能用代码绝不手写的原则
with open(yolo_format_classes_path,'r') as f1:
    lines1 = f1.readlines()
categories = []
for j,label in enumerate(lines1):
    label = label.strip()
    categories.append({'id':j+1,'name':label,'supercategory': 'None'})
"""========================================后文就正式开始了========================================="""
write_json_context = dict()
write_json_context['info'] = {'description': '', 'url': '', 'version': '', 'year': 2020, 'contributor': '', 'date_created': '2020-06-16 11:00:08.5'}
write_json_context['licenses'] = [{'id': 1, 'name': None, 'url': None}]
write_json_context['categories'] = categories
write_json_context['images'] = []
write_json_context['annotations'] = []
# 前面都造好了基础(为了和coco一致,其实很多都用不到的),现在开始解析自己的数据
with open(yolo_format_annotation_path,'r') as f2:
    lines2 = f2.readlines()

# 第n个标注框计数,也就是annotations中的id
num_bboxes = 0
# 每一行就是一张图片的标注信息。
# 其他格式也很好做,这个遍历就是图片文件路径,后面bboxes的遍历就是解析当前图片的标注信息
# 如果xml或者json的,我的csdn中也有labelme标注的xml和json的解析代码(很久很久以前的代码,其实有更简洁的解析,但是我懒得写,哈哈)
# 看懂我的代码,改起来不要太简单
for i,line in enumerate(lines2):

    img_context = {}
    # 我的数据以空格分隔的,具体查看上面的截图
    line = line.split(' ')
    # 我在想:如果这张图没有任何标注,要不要保留呢,我选择保留负样本,当然你也可以打开下面这段代码舍弃
    # if len(line) < 2:
    #     continue
    # 文件名最好不要有空格,这是一种习惯
    img_path = line[0].rstrip()
    img_name = os.path.basename(img_path)
    # 因为需要width和height,而我得yolo文件里没有,所以我还得读图片,很烦
    # 我就用opencv读取了,当然用其他库也可以
    # 别把图片路径搞错了,绝对路径和相对路径分清楚!
    height,width = cv2.imread(img_path).shape[:2]
    img_context['file_name'] = img_name
    img_context['height'] = height
    img_context['width'] = width
    img_context['date_captured'] = '2020-06-16 11:00:08.5'
    # 这么多id搞得我头都懵了,我猜这是第几张图序号吧,每行一张图,那当然就是第i张了
    img_context['id'] = i
    img_context['license'] = 1
    img_context['coco_url'] =''
    img_context['flickr_url'] = ''
    write_json_context['images'].append(img_context)
    # 这个地方如果有标注框继续,没有的话跳过,跟上面的区别在于是否将图片加入到images中
    # 如果images中有这张图但是没有标注信息,那就是负样本,反之亦然
    if len(line) < 2:
        continue
    for bbox in line[1:]:
        bbox_dict = {}
        xmin,ymin,xmax,ymax,class_id = bbox.strip().split(',')
        # 我就有时候int和str不注意各种报错
        xmin,ymin,xmax,ymax,class_id= float(xmin),float(ymin),float(xmax),float(ymax),int(class_id)
        bbox_dict['id'] = num_bboxes
        bbox_dict['image_id'] = i
        bbox_dict['category_id'] = class_id + 1
        bbox_dict['iscrowd'] = 0  # 前面有解释
        h,w = abs(ymax-ymin),abs(xmax-xmin)
        bbox_dict['area']  = h * w
        bbox_dict['bbox'] = [xmin,ymin,w,h]
        bbox_dict['segmentation'] = [[xmin,ymin,xmax,ymin,xmax,ymax,xmin,ymax]]
        write_json_context['annotations'].append(bbox_dict)
        num_bboxes+=1
    i+=1

# 终于搞定了,保存!
with open(coco_format_save_path,'w') as fw:
    json.dump(write_json_context,fw)

 

你可能感兴趣的:(YOLO,COCO)