coco关键点标注json_coco2017格式数据集制作

本文介绍了如何将CSV格式的标注数据转换成COCO2017标准的JSON格式,用于目标检测和关键点标注。文章详细展示了如何读取CSV,解析标注信息,以及构建COCO格式的images、annotations和categories,最终生成JSON文件。代码示例中包括了处理多目标和多框的情况。
Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

这篇文章提供了一个比较好的思路。总体做法还是离不开这个文章的做法。

上面文章作者提供的思路比较正统开始说明之前我们先说明一下coco2017的格式类型,这些网络上也说了很多了,这里再提及一下加深理解。

coco/

annotations/

instances_train2017.json

instances_val2017.json

images/

train2017/

0d4c5e4f-fc3c-4d5a-906c-105.jpg

val2017

0ddfc5aea-fcdac-421-92dad-144.jpg

以上格式摘自上面提到的文章,并且最后我们也是按这种方式生成的。

这里我们用到的格式也可以这么做,当然也可以适配自己的文件,比如要是每个视频下拆除的单张图,那么可以再多加一级目录出来。

具体的做法按照启发写到我的github项目里了,这里简要说明一下,当然github上后续也会更新。

csv格式制作

这里用csv也可以,用txt也可以,数据的格式并不是一个问题,而如何转换到我们想要的格式则有多种解决方式。

这里只展示csv的用法。

import os

import json

import cv2

import time

import argparse

import csv

parser = argparse.ArgumentParser(description='convert object label')

parser.add_argument('data', metavar='DIR',

help='path to dataset')

parser.add_argument('keyframe_dir', metavar='DIR',

help='path to frame dir')

parser.add_argument('--mode', type=str, choices=['train', 'val', 'test'])

args = parser.parse_args()

root = os.path.join(args.data, args.mode)

video_list = open(os.path.join(root, 'videolist.txt'),'r')

output_list = open('%s_list.txt' % args.mode,'w')

obj_name = open('objects_en.txt','r')

obj_list = [line.rstrip() for line in obj_name]

print(obj_list)

train_category = []

video_count = 0

start = time.time()

key_frame_count = 0

#output_folder = '%s_label' % args.mode

#if not os.path.exists(output_folder):

# os.makedirs(output_folder)

with open('val.csv','w') as f1:

for vid in video_list:

label = json.load(open(os.path.join(root, 'label', 'sample_' + vid.rstrip().split('.')[0] + '.json'), 'r'))

writer = csv.writer(f1)

for shot in label['shots']:

keyframe = shot['keyframe']

image_path = os.path.join(args.keyframe_dir, args.mode, vid[:-1], '%05d.jpg'% keyframe)

for target in shot['targets'] :

if target['category'] == 0:

if os.path.isfile(image_path):

xmin = target['bbox']['x']

xmax = xmin + target['bbox']['width']

ymin = target['bbox']['y']

ymax = ymin + target['bbox']['height']

cls_id = obj_list[int(target['tag'])]

writer.writerow([image_path,xmin,xmax,ymin,ymax,cls_id])#用write方法写入我们的csv文件里即可。

这里因为是适配了videonet比赛的数据格式,videonet数据集是一个视频数据集,目标检测也是其中一个任务,这里目标检测对应信息由官方给出的json来标注xyhw四个信息。我们csv的格式这里也是按

path xmin ymin xmax ymax id

上述格式生成csv文件,参考给出的代码也很好理解。通过csv文件将对应cocotrian或者validation格式的数据生成,经测试在maskrcnn-benchmark上是可以使用的。

以下给出train的coco形式的代码生成

# -*- coding: utf-8 -*-

'''

@time: 2019/01/11 11:28

spytensor

'''

import os

import json

import numpy as np

import pandas as pd

import glob

import cv2

import os

import shutil

from IPython import embed

from tqdm import tqdm

#from sklearn.model_selection import train_test_split

np.random.seed(41)

#0为背景

obj_name = open('objects_en.txt','r')

obj_list = [line.rstrip() for line in obj_name]

classname_to_id = {}

for i in range(len(obj_list)):

classname_to_id.setdefault(obj_list[i],i)

print(classname_to_id)

class Csv2CoCo:

def __init__(self,image_dir,total_annos):

self.images = []

self.annotations = []

self.categories = []

self.img_id = 0

self.ann_id = 0

self.image_dir = image_dir

self.total_annos = total_annos

def save_coco_json(self, instance, save_path):

json.dump(instance, open(save_path, 'w'), ensure_ascii=False, indent=2) # indent=2 更加美观显示

# 由txt文件构建COCO

def to_coco(self, keys):

self._init_categories()

for key in keys:

self.images.append(self._image(key))

shapes = self.total_annos[key]

for shape in shapes:

bboxi = []

for cor in shape[:-1]:

bboxi.append(int(cor))

label = shape[-1]

#print('label',label)

annotation = self._annotation(bboxi,label)

print('annotation',annotation)

self.annotations.append(annotation)

self.ann_id += 1

self.img_id += 1

instance = {}

instance['info'] = 'spytensor created'

instance['license'] = ['license']

instance['images'] = self.images

instance['annotations'] = self.annotations

instance['categories'] = self.categories

return instance

# 构建类别

def _init_categories(self):

for k, v in classname_to_id.items():

category = {}

category['id'] = v

category['name'] = k

self.categories.append(category)

# 构建COCO的image字段

def _image(self, path):

image = {}

print(path)

img = cv2.imread(self.image_dir + path)

image['height'] = img.shape[0]

image['width'] = img.shape[1]

image['id'] = self.img_id

image['file_name'] = path

return image

# 构建COCO的annotation字段

def _annotation(self, shape,label):

# label = shape[-1]

points = shape[:4]

annotation = {}

annotation['id'] = self.ann_id

annotation['image_id'] = self.img_id

annotation['category_id'] = int(classname_to_id[label])

#annotation['segmentation'] = self._get_seg(points)

annotation['bbox'] = self._get_box(points)

annotation['iscrowd'] = 0

annotation['area'] = 1.0

return annotation

# COCO的格式: [x1,y1,w,h] 对应COCO的bbox格式

def _get_box(self, points):

min_x = points[0]

min_y = points[1]

max_x = points[2]

max_y = points[3]

return [min_x, min_y, max_x - min_x, max_y - min_y]

# segmentation

def _get_seg(self, points):

min_x = points[0]

min_y = points[1]

max_x = points[2]

max_y = points[3]

h = max_y - min_y

w = max_x - min_x

a = []

a.append([min_x,min_y, min_x,min_y+0.5*h, min_x,max_y, min_x+0.5*w,max_y, max_x,max_y, max_x,max_y-0.5*h, max_x,min_y, max_x-0.5*w,min_y])

return a

if __name__ == '__main__':

csv_file = "train.csv"

image_dir = "/home/sda/videonet/train/image/train/"

saved_coco_path = "./"

# 整合csv格式标注文件

total_csv_annotations = {}

annotations = pd.read_csv(csv_file,header=None).values

for annotation in annotations:

#print(annotation[0].split(os.sep)[-2]+'/'+annotation[0].split(os.sep)[-1])

key = annotation[0].split(os.sep)[-2]+'/'+annotation[0].split(os.sep)[-1]

value = np.array([annotation[1:]])

if key in total_csv_annotations.keys():

total_csv_annotations[key] = np.concatenate((total_csv_annotations[key],value),axis=0)

else:

total_csv_annotations[key] = value

for k,v in total_csv_annotations.items():

print(k,v)

# 按照键值划分数据

total_keys = list(total_csv_annotations.keys())

train_keys = total_keys

#val_keys = total_keys

#train_keys, val_keys = train_test_split(total_keys, test_size=0.2)

print("train_n:", len(train_keys))#, 'val_n:', len(val_keys))

# 创建必须的文件夹

if not os.path.exists('%scoco/annotations/'%saved_coco_path):

os.makedirs('%scoco/annotations/'%saved_coco_path)

if not os.path.exists('%scoco/images/train2017/'%saved_coco_path):

os.makedirs('%scoco/images/train2017/'%saved_coco_path)

if not os.path.exists('%scoco/images/val2017/'%saved_coco_path):

os.makedirs('%scoco/images/val2017/'%saved_coco_path)

# 把训练集转化为COCO的json格式

for file in train_keys:

if not os.path.exists('{}coco/images/train2017/{}'.format(saved_coco_path,file.split('/')[0])):

print(file.split('/')[0])

os.makedirs('{}coco/images/train2017/{}'.format(saved_coco_path,file.split('/')[0]))

if not os.path.exists("{}coco/images/train2017/{}".format(saved_coco_path,file)):

shutil.copy(image_dir+file,"{}coco/images/train2017/{}".format(saved_coco_path,file))

elif os.path.exists('{}coco/images/train2017/{}'.format(saved_coco_path,file.split('/')[0])):

if not os.path.exists("{}coco/images/train2017/{}".format(saved_coco_path,file)):

shutil.copy(image_dir+file,"{}coco/images/train2017/{}".format(saved_coco_path,file))

l2c_train = Csv2CoCo(image_dir=image_dir,total_annos=total_csv_annotations)

train_instance = l2c_train.to_coco(train_keys)

l2c_train.save_coco_json(train_instance, '%scoco/annotations/instances_train2017.json'%saved_coco_path)

#for file in val_keys:

# shutil.copy(image_dir+file,"%scoco/images/val2017/"%saved_coco_path)

# 把验证集转化为COCO的json格式

#l2c_val = Csv2CoCo(image_dir=image_dir,total_annos=total_csv_annotations)

#val_instance = l2c_val.to_coco(val_keys)

#l2c_val.save_coco_json(val_instance, '%scoco/annotations/instances_val2017.json'%saved_coco_path)

和开头作者提到的方法不一样,我这里适配了自己的路径写到绝对路径,一定程度上保证了路径问题不会产生,新添加的多个if语句主要是有以下功能保证:

因为一张图片会包含多个目标物体,因此会可能有多个xyhw,当我们按上面生成csv代码时,因为一张图包含的多个xyhw,都会让所在的这张图重复写一遍,所以说我们用if先判断一遍看看是否是重复的,重复的我们跳过。

因为我们这里标注的是关键帧,所以说上一级目录是一个视频名,如果要把这个写到filename里,相当于我们还要再遍历一遍文件夹是否重复,所以再用到一次if判断。

对于train和validaiton是可以用一种方式生成的,而test会有一些变化,主要是test没有标注,我们只需要遍历后把filename写进去即可。

您可能感兴趣的与本文相关的镜像

Python3.8

Python3.8

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值