imgaug圖像增強記錄

 

話不多說,先奉上imgaug官網:https://imgaug.readthedocs.io/en/latest/index.html

官網的目錄,從中可以知道它能夠做到的增強範圍:

一.imgaug安裝

安裝依賴庫

pip install six numpy scipy matplotlib scikit-image opencv-python imageio

然後,直接在終端進行安裝,用anaconda的可以在Prompt進行安裝:

pip install imgaug

這裏如果不幸,會在一切看似順利的安裝過程中,突然出現一連串的紅色錯誤,如下

G:\python\Pyhton36\Scripts>pip install imgaug
Collecting imgaug
  Downloading https://files.pythonhosted.org/packages/af/fc/c56a7da8c23122b7c5325b941850013880a7a93c21dc95e2b1ecd4750108/imgaug-0.2.7-py3-none-any.whl (644kB)
    100% |████████████████████████████████| 645kB 73kB/s
Requirement already satisfied: scikit-image>=0.11.0 in g:\python\pyhton36\lib\site-packages (from imgaug) (0.14.1)
Collecting imageio (from imgaug)
  Downloading https://files.pythonhosted.org/packages/28/b4/cbb592964dfd71a9de6a5b08f882fd334fb99ae09ddc82081dbb2f718c81/imageio-2.4.1.tar.gz (3.3MB)
    100% |████████████████████████████████| 3.3MB 438kB/s
Collecting Shapely (from imgaug)
  Downloading https://files.pythonhosted.org/packages/a2/fb/7a7af9ef7a35d16fa23b127abee272cfc483ca89029b73e92e93cdf36e6b/Shapely-1.6.4.post2.tar.gz (225kB)
    100% |████████████████████████████████| 235kB 181kB/s
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\34905\AppData\Local\Temp\pip-install-43zide7u\Shapely\setup.py", line 80, in <module>
        from shapely._buildcfg import geos_version_string, geos_version, \
      File "C:\Users\34905\AppData\Local\Temp\pip-install-43zide7u\Shapely\shapely\_buildcfg.py", line 200, in <module>
        lgeos = CDLL("geos_c.dll")
      File "g:\python\pyhton36\lib\ctypes\__init__.py", line 348, in __init__
        self._handle = _dlopen(self._name, mode)
    OSError: [WinError 126] 找不到指定的模塊。
 
    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in C:\Users\34905\AppData\Local\Temp\pip-install-43zide7u\Shapely\

查閱了網上前輩的資料,需要先安裝shapely

通過這個網址 https://www.lfd.uci.edu/~gohlke/pythonlibs/#shapely (這是一個非常好的擴展包非正式網址,裏面有許多的工具可供使用) 中找到適合自己python版本的shapely下載到指定路徑

我是windows,64位操作系統,python3.5,我選擇下面這個

然後通過如下命令進行安裝:

G:\python\Pyhton36\Scripts>python -m pip install Shapely‑1.6.4.post2‑cp35‑cp35m‑win_amd64.whl

最後再重複之前安裝imgaug的命令:

pip install imgaug

搞定,收工,安裝完成

參考:https://blog.csdn.net/qq_16065939/article/details/85080630


二.github原代碼遇見問題,批量的BoundingBox帶XML文件的增強

github原作者地址:https://github.com/xinyu-ch/Data-Augment

存在一丟丟的錯誤,這裏進行了修改,往下看(第三節),已調試,可用,這裏講下遇見的一些小問題

1.如果不幸的遇見了下面的問題,這是一個常見問題,解決方式較爲統一:https://blog.csdn.net/qq_38163755/article/details/84494796

解決方式如下:

第一種解決方法,增加encoding=‘UTF-8’

FILE_OBJECT= open( 'train.txt','r', encoding='UTF-8' )

第二種方法,二進制讀取

FILE_OBJECT= open( 'train.txt', 'rb' )

之後,就可以看第三節,是對上文作者github部分做了修改後的,調試可用


三.調試後批量的BoundingBox帶XML文件的增強(可直接用)

  1. 創建要保存增強後的圖像和xml文件的文件夾
  2. 提前設定好採用什麼方式進行圖像的增強,是旋轉,還是加噪聲,是提升亮度,還是平移補充
  3. 然後讀進來一張圖片,和該圖像對應的xml內標籤的座標信息
  4. 對圖像和矩形框進行變換
  5. 最後保存增強後的圖片和xml文件
import xml.etree.ElementTree as ET
import pickle
import os
from os import getcwd
import numpy as np
from PIL import Image
import shutil
import matplotlib.pyplot as plt

import imgaug as ia
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), encoding='UTF-8')
    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)
        # print(xmin,ymin,xmax,ymax)
        bndboxlist.append([xmin, ymin, xmax, ymax])
        # print(bndboxlist)

    # ndbox = root.find('object').find('bndbox')
    return bndboxlist


# (506.0000, 330.0000, 528.0000, 348.0000) -> (520.4747, 381.5080, 540.5596, 398.6603)
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'), encoding='UTF-8' )  # 這裏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'), encoding='UTF-8' )  # 這裏root分別由兩個意思
    tree = ET.parse(in_file)
    elem = tree.find('filename')
    elem.text = (str("%06d" % int(id)) + '.png')
    xmlroot = tree.getroot()
    index = 0

    for object in xmlroot.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)

        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 += 1

        print("index=",index)


    tree.write(os.path.join(saveroot, str("%06d" % int(id)) + '.xml'))


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


if __name__ == "__main__":

    IMG_DIR = "F:\\image\\raw_xml"
    XML_DIR = "F:\\image\\xml"

    AUG_XML_DIR = "./Annotations"  # 存儲增強後的XML文件夾路徑
    try:
        shutil.rmtree(AUG_XML_DIR)
    except FileNotFoundError as e:
        a = 1
    mkdir(AUG_XML_DIR)

    AUG_IMG_DIR = "./JPEGImages"  # 存儲增強後的影像文件夾路徑
    try:
        shutil.rmtree(AUG_IMG_DIR)
    except FileNotFoundError as e:
        a = 1
    mkdir(AUG_IMG_DIR)

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

    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.Sharpen(alpha=(0, 1.0), lightness=(0.75, 1.5)),
        iaa.Crop(px=(0, 16)),
        iaa.Add((-10, 10), per_channel=0.5),
        iaa.Multiply((1.2, 1.5)),  # change brightness, doesn't affect BBs
        iaa.Affine(
            translate_px={"x": 15, "y": 15},
            scale=(0.8, 0.95)
            #rotate=(-30, 30)
        )  # 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)
            shutil.copy(os.path.join(XML_DIR, name), AUG_XML_DIR)
            shutil.copy(os.path.join(IMG_DIR, name[:-4] + '.png'), AUG_IMG_DIR)
            print(os.path.join(IMG_DIR, name[:-4] + '.png'))

            for epoch in range(AUGLOOP):
                seq_det = seq.to_deterministic()  # 保持座標和圖像同步改變,而不是隨機
                # 讀取圖片
                img = Image.open(os.path.join(IMG_DIR, name[:-4] + '.png'))
                # 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,str("%06d" % (len(files) + int(name[:-4]) + epoch * 250)) + '.png')

                    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,len(files) + int(name[:-4]) + epoch * 250)
                print(str("%06d" % (len(files) + int(name[:-4]) + epoch * 250)) + '.png')
                new_bndbox_list = []

 代碼中寫死了對數據的讀取方式:elem.text = (str("%06d" % int(id)) + '.png')

如果沒必要,就按下面這種形式進行命名

增強後,用labelImg查看的結果如下:

詳細部分參考這裏:https://blog.csdn.net/coooo0l/article/details/84492916#commentsedit

 

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