更改标注图片后对应更改 xml 文件

前提

通常制作目标检测的训练集的时候需要对目标物进行标注,标注一般是用原图(像素很高,大小很大),人眼能看到更多的细节;但是标注完成后,进行训练的时候,受 GPU 的内存的限制,图片不能太大,要不内存溢出,会出现报错,一般可以通过调整 batch_size 来避免这个情况,但是batch_size 最小是1,如果还是出现 GPU 内存溢出,那么就需要修改图片的大小了,那么原来标注的 xml 文件的信息也要做出相应的调整

代码思路

1.读取xml文件(调用python的xml模块),保存原图的长宽
2.修改xml文件的<size></size>里面的<width><highth>标签的内容,更改成resize后的图片长宽
3.根据原图长宽和resize后的图片长宽的比值,得出对应 x 轴和 y 轴坐标缩小的倍数
3.修改<bndbox>标签下<xmin><ymin><xmax><ymax>四个标签的内容,全部乘上缩小的倍数
4.把修改后的xml文件重命名,保存到新路径

xml 文件原始路径(图中四个文件夹中)

《更改标注图片后对应更改 xml 文件》

xml 输出的路径(图中的 annotation 文件夹)

《更改标注图片后对应更改 xml 文件》

完整代码(resize_xml.py)

import xml.etree.ElementTree as ET #导入xml模块
import pickle
import os
from os import listdir, getcwd
from os.path import join
from PIL import Image
import glob
import resize_img #加载resize_img.py文件


''' xml_dir:xml文件所在的路径 out_dir:xml文件输出的路径 img_w:resize后的图片宽 img_h:resize后的图片高 xml_index:xml文件的索引(用于文件命名) '''
def xml2xml(xml_dir,out_dir,img_w,img_h,xml_index=1):
    xml_file=open(xml_dir)
    xml=ET.parse(xml_file)
    #获取原图的长宽
    old_w=float(xml.find('size').find('width').text)
    old_h=float(xml.find('size').find('height').text)
    #更改长宽
    xml.find('size').find('width').text=str(img_w)
    xml.find('size').find('height').text=str(img_h)
    #图片缩小倍数
    factor_x=img_w/old_w
    factor_y=img_h/old_h
    
    for obj in xml.iter('object'):
        #原始 bobox 左上和右下坐标
        xmin=float(obj.find('bndbox').find('xmin').text)
        ymin=float(obj.find('bndbox').find('ymin').text)
        xmax=float(obj.find('bndbox').find('xmax').text)
        ymax=float(obj.find('bndbox').find('ymax').text)
        #更改图片尺寸之后的 bbox 左上和右下坐标
        obj.find('bndbox').find('xmin').text=str(xmin*factor_x)
        obj.find('bndbox').find('ymin').text=str(ymin*factor_y)
        obj.find('bndbox').find('xmax').text=str(xmax*factor_x)
        obj.find('bndbox').find('ymax').text=str(ymax*factor_y)
        #Labelplot=((str(xmin/factor_x),str(ymin/factor_y)),(str(xmax/factor_x),str(ymax/factor_y)))
    xml_index=str('%08d'%xml_index)
    xml.write(os.path.join(out_dir)+xml_index+'.xml')#保存到另一个目录
    xml_file.close()
    print("%s更改成功\n"%xml_dir)
    

def main():
    filepath='G:/tx'#xml的路径
    files,files_num,imgs_num=resize_img.file_name(filepath)
    
    out_dir='G:/tx/annotation/'
    xml_name=1
    
    for i in range(files_num-2):#遍历文件(不能包括目录下的annotation文件)
        filename=files[i+1]#文件索引从1开始
        for xmlfile in glob.glob(filepath+"/"+filename+"/*.xml"):#返回所有匹配的xml路径列表
            print(xmlfile)
            xml2xml(xmlfile,out_dir,img_w=960,img_h=600,xml_index=xml_name)
            xml_name=xml_name+1


if __name__ == '__main__':
    main()
    

resize_img.py 文件的地址:获取二级目录下所有图片并更改尺寸保存

    原文作者:G果
    原文地址: https://blog.csdn.net/weixin_42899627/article/details/109033775
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞