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
  4. 將這個txt轉換成完整路徑

 

1.1 原始圖像

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

 

1.2 xml文件  描述圖像中要識別的目標信息

每一個xml對應一張圖像,並且每個xml中存放的是標記的各個目標的位置和類別信息,命名通常與對應的原始圖像一樣

 

因為做的是目標檢測,所以接下來需要標記原始圖像中的目標區域。相關方法和工具有很多,這里需用labelImg,相關用法也有說明,基本就是框住目標區域然后雙擊類別,標記完整張圖像后點擊保存即可。操作界面如下:

通常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
  •  

該部分由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調用

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

  • 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調用 

  

#此腳本修改自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
  • 修改region層  classes 自己訓練的類 這里是1類  只有car
  • 修改region上一層convolutional層中 filters= (classes+5)*5    這里  classes為一類   filters= (1+5)*5=30
  •  

2.2 創建obj.names  在文件夾build\darknet\x64\data\里,里面是你所分的類 這里為一類 car

如果很多類,例如voc.data 分了很多類數據

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

  • 我們只有一類car 所以classes=1

 

  • train= 數據准備生成的 保存訓練圖片完整路徑的 train.txt

  • valid=數據准備生成的 保存測試圖片完整路徑的 var.txt

 

  •  backup = backup 存放的是 生成的權重文件路徑 默認x64/backp下

2.4 將原始圖片集存在build\darknet\x64\data\obj\

2.4 將數據處理得到的描述每個圖像中 目標信息的txt文件 也放在build\darknet\x64\data\obj\ 下

每個txt內容

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

每次迭代100次,保存下,取最后一個

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM