将labelme格式数据转化为标准的coco数据集格式方式
labelme标注图像生成的json格式:
{
"version":"3.11.2",
"flags":{},
"shapes":[#每个对象的形状
{#第一个对象
"label":"malignant",
"line_color":null,
"fill_color":null,
"points":[#边缘是由点构成,将这些点连在一起就是对象的边缘多边形
[
371,#第一个点x坐标
257#第一个点y坐标
],
...
[
412,
255
]
],
"shape_type":"polygon"#形状类型:多边形
},
{
"label":"malignant",#第一个对象的标签
"line_color":null,
"fill_color":null,
"points":[#第二个对象
[
522,
274
],
...
[
561,
303
]
],
"shape_type":"polygon"
},
{
"label":"malignant",#第二个对象的标签
"line_color":null,
"fill_color":null,
"imagePath":"../../val2017/000001.jpg",#原始图片的路径
"imageData":"somethingtoolong",#原图像数据通过该字段可以解析出原图像数据
"imageHeight":768,
"imageWidth":1024
}
coco标准数据集格式:
COCO通过大量使用AmazonMechanicalTurk来收集数据。COCO数据集现在有3种标注类型:objectinstances(目标实例),objectkeypoints(目标上的关键点),andimagecaptions(看图说话),使用JSON文件存储。
基本的JSON结构体类型
这3种类型共享下面所列的基本类型,包括image、categories、annotation类型。
Images类型:
"images":[
{
"height":768,
"width":1024,
"id":1,#图片id
"file_name":"000002.jpg"
}
]
categories类型:
"categories":[
{
"supercategory":"Cancer",#父类
"id":1,#标签类别id,0表示背景
"name":"benign"#子类
},
{
"supercategory":"Cancer",
"id":2,
"name":"malignant"
}
],
annotations类型:
"annotations":[
{
"segmentation":[#坐标点的坐标值
[
418,
256,
391,
293,
406,
323,
432,
340,
452,
329,
458,
311,
458,
286,
455,
277,
439,
264,
418,
293,
391,
256
]
],
"iscrowd":0,#单个的对象(iscrowd=0)可能需要多个polygon来表示
"image_id":1,#和image的id保持一致
"bbox":[#标注的边框值bbox是将segmentation包起来的水平矩形
391.0,
256.0,
67.0,
84.0
],
"area":5628.0,#标注的边框面积
"category_id":1,#所属类别id
"id":1#标注边框的id:1,2,3...,n
}
]
labelme转化为coco
#-*-coding:utf-8-*-
#!/usr/bin/envpython
importargparse
importjson
importmatplotlib.pyplotasplt
importskimage.ioasio
importcv2
fromlabelmeimportutils
importnumpyasnp
importglob
importPIL.Image
classMyEncoder(json.JSONEncoder):
defdefault(self,obj):
ifisinstance(obj,np.integer):
returnint(obj)
elifisinstance(obj,np.floating):
returnfloat(obj)
elifisinstance(obj,np.ndarray):
returnobj.tolist()
else:
returnsuper(MyEncoder,self).default(obj)
classlabelme2coco(object):
def__init__(self,labelme_json=[],save_json_path='./tran.json'):
'''
:paramlabelme_json:所有labelme的json文件路径组成的列表
:paramsave_json_path:json保存位置
'''
self.labelme_json=labelme_json
self.save_json_path=save_json_path
self.images=[]
self.categories=[]
self.annotations=[]
#self.data_coco={}
self.label=[]
self.annID=1
self.height=0
self.width=0
self.save_json()
defdata_transfer(self):
fornum,json_fileinenumerate(self.labelme_json):
withopen(json_file,'r')asfp:
data=json.load(fp)#加载json文件
self.images.append(self.image(data,num))
forshapesindata['shapes']:
label=shapes['label']
iflabelnotinself.label:
self.categories.append(self.categorie(label))
self.label.append(label)
points=shapes['points']#这里的point是用rectangle标注得到的,只有两个点,需要转成四个点
#points.append([points[0][0],points[1][1]])
#points.append([points[1][0],points[0][1]])
self.annotations.append(self.annotation(points,label,num))
self.annID+=1
defimage(self,data,num):
image={}
img=utils.img_b64_to_arr(data['imageData'])#解析原图片数据
#img=io.imread(data['imagePath'])#通过图片路径打开图片
#img=cv2.imread(data['imagePath'],0)
height,width=img.shape[:2]
img=None
image['height']=height
image['width']=width
image['id']=num+1
#image['file_name']=data['imagePath'].split('/')[-1]
image['file_name']=data['imagePath'][3:14]
self.height=height
self.width=width
returnimage
defcategorie(self,label):
categorie={}
categorie['supercategory']='Cancer'
categorie['id']=len(self.label)+1#0默认为背景
categorie['name']=label
returncategorie
defannotation(self,points,label,num):
annotation={}
annotation['segmentation']=[list(np.asarray(points).flatten())]
annotation['iscrowd']=0
annotation['image_id']=num+1
#annotation['bbox']=str(self.getbbox(points))#使用list保存json文件时报错(不知道为什么)
#list(map(int,a[1:-1].split(',')))a=annotation['bbox']使用该方式转成list
annotation['bbox']=list(map(float,self.getbbox(points)))
annotation['area']=annotation['bbox'][2]*annotation['bbox'][3]
#annotation['category_id']=self.getcatid(label)
annotation['category_id']=self.getcatid(label)#注意,源代码默认为1
annotation['id']=self.annID
returnannotation
defgetcatid(self,label):
forcategorieinself.categories:
iflabel==categorie['name']:
returncategorie['id']
return1
defgetbbox(self,points):
#img=np.zeros([self.height,self.width],np.uint8)
#cv2.polylines(img,[np.asarray(points)],True,1,lineType=cv2.LINE_AA)#画边界线
#cv2.fillPoly(img,[np.asarray(points)],1)#画多边形内部像素值为1
polygons=points
mask=self.polygons_to_mask([self.height,self.width],polygons)
returnself.mask2box(mask)
defmask2box(self,mask):
'''从mask反算出其边框
mask:[h,w]0、1组成的图片
1对应对象,只需计算1对应的行列号(左上角行列号,右下角行列号,就可以算出其边框)
'''
#np.where(mask==1)
index=np.argwhere(mask==1)
rows=index[:,0]
clos=index[:,1]
#解析左上角行列号
left_top_r=np.min(rows)#y
left_top_c=np.min(clos)#x
#解析右下角行列号
right_bottom_r=np.max(rows)
right_bottom_c=np.max(clos)
#return[(left_top_r,left_top_c),(right_bottom_r,right_bottom_c)]
#return[(left_top_c,left_top_r),(right_bottom_c,right_bottom_r)]
#return[left_top_c,left_top_r,right_bottom_c,right_bottom_r]#[x1,y1,x2,y2]
return[left_top_c,left_top_r,right_bottom_c-left_top_c,
right_bottom_r-left_top_r]#[x1,y1,w,h]对应COCO的bbox格式
defpolygons_to_mask(self,img_shape,polygons):
mask=np.zeros(img_shape,dtype=np.uint8)
mask=PIL.Image.fromarray(mask)
xy=list(map(tuple,polygons))
PIL.ImageDraw.Draw(mask).polygon(xy=xy,outline=1,fill=1)
mask=np.array(mask,dtype=bool)
returnmask
defdata2coco(self):
data_coco={}
data_coco['images']=self.images
data_coco['categories']=self.categories
data_coco['annotations']=self.annotations
returndata_coco
defsave_json(self):
self.data_transfer()
self.data_coco=self.data2coco()
#保存json文件
json.dump(self.data_coco,open(self.save_json_path,'w'),indent=4,cls=MyEncoder)#indent=4更加美观显示
labelme_json=glob.glob('./Annotations/*.json')
#labelme_json=['./Annotations/*.json']
labelme2coco(labelme_json,'./json/test.json')
以上这篇将labelme格式数据转化为标准的coco数据集格式方式就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。