一、数据集下载
Dataset之Cityscapes:Cityscapes数据集的简介、安装、使用方法之详细攻略_cityscapes dataset-CSDN博客
二、转为COCO格式
1、下载官方脚本地址:GitHub - mcordts/cityscapesScripts: README and scripts for the Cityscapes Dataset
2、cityscapesscripts/helpers/labels.py文件,找到需要的实例分割的类别。注意 hasInstances=Ture 的类别才能够用于实例分割,也就是说只有10类。
3、了解COCO格式
详解COCO数据格式的json文件内容_coco数据集json标注-CSDN博客
4、下面以其中的8类为例:
import cv2
import numpy as np
import os, glob
from shutil import copyfile
import datetime
import json
import os
import re
import fnmatch
from PIL import Image
import numpy as np
import pycococreatortools
ROOT_DIR = 'E:/Datesets/cityscapes/cityscapes_val'
IMAGE_DIR = os.path.join(ROOT_DIR, "images")
ANNOTATION_DIR = os.path.join(ROOT_DIR, "gt")
ANNOTATION_SAVE_DIR = os.path.join(ROOT_DIR, "annotations")
INSTANCE_DIR = os.path.join(ROOT_DIR, "instances")
IMAGE_SAVE_DIR = os.path.join(ROOT_DIR, "val_images")
INFO = {
"description": "Cityscapes_Instance Dataset",
"url": "https://github.com/waspinator/pycococreator",
"version": "0.1.0",
"year": "2020",
"contributor": "Kevin_Jia",
"date_created": "2020-1-23 19:19:19.123456"
}
LICENSES = [
{
"id": 1,
"name": "Attribution-NonCommercial-ShareAlike License",
"url": "http://creativecommons.org/licenses/by-nc-sa/2.0/"
}
]
CATEGORIES = [
{
'id': 1,
'name': 'person',
'supercategory': 'cityscapes',
},
{
'id': 2,
'name': 'rider',
'supercategory': 'cityscapes',
},
{
'id': 3,
'name': 'car',
'supercategory': 'cityscapes',
},
{
'id': 4,
'name': 'truck',
'supercategory': 'cityscapes',
},
{
'id': 5,
'name': 'bus',
'supercategory': 'cityscapes',
},
{
'id': 6,
'name': 'train',
'supercategory': 'cityscapes',
},
{
'id': 7,
'name': 'motorcycle',
'supercategory': 'cityscapes',
},
{
'id': 8,
'name': 'bicycle',
'supercategory': 'cityscapes',
}
]
background_label = list(range(-1, 24, 1)) + list(range(29, 31, 1))
idx=0
pic_scale = 1.0
h_bias = 1.0
def image_trans():
img_subfolders = os.listdir(IMAGE_DIR)
image_count = 0
for sub in img_subfolders:
# sub_path = sub + '/' + sub
image_sub_path = os.path.join(IMAGE_DIR, sub)
for image in os.listdir(image_sub_path):
img_path = os.path.join(image_sub_path, image)
ann_name = image.split('_')[0] + '_' + image.split('_')[1] + '_' + image.split('_')[2] + '_gtFine_instanceIds.png'
ann_sub_path = os.path.join(ANNOTATION_DIR, sub)
ann_path = os.path.join(ann_sub_path, ann_name)
if os.path.exists(ann_path):
pic = cv2.imread(img_path)
h, w = pic.shape[:2]
new_w = w * pic_scale
new_h = new_w / 2
top = int((h_bias*h-new_h)/2)
bottom = int((h_bias*h+new_h)/2)
left = int((w-new_w)/2)
right = int((w+new_w)/2)
roi = pic[top:bottom, left:right]
img_save_path = os.path.join(IMAGE_SAVE_DIR, image)
cv2.imwrite(img_save_path, roi)
annotation = cv2.imread(ann_path, -1)
ann_roi = annotation[top:bottom, left:right]
ann_save_path = os.path.join(ANNOTATION_SAVE_DIR, ann_name)
cv2.imwrite(ann_save_path, ann_roi)
else:
print(image + ' do not have instance annotation')
print(image_count)
image_count += 1
def data_loader():
imgs = os.listdir(IMAGE_SAVE_DIR)
masks_generator(imgs, ANNOTATION_SAVE_DIR)
def masks_generator(imges, ann_path):
global idx
pic_count = 0
for pic_name in imges:
image_name = pic_name.split('.')[0]
ann_folder = os.path.join(INSTANCE_DIR, image_name)
os.mkdir(ann_folder)
annotation_name = pic_name.split('_')[0] + '_' + pic_name.split('_')[1] + '_' + pic_name.split('_')[2] + '_gtFine_instanceIds.png'
# annotation_name = image_name + '_instanceIds.png'
print(annotation_name)
annotation = cv2.imread(os.path.join(ann_path, annotation_name), -1)
h, w = annotation.shape[:2]
ids = np.unique(annotation)
for id in ids:
if id in background_label:
continue
else:
class_id = id // 1000
if class_id == 24:
instance_class = 'person'
elif class_id == 25:
instance_class = 'rider'
elif class_id == 26:
instance_class = 'car'
elif class_id == 27:
instance_class = 'truck'
elif class_id == 28:
instance_class = 'bus'
elif class_id == 31:
instance_class = 'train'
elif class_id == 32:
instance_class = 'motorcycle'
elif class_id == 33:
instance_class = 'bicycle'
else:
continue
instance_mask = np.zeros((h, w, 3),dtype=np.uint8)
mask = annotation == id
instance_mask[mask] = 255
mask_name = image_name + '_' + instance_class + '_' + str(idx) + '.png'
cv2.imwrite(os.path.join(ann_folder, mask_name), instance_mask)
idx += 1
pic_count += 1
print(pic_count)
def json_generate():
person = 0
rider =0
car = 0
truck = 0
bus = 0
train = 0
motorcycle = 0
bicycle = 0
files = os.listdir(IMAGE_SAVE_DIR)
coco_output = {
"info": INFO,
"licenses": LICENSES,
"categories": CATEGORIES,
"images": [],
"annotations": []
}
image_id = 1
segmentation_id = 1
# go through each image
for image_filename in files:
image_name = image_filename.split('.')[0]
image_path = os.path.join(IMAGE_SAVE_DIR, image_filename)
annotation_sub_path = os.path.join(INSTANCE_DIR, image_name)
ann_files = os.listdir(annotation_sub_path)
if len(ann_files) == 0:
print("ao avaliable annotation")
continue
else:
image = Image.open(image_path)
image_info = pycococreatortools.create_image_info(
image_id, os.path.basename(image_filename), image.size)
coco_output["images"].append(image_info)
print(image_filename)
for annotation_filename in ann_files:
annotation_path = os.path.join(annotation_sub_path, annotation_filename)
for x in CATEGORIES:
if x['name'] in annotation_filename:
class_id = x['id']
break
# class_id = [x['id'] for x in CATEGORIES if x['name'] in annotation_filename][0]
if class_id == 1:
person += 1
elif class_id == 2:
rider += 1
elif class_id == 3:
car += 1
elif class_id == 4:
truck += 1
elif class_id == 5:
bus += 1
elif class_id == 6:
train += 1
elif class_id == 7:
motorcycle += 1
elif class_id == 8:
bicycle += 1
else:
print('illegal class id')
category_info = {'id': class_id, 'is_crowd': 'crowd' in image_filename}
binary_mask = np.asarray(Image.open(annotation_path)
.convert('1')).astype(np.uint8)
annotation_info = pycococreatortools.create_annotation_info(
segmentation_id, image_id, category_info, binary_mask,
image.size, tolerance=2)
if annotation_info is not None:
coco_output["annotations"].append(annotation_info)
segmentation_id = segmentation_id + 1
image_id = image_id + 1
print(image_id)
with open('{}/val_modified.json'.format(ROOT_DIR), 'w') as output_json_file:
json.dump(coco_output, output_json_file)
print(person, rider, car, truck, bus,train,motorcycle,bicycle)
if __name__ == "__main__":
#依次使用以下三个函数
image_trans()
#data_loader()
#json_generate()
在运行代码的时候可能会遇到一个错误(对于mask存在多部分时候报错):
File ".......pycococreator-master\pycococreatortools\pycococreatortools.py", line 99, in create_annotation_info
segmentation = binary_mask_to_polygon(binary_mask, tolerance)
File "........pycococreator-master\pycococreatortools\pycococreatortools.py", line 48, in binary_mask_to_polygon
contours = np.subtract(contours, 1)
ValueError: setting an array element with a sequence. The requested array has an inhomogeneous shape after 1 dimensions. The detected shape was (2,) + inhomogeneous part.
解决方法:
#contours = np.subtract(contours, 1)注释该行,使用下面代替
contours = [np.subtract(c, 1) for c in contours]
详情查看:将CityScapes数据集转换为COCO格式的实例分割数据集_cityscapes数据标签转coco-CSDN博客
三、转为YOLO 格式
分别将生成的训练集和测试集的json使用yolo v8自带的转换工具(注:尽量不要使用别人写的代码,后面介绍)
from ultralytics.data.converter import convert_coco
convert_coco(labels_dir='path/to/json/', use_segments=True)
别人的代码:
import os
import json
import shutil
def write_yolo_txt_file(txt_file_path,label_seg_x_y_list):
if not os.path.exists(txt_file_path):
with open(txt_file_path, "w") as file:
for element in label_seg_x_y_list:
file.write(str(element) + " ")
file.write('\n')
else:
with open(txt_file_path, "a") as file:
for element in label_seg_x_y_list:
file.write(str(element) + " ")
file.write('\n')
def read_json(in_json_path,img_dir,target_dir):
with open(in_json_path, "r", encoding='utf-8') as f:
# json.load数据到变量json_data
json_data = json.load(f)
# print(len(json_data['annotations']))
# print(len(json_data['images']))
# print(len(json_data['categories']))
for annotation in json_data['annotations']: # 遍历标注数据信息
# print(annotation)
category_id = annotation['category_id']
image_id = annotation['image_id']
for image in json_data['images']: # 遍历图片相关信息
if image['id'] == image_id:
width = image['width'] # 图片宽
height = image['height'] # 图片高
img_file_name = image['file_name'] # 图片名称
txt_file_name = image['file_name'].split('.')[0] + '.txt' # 要保存的对应txt文件名
break
# print(width,height,img_file_name,txt_file_name)
segmentation = annotation['segmentation'] # 图像分割点信息[[x1,y1,x2,y2,...,xn,yn]]
seg_x_y_list = [i/width if num%2==0 else i/height for num,i in enumerate(segmentation[0])] # 归一化图像分割点信息
label_seg_x_y_list = seg_x_y_list[:]
label_seg_x_y_list.insert(0,category_id-1) # 图像类别与分割点信息[label,x1,y1,x2,y2,...,xn,yn] ###coco从1开始的
# print(label_seg_x_y_list)
# 写txt文件
txt_file_path = target_dir + 'labels/' + txt_file_name
# print(txt_file_path)
write_yolo_txt_file(txt_file_path,label_seg_x_y_list)
# 选出txt对应img文件
img_file_path = img_dir + img_file_name
# print(img_file_path)
shutil.copy(img_file_path,target_dir + 'images/')
if __name__=="__main__":
img_dir = '......../cityscapes/cityscapes_train/val_images/'
target_dir = '...../cityscapes/cityscapes_train/train/'
if not os.path.exists(target_dir):
os.mkdir(target_dir)
in_json_path = "......./cityscapes/cityscapes_train/val_modified.json"
read_json(in_json_path,img_dir,target_dir)
四、效果
为什么别人写的代码存在问题呢?(主要还是因为存在一个实例分为多个部分)
yolo自带的转换后的标签:
别人代码转换后的标签: