原图像大小为1024*2048,输入网络中太大。便将其裁剪为两张1024*1024大小的图像,同时对其对应的xml(VOC格式)进行修改,代码参考了csdn其他博主的,具体是哪个,找不到了,未添加参考源,着实抱歉。
标签保留策略是如果一个标注框恰好在中间且被切分为了两块,均保留(后续还需要人工检核修改,因为有的标注框会很小很小)。
import cv2
import xml.etree.ElementTree as ET
import os
import numpy as np
from tqdm import tqdm
from PIL import Image
# 数据扩增
# 读xml文档返回每个目标边界框信息
def read_xml_annotation(root, image_id): # (源xml文件夹地址和文件夹内所有图像名称)
in_file = open(os.path.join(root, image_id))
tree = ET.parse(in_file)
root = tree.getroot()
bndboxlist = []
for object in root.findall('object'): # 找到root节点下的所有country节点
bndbox = object.find('bndbox') # 子节点下节点rank的值
xmin = int(bndbox.find('xmin').text)
xmax = int(bndbox.find('xmax').text)
ymin = int(bndbox.find('ymin').text)
ymax = int(bndbox.find('ymax').text)
bndboxlist.append([xmin, ymin, xmax, ymax])
bndbox = root.find('object').find('bndbox')
return bndboxlist
# 更改xml信息将裁剪至每个小部分的对应目标边界框进行提取
def change_xml_list_annotation(root, image_id, new_target, saveroot, id):
in_file = open(os.path.join(root, str(image_id) + '.xml')) # 这里root分别由两个意思
tree = ET.parse(in_file)
# 修改xml文件中的filename
elem = tree.find('filename')
elem.text = (str(id) + '.jpg')
xmlroot = tree.getroot()
# 修改xml文件中的path
elem = tree.find('path')
if elem != None:
elem.text = (saveroot + str(id) + '.jpg')
#修改xml文件中的图像宽高
tree.find('size').find('width').text = str(1024)
tree.find('size').find('height').text = str(1024)
index = 0
for object in xmlroot.findall('object'): # 找到root节点下的所有country节点
bndbox = object.find('bndbox') # 子节点下节点rank的值
new_xmin = new_target[index][0]
new_ymin = new_target[index][1]
new_xmax = new_target[index][2]
new_ymax = new_target[index][3]
xmin = bndbox.find('xmin')
xmin.text = str(new_xmin)
ymin = bndbox.find('ymin')
ymin.text = str(new_ymin)
xmax = bndbox.find('xmax')
xmax.text = str(new_xmax)
ymax = bndbox.find('ymax')
ymax.text = str(new_ymax)
if xmin.text == "0" and ymin.text == "0" and xmax.text == "0" and ymax.text == "0":
xmlroot.remove(object) # 由于在后续设置中将超出五个裁剪完成图像范围的目标边界框的四个参数全部设为0,此处将参数为0的object删除掉,剩余满足裁剪范围内的目标边界框
index = index + 1
tree.write(os.path.join(saveroot, str(id + '.xml')))
# 遍历指定目录,显示目录下的所有文件名
def CropImage4File(filepath, destpath):
pathDir = os.listdir(filepath) # 列出文件路径中的所有路径或文件
for allDir in pathDir:
child = os.path.join(filepath, allDir)
dest = os.path.join(destpath, allDir)
if os.path.isfile(child):
image = cv2.imread(child)
sp = image.shape # 获取图像形状:返回【行数值,列数值】列表
sz1 = sp[0] # 图像的高度(行 范围)
sz2 = sp[1] # 图像的宽度(列 范围)
#sz3 = sp[2] #像素值由【RGB】三原色组成
#你想对文件的操作
n, s = os.path.splitext(dest)
a1 = 0 # x start
b1 = int(sz1) # x end 列
c1 = 0 # y start
d1 = int(sz2/2) # y end 行
cropImg1 = image[a1:b1, c1:d1] # 裁剪图像
cv2.imwrite(n + '_1' + s, cropImg1) # 写入图像路径
a2 = 0 # x start
b2 = int(sz1) # x end
c2 = int(sz2/2) # y start
d2 = int(sz2) # y end
cropImg2 = image[a2:b2, c2:d2] # 裁剪图像
cv2.imwrite(n + '_2' + s, cropImg2) # 写入图像路径
if __name__ == '__main__':
filepath = 'E:/yolov5-master/VOCData/9.15text/images/' # 源图像
XML_DIR = 'E:/yolov5-master/VOCData/Annotations/' # 源xml
destpath = 'E:/yolov5-master/qiege/image_qiege/' # 保存裁剪图片的文件夹地址
AUG_XML_DIR = 'E:/yolov5-master/qiege/labels_qiege/' # 保存xml地址
new_bndbox_list = [] # 提前清空存储anchor,否则anchor会重复覆盖
CropImage4File(filepath,destpath)
for name in tqdm(os.listdir(XML_DIR), desc='Processing'):
bndbox = read_xml_annotation(XML_DIR, name) # 一张图片的边界框信息
og_xml = open(os.path.join(XML_DIR, name))
tree = ET.parse(og_xml)
elem = tree.find('filename')
elem.text = (name[:-4] + '.jpg') # 每一次将xml文件中的filename节点信息进行更改
img = Image.open(os.path.join(filepath, name[:-4] + '.jpg'))
img = np.asarray(img)
i_h, i_w, _ = img.shape
# 分别依据左上右上左下右下和中心位置对满足要求的目标边界框进行分别提取,并保存在各自对应的xml文件中,若目标边界框在裁剪图片边缘上,则舍弃
for i in range(len(bndbox)):
x1 = bndbox[i][0]
y1 = bndbox[i][1]
x2 = bndbox[i][2]
y2 = bndbox[i][3]
n_x1 = 0
n_y1 = 0
n_x2 = 0
n_y2 = 0
#anchor在左半部分,全保留
if x1 < i_w / 2 and x2 < i_w / 2 and y1 < i_h and y2 < i_h :
n_x1 = x1
n_y1 = y1
n_x2 = x2
n_y2 = y2
#anchor被切割,将x的最大值赋值为1024(裁剪后的图像最大宽)
if x1 <i_w / 2 and x2 >i_w / 2 and y1 < i_h and y2 < i_h :
n_x1 = x1
n_y1 = y1
n_x2 = 1024
n_y2 = y2
new_bndbox_list.append([n_x1, n_y1, n_x2, n_y2])
epoch = 1
# 存储变化后的XML
change_xml_list_annotation(XML_DIR, name[:-4], new_bndbox_list, AUG_XML_DIR, str(name[:-4]) + '_' + str(epoch))
# 将new_bndbox_list清零
new_bndbox_list = []
for i in range(len(bndbox)):
x1 = bndbox[i][0]
y1 = bndbox[i][1]
x2 = bndbox[i][2]
y2 = bndbox[i][3]
n_x1 = 0
n_y1 = 0
n_x2 = 0
n_y2 = 0
#anchor全在右半部分,全保留
if x1 > i_w / 2 and x2 > i_w / 2 and y1 < i_h and y2 < i_h :
n_x1 = x1 - 1024
n_y1 = y1
n_x2 = x2 - 1024
n_y2 = y2
#anchor被切割,将x最小值赋值为0,最大值减去1024
if x1 <i_w / 2 and x2 >i_w / 2 and y1 < i_h and y2 < i_h :
n_x1 = 0
n_y1 = y1
n_x2 = x2 - 1024
n_y2 = y2
new_bndbox_list.append([n_x1, n_y1, n_x2, n_y2])
epoch = 2
# 存储变化后的XML
change_xml_list_annotation(XML_DIR, name[:-4], new_bndbox_list, AUG_XML_DIR, str(name[:-4]) + '_' + str(epoch))
效果如下:
原图像大小为1024*2048,输入网络中太大。便将其裁剪为两张1024*1024大小的图像,同时对其对应的xml(VOC格式)进行修改。标签保留策略是如果一个标注框恰好在中间且被切分为了两块,均保留
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录本文主要内容一、代码内容二、使用需要修改部分1. 数据标注种类修改2. 修改数据路径以及裁剪图像值3.测试效果
本文主要内容
本文可实现图像与xml格式标签同步分割,文中代码参考自网络。裁剪图像部分见上篇文章:基于Python的有重叠区域的批量图像分割
一、代码内容
import cv2
import os
from xml.dom.minidom import Document
import xml.etree.Elemen.
这段时间有个小任务是提取出图片中的手部物体,然后我就用labelimg打标软件给部分图片打了标(生成xml标签文件),顺手写了个小脚本将这些目标从原图中裁剪出来,效果如下所示,感觉还可以。
原始图片(实例1):
裁剪效果(实例1):
原始图片(实例2):
裁剪效果(实例2,此处空手为打标,故未裁剪):
本代码针对以下问题均有解决:
1、同一xml文件有多个目标框;
2、图片和xml文件在不同或相同文件夹下;
3、部分图片未打标,对应的xml文件不存在;
4、图片文件夹中有非图片(png,
上周,我被要求用Java编写一些东西,该东西能够将单个30GB XML文件拆分为可配置文件大小的较小部分。 该文件的使用者将是一个中间件应用程序,该应用程序存在XML较大的问题。 在后台,它使用某种DOM解析技术,使它在一段时间后耗尽内存。 由于它是基于供应商的中间件,因此我们无法自行纠正。 最好的选择是创建一些预处理工具,该工具会先将大文件分成多个较小的块,然后再由中间件处理。
XML...
MyBatis在运行时根据配置文件中的信息来找到对应的xml文件。首先,MyBatis配置文件中需要指定包含`mapper`的目录,即`<mappers>`标签。MyBatis会扫描该目录及其子目录下的所有文件,并检查文件名是否以`Mapper.xml`结尾。
如果文件名符合条件,MyBatis会尝试读取该xml文件。在xml文件中定义了多个`<mapper>`标签,每个标签对应了一个dao接口,其中的`namespace`属性指定了该接口的全限定名。
当需要执行某个dao方法时,MyBatis就会根据这个方法所属的接口的全限定名和方法名,拼接出对应的`mapper`标签的`id`属性值。然后,MyBatis会根据`namespace`和`id`属性值,找到对应的`<select>`、`<delete>`、`<insert>`或`<update>`标签,然后根据标签中的SQL语句和参数信息,生成对应的SQL命令并执行。
如果在执行过程中发现无法找到对应的xml文件或`mapper`标签,MyBatis就会抛出异常。因此,在使用MyBatis时,需要确保配置文件和xml文件的路径、文件名、接口名、方法名等信息都正确无误,避免出现找不到xml文件或方法无法执行的情况。