python实现提取COCO,VOC数据集中特定的类


Posted in Python onMarch 10, 2020

1.python提取COCO数据集中特定的类

安装pycocotools github地址:https://github.com/philferriere/cocoapi

pip install git+https://github.com/philferriere/cocoapi.git#subdirectory=PythonAPI

提取特定的类别如下:

from pycocotools.coco import COCO
import os
import shutil
from tqdm import tqdm
import skimage.io as io
import matplotlib.pyplot as plt
import cv2
from PIL import Image, ImageDraw
 
#the path you want to save your results for coco to voc
savepath="/media/huanglong/Newsmy/COCO/" #保存提取类的路径,我放在同一路径下
img_dir=savepath+'images/'
anno_dir=savepath+'Annotations/'
# datasets_list=['train2014', 'val2014']
datasets_list=['train2014']
 
classes_names = ['person'] #coco有80类,这里写要提取类的名字,以person为例
#Store annotations and train2014/val2014/... in this folder
dataDir= '/media/huanglong/Newsmy/COCO/' #原coco数据集
 
headstr = """\
<annotation>
 <folder>VOC</folder>
 <filename>%s</filename>
 <source>
 <database>My Database</database>
 <annotation>COCO</annotation>
 <image>flickr</image>
 <flickrid>NULL</flickrid>
 </source>
 <owner>
 <flickrid>NULL</flickrid>
 <name>company</name>
 </owner>
 <size>
 <width>%d</width>
 <height>%d</height>
 <depth>%d</depth>
 </size>
 <segmented>0</segmented>
"""
objstr = """\
 <object>
 <name>%s</name>
 <pose>Unspecified</pose>
 <truncated>0</truncated>
 <difficult>0</difficult>
 <bndbox>
  <xmin>%d</xmin>
  <ymin>%d</ymin>
  <xmax>%d</xmax>
  <ymax>%d</ymax>
 </bndbox>
 </object>
"""
 
tailstr = '''\
</annotation>
'''
 
#if the dir is not exists,make it,else delete it
def mkr(path):
 if os.path.exists(path):
 shutil.rmtree(path)
 os.mkdir(path)
 else:
 os.mkdir(path)
mkr(img_dir)
mkr(anno_dir)
def id2name(coco):
 classes=dict()
 for cls in coco.dataset['categories']:
 classes[cls['id']]=cls['name']
 return classes
 
def write_xml(anno_path,head, objs, tail):
 f = open(anno_path, "w")
 f.write(head)
 for obj in objs:
 f.write(objstr%(obj[0],obj[1],obj[2],obj[3],obj[4]))
 f.write(tail)
 
 
def save_annotations_and_imgs(coco,dataset,filename,objs):
 #eg:COCO_train2014_000000196610.jpg-->COCO_train2014_000000196610.xml
 anno_path=anno_dir+filename[:-3]+'xml'
 img_path=dataDir+dataset+'/'+filename
 print(img_path)
 dst_imgpath=img_dir+filename
 
 img=cv2.imread(img_path)
 #if (img.shape[2] == 1):
 # print(filename + " not a RGB image")
 # return
 shutil.copy(img_path, dst_imgpath)
 
 head=headstr % (filename, img.shape[1], img.shape[0], img.shape[2])
 tail = tailstr
 write_xml(anno_path,head, objs, tail)
 
 
def showimg(coco,dataset,img,classes,cls_id,show=True):
 global dataDir
 I=Image.open('%s/%s/%s'%(dataDir,dataset,img['file_name']))
 #通过id,得到注释的信息
 annIds = coco.getAnnIds(imgIds=img['id'], catIds=cls_id, iscrowd=None)
 # print(annIds)
 anns = coco.loadAnns(annIds)
 # print(anns)
 # coco.showAnns(anns)
 objs = []
 for ann in anns:
 class_name=classes[ann['category_id']]
 if class_name in classes_names:
  print(class_name)
  if 'bbox' in ann:
  bbox=ann['bbox']
  xmin = int(bbox[0])
  ymin = int(bbox[1])
  xmax = int(bbox[2] + bbox[0])
  ymax = int(bbox[3] + bbox[1])
  obj = [class_name, xmin, ymin, xmax, ymax]
  objs.append(obj)
  draw = ImageDraw.Draw(I)
  draw.rectangle([xmin, ymin, xmax, ymax])
 if show:
 plt.figure()
 plt.axis('off')
 plt.imshow(I)
 plt.show()
 
 return objs
 
for dataset in datasets_list:
 #./COCO/annotations/instances_train2014.json
 annFile='{}/annotations/instances_{}.json'.format(dataDir,dataset)
 
 #COCO API for initializing annotated data
 coco = COCO(annFile)

 #show all classes in coco
 classes = id2name(coco)
 print(classes)
 #[1, 2, 3, 4, 6, 8]
 classes_ids = coco.getCatIds(catNms=classes_names)
 print(classes_ids)
 for cls in classes_names:
 #Get ID number of this class
 cls_id=coco.getCatIds(catNms=[cls])
 img_ids=coco.getImgIds(catIds=cls_id)
 print(cls,len(img_ids))
 # imgIds=img_ids[0:10]
 for imgId in tqdm(img_ids):
  img = coco.loadImgs(imgId)[0]
  filename = img['file_name']
  # print(filename)
  objs=showimg(coco, dataset, img, classes,classes_ids,show=False)
  print(objs)
  save_annotations_and_imgs(coco, dataset, filename, objs)

2. 将上一步提取的COCO 某一类 xml转为COCO标准的json文件:

# -*- coding: utf-8 -*-
# @Time : 2019/8/27 10:48
# @Author :Rock
# @File : voc2coco.py
# just for object detection
import xml.etree.ElementTree as ET
import os
import json

coco = dict()
coco['images'] = []
coco['type'] = 'instances'
coco['annotations'] = []
coco['categories'] = []

category_set = dict()
image_set = set()

category_item_id = 0
image_id = 0
annotation_id = 0


def addCatItem(name):
 global category_item_id
 category_item = dict()
 category_item['supercategory'] = 'none'
 category_item_id += 1
 category_item['id'] = category_item_id
 category_item['name'] = name
 coco['categories'].append(category_item)
 category_set[name] = category_item_id
 return category_item_id


def addImgItem(file_name, size):
 global image_id
 if file_name is None:
 raise Exception('Could not find filename tag in xml file.')
 if size['width'] is None:
 raise Exception('Could not find width tag in xml file.')
 if size['height'] is None:
 raise Exception('Could not find height tag in xml file.')
 img_id = "%04d" % image_id
 image_id += 1
 image_item = dict()
 image_item['id'] = int(img_id)
 # image_item['id'] = image_id
 image_item['file_name'] = file_name
 image_item['width'] = size['width']
 image_item['height'] = size['height']
 coco['images'].append(image_item)
 image_set.add(file_name)
 return image_id


def addAnnoItem(object_name, image_id, category_id, bbox):
 global annotation_id
 annotation_item = dict()
 annotation_item['segmentation'] = []
 seg = []
 # bbox[] is x,y,w,h
 # left_top
 seg.append(bbox[0])
 seg.append(bbox[1])
 # left_bottom
 seg.append(bbox[0])
 seg.append(bbox[1] + bbox[3])
 # right_bottom
 seg.append(bbox[0] + bbox[2])
 seg.append(bbox[1] + bbox[3])
 # right_top
 seg.append(bbox[0] + bbox[2])
 seg.append(bbox[1])

 annotation_item['segmentation'].append(seg)

 annotation_item['area'] = bbox[2] * bbox[3]
 annotation_item['iscrowd'] = 0
 annotation_item['ignore'] = 0
 annotation_item['image_id'] = image_id
 annotation_item['bbox'] = bbox
 annotation_item['category_id'] = category_id
 annotation_id += 1
 annotation_item['id'] = annotation_id
 coco['annotations'].append(annotation_item)


def parseXmlFiles(xml_path):
 for f in os.listdir(xml_path):
 if not f.endswith('.xml'):
  continue

 bndbox = dict()
 size = dict()
 current_image_id = None
 current_category_id = None
 file_name = None
 size['width'] = None
 size['height'] = None
 size['depth'] = None

 xml_file = os.path.join(xml_path, f)
 # print(xml_file)

 tree = ET.parse(xml_file)
 root = tree.getroot()
 if root.tag != 'annotation':
  raise Exception('pascal voc xml root element should be annotation, rather than {}'.format(root.tag))

 # elem is <folder>, <filename>, <size>, <object>
 for elem in root:
  current_parent = elem.tag
  current_sub = None
  object_name = None

  if elem.tag == 'folder':
  continue

  if elem.tag == 'filename':
  file_name = elem.text
  if file_name in category_set:
   raise Exception('file_name duplicated')

  # add img item only after parse <size> tag
  elif current_image_id is None and file_name is not None and size['width'] is not None:
  if file_name not in image_set:
   current_image_id = addImgItem(file_name, size)
   # print('add image with {} and {}'.format(file_name, size))
  else:
   raise Exception('duplicated image: {}'.format(file_name))
   # subelem is <width>, <height>, <depth>, <name>, <bndbox>
  for subelem in elem:
  bndbox['xmin'] = None
  bndbox['xmax'] = None
  bndbox['ymin'] = None
  bndbox['ymax'] = None

  current_sub = subelem.tag
  if current_parent == 'object' and subelem.tag == 'name':
   object_name = subelem.text
   if object_name not in category_set:
   current_category_id = addCatItem(object_name)
   else:
   current_category_id = category_set[object_name]

  elif current_parent == 'size':
   if size[subelem.tag] is not None:
   raise Exception('xml structure broken at size tag.')
   size[subelem.tag] = int(subelem.text)

  # option is <xmin>, <ymin>, <xmax>, <ymax>, when subelem is <bndbox>
  for option in subelem:
   if current_sub == 'bndbox':
   if bndbox[option.tag] is not None:
    raise Exception('xml structure corrupted at bndbox tag.')
   bndbox[option.tag] = int(option.text)

  # only after parse the <object> tag
  if bndbox['xmin'] is not None:
   if object_name is None:
   raise Exception('xml structure broken at bndbox tag')
   if current_image_id is None:
   raise Exception('xml structure broken at bndbox tag')
   if current_category_id is None:
   raise Exception('xml structure broken at bndbox tag')
   bbox = []
   # x
   bbox.append(bndbox['xmin'])
   # y
   bbox.append(bndbox['ymin'])
   # w
   bbox.append(bndbox['xmax'] - bndbox['xmin'])
   # h
   bbox.append(bndbox['ymax'] - bndbox['ymin'])
   # print('add annotation with {},{},{},{}'.format(object_name, current_image_id, current_category_id,
   #      bbox))
   addAnnoItem(object_name, current_image_id, current_category_id, bbox)


if __name__ == '__main__':
	#修改这里的两个地址,一个是xml文件的父目录;一个是生成的json文件的绝对路径
 xml_path = r'G:\dataset\COCO\person\coco_val2014\annotations\\'
 json_file = r'G:\dataset\COCO\person\coco_val2014\instances_val2014.json'
 parseXmlFiles(xml_path)
 json.dump(coco, open(json_file, 'w'))

3.python提取Pascal Voc数据集中特定的类

# -*- coding: utf-8 -*-
# @Function:There are 20 classes in VOC data set. If you need to extract specific classes, you can use this program to extract them.
 
import os
import shutil
ann_filepath='E:/VOCdevkit/VOC2012/Annotations/'
img_filepath='E:/VOCdevkit/VOC2012/JPEGImages/'
img_savepath='E:TrafficDatasets/JPEGImages/'
ann_savepath='E:TrafficDatasets/Annotations/'
if not os.path.exists(img_savepath):
 os.mkdir(img_savepath)
 
if not os.path.exists(ann_savepath):
 os.mkdir(ann_savepath)
names = locals()
classes = ['aeroplane','bicycle','bird', 'boat', 'bottle',
  'bus', 'car', 'cat', 'chair', 'cow','diningtable',
  'dog', 'horse', 'motorbike', 'pottedplant',
  'sheep', 'sofa', 'train', 'tvmonitor', 'person']
 
 
for file in os.listdir(ann_filepath):
 print(file)
 
 fp = open(ann_filepath + '\\' + file) #打开Annotations文件
 ann_savefile=ann_savepath+file
 fp_w = open(ann_savefile, 'w')
 lines = fp.readlines()
 
 ind_start = []
 ind_end = []
 lines_id_start = lines[:] 
 
 lines_id_end = lines[:]
 
 classes1 = '\t\t<name>bicycle</name>\n'
 classes2 = '\t\t<name>bus</name>\n'
 classes3 = '\t\t<name>car</name>\n'
 classes4 = '\t\t<name>motorbike</name>\n'
 classes5 = '\t\t<name>train</name>\n'
 
 #在xml中找到object块,并将其记录下来
 while "\t<object>\n" in lines_id_start:
 a = lines_id_start.index("\t<object>\n")
 ind_start.append(a) #ind_start是<object>的行数
 lines_id_start[a] = "delete"
 
 
 while "\t</object>\n" in lines_id_end:
 b = lines_id_end.index("\t</object>\n")
 ind_end.append(b) #ind_end是</object>的行数
 lines_id_end[b] = "delete"
 
 #names中存放所有的object块
 i = 0
 for k in range(0, len(ind_start)):
 names['block%d' % k] = []
 for j in range(0, len(classes)):
  if classes[j] in lines[ind_start[i] + 1]:
  a = ind_start[i]
  for o in range(ind_end[i] - ind_start[i] + 1):
   names['block%d' % k].append(lines[a + o])
  break
 i += 1
 #print(names['block%d' % k])
 
 
 #xml头
 string_start = lines[0:ind_start[0]]
 
 #xml尾
 if((file[2:4]=='09') | (file[2:4]=='10') | (file[2:4]=='11')):
 string_end = lines[(len(lines) - 11):(len(lines))]
 else:
 string_end = [lines[len(lines) - 1]] 
 
 
 #在给定的类中搜索,若存在则,写入object块信息
 a = 0
 for k in range(0, len(ind_start)):
 if classes1 in names['block%d' % k]:
  a += 1
  string_start += names['block%d' % k]
 if classes2 in names['block%d' % k]:
  a += 1
  string_start += names['block%d' % k]
 if classes3 in names['block%d' % k]:
  a += 1
  string_start += names['block%d' % k]
 if classes4 in names['block%d' % k]:
  a += 1
  string_start += names['block%d' % k]
 if classes5 in names['block%d' % k]:
  a += 1
  string_start += names['block%d' % k]
 
 string_start += string_end
 # print(string_start)
 for c in range(0, len(string_start)):
 fp_w.write(string_start[c])
 fp_w.close()
 #如果没有我们寻找的模块,则删除此xml,有的话拷贝图片
 if a == 0:
 os.remove(ann_savepath+file)
 else:
 name_img = img_filepath + os.path.splitext(file)[0] + ".jpg"
 shutil.copy(name_img, img_savepath)
 fp.close()

以上这篇python实现提取COCO,VOC数据集中特定的类就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python中的匿名函数使用简介
Apr 27 Python
python 性能优化方法小结
Mar 31 Python
python里使用正则表达式的组嵌套实例详解
Oct 24 Python
python 接口测试response返回数据对比的方法
Feb 11 Python
Python实现随机生成手机号及正则验证手机号的方法
Apr 25 Python
Python中交换两个元素的实现方法
Jun 29 Python
python输入整条数据分割存入数组的方法
Nov 13 Python
解决Python正则表达式匹配反斜杠''\''问题
Jul 17 Python
Django密码系统实现过程详解
Jul 19 Python
python使用pandas抽样训练数据中某个类别实例
Feb 28 Python
Django使用list对单个或者多个字段求values值实例
Mar 31 Python
python 三边测量定位的实现代码
Apr 22 Python
Python 生成VOC格式的标签实例
Mar 10 #Python
python3用urllib抓取贴吧邮箱和QQ实例
Mar 10 #Python
python目标检测给图画框,bbox画到图上并保存案例
Mar 10 #Python
python opencv 检测移动物体并截图保存实例
Mar 10 #Python
Python标准库json模块和pickle模块使用详解
Mar 10 #Python
Python xlrd excel文件操作代码实例
Mar 10 #Python
python图片剪裁代码(图片按四个点坐标剪裁)
Mar 10 #Python
You might like
数据库相关问题
2006/10/09 PHP
探讨PHP JSON中文乱码的解决方法详解
2013/06/06 PHP
php单一接口的实现方法
2015/06/20 PHP
JavaScript和JQuery实用代码片段(一)
2010/04/07 Javascript
jquery each的几种常用的使用方法示例
2014/01/21 Javascript
js中的caller和callee属性介绍和例子
2014/06/07 Javascript
extjs_02_grid显示本地数据、显示跨域数据
2014/06/23 Javascript
AngularJS的一些基本样式初窥
2015/07/27 Javascript
javascript禁止访客复制网页内容的实现代码
2015/08/05 Javascript
Bootstrap表单布局样式源代码
2016/07/04 Javascript
浅谈JS正则表达式的RegExp对象和括号的使用
2016/07/28 Javascript
js 提交form表单和设置form表单请求路径的实现方法
2016/10/25 Javascript
探索Vue.js component内容实现
2016/11/03 Javascript
javascript读取文本节点方法小结
2016/12/15 Javascript
Cropper.js 实现裁剪图片并上传(PC端)
2017/08/20 Javascript
解决JQuery全选/反选第二次失效的问题
2017/10/11 jQuery
JS+HTML+CSS实现轮播效果
2017/11/28 Javascript
详解webpack+express多页站点开发
2017/12/22 Javascript
vue-cli构建vue项目的步骤详解
2019/01/27 Javascript
vue+django实现一对一聊天功能的实例代码
2019/07/17 Javascript
微信小程序修改checkbox的样式代码实例
2020/01/21 Javascript
Vue Object 的变化侦测实现代码
2020/04/15 Javascript
Vue将props值实时传递 并可修改的操作
2020/08/09 Javascript
vue项目里面引用svg文件并给svg里面的元素赋值
2020/08/17 Javascript
原生js实现自定义难度的扫雷游戏
2021/01/22 Javascript
[14:03]2017DOTA2亚洲邀请赛开幕式:12神兵演绎水墨中华
2017/04/01 DOTA
Python与R语言的简要对比
2017/11/14 Python
Linux下Pycharm、Anaconda环境配置及使用踩坑
2018/12/19 Python
numpy数组广播的机制
2019/07/12 Python
网上常见的一份Linux面试题(多项选择部分)
2015/02/07 面试题
司法局群众路线教育实践活动整改措施思想汇报
2014/10/13 职场文书
2015元旦晚会主持人开场白+结束语
2014/12/14 职场文书
2015年安置帮教工作总结
2015/05/22 职场文书
Pytorch 如何实现LSTM时间序列预测
2021/05/17 Python
只需要这一行代码就能让python计算速度提高十倍
2021/05/24 Python
Nginx如何限制IP访问只允许特定域名访问
2022/07/23 Servers