iT邦幫忙

2023 iThome 鐵人賽

DAY 28
0
AI & Data

YOLO系列網路技術採用以及實作系列 第 28

[DAY 28] 訓練資料擴充(補充)

  • 分享至 

  • xImage
  •  

小前言:

  昨天我分享了有關標註檔案格式的批次轉換方法。今天要分享的是如果您的訓練影像數量不足,想要擴充資料,該怎麼辦?當然,一種方法是多蒐集更多影像,但這通常需要額外的時間和努力,特別是在標註這些影像的過程中。

 因此,我考慮了如何能從現有影像生成更多的訓練影像,尤其在某些領域的影像蒐集相當困難時。一個方法是參考分類任務中常見的技巧,例如對影像進行平移、旋轉、縮放等變換,用以生成更多的訓練樣本。

 雖然上述的方法能夠生成更多的影像,但仍需要耗費時間在手動標註影像上。因此今天要分享給各位的是,能藉由現有圖片以及標註檔,自動生成影像以及標註檔出來的方法。

步驟(以aircraft_fuselage_voc資料夾的影像及標註檔為例):

  • 這邊會創立一個名稱為"example"的資料夾,並分別存放5張影像及對應標註檔,作為範例,模擬訓練影像不足的狀況。
  • 並舉一張影像擴充十張影像的例子:
    https://ithelp.ithome.com.tw/upload/images/20231013/20120310X3Gux5BTXL.png
  1. 創建images以及labels資料夾,並將原圖及其標註檔分開放在images以及labels資料夾中。
    https://ithelp.ithome.com.tw/upload/images/20231013/20120310SvdFn0FIOC.png
  2. 創建aug_images以及aug_labels資料夾,用來存放擴充出來的影像及標註檔。
    https://ithelp.ithome.com.tw/upload/images/20231013/20120310ZzfYeNaUA3.png
  3. 撰寫python程式:名稱:aug_with_label.py:
  • 說明都寫在程式註解當中。
    #本程式碼用以將圖片連同其標註檔一起augmentation
    #Library import
    from bs4 import BeautifulSoup
    import imgaug as ia
    import imageio
    from imgaug.augmentables.bbs import BoundingBox,BoundingBoxesOnImage
    from imgaug import augmenters as iaa
    from lxml import etree
    from tqdm import trange
    import glob
    
    #Create functions
    class CreateAnnotations:
        def __init__(self,foldername,filename):
            self.root=etree.Element("annotation")
            child1=etree.SubElement(self.root,"folder")
            child1.text=foldername
    
            child2=etree.SubElement(self.root,"filename")
            child2.text=filename
    
            child3=etree.SubElement(self.root,"path")
            child3.text=filename
    
            child4=etree.SubElement(self.root,"source")
    
            child5=etree.SubElement(child4,"database")
            child5.text="Unknown"
    
        def set_size(self,imgshape):
            (height,witdh,channel)=imgshape
            size=etree.SubElement(self.root,"size")
            widthn =etree.SubElement(size,"width")
            widthn.text = str(witdh)
            heightn = etree.SubElement(size, "height")
            heightn.text = str(height)
            channeln = etree.SubElement(size, "depth")
            channeln.text = str(channel)
    
        def savefile(self,filename):
            tree=etree.ElementTree(self.root)
            tree.write(filename,pretty_print=True,xml_declaration=False,encoding="utf-8")
    
        def add_pic_attr(self, label, xmin, ymin, xmax, ymax):
            object = etree.SubElement(self.root, "object")
            namen = etree.SubElement(object, "name")
            namen.text = label
            bndbox = etree.SubElement(object, "bndbox")
            xminn = etree.SubElement(bndbox, "xmin")
            xminn.text = str(xmin)
            yminn = etree.SubElement(bndbox, "ymin")
            yminn.text = str(ymin)
            xmaxn = etree.SubElement(bndbox, "xmax")
            xmaxn.text = str(xmax)
            ymaxn = etree.SubElement(bndbox, "ymax")
            ymaxn.text = str(ymax)
    
    #資料擴增的方法,可以自行添加新的擴增方式   
    seq=iaa.Sequential([
        iaa.Affine(rotate=(-60, 60)),
        iaa.Fliplr(0.5),
        #iaa.GaussianBlur(sigma=(0,3.0)),
        #iaa.AdditiveGaussianNoise(scale=(10, 60)),
        iaa.Crop(percent=(0, 0.2)),
        iaa.Add(50, per_channel=True),
        iaa.Sharpen(alpha=0.5),
        iaa.Affine(shear=(-16, 16))
    ])
    
    #開始擴增
    #原檔影像位置
    file_dir='./example/images/'
    img_list=glob.glob(file_dir+'*.jpg')
    n=len(img_list)
    print('原圖共有'+str(n)+'張影像')
    #for i in trange(n):
    for i in img_list:
        i=i.replace("\\", "/")
        i=i[17:-4]
        print(i)
        soup =BeautifulSoup(open('./example/labels/'+str(i)+".xml",encoding="utf-8"),"lxml")#原標註檔
        image=imageio.imread('./example/images/'+str(i)+".jpg")#原影像,須注意副檔名
        bbsOnImg=[]
        for objects in soup.find_all(name="object"):
            object_name=str(objects.find(name="name").string)
            xmin=int(objects.xmin.string)
            ymin=int(objects.ymin.string)
            xmax=int(objects.xmax.string)
            ymax=int(objects.ymax.string)
            bbsOnImg.append(BoundingBox(x1=xmin,x2=xmax,y1=ymin,y2=ymax,label=object_name))
        bbs=BoundingBoxesOnImage(bbsOnImg,shape=image.shape)
        #這邊舉例一張影像擴充十張
        for j in range(10):
            j=j+1
            image_aug,bbs_aug=seq(image=image,bounding_boxes=bbs)
            bbs_aug_clip=bbs_aug.clip_out_of_image()
            #擴充出來的標註檔資料夾存放位置
            foldername = "./example/aug_labels/"
            filename = str(i)+"_"+str(j)+".jpg"
            anno = CreateAnnotations(foldername, filename)
            anno.set_size(image_aug.shape)
            for index,bb in enumerate(bbs_aug_clip):
                xmin = int(bb.x1)
                ymin = int(bb.y1)
                xmax = int(bb.x2)
                ymax = int(bb.y2)
                label = str(bb. label)
                anno.add_pic_attr(label, xmin, ymin, xmax, ymax)
            anno.savefile("{}{}.xml".format(foldername,filename.split(".")[0]))
            #擴充出來的影像資料夾存放位置
            aug_img_path='./example/aug_images/'
            imageio.imsave(aug_img_path+filename, image_aug)
    
  1. 安裝所需套件:
    pip install beautifulsoup4 imgaug
    
  2. 執行程式:
    python aug_with_label.py
    

執行完成後

  • 擴增的影像
    https://ithelp.ithome.com.tw/upload/images/20231013/201203101JDfrIt4kP.png
  • 擴增的標註檔
    https://ithelp.ithome.com.tw/upload/images/20231013/201203109xHQiQwLED.png

 自行蒐集新影像仍然是首選。儘管自動生成影像及標註檔的方法可以幫助擴充訓練資料,但過多由原始影像生成的擴充影像可能會導致模型出現過度擬合的問題。因此最好的做法是在自行蒐集的新影像的基礎上進行訓練,以確保模型在真實場景中的性能。

 然而,少量由原始影像生成的擴充影像仍可以有助於提高模型的魯棒性,這對於模型的泛化能力是有益的。因此在選擇擴增數量時,可以自行評估和嘗試調整,以達到模型最佳效果。


上一篇
[DAY 27] 訓練資料前處理(補充)
下一篇
[DAY 29] 模型訓練結果
系列文
YOLO系列網路技術採用以及實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
hsien220618
iT邦新手 5 級 ‧ 2024-02-22 21:54:17

請問上述的語法能夠用在YOLO格式嗎

Xian iT邦新手 5 級 ‧ 2024-03-05 16:23:04 檢舉

可以喔,需要額外注意的是:
本資料擴增方法: 原圖標註檔為xml格式,經由本文code後會生成擴增後的圖片以及其標註檔,但因為生成的同樣為xml格式,故需要前一天文章提供的xml轉txt格式的code,如此一來就可以將轉好的圖片以及txt格式標註檔輸入至模型進行訓練了。

我要留言

立即登入留言