简介:本项目用于目标检测中的旋转框检测,获得目标框的旋转角度。使用的是PaddleDetection-release-2.2版本。通用的旋转框数据集是Dota,我们使用的模型S2ANet使用的是COCO数据集,本文实现如何将自己制作的旋转框数据集(VOC格式)->COCO旋转数据集。(本文禁止转载)

使用工具:

  • roLabelImg 用来标注旋转框
  • PaddleDetection-release-2.2

第一步:使用roLabelImg标注自己的数据集

1:安装roLabelImg

下载文件

解压文件

进入此文件下的cmd(建议直接使用base环境 用Conda创建环境题主会报错,当然你们也可以先按照上面的开发文档试试)

输入命令安装一下依赖包(basepython3.7)

pip install PyQt5
pip install lxml
pyrcc4 -o resources.py resources.qrc
python roLabelImg.py # 打开软件

2:使用roLabelImg标注图像

第二步:将标注的VOC数据集转换为COCO数据集

1:标注好的VOC数据集格式

  • images存放的是照片
  • annotations是标注的xml文件 框的格式是 中心点宽高角度[cx, cy, w, h, angle]

2:数据集格式转换

这里就不罗嗦了 直接贴代码

import argparse
import glob
import json
import os
import os.path as osp
import shutil
import xml.etree.ElementTree as ET
from tqdm import tqdmimport numpy as np
import PIL.ImageDrawlabel_to_num = {}
categories_list = []
labels_list = []class MyEncoder(json.JSONEncoder):def default(self, obj):if isinstance(obj, np.integer):return int(obj)elif isinstance(obj, np.floating):return float(obj)elif isinstance(obj, np.ndarray):return obj.tolist()else:return super(MyEncoder, self).default(obj)def images_labelme(data, num):image = {}image['height'] = data['imageHeight']image['width'] = data['imageWidth']image['id'] = num + 1if '\\' in data['imagePath']:image['file_name'] = data['imagePath'].split('\\')[-1]else:image['file_name'] = data['imagePath'].split('/')[-1]return imagedef images_cityscape(data, num, img_file):image = {}image['height'] = data['imgHeight']image['width'] = data['imgWidth']image['id'] = num + 1image['file_name'] = img_filereturn imagedef categories(label, labels_list):category = {}category['supercategory'] = 'component'category['id'] = len(labels_list) + 1category['name'] = labelreturn categorydef annotations_rectangle(points, label, image_num, object_num, label_to_num):annotation = {}seg_points = np.asarray(points).copy()seg_points[1, :] = np.asarray(points)[2, :]seg_points[2, :] = np.asarray(points)[1, :]annotation['segmentation'] = [list(seg_points.flatten())]annotation['iscrowd'] = 0annotation['image_id'] = image_num + 1annotation['bbox'] = list(map(float, [points[0][0], points[0][1], points[1][0] - points[0][0], points[1][1] - points[0][1]]))annotation['area'] = annotation['bbox'][2] * annotation['bbox'][3]annotation['category_id'] = label_to_num[label]annotation['id'] = object_num + 1return annotationdef annotations_polygon(height, width, points, label, image_num, object_num,label_to_num):annotation = {}annotation['segmentation'] = [list(np.asarray(points).flatten())]annotation['iscrowd'] = 0annotation['image_id'] = image_num + 1annotation['bbox'] = list(map(float, get_bbox(height, width, points)))annotation['area'] = annotation['bbox'][2] * annotation['bbox'][3]annotation['category_id'] = label_to_num[label]annotation['id'] = object_num + 1return annotationdef get_bbox(height, width, points):polygons = pointsmask = np.zeros([height, width], 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)index = np.argwhere(mask == 1)rows = index[:, 0]clos = index[:, 1]left_top_r = np.min(rows)left_top_c = np.min(clos)right_bottom_r = np.max(rows)right_bottom_c = np.max(clos)return [left_top_c, left_top_r, right_bottom_c - left_top_c,right_bottom_r - left_top_r]def deal_json(ds_type, img_path, json_path):data_coco = {}images_list = []annotations_list = []image_num = -1object_num = -1for img_file in os.listdir(img_path):img_label = os.path.splitext(img_file)[0]if img_file.split('.')[-1] not in ['bmp', 'jpg', 'jpeg', 'png', 'JPEG', 'JPG', 'PNG']:continuelabel_file = osp.join(json_path, img_label + '.json')print('Generating dataset from:', label_file)image_num = image_num + 1with open(label_file) as f:data = json.load(f)if ds_type == 'labelme':images_list.append(images_labelme(data, image_num))elif ds_type == 'cityscape':images_list.append(images_cityscape(data, image_num, img_file))if ds_type == 'labelme':for shapes in data['shapes']:object_num = object_num + 1label = shapes['label']if label not in labels_list:categories_list.append(categories(label, labels_list))labels_list.append(label)label_to_num[label] = len(labels_list)p_type = shapes['shape_type']if p_type == 'polygon':points = shapes['points']annotations_list.append(annotations_polygon(data['imageHeight'], data['imageWidth'], points, label, image_num,object_num, label_to_num))if p_type == 'rectangle':(x1, y1), (x2, y2) = shapes['points']x1, x2 = sorted([x1, x2])y1, y2 = sorted([y1, y2])points = [[x1, y1], [x2, y2], [x1, y2], [x2, y1]]annotations_list.append(annotations_rectangle(points, label, image_num,object_num, label_to_num))elif ds_type == 'cityscape':for shapes in data['objects']:object_num = object_num + 1label = shapes['label']if label not in labels_list:categories_list.append(categories(label, labels_list))labels_list.append(label)label_to_num[label] = len(labels_list)points = shapes['polygon']annotations_list.append(annotations_polygon(data['imgHeight'], data['imgWidth'], points, label, image_num, object_num,label_to_num))data_coco['images'] = images_listdata_coco['categories'] = categories_listdata_coco['annotations'] = annotations_listreturn data_cocodef voc_get_label_anno(ann_dir_path, ann_ids_path, labels_path):with open(labels_path, 'r') as f:labels_str = f.read().split()labels_ids = list(range(1, len(labels_str) + 1))with open(ann_ids_path, 'r') as f:ann_ids = [lin.strip().split(' ')[-1] for lin in f.readlines()]ann_paths = []for aid in ann_ids:if aid.endswith('xml'):ann_path = os.path.join(ann_dir_path, aid)else:ann_path = os.path.join(ann_dir_path, aid + '.xml')ann_paths.append(ann_path)return dict(zip(labels_str, labels_ids)), ann_pathsdef voc_get_image_info(annotation_root, im_id):filename = annotation_root.findtext('filename')assert filename is not Noneimg_name = os.path.basename(filename)size = annotation_root.find('size')width = float(size.findtext('width'))height = float(size.findtext('height'))image_info = {'file_name': filename + ".bmp", # 这个bmp是你自己数据集的格式 不要忘了改'height': height,'id': im_id,'width': width}return image_info# voc -> coco格式转换
def voc_get_coco_annotation(obj, label2id):label = obj.findtext('name')assert label in label2id, "label is not in label2id."category_id = label2id[label]robndbox = obj.find('robndbox')cx = float(robndbox.findtext('cx')) cy = float(robndbox.findtext('cy'))w = float(robndbox.findtext('w'))h = float(robndbox.findtext('h'))angle = float(robndbox.findtext('angle'))x1 = cx + w/2y1 = cy + h/2anno = {'area': w * h,'bbox': [x1,y1,w,h,angle],'category_id': category_id,'ignore': 0,'iscrowd': 0,"segmentation": []}return annodef voc_xmls_to_cocojson(annotation_paths, label2id, output_dir, output_file):output_json_dict = {"annotations": [],"categories": [],"images": [],"type": "instances"}bnd_id = 1  # bounding box start idim_id = 0print('Start converting !')for a_path in tqdm(annotation_paths):# Read annotation xmlann_tree = ET.parse(a_path)ann_root = ann_tree.getroot()img_info = voc_get_image_info(ann_root, im_id)output_json_dict['images'].append(img_info)for obj in ann_root.findall('object'):ann = voc_get_coco_annotation(obj=obj, label2id=label2id)ann.update({'image_id': im_id, 'id': bnd_id})output_json_dict['annotations'].append(ann)bnd_id = bnd_id + 1im_id += 1for label, label_id in label2id.items():category_info = {'supercategory': 'none', 'id': label_id, 'name': label}output_json_dict['categories'].append(category_info)output_file = os.path.join(output_dir, output_file)with open(output_file, 'w') as f:output_json = json.dumps(output_json_dict)f.write(output_json)def main():parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)parser.add_argument('--dataset_type',help='the type of dataset, can be `voc`, `labelme` or `cityscape`')parser.add_argument('--json_input_dir', help='input annotated directory')parser.add_argument('--image_input_dir', help='image directory')parser.add_argument('--output_dir', help='output dataset directory', default='./')parser.add_argument('--train_proportion',help='the proportion of train dataset',type=float,default=1.0)parser.add_argument('--val_proportion',help='the proportion of validation dataset',type=float,default=0.0)parser.add_argument('--test_proportion',help='the proportion of test dataset',type=float,default=0.0)parser.add_argument('--voc_anno_dir',help='In Voc format dataset, path to annotation files directory.',type=str,default=None)parser.add_argument('--voc_anno_list',help='In Voc format dataset, path to annotation files ids list.',type=str,default=None)parser.add_argument('--voc_label_list',help='In Voc format dataset, path to label list. The content of each line is a category.',type=str,default=None)parser.add_argument('--voc_out_name',type=str,default='voc.json',help='In Voc format dataset, path to output json file')args = parser.parse_args()try:assert args.dataset_type in ['voc', 'labelme', 'cityscape']except AssertionError as e:print('Now only support the voc, cityscape dataset and labelme dataset!!')os._exit(0)if args.dataset_type == 'voc':assert args.voc_anno_dir and args.voc_anno_list and args.voc_label_listlabel2id, ann_paths = voc_get_label_anno(args.voc_anno_dir, args.voc_anno_list, args.voc_label_list)voc_xmls_to_cocojson(annotation_paths=ann_paths,label2id=label2id,output_dir=args.output_dir,output_file=args.voc_out_name)else:try:assert os.path.exists(args.json_input_dir)except AssertionError as e:print('The json folder does not exist!')os._exit(0)try:assert os.path.exists(args.image_input_dir)except AssertionError as e:print('The image folder does not exist!')os._exit(0)try:assert abs(args.train_proportion + args.val_proportion \+ args.test_proportion - 1.0) < 1e-5except AssertionError as e:print('The sum of pqoportion of training, validation and test datase must be 1!')os._exit(0)# Allocate the dataset.total_num = len(glob.glob(osp.join(args.json_input_dir, '*.json')))if args.train_proportion != 0:train_num = int(total_num * args.train_proportion)out_dir = args.output_dir + '/train'if not os.path.exists(out_dir):os.makedirs(out_dir)else:train_num = 0if args.val_proportion == 0.0:val_num = 0test_num = total_num - train_numout_dir = args.output_dir + '/test'if args.test_proportion != 0.0 and not os.path.exists(out_dir):os.makedirs(out_dir)else:val_num = int(total_num * args.val_proportion)test_num = total_num - train_num - val_numval_out_dir = args.output_dir + '/val'if not os.path.exists(val_out_dir):os.makedirs(val_out_dir)test_out_dir = args.output_dir + '/test'if args.test_proportion != 0.0 and not os.path.exists(test_out_dir):os.makedirs(test_out_dir)count = 1for img_name in os.listdir(args.image_input_dir):if count <= train_num:if osp.exists(args.output_dir + '/train/'):shutil.copyfile(osp.join(args.image_input_dir, img_name),osp.join(args.output_dir + '/train/', img_name))else:if count <= train_num + val_num:if osp.exists(args.output_dir + '/val/'):shutil.copyfile(osp.join(args.image_input_dir, img_name),osp.join(args.output_dir + '/val/', img_name))else:if osp.exists(args.output_dir + '/test/'):shutil.copyfile(osp.join(args.image_input_dir, img_name),osp.join(args.output_dir + '/test/', img_name))count = count + 1# Deal with the json files.if not os.path.exists(args.output_dir + '/annotations'):os.makedirs(args.output_dir + '/annotations')if args.train_proportion != 0:train_data_coco = deal_json(args.dataset_type,args.output_dir + '/train',args.json_input_dir)train_json_path = osp.join(args.output_dir + '/annotations','instance_train.json')json.dump(train_data_coco,open(train_json_path, 'w'),indent=4,cls=MyEncoder)if args.val_proportion != 0:val_data_coco = deal_json(args.dataset_type,args.output_dir + '/val',args.json_input_dir)val_json_path = osp.join(args.output_dir + '/annotations','instance_val.json')json.dump(val_data_coco,open(val_json_path, 'w'),indent=4,cls=MyEncoder)if args.test_proportion != 0:test_data_coco = deal_json(args.dataset_type,args.output_dir + '/test',args.json_input_dir)test_json_path = osp.join(args.output_dir + '/annotations','instance_test.json')json.dump(test_data_coco,open(test_json_path, 'w'),indent=4,cls=MyEncoder)if __name__ == '__main__':main()

代码是我在PaddleDetection的tools/x2coco的基础上改的 本身自己比较菜 只能改别人的东西

注意:

  • 代码203行 自己数据集格式 .bmp 记得改成自己的
  • 代码必须在PaddleDetection环境下才能运行
  • 运行命令
python tools/x2coco.py \--dataset_type voc \--voc_anno_dir path/to/VOCdevkit/VOC2007/Annotations/ \ # xml文件--voc_anno_list path/to/VOCdevkit/VOC2007/ImageSets/Main/trainval.txt \ # VOC数据表--voc_label_list dataset/voc/label_list.txt \ # 数据标签类别名称文件--voc_out_name voc_train.json

补充:

  1. label_list.txt文件自己直接创建就行

2:如何生成trainval.txt 文件

这是trainval.txt文件内容

生成代码

# coding: utf-8
import os
import randomtrainval_percent = 1  # 训练集验证集总占比
train_percent = 0.95  # 训练集在trainval_percent里的train占比
xmlfilepath = 'D:/MicroWork/PaddleDetection-release-2.2/datasum/spinedata/Annotations'  #'D:/dataset/VOCdevkit/Annotations'
txtsavepath = 'D:/MicroWork/PaddleDetection-release-2.2/datasum/spinedata/ImagesSets/Main'
total_xml = os.listdir(xmlfilepath)num = len(total_xml)
list = range(num)
tv = int(num * trainval_percent)
tr = int(tv * train_percent)
trainval = random.sample(list, tv)
train = random.sample(trainval, tr)ftrainval = open('D:/MicroWork/PaddleDetection-release-2.2/datasum/spinedata/ImageSets/Main/trainval.txt', 'w')
ftest = open('D:/MicroWork/PaddleDetection-release-2.2/datasum/spinedata/ImageSets/Main/test.txt', 'w')
ftrain = open('D:/MicroWork/PaddleDetection-release-2.2/datasum/spinedata/ImageSets/Main/train.txt', 'w')
fval = open('D:/MicroWork/PaddleDetection-release-2.2/datasum/spinedata/ImageSets/Main/val.txt', 'w')for i in list:name = total_xml[i][:-4] + '\n'if i in trainval:ftrainval.write(name)if i in train:ftrain.write(name)else:fval.write(name)else:ftest.write(name)ftrainval.close()
ftrain.close()
fval.close()
ftest.close()

在数据集文件夹下创建 ImageSets/Main 文件夹

先使用这段Code在Main文件夹下生成 一下文件

上面的 trainval.txt 就是我们要使用的

[PaddleDetection] S2ANet检测旋转框自制作数据准备相关推荐

  1. 解决rotatedRectangleIntersection计算目标检测旋转框IOU不准确问题C++、opencv

    问题 语言 :C++ OpenCV版本:3.4.0 在目标检测中,后处理阶段会用到非极大值抑制来过滤目标框,而计算两个框的IOU(交并比)则是其关键的一环,先计算两个框相交的点,再求出这些点构成的多边 ...

  2. 目标检测矩形框与polygon数据增加--裁剪,拓展,旋转

    1.裁剪 import torch from torchvision import transforms import cv2 import numpy as np import types from ...

  3. Qt表格中以旋转框的形式数据交互

     Qt中自带的例子.详细情况,还得仔细看一下Model/View那一章. The Spin Box Delegate example shows how to create an editor for ...

  4. 旋转框目标检测mmrotate v0.3.1入门

    1.旋转目标监测的定义 受益于通用物体检测的蓬勃发展,目前大多数旋转物体检测模型都是基于经典的通用物体检测模型.随着检测任务的发展,水平箱已经不能满足某些细分领域研究人员的需求.通过重新定义对象表示, ...

  5. 航拍车辆旋转框定位以及航向检测

    引言 近年来,随着经济的快速发展,中国城市化发展迅速,城市车辆增多,交通网络也日益复杂.但交通的发展在给人们生活和工作带来便捷的同时,车多路繁的状况也给出行安全带来了隐患,更是给交通管理和监控提出了难 ...

  6. 针对遥感目标检测(小目标、旋转框、密集目标)的论文整理

    文献整理 文章目录 文献整理 A Multi-Feature Fusion-Based Change Detection Method for Remote Sensing Images 内容摘要 A ...

  7. 旋转框检测方法综述:RotateAnchor系列

    ↑ 点击蓝字 关注极市平台 作者丨emiya@知乎 来源丨https://zhuanlan.zhihu.com/p/105881332 极市导读 本文主要介绍了RRPN.R3Det.ROITransf ...

  8. 基于dota的目标检测(旋转框)论文阅读Oriented Object Detection in Aerial Images with Box Boundary-Aware Vectors

    基于dota的目标检测(旋转框)|论文阅读Oriented Object Detection in Aerial Images with Box Boundary-Aware Vectors 文章目录 ...

  9. 飞桨PaddlePaddle升级解读 | PaddleDetection物体检测统一框架

    目标检测是机器视觉领域的核心问题之一.7 月 3 日百度 AI 开发者大会,飞桨核心框架 Paddle Fluid v1.5 宣布开源了 PaddleDetection 物体检测统一框架,用户可以非常 ...

  10. texstudio自动拼写检测_飞桨PaddleDetection物体检测统一框架详解

    目标检测是机器视觉领域的核心问题之一.7 月 3 日百度 AI 开发者大会,飞桨核心框架 Paddle Fluid v1.5 宣布开源了 PaddleDetection 物体检测统一框架,用户可以非常 ...

最新文章

  1. html 自动弹出框
  2. android launchmode singleinstance问题
  3. win7配置Eclipse+Cocos2dx+android开发环境
  4. ubuntu14.04 LTS 源码编译安装postgreSQL
  5. BlueCatTools-域名批量查询软件介绍
  6. Main函数参数argc,argv说明
  7. java Excel导出 xlsx格式(超简单)
  8. php dfa,DFA 算法的PHP实现
  9. 简书python_python爬虫(以简书为例)
  10. Java中stringbutter_java 中String和StringBuffer与StringBuilder的区别及使用方法
  11. OC 获取view相对位置_【黑苹果系列】小白教程之DSD补丁篇 | 7分钟教你优雅定制最关键的OC补丁(clover通用)...
  12. 北斗文档下载工具-百度文库文档每天免费2次机会下载
  13. AutoCAD将DWG图纸转为PNG图片
  14. js实现代码高亮显示
  15. 软考信息系统项目管理师论成本管理范文
  16. 2018.12.15【HDU4622】Reincarnation(后缀自动机SAM)
  17. java es nested,Nested
  18. 互联网晚报|12/27星期二| ​​国家卫健委:取消入境后全员核酸检测和集中隔离;新冠肺炎更名为新冠感染;知网回应被罚8760万...
  19. python类初始化返回实例_Python基础——类、实例及初始化
  20. 基于KCOM3模块编写脚本控制电脑键盘鼠标,附控制软件

热门文章

  1. 小波变换matlab代码,matlab小波变换代码
  2. 离散小波变换wavedec matlab,Matlab实现小波变换
  3. mysql求平方根_MySQL数据库中如何求一个数的二次平方根(SQRT函数)呢?
  4. 002HTML常用标签
  5. 计算机视觉和模式识别领域企业论坛,第三届中国模式识别与计算机视觉大会(PRCV 2020)圆满举办...
  6. 分布式系统的阿喀琉斯之踵:数据一致性
  7. java限时抢购_Java生鲜电商平台-生鲜电商限时抢购功能设计与代码实战(小程序/APP)...
  8. c语言实现双拼算法,【连载】(开始学习C语言的指针)——乐创DIY C语言讲义——6.1节...
  9. 复旦MBAer聊“进博”:希望已至,寻路未来!
  10. java根据日期计算星期几_利用Java计算某个日期是星期几