1. 程式人生 > >YOLO_DarkNet_解析之旅_voc_label.py 的解析

YOLO_DarkNet_解析之旅_voc_label.py 的解析

最近一段時間正好在準備做yolo方面的專案

下面是yolo 訓練指令碼的解析,歡迎探討!

voc_label.py 

# -*- coding: utf-8 -*-
#xml解析包
import xml.etree.ElementTree as ET
import pickle
import os
#os.listdir() 方法用於返回指定的資料夾包含的檔案或資料夾的名字的列表
from os import listdir, getcwd
from os.path import join

sets=[('2012', 'train'), ('2012', 'val'), ('2007', 'train'), ('2007', 'val'), ('2007', 'test')]

classes = ["aeroplane", "bicycle", "bird", "boat", "bottle", "bus", "car", "cat", "chair", "cow", "diningtable", "dog", "horse", "motorbike", "person", "pottedplant", "sheep", "sofa", "train", "tvmonitor"]


#進行歸一化操作
def convert(size, box):
    '''
    歸一化操作,講對應的box的位置中心和和長款都進行給予圖片大小的歸一化
    #size[0] = 圖片的寬,size[1] = 圖片的高, b= bndbox的陣列 = ['xmin','xmax','ymin','ymax']
    '''
    #進行縮放
    dw = 1./(size[0])
    dh = 1./(size[1])
    #獲取中心x
    x = (box[0] + box[1])/2.0 - 1
    #獲取中心y
    y = (box[2] + box[3])/2.0 - 1
    #獲取box的寬
    w = box[1] - box[0]
    #獲取box的高
    h = box[3] - box[2]
    #對其進行縮放,使得這四個值控制在0-1之間
    x = x*dw
    w = w*dw
    y = y*dh
    h = h*dh
    return (x,y,w,h)

#year ='2012', 對應圖片的id(檔名)
def convert_annotation(year, image_id):
    '''
    將對應檔名的xml檔案轉化為label檔案,xml檔案包含了對應的bunding框以及圖片長款大小等資訊,
    通過對其解析,然後進行歸一化最終讀到label檔案中去,也就是說
    一張圖片檔案對應一個xml檔案,然後通過解析和歸一化,能夠將對應的資訊儲存到唯一一個label檔案中去
    labal檔案中的格式:calss x y w h  同時,一張圖片對應的類別有多個,所以對應的bunding的資訊也有多個
    '''
    #對應的通過year 找到相應的資料夾,並且開啟相應image_id的xml檔案,其對應bund檔案
    in_file = open('/home/k/SoftWare/docker/VOC_data/VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
    #準備在對應的image_id 中寫入對應的label,分別為 
    #<object-class> <x> <y> <width> <height>
    out_file = open('/home/k/SoftWare/docker/VOC_data/VOCdevkit/VOC%s/labels/%s.txt'%(year, image_id), 'w')

    #解析xml檔案
    tree=ET.parse(in_file)
    #獲得對應的鍵值對
    root = tree.getroot()
    #獲得圖片的尺寸大小
    size = root.find('size')
    #獲得寬
    w = int(size.find('width').text)
    #獲得高
    h = int(size.find('height').text)
    #遍歷目標obj
    for obj in root.iter('object'):
	#獲得difficult ??
        difficult = obj.find('difficult').text
	#獲得類別 =string 型別
        cls = obj.find('name').text
        #如果類別不是對應在我們預定好的class檔案中,或difficult==1則跳過
        if cls not in classes or int(difficult)==1:
            continue
	#通過類別名稱找到id
        cls_id = classes.index(cls)
	#找到bndbox 物件
        xmlbox = obj.find('bndbox')
	#獲取對應的bndbox的陣列 = ['xmin','xmax','ymin','ymax']
        b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
	#帶入進行歸一化操作
	#w = 寬, h = 高, b= bndbox的陣列 = ['xmin','xmax','ymin','ymax']
        bb = convert((w,h), b)
	#bb 對應的是歸一化後的(x,y,w,h)
	#生成 calss x y w h 在label檔案中
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')

#返回當前工作目錄
wd = getcwd()

#year ='2012', image_set ='train'

for year, image_set in sets:
    '''
    對所有的檔案資料集進行遍歷
    做了兩個工作:
    1.講所有圖片檔案都遍歷一遍,並且將其所有的全路徑都寫在對應的txt檔案中去,方便定位
    2.同時對所有的圖片檔案進行解析和轉化,將其對應的bundingbox 以及類別的資訊全部解析寫到label 檔案中去
         最後再通過直接讀取檔案,就能找到對應的label 資訊
    '''
    #先找labels資料夾如果不存在則建立
    if not os.path.exists('/home/k/SoftWare/docker/VOC_data/VOCdevkit/VOC%s/labels/'%(year)):
        os.makedirs('/home/k/SoftWare/docker/VOC_data/VOCdevkit/VOC%s/labels/'%(year))

    #讀取在ImageSets/Main 中的train、test..等檔案的內容
    #包含對應的檔名稱
    image_ids = open('/home/k/SoftWare/docker/VOC_data/VOCdevkit/VOC%s/ImageSets/Main/%s.txt'%(year, image_set)).read().strip().split()
    #開啟對應的2012_train.txt 檔案對其進行寫入準備
    list_file = open('%s_%s.txt'%(year, image_set), 'w')
    #將對應的檔案_id以及全路徑寫進去並換行
    for image_id in image_ids:
        list_file.write('/home/k/SoftWare/docker/VOC_data/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(year, image_id))
	#呼叫  year = 年份  image_id = 對應的檔名_id
        convert_annotation(year, image_id)
    #關閉檔案
    list_file.close()

#os.system(‘comand’) 會執行括號中的命令,如果命令成功執行,這條語句返回0,否則返回1
os.system("cat 2007_train.txt 2007_val.txt 2012_train.txt 2012_val.txt > train.txt")
os.system("cat 2007_train.txt 2007_val.txt 2007_test.txt 2012_train.txt 2012_val.txt > train.all.txt")

 另外,看到了voc資料集中的

<pose>Left</pose>
        <truncated>1</truncated>
        <difficult>0</difficult>

 

這幾個標籤不是很明白希望有高人指點!!