天天看點

YOLO2 (2) 測試自己的資料

Windos10 linux同樣過程

現有問題:

本文過程在linux下類似,可以正常通過。windons下,運作python腳本出現問題,無法正常輸出0001.txt(标定檔案),是以隻能使用linux生成标定檔案和路徑檔案txt,然後複制到windons下使用。

待解決問題:

重寫訓練部分代碼,使得windons程式直接讀取原始圖像和标記檔案,其餘檔案自動生成,然後開始訓練、

1 準備資料

輸入原始資料--yolo2訓練----輸出權重檔案

這裡用100張做樣例:

原始資料

  1. 原始圖像0001.jpg   - 0100.jpg                                                                       10張
  2. 描述圖像中目标資訊的0001.txt  - 0100.txt                                                    10個
  3. 存儲每個訓練圖像絕對完整路徑的train.txt                                                   1個
  4. 存儲每個測試圖像絕對完整路徑   var.txt                                                      1個

問題1 無法直接得到 原始資料 2.描述圖像中目标資訊的txt,采間接的辦法

  1. 使用标圖軟體得到描述圖像資訊的0001.xml                                  每個圖象對應一張
  2. 0001.xml 通過python腳本轉換 0001.txt

問題2 無法直接得到3,4完整路徑,間接先擷取圖檔名,然後加上路徑名

  1. 擷取 訓練圖像的名字到一個 train.txt
  2. 将這個txt轉換成完整路徑
  3. 擷取 測試圖像的名字到一個var.txt

1.1 原始圖像

首先準備好自己的資料集,最好固定格式,此處為例,采用jpg格式的圖像,在名字上最好使用像VOC一樣類似000001.jpg、000002.jpg這樣

YOLO2 (2) 測試自己的資料

1.2 xml檔案  描述圖像中要識别的目标資訊

每一個xml對應一張圖像,并且每個xml中存放的是标記的各個目标的位置和類别資訊,命名通常與對應的原始圖像一樣

YOLO2 (2) 測試自己的資料

因為做的是目标檢測,是以接下來需要标記原始圖像中的目标區域。相關方法和工具有很多,這裡需用​​labelImg​​,相關用法也有說明,基本就是框住目标區域然後輕按兩下類别,标記完整張圖像後點選儲存即可。操作界面如下:

YOLO2 (2) 測試自己的資料

通常save之後會将标記的資訊儲存在xml檔案,其名字通常與對應的原始圖像一樣。

其中每個xml檔案是這樣的畫風

<?xml version="1.0" ?>  
<annotation>  
    <folder>JPEGImages</folder>  
    <filename>00000</filename>  
    <path>/home/kinglch/VOC2007/JPEGImages/00000.jpg</path>  
    <source>  
        <database>Unknown</database>  
    </source>  
    <size>  
        <width>704</width>  
        <height>576</height>  
        <depth>3</depth>  
    </size>  
    <segmented>0</segmented>  
    <object>  
        <name>person</name>  
        <pose>Unspecified</pose>  
        <truncated>0</truncated>  
        <difficult>0</difficult>  
        <bndbox>  
            <xmin>73</xmin>  
            <ymin>139</ymin>  
            <xmax>142</xmax>  
            <ymax>247</ymax>  
        </bndbox>  
    </object>  
    <object>  
        <name>person</name>  
        <pose>Unspecified</pose>  
        <truncated>0</truncated>  
        <difficult>0</difficult>  
        <bndbox>  
            <xmin>180</xmin>  
            <ymin>65</ymin>  
            <xmax>209</xmax>  
            <ymax>151</ymax>  
        </bndbox>  
    </object>  
      

  

1.3 xml-txt檔案  描述圖像中要識别的目标資訊

生成的xml檔案不是yolo2讀取的格式,是以需要轉換為和圖像名稱一樣的txt。

轉換後的txt格式:​

​<object-class> <x> <y> <width> <height>​

  • 0 15 4 25 25           目标為第一類  起始位置 (15, 4)   長 25 寬 25
  • 0 11 36 25 25         目标為第一類  起始位置 (11, 36)   長 25 寬 25
  • YOLO2 (2) 測試自己的資料

該部分由1.4中的creat_list.py腳本自動完成。

1.4擷取圖像的路徑,以便YOLO程式能夠找到圖檔

圖像分為兩類,一類充當測試資料 剩下的充當訓練資料。是以需要分别建立txt儲存他們的路徑位址。這裡使用python腳本來自動生成路徑。

生成過程分兩步,首先擷取圖像的名字 

1.4.1 圖檔名 train.txt   隻存每個訓練的圖象的名字  

1.4.2 圖檔名 val.txt     隻存每個驗證的圖像的名字

在生成infrared_train.txt與infrared_val.txt這兩個檔案時,會分别用到這兩個文檔。文檔裡包含了用于訓練/驗證的圖檔的名稱,裡面的資料組成很簡單,每行都是一個圖檔的名稱,并不包含圖檔的字尾(.jpg),比如文檔中: 

  • 第一行是: 0000 
  • 第二行是: 0001 

該部分工作由生成腳本:creat_list.py:完成

自己需要改三個路徑:

  • 圖檔原始位址
  • 生成用于儲存訓練集圖像名字train.txt的路徑
  • 生成用于儲存測試集圖像名字val.txt的路徑
#這個小腳本是用來打開圖檔檔案所在檔案夾,把前900個用于訓練的圖檔的名稱儲存在tain.txt,後103個用于驗證的圖檔儲存在val.txt
import os
from os import listdir, getcwd
from os.path import join
if __name__ == '__main__':
    source_folder='/home/yolo_v2_tinydarknet/darknet/infrared/image/dout/'#位址是所有圖檔的儲存地點
    dest='/home/yolo_v2_tinydarknet/darknet/infrared/train.txt' #儲存train.txt的位址
    dest2='/home/yolo_v2_tinydarknet/darknet/infrared/val.txt'  #儲存val.txt的位址
    file_list=os.listdir(source_folder)       #指派圖檔所在檔案夾的檔案清單
    train_file=open(dest,'a')                 #打開檔案
    val_file=open(dest2,'a')                  #打開檔案
    for file_obj in file_list:                #通路檔案清單中的每一個檔案
        file_path=os.path.join(source_folder,file_obj) 
        #file_path儲存每一個檔案的完整路徑
        file_name,file_extend=os.path.splitext(file_obj)
        #file_name 儲存檔案的名字,file_extend儲存檔案擴充名
        file_num=int(file_name) 
        #把每一個檔案命str轉換為 數字 int型 每一檔案名字都是由四位數字組成的  如 0201 代表 201     高位補零  
        if(file_num<900):                     #保留900個檔案用于訓練
            #print file_num
            train_file.write(file_name+'\n')  #用于訓練前900個的圖檔路徑儲存在train.txt裡面,結尾加回車換行
        else :
            val_file.write(file_name+'\n')    #其餘的檔案儲存在val.txt裡面
    train_file.close()#關閉檔案
    val_file.close()
      

 然後通過得到的名字生成完整路徑 

3.3  infrared_train.txt    存放訓練的圖像的位址

3.4 infrared_val.txt      存放測試的圖像的位址

文檔裡包含了所有用于訓練/驗證的圖檔的完整路徑,每一行都是一個圖檔的完整路徑,例如 

第一行是: /home/yolo_v2_tinydarknet/darknet/infrared/image/dout/0000.jpg 

第二行是 :/home/yolo_v2_tinydarknet/darknet/infrared/image/dout/0001.jpg 

該部分由以下腳本完成

需要分兩次執行腳本。兩次不一樣的地方标紅

第一次 生成訓練集的完整路徑

  • 1修改圖像生成的xml檔案所在地
  •  in_file = open('/home/yolo_v2_tinydarknet/darknet/infrared/labels/dout_original/%s.xml'%(image_id))#與圖檔對應的xml檔案所在的位址
  • 2修改轉化後生成的txt的儲存路徑
  •  out_file = open('/home/yolo_v2_tinydarknet/darknet/infrared/labels/%s.txt'%(image_id),'w') #與此xml對應的轉換後的txt,這個txt的儲存完整路徑
  • 3打開訓練集的兩行代碼注釋,并将測試集的兩行代碼注釋加上
  • image_ids = open('/home/yolo_v2_tinydarknet/darknet/infrared/train.txt').read().strip().split()  #如果是訓練集資料打開這一行,注釋下一行
  • list_file = open('infrared_train.txt', 'w')     #把結果寫入到indrared_train.txt檔案中,如果是訓練集資料打開這一行,注釋下一行
  • 4修改圖檔路徑
  •  list_file.write('/home/yolo_v2_tinydarknet/darknet/infrared/image/dout/%s.jpg\n'%(image_id))  #把每一用于訓練或驗證的圖檔的完整的路徑寫入到infrared_train.txt中  這個檔案會被voc.data yolo.c調用

第二次 生成測試集的完整路徑

  • 3打開測試集的兩行代碼注釋,并将訓練集的兩行代碼注釋加上
  • image_ids = open('/home/yolo_v2_tinydarknet/darknet/infrared/train.txt').read().strip().split()  #如果是測試資料打開這一行,注釋下一行
  • list_file = open('infrared_train.txt', 'w')     #把結果寫入到indrared_train.txt檔案中,如果測試集資料打開這一行,注釋下一行
  •  list_file.write('/home/yolo_v2_tinydarknet/darknet/infrared/image/dout/%s.jpg\n'%(image_id))  #把每一用于訓練或驗證的圖檔的完整的路徑寫入到infrared_train.txt中  這個檔案會被voc.data yolo.c調用 
#此腳本修改自voc_label.py。修改的原因是:我的訓練集跟voc有些不同。
#由于資料集中包括用于訓練的資料和用于驗證的資料,是以此腳本可能需要分别對這兩種資料各運作一次,對兩種資料隻需要簡單地注釋掉相應語句即可
#這個腳本需要train.txt ,這個檔案是我用腳本creat_list.py生成的,儲存了用于訓練的圖檔的名字id,儲存了用于訓練的圖檔的名字
#這個腳本需要val.txt檔案,這個檔案是我用腳本creat_list.py生成的,儲存了用于驗證的圖檔的名字id,儲存了用于驗證的圖檔的名字
#這個腳本還需要xml格式的标簽檔案,我的訓練集xml檔案的格式與voc2007的類似,xml檔案的名稱與對應的用于訓練的圖檔的名稱相同
#這個腳本會生成 indrared_train.txt檔案 ,用于儲存每一用于訓練的圖檔的完整的路徑,随後會被voc.data yolo.c使用
#這個腳本會生成 indrared_val.txt檔案 ,用于儲存每一用于驗證的圖檔的完整的路徑,随後會被voc.data yolo.c使用
#這個腳本還會生成 txt格式的yolo可識别的标簽檔案,轉換自每一個用于訓練或驗證的圖檔對應的xml檔案,txt格式的檔案名稱與對應的xml檔案名相同,但是内容不同,擴充名不同
#這個腳本 需要與圖檔對應的xml檔案所在的位址,需要,轉換後生成的txt的完整儲存路徑
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
#sets=[('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')] #按照自己的檔案格式改的,不需要判斷是那個voc資料包
classes = ["n00000001"]#因為我的資料集隻有一個類别
def convert(size, box):#voc_label.py 自帶的函數,沒有修改
    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('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
    in_file = open('/home/yolo_v2_tinydarknet/darknet/infrared/labels/dout_original/%s.xml'%(image_id))#與圖檔對應的xml檔案所在的位址
    out_file = open('/home/yolo_v2_tinydarknet/darknet/infrared/labels/%s.txt'%(image_id),'w') #與此xml對應的轉換後的txt,這個txt的儲存完整路徑
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')  #通路size标簽的資料
    w = int(size.find('width').text)#讀取size标簽中寬度的資料
    h = int(size.find('height').text)#讀取size标簽中高度的資料

    for obj in root.iter('object'):
       # difficult = obj.find('difficult').text   #由于自己的檔案裡面沒有diffcult這一個标簽,是以就屏蔽之
        cls = obj.find('name').text
        if cls not in classes :#or int(difficult) == 1:
            continue
        cls_id = classes.index(cls)
        xmlbox = obj.find('bndbox')   #通路boundbox标簽的資料并進行處理,都按yolo自帶的代碼來,沒有改動
        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')

#image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()  #之前代碼是按照sets裡面的字元來通路儲存有圖檔名字的train或者val的txt檔案
image_ids = open('/home/yolo_v2_tinydarknet/darknet/infrared/train.txt').read().strip().split()  #如果是訓練集資料打開這一行,注釋下一行
#image_ids = open('/home/yolo_v2_tinydarknet/darknet/infrared/val.txt').read().strip().split()  #如果是驗證資料集資料打開這一行,注釋上一行
#list_file = open('%s_%s.txt'%(year, image_set), 'w')
list_file = open('infrared_train.txt', 'w')     #把結果寫入到indrared_train.txt檔案中,如果是訓練集資料打開這一行,注釋下一行
#list_file = open('infrared_val.txt', 'w')     #把結果寫入到indrared_train.txt檔案中,如果是驗證資料集資料打開這一行,注釋上一行
for image_id in image_ids:
    #list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
    list_file.write('/home/yolo_v2_tinydarknet/darknet/infrared/image/dout/%s.jpg\n'%(image_id))  #把每一用于訓練或驗證的圖檔的完整的路徑寫入到infrared_train.txt中  這個檔案會被voc.data yolo.c調用
    convert_annotation(image_id)   #把圖檔的名稱id傳給函數,用于把此圖檔對應的xml中的資料轉換成yolo要求的txt格式
list_file.close() #關閉檔案
      

原始資料結果

經過以上步驟,我們現在得到以下資料:

  1. 原始照片                                                                                        100張      jpg
  2. 和原始照片名一樣的,用于儲存圖像中要識别的目标資訊的txt     100個      txt
  3. 用于參加訓練的圖檔的路徑位址 infrared_train.txt                           一個      txt
  4. 用于參加訓練的圖檔的路徑位址 infrared_val.txt                              一個     txt

2 修改工程配置檔案

在工程生成的x64/data路徑下

2.1建立 yolo-obj.cfg 檔案,内容複制yolo-voc.2.0.cfg檔案(x64路徑下),但是修改:

  • 第一行
  • change line batch to ​​batch=64​​
  • 第二行
  • change line subdivisions to ​​subdivisions=8​​
  • YOLO2 (2) 測試自己的資料
  • 修改region層  classes 自己訓練的類 這裡是1類  隻有car
  • YOLO2 (2) 測試自己的資料
  • 修改region上一層convolutional層中 filters= (classes+5)*5    這裡  classes為一類   filters= (1+5)*5=30
  • YOLO2 (2) 測試自己的資料

2.2 建立obj.names  在檔案夾build\darknet\x64\data\裡,裡面是你所分的類 這裡為一類 car

YOLO2 (2) 測試自己的資料

如果很多類,例如voc.data 分了很多類資料

YOLO2 (2) 測試自己的資料

2.3 建立obj.data在 build\darknet\x64\data\路徑下

  • 我們隻有一類car 是以classes=1
YOLO2 (2) 測試自己的資料
  • train= 資料準備生成的 儲存訓練圖檔完整路徑的 train.txt
YOLO2 (2) 測試自己的資料
YOLO2 (2) 測試自己的資料
  • valid=資料準備生成的 儲存測試圖檔完整路徑的 var.txt
YOLO2 (2) 測試自己的資料
YOLO2 (2) 測試自己的資料
  •  backup = backup 存放的是 生成的權重檔案路徑 預設x64/backp下

2.4 将原始圖檔集存在​

​build\darknet\x64\data\obj\​

​ 下

2.4 将資料處理得到的描述每個圖像中 目标資訊的txt檔案 也放在build\darknet\x64\data\obj\ 下

YOLO2 (2) 測試自己的資料

每個txt内容

YOLO2 (2) 測試自己的資料

3 開始訓練

3.1 訓練需要用到一個檔案

下載下傳 pre-trained weights for the convolutional layers (76 MB):

​​http://pjreddie.com/media/files/darknet19_448.conv.23​​ 

放在build\darknet\x64下

3.2 運作訓練指令  指令行進入build\darknet\x64下

darknet.exe detector train data/obj.data data/yolo-obj.cfg darknet19_448.conv.23
      

3.3生成結果在 build\darknet\x64\backup