# -*- coding:utf-8 -*-
# !/usr/bin/env python

import argparse
import json
import matplotlib.pyplot as plt
import skimage.io as io
import cv2
from labelme import utils
import numpy as np
import glob
import PIL.Image
from shapely.geometry import Polygon

class labelme2coco(object):
  def __init__(self,labelme_json=[],save_json_path='./new.json'):
    '''
    :param labelme_json: 所有labelme的json文件路径组成的列表
    :param save_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()

  def data_transfer(self):
    for num,json_file in enumerate(self.labelme_json):
      with open(json_file,'r') as fp:
        data = json.load(fp) # 加载json文件
        self.images.append(self.image(data,num))
        for shapes in data['shapes']:
          #label=shapes['label'].split('_')
          label=shapes['label'][:-1]
          print(shapes['label'])
          print(label)
          if label not in self.label:
            self.categories.append(self.categorie(label))
            self.label.append(label)
          points=shapes['points']
          self.annotations.append(self.annotation(points,label,num))
          self.annID+=1
    print(self.label)

  def image(self,data,num):
    image={}
    img = utils.img_b64_to_array(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]

    self.height=height
    self.width=width

    return image

  def categorie(self,label):
    categorie={}
    categorie['supercategory'] = label
    categorie['id']=len(self.label)+1 # 0 默认为背景
    categorie['name'] = label
    return categorie

  def annotation(self,points,label,num):
    annotation={}
    annotation['segmentation']=[list(np.asarray(points).flatten())]
    poly = Polygon(points)
    area_ = round(poly.area,6)
    annotation['area'] = area_
    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['category_id'] = self.getcatid(label)
    annotation['id'] = self.annID
    return annotation

  def getcatid(self,label):
    for categorie in self.categories:
      if label==categorie['name']:
        return categorie['id']
    return -1

  def getbbox(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)
    return self.mask2box(mask)

  def mask2box(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格式

  def polygons_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)
    return mask

  def data2coco(self):
    data_coco={}
    data_coco['images']=self.images
    data_coco['categories']=self.categories
    data_coco['annotations']=self.annotations
    return data_coco

  def save_json(self):
    self.data_transfer()
    self.data_coco = self.data2coco()
    # 保存json文件
    json.dump(self.data_coco, open(self.save_json_path, 'w'), indent=4) # indent=4 更加美观显示

labelme_json=glob.glob('./*.json')
# labelme_json=['./1.json']

labelme2coco(labelme_json,'./new.json')

labelme2COCO的更多相关文章

  1. labelme2coco问题:TypeError: Object of type 'int64' is not JSON serializable

    最近在做MaskRCNN 在自己的数据(labelme)转为COCOjson格式遇到问题:TypeError: Object of type 'int64' is not JSON serializa ...

  2. coco标注信息与labelme标注信息的详解、相互转换及可视化

    引言 在做实例分割或语义分割的时候,我们通常要用labelme进行标注,labelme标注的json文件与coco数据集已经标注好的json文件的格式和内容有差异.如果要用coco数据集的信息,就要对 ...

  3. [炼丹术]yolact训练模型学习总结

    yolact训练模型学习总结 一.YOLACT介绍(You Only Look At CoefficienTs) 1.1 简要介绍 yolact是一种用于实时实例分割的简单.全卷积模型. (A sim ...

随机推荐

  1. 1、spark集群搭建

    前提:已经搭建完全分布式的Hadoop集群,请参看http://www.cnblogs.com/netbloomy/p/6660131.html 1.Scala2.12.1环境搭建 1).下载scal ...

  2. (转)Inno Setup入门(十)——操作注册表

    本文转载自:http://blog.csdn.net/yushanddddfenghailin/article/details/17250871 有些程序需要随系统启动,或者需要建立某些文件关联等问题 ...

  3. 【转】使用 JMeter 完成常用的压力测试

    本文介绍了 JMeter 相关的基本概念.并以 JMeter 为例,介绍了使用它来完成最常用的三种类型服务器,即 Web 服务器.数据库服务器和消息中间件,压力测试的方法.步骤以及注意事项.      ...

  4. Codeforces 982C(dfs+思维)

    C. Cut 'em all! time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  5. ngui自适应

    增加UIROOT using UnityEngine; namespace Com.Xyz.UI { [ExecuteInEditMode] [RequireComponent(typeof(UIRo ...

  6. 网络 、osi 七层模型、tcp/ip 五层参考

    网络 网络的本质就是通讯,比特传输 网络拓扑 物理布局pc -- 交换机 -- 路由器逻辑布局pc -- 路由器 交换机的产生 网络之初,是通过网线互相连通到各个主机,存在的问题就是2个pc都要与服务 ...

  7. Linux Platform devices 平台设备驱动

    设备总线驱动模型:http://blog.csdn.net/lizuobin2/article/details/51570196 本文主要参考:http://www.wowotech.net/devi ...

  8. html5的canvas方法的总结

    canvas的方法 save()保存当前环境的状态 restore() 返回之前保存过的路径状态和属性 createEvent() getContext()返回一个对象,指出访问绘图功能必要的API ...

  9. Oracle 10 Recycle Bin回收站

    这个功能从10g开始有了. (1)什么是Recycle Bin实际上,Recycle Bin只是一个保存被drop的对象的一个数据字典表.所以,可以通过如下语句查询回收站中的信息:select * f ...

  10. Python,OpenGL生命游戏

    初学Python和OpenGL,练手的第一个小程序life.py,这个小程序在日后会不断调整,增加类.优化判断及操作 执行效果: 按正规生命游戏的规则: 1.周围生命等于3时产生生命 2.周围生命等于 ...