检测之YOLO转VOC


检测系列相关文章参考如下链接:

  1. VOC数据的结构介绍及自定义生成,用labelimg自已标注
  2. VOC标准数据的生成及分析,VOC易用labelimg生成,做为基础的检测数据类型
  3. VOC转YOLO,方便YOLO系列模型使用
  4. VOC转COCO,方便用于COCO map评估
  5. YOLO转VOC,方便使用我们的VOC相关分析和处理代码
  6. COCO转VOC,方便使用我们的VOC相关分析和处理代码
    以上数据格式互转,方便我们处理各种收集的开源数据和自己标记的数据的整合。当然也不是特别的全面,但是工作中常用的主流的格式是包含的。
    觉的有价值的小伙伴可以给点个赞。

目标检测对输入数据的格式要求不尽相同,本文提供的是yolo转VOC格式的代码。

1、整理Yolo图像和标签文件

有时候yolo的标注文件比较乱,特别是图片和标注文件并非完全对应,这时需要先做一个处理。我们利用交集的方法,来保证图片和标签的一一对应。

代码如下:

imgs=sorted(os.listdir('/yourpath/images'))
lbs=sorted(os.listdir('/yourpath/labels'))
l = [os.path.splitext(i)[0] for i in lbs]  #去掉图片的后缀
b = [os.path.splitext(i)[0] for i in imgs]  # 去掉标注文件的后缀
a=list(set(b) & set(l)) # 这就得到图片和标注文件的一一对应

接着,把一一对应的图片和标签文件取出来,从而得到一个标准的正确的yolo目标检测数据集,代码如下:

for i in tqdm(a):
    img = os.path.join('/yourpath/images/',i+'.jpg')
    lb = os.path.join('/yourpath/labels/',i+'.txt')
    shutil.copy(img,'/yournewpath/images')
    shutil.copy(lb,'/yournewpath/labels')

2、实现yolo到voc的转换

直接上代码,相关说明看代码的注释


import  os, cv2, shutil
from lxml import etree, objectify
from tqdm import tqdm
from PIL import Image
import numpy as np
import time
import os.path as osp
import json

def cover_copy(src,dst):
    '''
    src和dst都必须是文件,该函数是执行覆盖操作
    '''
    if os.path.exists(dst):
        os.remove(dst)
        shutil.copy(src,dst)
    else:
        shutil.copy(src,dst)

def yolo2voc(sourcedir,savedir,class_names):
    """_summary_

    Args:
        sourcedir (_type_): /yournewpath 写到images 和labels上一级
        savedir (_type_): 写到JPEGImages和Annotations上一级
        class_names(list): yolo数据中所有的类别,顺序要与索引对应上
    """

    img_savepath= osp.join(savedir,'JPEGImages')
    ann_savepath=osp.join(savedir,'Annotations')
    for p in [img_savepath,ann_savepath]:
        if osp.exists(p):
            shutil.rmtree(p)
            os.makedirs(p)
        else:
            os.makedirs(p)
    filenames = os.listdir(osp.join(sourcedir,'images'))
    for filename in tqdm(filenames):
        filepath = osp.join(sourcedir,'images',filename)
        annfilepath=osp.join(sourcedir,'labels',osp.splitext(filename)[0]+'.txt')
        annopath = osp.join(ann_savepath,osp.splitext(filename)[0] + ".xml") #生成的xml文件保存路径
        dst_path = osp.join(img_savepath,filename)   
        im = Image.open(filepath)
        image = np.array(im).astype(np.uint8)
        w=image.shape[1]
        h=image.shape[0]
        cover_copy(filepath, dst_path)#把原始图像复制到目标文件夹
        anns=[i.strip().split() for i in open(annfilepath).readlines()]
        objs = []
        for ann in anns:
            name = class_names[int(ann[0])]   
            xcenter = float(ann[1])*w
            ycenter = float(ann[2])*h
            bw=float(ann[3])*w
            bh=float(ann[4])*h
            xmin = (int)(xcenter-bw/2)
            ymin = (int)(ycenter-bh/2)
            xmax = (int)(xcenter+bw/2)
            ymax = (int)(ycenter+bh/2)
            obj = [name, 1.0, xmin, ymin, xmax, ymax]
            #标错框在这里
            if not(xmin-xmax==0 or ymin-ymax==0):
                objs.append(obj)

        E = objectify.ElementMaker(annotate=False)
        anno_tree = E.annotation(
            E.folder('VOC'),
            E.filename(filename),
            E.source(
                E.database('YOLO'),
                E.annotation('VOC'),
                E.image('YOLO')
            ),
            E.size(
                E.width(image.shape[1]),
                E.height(image.shape[0]),
                E.depth(image.shape[2])
            ),
            E.segmented(0)
        )

        for obj in objs:
            E2 = objectify.ElementMaker(annotate=False)
            anno_tree2 = E2.object(
                E.name(obj[0]),
                E.pose(),
                E.truncated("0"),
                E.difficult(0),
                E.bndbox(
                    E.xmin(obj[2]),
                    E.ymin(obj[3]),
                    E.xmax(obj[4]),
                    E.ymax(obj[5])
                )
            )
            anno_tree.append(anno_tree2)
        etree.ElementTree(anno_tree).write(annopath, pretty_print=True)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值