# -*- 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. JavaScript中的函数(一)

    javaScript中的函数实际上是对象,每一个函数都是Function类型的实例,和其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也就是一个指向函数对象的指针,也就是函数对象的一个 ...

  2. 1.JMeter===添加响应断言

    断言即Lr中的检查点,我们在进行测试时,需要对每次请求测试的返回做检验 1.以百度做案例,添加线程组==添加HTTP请求==添加查看结果树 2.在HTTP请求下添加响应断言 注:模式匹配规则,比较常用 ...

  3. caffe读取多标签的lmdb数据

    问题描述: lmdb文件支持数据+标签的形式,但是却只能写入一个标签,引入多标签的解决方法有很多,这儿详细说一下我的办法:制作多个data数据,分别加入一个标签.我的方法只适用于标签数量较少的情况,标 ...

  4. Linux 制作补丁 打补丁 撤销补丁

    1.制作补丁 diff - 逐行比较文件 格式 diff   参数   旧文件/旧文件夹   新文件/新文件夹 -N   将不存在的文件看作是空的 -a   将所有文件都视为文本文件 -u   以合并 ...

  5. 类的声明与实例化及构造方法析构方法(PHP学习)

    <?php class human{ public static $leg=2; public $name = 'leo'; public $age = '25'; public functio ...

  6. C/S模式与B/S模式的详细介绍

    网络程序开发的两种计算模式--C/S模式与B/S模式.两种各有千秋,用于不同场合. C/S适用于专人使用,安全性要求较高的系统: B/S适用于交互性比较频繁的场合,容易被人们所接受,倍受用户和软件开发 ...

  7. PPP PDP 及GPRS

    1.相关概念: PDP:Packet Data Protocol 分组数据协议 PLMN:Public Land Mobile Network,公共陆地移动网络 APN:Access Point Na ...

  8. 无法解析的外部符号 _WinMain@16

    无法解析的外部符号 _WinMain@16 Ctrl+F7 编译的时候没有错误,而F6生成解决方案的时候出现如下两个错误: 1:error LNK2019: 无法解析的外部符号 _WinMain@16 ...

  9. c#实现QQ群成员列表导出及邮件群发之群列表及群成员获取

    主题已迁移至:http://atiblogs.com/ ITO-神奇的程序员

  10. 让输入的字符转义成html实体的方法

    使用 htmlspecialchars() 函数,代码不会执行,因为会被保存为转义代码 总结测试方法: https://www.cnblogs.com/kaibindirver/p/10321448. ...