圖像增強方法,SSD有BBOX的情況用這個方法比較好。

參考:

https://blog.csdn.net/limiyudianzi/article/details/86497345

https://github.com/cyndi088/DataAugmentation/blob/master/augmentation.py

#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
import sys
import os
import shutil
import numpy as np
import imgaug as ia
import xml.etree.ElementTree as ET

from PIL import Image
from imgaug import augmenters as iaa

ia.seed(1)


def read_xml_annotation(root, image_id):
    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])

    return bndboxlist


def change_xml_annotation(root, image_id, new_target):
    new_xmin = new_target[0]
    new_ymin = new_target[1]
    new_xmax = new_target[2]
    new_ymax = new_target[3]

    in_file = open(os.path.join(root, str(image_id) + '.xml'))  # 這裏root分別由兩個意思
    tree = ET.parse(in_file)
    xmlroot = tree.getroot()
    object = xmlroot.find('object')
    bndbox = object.find('bndbox')
    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)
    tree.write(os.path.join(root, str("%06d" % str(id) + '.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)
    elem = tree.find('filename')
    elem.text = _id + '.jpg'
    xmlroot = tree.getroot()
    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)

        index = index + 1

    tree.write(os.path.join(saveroot, _id + '.xml'))


def mkdir(path):
    # 去除首位空格
    path = path.strip()
    # 去除尾部 \ 符號
    path = path.rstrip("\\")
    # 判斷路徑是否存在
    isExists = os.path.exists(path)
    # 判斷結果
    if not isExists:
        # 如果不存在則創建目錄
        os.makedirs(path)
        print(path + ' 創建成功')
        return True
    else:
        # 如果目錄存在則不創建,並提示目錄已存在
        print(path + ' 目錄已存在')
        return False


if __name__ == "__main__":
#    reload(sys)                         # 2
#    sys.setdefaultencoding('utf-8')     # 3

    IMG_DIR = "./JPEGImages"  # 需要增強的影像文件夾路徑
    XML_DIR = "./Annotations"  # 需要增強的XML文件夾路徑

    AUG_IMG_DIR = "./jpegtest"  # 存儲增強後的影像文件夾路徑
    AUG_XML_DIR = "./annotationstest"  # 存儲增強後的XML文件夾路徑

    try:
        shutil.rmtree(AUG_IMG_DIR)
    except FileNotFoundError as e:
        a = 1
    mkdir(AUG_IMG_DIR)

    try:
        shutil.rmtree(AUG_XML_DIR)
    except FileNotFoundError as e:
        a = 1
    mkdir(AUG_XML_DIR)

    AUGLOOP = 8  # 每張影像增強的數量

    boxes_img_aug_list = []
    new_bndbox = []
    new_bndbox_list = []

    # 影像增強
    seq = iaa.Sequential([
        iaa.Flipud(0.5),  # vertically flip 20% of all images
        iaa.Fliplr(0.5),  # 鏡像
        iaa.Multiply((1.2, 1.5)),  # change brightness, doesn't affect BBs
        iaa.GaussianBlur(sigma=(0, 3.0)),  # iaa.GaussianBlur(0.5),
        iaa.Affine(
            translate_px={"x": 15, "y": 15},
            scale=(0.8, 0.95)
            #rotate=(-5, 5)
        )  # translate by 40/60px on x/y axis, and scale to 50-70%, affects BBs
    ])

    for root, sub_folders, files in os.walk(XML_DIR):

        for name in files:

            bndbox = read_xml_annotation(XML_DIR, name)

            for epoch in range(AUGLOOP):
                seq_det = seq.to_deterministic()  # 保持座標和圖像同步改變,而不是隨機
                # 讀取圖片
                img = Image.open(os.path.join(IMG_DIR, name[:-4] + '.jpg'))
                # sp = img.size
                img = np.asarray(img)
                # bndbox 座標增強
                for i in range(len(bndbox)):
                    bbs = ia.BoundingBoxesOnImage([
                        ia.BoundingBox(x1=bndbox[i][0], y1=bndbox[i][1], x2=bndbox[i][2], y2=bndbox[i][3]),
                    ], shape=img.shape)

                    bbs_aug = seq_det.augment_bounding_boxes([bbs])[0]
                    boxes_img_aug_list.append(bbs_aug)

                    # new_bndbox_list:[[x1,y1,x2,y2],...[],[]]
                    n_x1 = int(max(1, min(img.shape[1], bbs_aug.bounding_boxes[0].x1)))
                    n_y1 = int(max(1, min(img.shape[0], bbs_aug.bounding_boxes[0].y1)))
                    n_x2 = int(max(1, min(img.shape[1], bbs_aug.bounding_boxes[0].x2)))
                    n_y2 = int(max(1, min(img.shape[0], bbs_aug.bounding_boxes[0].y2)))
                    if n_x1 == 1 and n_x1 == n_x2:
                        n_x2 += 1
                    if n_y1 == 1 and n_y2 == n_y1:
                        n_y2 += 1
                    if n_x1 >= n_x2 or n_y1 >= n_y2:
                        print('error', name)
                    new_bndbox_list.append([n_x1, n_y1, n_x2, n_y2])
                # 存儲變化後的圖片
                image_aug = seq_det.augment_images([img])[0]
                path = os.path.join(AUG_IMG_DIR, name[:-4] + '_' + str(epoch) + '.jpg')
                image_auged = bbs.draw_on_image(image_aug, thickness=0)
                Image.fromarray(image_auged).save(path)

                # 存儲變化後的XML
                change_xml_list_annotation(XML_DIR, name[:-4], new_bndbox_list, AUG_XML_DIR,
                                           name[:-4] + '_' + str(epoch))
                print(name[:-4] + '_' + str(epoch) + '.jpg')
                new_bndbox_list = []

--------------------------

在圖像增強序列中,把一下的一些方法用上,效果更強

seq = iaa.Sequential(
    [
        iaa.Fliplr(0.5), # 對50%的圖像進行鏡像翻轉
        iaa.Flipud(0.2), # 對20%的圖像做左右翻轉

        sometimes(iaa.Crop(percent=(0, 0.1))),
       #這裏沿襲我們上面提到的sometimes,對隨機的一部分圖像做crop操作
        # crop的幅度爲0到10%

        sometimes(iaa.Affine(                          #對一部分圖像做仿射變換
            scale={"x": (0.8, 1.2), "y": (0.8, 1.2)},#圖像縮放爲80%到120%之間
            translate_percent={"x": (-0.2, 0.2), "y": (-0.2, 0.2)}, #平移±20%之間
            rotate=(-45, 45),   #旋轉±45度之間
            shear=(-16, 16),    #剪切變換±16度,(矩形變平行四邊形)
            order=[0, 1],   #使用最鄰近差值或者雙線性差值
            cval=(0, 255),  #全白全黑填充
            mode=ia.ALL    #定義填充圖像外區域的方法
        )),
        
        # 使用下面的0個到5個之間的方法去增強圖像。注意SomeOf的用法
        iaa.SomeOf((0, 5),
            [
                # 將部分圖像進行超像素的表示。o(╥﹏╥)o用超像素增強作者還是第一次見,比較孤陋寡聞
                sometimes(
                    iaa.Superpixels(
                        p_replace=(0, 1.0),
                        n_segments=(20, 200)
                    )
                ),

                #用高斯模糊,均值模糊,中值模糊中的一種增強。注意OneOf的用法
                iaa.OneOf([
                    iaa.GaussianBlur((0, 3.0)),
                    iaa.AverageBlur(k=(2, 7)), # 核大小2~7之間,k=((5, 7), (1, 3))時,核高度5~7,寬度1~3
                    iaa.MedianBlur(k=(3, 11)),
                ]),

                #銳化處理
                iaa.Sharpen(alpha=(0, 1.0), lightness=(0.75, 1.5)),

                #浮雕效果
                iaa.Emboss(alpha=(0, 1.0), strength=(0, 2.0)),

                #邊緣檢測,將檢測到的賦值0或者255然後疊在原圖上
                sometimes(iaa.OneOf([
                    iaa.EdgeDetect(alpha=(0, 0.7)),
                    iaa.DirectedEdgeDetect(
                        alpha=(0, 0.7), direction=(0.0, 1.0)
                    ),
                ])),

                # 加入高斯噪聲
                iaa.AdditiveGaussianNoise(
                    loc=0, scale=(0.0, 0.05*255), per_channel=0.5
                ),

                # 將1%到10%的像素設置爲黑色
              # 或者將3%到15%的像素用原圖大小2%到5%的黑色方塊覆蓋
                iaa.OneOf([
                    iaa.Dropout((0.01, 0.1), per_channel=0.5),
                    iaa.CoarseDropout(
                        (0.03, 0.15), size_percent=(0.02, 0.05),
                        per_channel=0.2
                    ),
                ]),

                #5%的概率反轉像素的強度,即原來的強度爲v那麼現在的就是255-v
                iaa.Invert(0.05, per_channel=True),

                # 每個像素隨機加減-10到10之間的數
                iaa.Add((-10, 10), per_channel=0.5),

                # 像素乘上0.5或者1.5之間的數字.
                iaa.Multiply((0.5, 1.5), per_channel=0.5),

                # 將整個圖像的對比度變爲原來的一半或者二倍
                iaa.ContrastNormalization((0.5, 2.0), per_channel=0.5),

                # 將RGB變成灰度圖然後乘alpha加在原圖上
                iaa.Grayscale(alpha=(0.0, 1.0)),

                #把像素移動到周圍的地方。這個方法在mnist數據集增強中有見到
                sometimes(
                    iaa.ElasticTransformation(alpha=(0.5, 3.5), sigma=0.25)
                ),

                # 扭曲圖像的局部區域
                sometimes(iaa.PiecewiseAffine(scale=(0.01, 0.05)))
            ],
            
            random_order=True # 隨機的順序把這些操作用在圖像上
        )
    ],
    random_order=True # 隨機的順序把這些操作用在圖像上
)
=====================挑選整理後可以看如下===================

#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
import sys
import os
import shutil
import numpy as np
import imgaug as ia
import xml.etree.ElementTree as ET

from PIL import Image
from imgaug import augmenters as iaa
sometimes = lambda aug: iaa.Sometimes(0.1, aug)

ia.seed(1)


def read_xml_annotation(root, image_id):
    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])

    return bndboxlist


def change_xml_annotation(root, image_id, new_target):
    new_xmin = new_target[0]
    new_ymin = new_target[1]
    new_xmax = new_target[2]
    new_ymax = new_target[3]

    in_file = open(os.path.join(root, str(image_id) + '.xml'))  # 這裏root分別由兩個意思
    tree = ET.parse(in_file)
    xmlroot = tree.getroot()
    object = xmlroot.find('object')
    bndbox = object.find('bndbox')
    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)
    tree.write(os.path.join(root, str("%06d" % str(id) + '.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)
    elem = tree.find('filename')
    elem.text = _id + '.jpg'
    xmlroot = tree.getroot()
    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)

        index = index + 1

    tree.write(os.path.join(saveroot, _id + '.xml'))


def mkdir(path):
    # 去除首位空格
    path = path.strip()
    # 去除尾部 \ 符號
    path = path.rstrip("\\")
    # 判斷路徑是否存在
    isExists = os.path.exists(path)
    # 判斷結果
    if not isExists:
        # 如果不存在則創建目錄
        os.makedirs(path)
        print(path + ' 創建成功')
        return True
    else:
        # 如果目錄存在則不創建,並提示目錄已存在
        print(path + ' 目錄已存在')
        return False


if __name__ == "__main__":
#    reload(sys)                         # 2
#    sys.setdefaultencoding('utf-8')     # 3

    IMG_DIR = "./JPEGImages"  # 需要增強的影像文件夾路徑
    XML_DIR = "./Annotations"  # 需要增強的XML文件夾路徑

    AUG_IMG_DIR = "./jpegtest"  # 存儲增強後的影像文件夾路徑
    AUG_XML_DIR = "./annotationstest"  # 存儲增強後的XML文件夾路徑

    try:
        shutil.rmtree(AUG_IMG_DIR)
    except FileNotFoundError as e:
        a = 1
    mkdir(AUG_IMG_DIR)

    try:
        shutil.rmtree(AUG_XML_DIR)
    except FileNotFoundError as e:
        a = 1
    mkdir(AUG_XML_DIR)

    AUGLOOP = 8  # 每張影像增強的數量

    boxes_img_aug_list = []
    new_bndbox = []
    new_bndbox_list = []

    # 影像增強
    seq = iaa.Sequential([
        iaa.Flipud(0.5),  # vertically flip 20% of all images
        iaa.Fliplr(0.5),  # 鏡像
        sometimes(iaa.Multiply((1.2, 1.5))),  # change brightness, doesn't affect BBs
        sometimes(iaa.Sharpen(alpha=(0, 1.0), lightness=(0.75, 1.5))),
        sometimes(iaa.GaussianBlur(sigma=(0, 3.0))),  # iaa.GaussianBlur(0.5),
        sometimes(iaa.ContrastNormalization((0.5, 2.0), per_channel=0.5)),
        iaa.Scale(1.50,
          interpolation='cubic',
          name=None,
          deterministic=False,
          random_state=None),
        #iaa.Affine(
        #    translate_px={"x": 15, "y": 15},
        #    scale=(1.5, 1.5)
        #    #rotate=(-5, 5)
        #)  # translate by 40/60px on x/y axis, and scale to 50-70%, affects BBs
    ])


    for root, sub_folders, files in os.walk(XML_DIR):

        for name in files:

            bndbox = read_xml_annotation(XML_DIR, name)

            for epoch in range(AUGLOOP):
                seq_det = seq.to_deterministic()  # 保持座標和圖像同步改變,而不是隨機
                # 讀取圖片
                img = Image.open(os.path.join(IMG_DIR, name[:-4] + '.jpg'))
                # sp = img.size
                img = np.asarray(img)
                # bndbox 座標增強
                for i in range(len(bndbox)):
                    bbs = ia.BoundingBoxesOnImage([
                        ia.BoundingBox(x1=bndbox[i][0], y1=bndbox[i][1], x2=bndbox[i][2], y2=bndbox[i][3]),
                    ], shape=img.shape)

                    bbs_aug = seq_det.augment_bounding_boxes([bbs])[0]
                    boxes_img_aug_list.append(bbs_aug)

                    # new_bndbox_list:[[x1,y1,x2,y2],...[],[]]
                    n_x1 = int(max(1, min(img.shape[1], bbs_aug.bounding_boxes[0].x1)))
                    n_y1 = int(max(1, min(img.shape[0], bbs_aug.bounding_boxes[0].y1)))
                    n_x2 = int(max(1, min(img.shape[1], bbs_aug.bounding_boxes[0].x2)))
                    n_y2 = int(max(1, min(img.shape[0], bbs_aug.bounding_boxes[0].y2)))
                    if n_x1 == 1 and n_x1 == n_x2:
                        n_x2 += 1
                    if n_y1 == 1 and n_y2 == n_y1:
                        n_y2 += 1
                    if n_x1 >= n_x2 or n_y1 >= n_y2:
                        print('error', name)
                    new_bndbox_list.append([n_x1, n_y1, n_x2, n_y2])
                # 存儲變化後的圖片
                image_aug = seq_det.augment_images([img])[0]
                path = os.path.join(AUG_IMG_DIR, name[:-4] + '_' + str(epoch) + '.jpg')
                image_auged = bbs.draw_on_image(image_aug, thickness=0)
                Image.fromarray(image_auged).save(path)

                # 存儲變化後的XML
                change_xml_list_annotation(XML_DIR, name[:-4], new_bndbox_list, AUG_XML_DIR,
                                           name[:-4] + '_' + str(epoch))
                print(name[:-4] + '_' + str(epoch) + '.jpg')
                new_bndbox_list = []

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章