数据增强之通过相似不变性变换、亮度、对比度、饱和度及清晰度进行数据集扩充
-
深度学习往往面临:1.数据标注过程很麻烦;2.部分场景数据集预测结果不佳
-
针对以上弊端,通过本文方法进行数据集扩充对训练过程尤为重要
-
本文主要依靠PIL(pillow)中的图像变换及增强模块进行图像数据集增强处理
-
并且在进行数据扩充的同时进行标注文件
.xml
格式文件相应的修改 -
具体实现就分为如下两个模块吧,下边详解一下:
-
- 图像变换
-
- xml标注文件修改
-
1.图像变换
- 直接调用PIL的变换函数与读写函数,具体使用不作多介绍
- PIL中文教程:https://www.osgeo.cn/pillow/handbook/tutorial.html
- 实现代码如下:
'''
批量读取文件夹路径下的图像,然后经过左右、上下翻转,亮度、对比度调整、色调调整进行图像数据集扩充,并自动复制其标签文件进行重命名保存
图像增强:亮度、对比度、饱和度变换
'''
import matplotlib.pyplot as plt
import xmlTF
from PIL import Image,ImageEnhance
import shutil
import os
path='./imgs/'
t=1200
imgname=""
xmlname=""
imglist=os.listdir(path)
for i in range(len(imglist)):
str_=imglist[i].split(".")[-1]
if(str_=="jpg"):
imgname=path+imglist[i]
xmlname = path + imglist[i].split(".")[0] + ".xml"
elif(str_=="xml"):
continue
print(t," - ",imgname)
img_ = Image.open(imgname)
# 水平翻转
img0 = img_.transpose(Image.FLIP_LEFT_RIGHT)
img0.save(path+str(t)+".jpg")
shutil.copy(xmlname, path+str(t)+".xml")
newname = path + str(t) + ".xml"
xmlTF.xmlFlip(newname,1)
t+=1
# 垂直翻转
img1=img_.transpose(Image.FLIP_TOP_BOTTOM)
img1.save(path + str(t) + ".jpg")
shutil.copy(xmlname, path + str(t) + ".xml")
newname = path + str(t) + ".xml"
xmlTF.xmlFlip(newname, 2)
t += 1
# 对角线翻转
img2=img1.transpose(Image.FLIP_LEFT_RIGHT)
img2.save(path + str(t) + ".jpg")
shutil.copy(xmlname, path + str(t) + ".xml")
newname = path + str(t) + ".xml"
xmlTF.xmlFlip(newname, 3)
t += 1
#
# plt.subplot(2,2,1)
# plt.imshow(img_)
# plt.subplot(2,2,2)
# plt.imshow(img0)
# plt.subplot(2,2,3)
# plt.imshow(img1)
# plt.subplot(2,2,4)
# plt.imshow(img2)
# plt.show()
#色彩调整:
# 亮度调整
brightEnhancer = ImageEnhance.Brightness(img_.copy())
img_0 = brightEnhancer.enhance(0.8)
img_0.save(path + str(t) + ".jpg")
shutil.copy(xmlname, path + str(t) + ".xml")
t += 1
img_1 = brightEnhancer.enhance(1.5)
img_1.save(path + str(t) + ".jpg")
shutil.copy(xmlname, path + str(t) + ".xml")
t += 1
# 对比度调整
contrastEnhancer = ImageEnhance.Contrast(img_.copy())
img_2 = contrastEnhancer.enhance(1.2)
img_2.save(path + str(t) + ".jpg")
shutil.copy(xmlname, path + str(t) + ".xml")
t += 1
img_3 = contrastEnhancer.enhance(1.7)
img_3.save(path + str(t) + ".jpg")
shutil.copy(xmlname, path + str(t) + ".xml")
t += 1
# 饱和度调整
colorEnhancer = ImageEnhance.Color(img_.copy())
img_4 = colorEnhancer.enhance(1.2)
img_4.save(path + str(t) + ".jpg")
shutil.copy(xmlname, path + str(t) + ".xml")
t += 1
img_5 = colorEnhancer.enhance(1.8)
img_5.save(path + str(t) + ".jpg")
shutil.copy(xmlname, path + str(t) + ".xml")
t += 1
# 清晰度调整
SharpnessEnhancer = ImageEnhance.Sharpness(img_.copy())
img_6 = SharpnessEnhancer.enhance(0.7)
img_6.save(path + str(t) + ".jpg")
shutil.copy(xmlname, path + str(t) + ".xml")
t += 1
img_7 = SharpnessEnhancer.enhance(1.5)
img_7.save(path + str(t) + ".jpg")
shutil.copy(xmlname, path + str(t) + ".xml")
t += 1
# plt.figure()
# plt.subplot(2, 5, 1),plt.imshow(img_),plt.title("1")
# plt.subplot(2, 5, 2),plt.imshow(img_0),plt.title("2")
# plt.subplot(2, 5, 3),plt.imshow(img_2),plt.title("3")
# plt.subplot(2, 5, 4),plt.imshow(img_4),plt.title("4")
# plt.subplot(2, 5, 5),plt.imshow(img_6),plt.title("5")
#
# plt.subplot(2, 5, 6), plt.imshow(img_),plt.title("6")
# plt.subplot(2, 5, 7), plt.imshow(img_1),plt.title("7")
# plt.subplot(2, 5, 8), plt.imshow(img_3),plt.title("8")
# plt.subplot(2, 5, 9), plt.imshow(img_5),plt.title("9")
# plt.subplot(2, 5, 10), plt.imshow(img_7),plt.title("10")
#
# plt.show()
2. 标注文件修改
- 修改
.xml
文件主要是读写其内容,并针对性的 做出一些修改 - 具体实现代码
xmlTF.py
如下:
'''
实现对.xml标签文件的一系列修改:
1.实现传入xml文件的检测框的水平、竖直与对角线翻转
'''
import os
import xml.etree.ElementTree as ET
def checkname(xmlpath):
with open(xmlpath, 'r') as f:
tree = ET.parse(f)
root = tree.getroot()
# print(root)
# print(list(root))
in_name=root.find("filename").text
in_path=root.find("path").text
xmlname=xmlpath.split("\\")[-1].split(".")[0]
a=xmlname
b=in_name.split(".")[0]
if(xmlname != in_name.split(".")[0]):
print(a, " - ", b)
root.find("filename").text=xmlname +".jpg"
root.find("path").text=in_path.rsplit("\\",1)[0]+"\\"+xmlname +".jpg"
tree.write(xmlpath)
def xmlFlip(xmlpath, flg):
'''
当图像发生翻转时,相对应的xml文件内容也做出相应变化
:param xmlpath: xml路径名字
:param flg: 操作类型:1-水平、 2-竖直、 3-对角线翻转
:return:保存修改后的文件
'''
#print(xmlpath)
# read xml
with open(xmlpath, 'r') as f:
tree = ET.parse(f)
root = tree.getroot()
# print(root)
# print(list(root))
size = root.find("size")
w = int(size.find("width").text)
h = int(size.find("height").text)
# print("w = ",w.text,"h = ",h.text)
# 查看多个重复元素
for obj in root.iter("object"):
box = obj.find("bndbox")
x_min = int(box.find("xmin").text)
y_min = int(box.find("ymin").text)
x_max = int(box.find("xmax").text)
y_max = int(box.find("ymax").text)
#水平翻转,x变化
if flg==1:
box.find("xmin").text = str(w - 1 - x_min)
box.find("xmax").text = str(w - 1 - x_max)
#竖直翻转,y变化
elif flg==2:
box.find("ymin").text = str(h - 1 - y_min)
box.find("ymax").text = str(h - 1 - y_max)
#对角线翻转,x,y都发生变化
elif flg==3:
box.find("xmin").text = str(w - 1 - x_min)
box.find("xmax").text = str(w - 1 - x_max)
box.find("ymin").text = str(h - 1 - y_min)
box.find("ymax").text = str(h - 1 - y_max)
# print("x1,y1,x2,y2 = ",[x_min,y_min,x_max,y_max])
#如果存在中文,则需要在.write()中设置 encoding='utf-8'
# tree.write(newpath + "//" + i)
# print(newpath + "//" + i)
# newpath="./xmls/"+xmlpath.split("/")[-1]
# tree.write(newpath)
tree.write(xmlpath)
- 如上所示,第一个函数为检查复制的标注文件中的图像名字和路径是否与
xml文件
一致,当然,如果内容中filename
和path
不一致,但是xml名字
与图像
名称一致,标签也是一一对应的,但是俺略微有点强迫症,就实现了一下检查名称并修改,其调用如下: - 当然,在数据增强中也可添加此功能。
#批量赋值图像的标注文件.xml并重命名为图像名字
import os
import shutil
import xmlTF
# imgspath="./file3/jpg"
# xmlpath="file3/jpg/005.xml"
imgspath="./images"
xmlpath="./images/0.xml"
for root,dirs,files in os.walk(imgspath,topdown=True):
for name in files:
str=name.split('.')
if(str[-1] == 'jpg'):
newname=str[0]+'.xml'
newxml=os.path.join(root,newname)
print(newxml)
if not os.path.exists(newxml):
shutil.copy(xmlpath,newxml)
xmlTF.checkname((newxml))