iT邦幫忙

2023 iThome 鐵人賽

DAY 27
0
AI & Data

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

[DAY 27] 訓練資料前處理(補充)

  • 分享至 

  • xImage
  •  

小前言:

這幾天我整理了YOLOv1到YOLOv8的過程,期間我注意到使用的兩個資料集都按照YOLO的標註方式和資料集放置方式。因此只需將資料集複製到YOLO程式碼的資料夾中就可以進行訓練。然而,當蒐集到的標註格式不符合這種標準時,應該如何處理呢?今天我將分享一些有關標註檔案的前處理方法。

XML檔案轉TXT格式

這邊剛好Aircraft_Fuselage_DET2023資料集中,有準備一個aircraft_fuselage_voc資料夾,裡面存放的正是XML格式的標註檔案,可用來進行測試,以下準備兩種轉換方式:

  • 利用labelimg進行轉換格式:

    1. 開啟labelimg,點選Open Dir按鈕選擇資料集影像的位置,再點擊Change Save Dir,選擇Voc資料夾中的xml格式標註檔案資料夾位置。

      https://ithelp.ithome.com.tw/upload/images/20231012/20120310ZSGS102AYs.png

    2. 點擊畫面左側Change Save Format按鈕,點擊直到出現YOLO圖示為止,並按Save按鈕,則會生成YOLO的txt格式標註檔案。

      https://ithelp.ithome.com.tw/upload/images/20231012/20120310gDro5mAtoP.png
      https://ithelp.ithome.com.tw/upload/images/20231012/20120310DNOwiEGJSH.png

    • 此方法不用額外編寫格式轉換程式碼,但是缺點是需要一張一張影像進行轉換,較耗時。
  • Python程式批次轉換:

    • 這邊分享個人寫的python批次轉換程式:
    1. 創建一個名稱為TxtAnnotations的資料夾,要用來存放轉換好的txt格式標註檔案。
    2. 執行程式以前要先將classes.txt移出檔案夾外。
      https://ithelp.ithome.com.tw/upload/images/20231012/20120310VFU61eaiUn.png
    3. 程式碼內容(個人自己寫的):
      #本程式碼將label從xml格式轉成txt格式
      import copy
      from lxml.etree import Element,SubElement,tostring,ElementTree
      import xml.etree.ElementTree as ET
      import pickle
      import os
      from os import listdir,getcwd
      from os.path import join
      #辨識的類別
      classes=['scratch','paint_peel','rust','rivet_damage']
      def convert(size,box):
          dw=1./size[0]
          dh=1./size[1]
          x=(box[0]+box[1])/2.0
          y=(box[2]+box[3])/2.0
          w=box[1]-box[0]
          h=box[3]-box[2]
          x=x*dw
          w=w*dw
          y=y*dh
          h=h*dh
          return (x,y,w,h)
      
      def convert_annotation(image_id):
          #轉換前的標註檔案位置
          in_file=open('./Annotations/%s.xml'%(image_id),encoding='UTF-8')
          #轉換後的標註檔案位置
          out_file=open('./TxtAnnotations/%s.txt'%(image_id),'w')
          tree=ET.parse(in_file)
          root=tree.getroot()
          size=root.find('size')
          w=int(size.find('width').text)
          h=int(size.find('height').text)
          for obj in root.iter('object'):
              cls=obj.find('name').text
              if cls not in classes:
                  continue
              cls_id=classes.index(cls)
              xmlbox=obj.find('bndbox')
              b=(float(xmlbox.find('xmin').text),float(xmlbox.find('xmax').text),float(xmlbox.find('ymin').text),float(xmlbox.find('ymax').text))
              bb=convert((w,h),b)
              out_file.write(str(cls_id)+" "+" ".join([str(a) for a in bb])+'\n')
      #轉換前的標註檔案位置,這邊是要將要轉換的檔案名稱列出來
      xml_path=os.path.join('./Annotations/')
      img_xmls=os.listdir(xml_path)
      for img_xml in img_xmls:
          label_name=img_xml.split('.')[0]
          #print(label_name)
          convert_annotation(label_name)
      

轉換後的結果:

https://ithelp.ithome.com.tw/upload/images/20231012/20120310Bu3SNixb9r.png

比較轉換後的001.txt以及aircraft_fuselage_yolo資料夾的001.txt檔案內容:

https://ithelp.ithome.com.tw/upload/images/20231012/20120310H0K9p6pKgH.png

  • 會發現轉換後的001.txt檔案比aircraft_fuselage_yolo資料夾的標註檔案少了很多小數點位,可以利用labelimg程式開啟標註檔案來看,不會有任何影響,請各位放心。

今天跟各位分享的格式轉換格式,是因為個人過去在實作的過程中時常會遇到格式不符YOLO所需的狀況,因此自己編寫一個格式轉換的程式碼,也跟大家分享。

本來規劃會實作兩個資料集,但是因為兩個資料集的處理方式一樣,因此另外一個資料集就不再重複說明,最後會以Aircraft_Fuselage_DET2023的訓練結果進行展示。


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

1 則留言

0
hsien220618
iT邦新手 5 級 ‧ 2024-02-22 21:53:33

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

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

可以喔,yolo所需的標註檔為txt格式,有時網路上公開資料集會取得xml的標註格式,便可以利用此code將xml格式轉成txt格式,進而輸入至yolo model進行訓練。

我要留言

立即登入留言