(21)数据增强之通过相似不变性变换、亮度、对比度、饱和度及清晰度进行数据集扩充

数据增强之通过相似不变性变换、亮度、对比度、饱和度及清晰度进行数据集扩充

  • 深度学习往往面临:1.数据标注过程很麻烦;2.部分场景数据集预测结果不佳

  • 针对以上弊端,通过本文方法进行数据集扩充对训练过程尤为重要

  • 本文主要依靠PIL(pillow)中的图像变换及增强模块进行图像数据集增强处理

  • 并且在进行数据扩充的同时进行标注文件.xml格式文件相应的修改

  • 具体实现就分为如下两个模块吧,下边详解一下:

      1. 图像变换
      1. xml标注文件修改

1.图像变换

'''
批量读取文件夹路径下的图像,然后经过左右、上下翻转,亮度、对比度调整、色调调整进行图像数据集扩充,并自动复制其标签文件进行重命名保存
图像增强:亮度、对比度、饱和度变换
'''

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文件一致,当然,如果内容中filenamepath不一致,但是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))

猜你喜欢

转载自blog.csdn.net/yohnyang/article/details/129566525