目标检测数据准备工作

花了几天时间调试了一下SSD网络,对于FLIR数据集训练测试进行了准备工作,最终顺利调通

json_yolo格式准换

from __future__ import print_function
import argparse
import glob
import os
import json

if __name__ == '__main__':
    # 命令行打印参数
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "path", default='E:/CNN/ssd/data/json/',help='Directory of json files containing annotations')  # json文件路径
    parser.add_argument(
        "output_path",default='E:/CNN/ssd/data/xml/', help='Output directory for image.txt files')  # 生成的txt保存路径
    args = parser.parse_args()

    # os.path.join 合并路径
    # glob.glob 获取所有匹配的路径
    json_files = sorted(glob.glob(os.path.join(args.path, '*.json')))  # 得到json文件路径下的所有json文件

    for json_file in json_files:
        with open(json_file) as f:
            data = json.load(f)  # 将json文件转化为字典
            images = data['images']
            annotations = data['annotations']

            # 图片w h,为归一化作准备
            width = 640.0
            height = 512.0

            for i in range(0, len(images)):
                converted_results = []
                for ann in annotations:
                    if ann['image_id'] == i and ann['category_id'] <= 3:  # FLIR数据集中只有1-3
                        cat_id = int(ann['category_id'])

                        # letf top为左下角坐标 bbox_width bbox_height为目标框长宽
                        # 将bbox数值转化为float类型
                        left, top, bbox_width, bbox_height = map(float, ann['bbox'])

                        # Yolo的id从0开始,FILIR从1开始
                        cat_id -= 1

                        # 求中心点坐标
                        x_center, y_center = (
                            left + bbox_width / 2, top + bbox_height / 2)

                        # 归一化
                        x_rel, y_rel = (x_center / width, y_center / height)
                        w_rel, h_rel = (bbox_width / width, bbox_height / height)
                        converted_results.append(
                            (cat_id, x_rel, y_rel, w_rel, h_rel))

                image_name = images[i]['file_name']

                # 这里image_name是thermal_8_bit/FLIR_xxxxx.jpeg格式,我们文件名只需要FLIR_xxxxx部分
                image_name = image_name[14:-5]

                print(image_name)  # 验证是名称否正确

                file = open(args.output_path + str(image_name) + '.txt', 'w+')
                file.write('\n'.join('%d %.6f %.6f %.6f %.6f' % res for res in converted_results))
                file.close()

yolo_xml转换

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Aug 17 22:10:01 2018
@author: Caroline Pacheco do E. Silva
"""

import os
import cv2
from xml.dom.minidom import parseString
from lxml.etree import Element, SubElement, tostring
import numpy as np
from os.path import join

## coco classes    选择你的json、yolo格式的类别,并按顺序进行排列
YOLO_CLASSES = ('person', 'bicycle', 'car', 'motorcycle')
# YOLO_CLASSES = ('person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',
#                 'train', 'truck', 'boat', 'traffic light', 'fire hydrant',
#                 'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog',
#                 'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra',
#                 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie',
#                 'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball',
#                 'kite', 'baseball bat', 'baseball glove', 'skateboard',
#                 'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup',
#                 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
#                 'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza',
#                 'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed',
#                 'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote',
#                 'keyboard', 'cell phone', 'microwave' 'oven', 'bike', 'hydrant',
#                 'motor', 'rider', 'clock', 'light', 'sign',
#                 'motor vehicle', 'human face','hair drier', 'license plate')



## converts the normalized positions  into integer positions
def unconvert(class_id, width, height, x, y, w, h):
    xmax = int((x * width) + (w * width) / 2.0)
    xmin = int((x * width) - (w * width) / 2.0)
    ymax = int((y * height) + (h * height) / 2.0)
    ymin = int((y * height) - (h * height) / 2.0)
    class_id = int(class_id)
    return (class_id, xmin, xmax, ymin, ymax)


## path root folder
ROOT = 'E:/CNN/ssd/data/yolo'


## converts coco into xml
def xml_transform(root, classes):
    class_path = join(root, 'labels')
    ids = list()
    l = os.listdir(class_path)

    check = '.DS_Store' in l
    if check == True:
        l.remove('.DS_Store')

    ids = [x.split('.')[0] for x in l]

    annopath = join(root, 'labels', '%s.txt')
    imgpath = join(root, 'images', '%s.jpeg')

    os.makedirs(join(root, 'outputs'), exist_ok=True)
    outpath = join(root, 'outputs', '%s.xml')

    for i in range(len(ids)):
        img_id = ids[i]
        img = cv2.imread(imgpath % img_id)
        height, width, channels = img.shape  # pega tamanhos e canais das images

        node_root = Element('annotation')
        node_folder = SubElement(node_root, 'folder')
        node_folder.text = 'VOC2007'
        img_name = img_id + '.jpeg'

        node_filename = SubElement(node_root, 'filename')
        node_filename.text = img_name

        node_source = SubElement(node_root, 'source')
        node_database = SubElement(node_source, 'database')
        node_database.text = 'Coco database'

        node_size = SubElement(node_root, 'size')
        node_width = SubElement(node_size, 'width')
        node_width.text = str(width)

        node_height = SubElement(node_size, 'height')
        node_height.text = str(height)

        node_depth = SubElement(node_size, 'depth')
        node_depth.text = str(channels)

        node_segmented = SubElement(node_root, 'segmented')
        node_segmented.text = '0'

        target = (annopath % img_id)
        if os.path.exists(target):
            label_norm = np.loadtxt(target).reshape(-1, 5)

            for i in range(len(label_norm)):
                labels_conv = label_norm[i]
                new_label = unconvert(labels_conv[0], width, height, labels_conv[1], labels_conv[2], labels_conv[3],
                                      labels_conv[4])
                node_object = SubElement(node_root, 'object')
                node_name = SubElement(node_object, 'name')
                node_name.text = classes[new_label[0]]

                node_pose = SubElement(node_object, 'pose')
                node_pose.text = 'Unspecified'

                node_truncated = SubElement(node_object, 'truncated')
                node_truncated.text = '0'
                node_difficult = SubElement(node_object, 'difficult')
                node_difficult.text = '0'
                node_bndbox = SubElement(node_object, 'bndbox')
                node_xmin = SubElement(node_bndbox, 'xmin')
                node_xmin.text = str(new_label[1])
                node_ymin = SubElement(node_bndbox, 'ymin')
                node_ymin.text = str(new_label[3])
                node_xmax = SubElement(node_bndbox, 'xmax')
                node_xmax.text = str(new_label[2])
                node_ymax = SubElement(node_bndbox, 'ymax')
                node_ymax.text = str(new_label[4])
                xml = tostring(node_root, pretty_print=True)
                dom = parseString(xml)
        print(xml)
        f = open(outpath % img_id, "wb")
        # f = open(os.path.join(outpath, img_id), "w")
        # os.remove(target)
        f.write(xml)
        f.close()


xml_transform(ROOT, YOLO_CLASSES)

提取文件名并保存成txt格式文件

import os  #通过os模块调用系统命令

file_path = "E:/CNN/ssd/data/xml/"  #文件路径
path_list = os.listdir(file_path) #遍历整个文件夹下的文件name并返回一个列表

path_name = []#定义一个空列表

for i in path_list:
    path_name.append(i.split(".")[0]) #若带有后缀名,利用循环遍历path_list列表,split去掉后缀名

#path_name.sort() #排序

for file_name in path_name:
    # "a"表示以不覆盖的形式写入到文件中,当前文件夹如果没有"save.txt"会自动创建
    with open("E:/CNN/ssd/data/train.txt", "a") as file:
        file.write(file_name + "\n")
        print(file_name)
    file.close()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值