(14)数据增强之图像裁剪+标签文件.xml内容修改、json读取与修改

数据增强之图像裁剪+标签文件.xml内容修改

背景: 在训练模型时,为了达到较好的拟合效果,可能会对原有的数据集进行相似不变性变换、裁剪等一系列操作,而对于之前已标定好的label文件,同时也需要做出相应的一些变动,所以中间就涉及到了.xml文件内容的读取与更改


参考相关博客,推荐参考:python 读取与修改 XML(增删改查)
将修改demo总结如下:

1. xml文件格式示例

  • 给出任意一张图像的标注label:
<annotation>
    <folder>detection</folder>
    <filename>00001.png</filename>
    <size>
        <width>478</width>
        <height>270</height>
        <depth>3</depth>
    </size>
    <segmented>0</segmented>
    <object>
        <name>person</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>420</xmin>
            <ymin>125</ymin>
            <xmax>462</xmax>
            <ymax>256</ymax>
        </bndbox>
    </object>
    <object>
        <name>person</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>463</xmin>
            <ymin>125</ymin>
            <xmax>479</xmax>
            <ymax>255</ymax>
        </bndbox>
    </object>
    <object>
        <name>person</name>
        <pose>Unspecified</pose>
        <truncated>0</truncated>
        <difficult>0</difficult>
        <bndbox>
            <xmin>286</xmin>
            <ymin>97</ymin>
            <xmax>301</xmax>
            <ymax>138</ymax>
        </bndbox>
    </object>
</annotation>

2. 读取与修改内容

  • 导入包:
import os
import cv2
import xml.etree.ElementTree as ET
  • 访问与查找
import xml.etree.ElementTree as ET

tree = ET.parse('students.xml')
root = tree.getroot()  # 使用getroot()获取根节点,得到的是一个Element对象

#root = ET.fromstring(country_data_as_string) #从字符串变量中读取,返回的是Element对象


########################## 访问XML ###################################
"""
tag = element.text      #访问Element标签
attrib = element.attrib #访问Element属性
text = element.text     #访问Element文本
"""

for element in root.findall('student'):
    tag = element.tag                  # 访问Element标签
    attrib = element.attrib            # 访问Element属性
    text = element.find('name').text   # 访问Element文本
    print(tag, attrib, text)

print(root[0][0].text)                 # 子节点是嵌套的,我们可以通关索引访问特定的子节点

########################## 查找元素 ###################################
print("============ Element.iter() ===============")
for student in root.iter('student'):   # Element.iter()
    print(student[0].text)


print("============ Element.findall() ============")
for element in root.findall('student'):# Element.findall()
    name = element.find('name').text
    age = element.find('age').text
    score = element.find('score').text

    print (name,age,score)
  • 修改标签
'''
通过解析xml文件,批量修改xml文件里的标签名称,比如把标签zero改成num
'''
import os.path
import glob
import xml.etree.ElementTree as ET

path = r'D:/picture/Annotations/'    #存储标签的路径,修改为自己的Annotations标签路径   
for xml_file in glob.glob(path + '/*.xml'):
    ####### 返回解析树
	tree = ET.parse(xml_file)
	##########获取根节点
	root = tree.getroot()
	#######对所有目标进行解析
	for member in root.findall('object'):
		objectname = member.find('name').text
		if objectname == 'zero':      #原来的标签名字
			print(objectname)
			member.find('name').text = str('num')    #替换的标签名字
			tree.write(xml_file)
  • 读取文件夹下图像进行裁剪,并对xml坐标进行修改并保存到新路径
    在这里插入图片描述
import os
import cv2
import xml.etree.ElementTree as ET


ROOT="datas1207"
dirs=os.listdir("datas1207")

#处理第几个文件
n=0
print(dirs[n])

path=ROOT+"//"+dirs[n]
imglist=os.listdir(path)
#print(imglist)

for i in imglist:
    # 设置新路径
    newpath = str(n)
    if not os.path.exists(newpath):
        os.mkdir(newpath)
        
    if i.split(".")[-1]=="jpg":
        file=path+"//"+i
        img=cv2.imread(file)
        dst=img[687:2047,709:2232]
        newname=newpath+"//"+i
        cv2.imwrite(newname,dst)
    if i.split(".")[-1]=="xml":
        file=path+"//"+i
        #print(file)

        #read xml
        with open(file,'r') as f:
            tree=ET.parse(f)
        root=tree.getroot()
        # print(root)
        # print(list(root))

        size=root.find("size")
        w=size.find("width")
        h=size.find("height")
        #print("w = ",w.text,"h = ",h.text)
        #修改内容
        w.text= '1523'
        h.text='1360'

        #查看多个重复元素
        for obj in root.iter("object"):
            box=obj.find("bndbox")
            x_min=str(int(box.find("xmin").text)-709)
            y_min=str(int(box.find("ymin").text)-687)
            x_max=str(int(box.find("xmax").text)-709)
            y_max=str(int(box.find("ymax").text)-687)
            #print("x1,y1,x2,y2 = ",[x_min,y_min,x_max,y_max])
            
        tree.write(newpath+"//"+i)
        print(newpath+"//"+i)

3. json文件读取与修改

打开json文件,设端点查看其内部数据结构:

'''
python读取并修改json文件
'''

import json

path="20221118173251.json"

data={}

with open(path,'r',encoding='utf-8') as f:
    params=json.load(f)
    print("finish")

在这里插入图片描述
重点是 shape字典:
在这里插入图片描述

 for para in params:
        print(para)

***output:
version
flags
shapes
imagePath
imageData
imageHeight
imageWidth
finish

找到shape并输出:

shapes=params["shapes"]
    for shap in shapes:
        print(shap)

在这里插入图片描述
找到多边形坐标点并输出:

 shapes=params["shapes"]
    for shap in shapes:
        #print(shap)
        points=shap["points"]
        print(points)
        

在这里插入图片描述

  • 下边给出修改json文件的流程吧:

    • 场景:已经对数据集做出的标注,多边形标注,但是原图在旋转后凤娥效果更好,所以需要处理标签文件,使得里边的坐标以及图像数据同时变化

    • 1.先将原图进行相应旋转,然后简单标注(1个label),生成对应的json文件,将json文件保存到文件夹1和2
      在这里插入图片描述

    • 2.原来的标签文件json复制到文件夹0

    • 3.具体代码实现如下:

'''
python读取并修改json文件
'''

import json
import numpy as np
import cv2

def calH(angle,w=3840,h=2160):
    '''
    :param angle:旋转角度,顺时针为正
    :param w: 原图宽度
    :param h: 原图高度
    :return: 返回仿射变换矩阵
    '''
    if(angle==90):
        pts1=np.float32([[0,0],[w,0],[w,h]])
        pts2=np.float32([[h,0],[h,w],[0,w]])
        M=cv2.getAffineTransform(pts1,pts2)
        return M

def ptAffine(pt,H):
    '''
    :param pt:输入坐标点
    :param H:输入仿射变换矩阵
    :return: 仿射后的坐标点
    '''

    x=H[0,0]*pt[0]+H[0,1]*pt[1]+H[0,2]
    y=H[1,0]*pt[0]+H[1,1]*pt[1]+H[1,2]

    print("pt = ",pt,"  x = ",x,",  y = ",y)
    return[x,y]

label="20221118173251.json"
path0="0//"+label
path1="1//"+label  #竖直标签

data={}
M=calH(90)
print(M)

with open(path0,'r',encoding='utf-8') as f:
    params=json.load(f)
    #for para in params:
        #print(para)
    with open(path1, 'r', encoding='utf-8') as f_:
        params_ = json.load(f_)
    params["imageData"]=params_["imageData"]
    params["imageHeight"]=3840
    params["imageWidth"]=2160
    shapes=params["shapes"]
    for i in range(len(shapes)):
        #print(shap)
        points=shapes[i]["points"]
        #print(points)
        #针对单个坐标
        for j in range(len(points)):
            params["shapes"][i]["points"][j]=ptAffine(points[j],M)
    dict=params
f.close()

with open("2//"+label, 'w') as r:
    # 定义为写模式,名称定义为r

    json.dump(dict, r)
    # 将dict写入名称为r的文件中

r.close()

print("finish")
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

明月醉窗台

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值