8.SSD目標檢測之二:制作自己的訓練集

最近秋色甚好剧董,一場大風刮散了霧霾,難得幾天的好天氣茫负,周末回家在大巴上看著高速兩旁夕陽照射下黃澄澄的樹葉蕉鸳,暈車好像也好了很多。
特地周六趕回來為了周末去拍點素材忍法,周日天氣也好潮尝,去了陜師大拍了照片和視頻。
說正經(jīng)的饿序,如何來制作數(shù)據(jù)集勉失。

1.采集照片。

這個不用說原探,首先是要找照片乱凿,如果要訓練自己的模型的話,數(shù)據(jù)采集這里也基本是要親力親為的咽弦,我自己是想檢測無人機徒蟆,所以百度搜了一部分圖片,自己把無人機飛起來然后用相機再拍了一些离唬,去掉一些重復的后专,最終150張照片。
單反的分辨率已經(jīng)調(diào)到最低但是還是有3000 * 2000输莺,而且無人機飛的較高的話我焦距有限戚哎,拍到的照片無人機占比很小。
所以我對照片進行了重新裁剪嫂用,這一部分是用lightroom來做的型凳,結(jié)束之后全部導出,大小限制在1m嘱函。
然后對照片進行重命名甘畅,這部分后來發(fā)現(xiàn)是不用做的,圖片命名為任意名稱其實都是可以的往弓,不過為了和VOC2007的數(shù)據(jù)集保持一致疏唾,還是做了重新命名,規(guī)則是六位數(shù)函似,最后面是序號槐脏,前面不夠的話補零。
這個在python里面做的話就比較簡單了撇寞,用5個零的字符串00000加上索引index顿天,然后最后取末六個字符就可以了堂氯。
簡單代碼:

import os
import cv2
import time
import matplotlib.pyplot as plt
#原圖路徑和保存圖片的路徑
imgPath="C:\\Users\\zhxing\\Desktop\\VOCtrainval_06-Nov-2007\\VOCdevkit\\MyDate\\JPEGImages\\img\\"
savePath="C:\\Users\\zhxing\\Desktop\\VOCtrainval_06-Nov-2007\\VOCdevkit\\MyDate\\JPEGImages\\"
imgList=os.listdir(imgPath)

for i in range(1,len(imgList)):
    img=cv2.imread(imgPath+imgList[i])
    str_tmp="000000"+str(i)
    cv2.imwrite(savePath+str_tmp[-6:]+".jpg",img)      #后六位命名
print("done!!")

2.標記照片。

標記的話用軟件:LabelImg牌废。
鏈接:https://pan.baidu.com/s/15Tkwstfumzq8gn5Jb3Vj1Q 提取碼:y1d2
使用方法也比較簡單咽白,首先在data文件夾下的txt文件下寫上所有類別的名稱,用英文鸟缕。
然后打開軟件晶框,對每一張照片進行畫框,貼標簽叁扫,保存xml操作三妈。

結(jié)合快捷鍵其實很快:

A: prev image
D: next image
W:creat rectbox
ctrl+s: save xml

圖像中有幾個目標就標定幾個目標,每個目標標簽都需要指定莫绣,我的類別只有一類所以標記起來挺快的,大概一個小時左右就標記完成了悠鞍。

3.用xml文件來生成.tfrecord文件对室。

這個是必須的,tensorflow版本的SSD代碼需要使用 .tfrecord文件來做為訓練文件(如果是自己寫模型的話用矩陣也是可以的)咖祭。
需要提前新建tfrecords_文件夾
代碼:
需要改的地方主要是各個文件夾以及每個 .tfrecord文件包含xml文件的個數(shù)掩宜,這個自己設(shè)置就好了,跑的非常之快么翰,幾秒鐘就完事牺汤。

import os
import sys
import random
import numpy as np
import tensorflow as tf
import xml.etree.ElementTree as ET  # 操作xml文件



#labels
VOC_LABELS = {
    'none': (0, 'Background'),
    'DJI': (1, 'Product')
}

#標簽和圖片所在的文件夾
DIRECTORY_ANNOTATIONS = "Annotations\\"
DIRECTORY_IMAGES = "JPEGImages\\"

# 隨機種子.
RANDOM_SEED = 4242
SAMPLES_PER_FILES = 10  # 每個.tfrecords文件包含幾個.xml樣本


def int64_feature(value):
    if not isinstance(value, list):
        value = [value]
    return tf.train.Feature(int64_list=tf.train.Int64List(value=value))

def float_feature(value):
    if not isinstance(value, list):
        value = [value]
    return tf.train.Feature(float_list=tf.train.FloatList(value=value))

def bytes_feature(value):
    if not isinstance(value, list):
        value = [value]
    return tf.train.Feature(bytes_list=tf.train.BytesList(value=value))

# 圖片處理
def _process_image(directory, name):
    #讀取照片
    filename = directory + DIRECTORY_IMAGES + name + '.jpg'
    image_data = tf.gfile.FastGFile(filename, 'rb').read()
    #讀取xml文件
    filename = os.path.join(directory, DIRECTORY_ANNOTATIONS, name + '.xml')
    tree = ET.parse(filename)
    root = tree.getroot()

    size = root.find('size')
    shape = [int(size.find('height').text),
             int(size.find('width').text),
             int(size.find('depth').text)]
    bboxes = []
    labels = []
    labels_text = []
    difficult = []
    truncated = []

    for obj in root.findall('object'):
        label = obj.find('name').text
        labels.append(int(VOC_LABELS[label][0]))
        labels_text.append(label.encode('ascii'))  # 變?yōu)閍scii格式

        if obj.find('difficult'):
            difficult.append(int(obj.find('difficult').text))
        else:
            difficult.append(0)
        if obj.find('truncated'):
            truncated.append(int(obj.find('truncated').text))
        else:
            truncated.append(0)

        bbox = obj.find('bndbox')
        a = float(bbox.find('ymin').text) / shape[0]
        b = float(bbox.find('xmin').text) / shape[1]
        a1 = float(bbox.find('ymax').text) / shape[0]
        b1 = float(bbox.find('xmax').text) / shape[1]
        a_e = a1 - a

        b_e = b1 - b
        if abs(a_e) < 1 and abs(b_e) < 1:
            bboxes.append((a, b, a1, b1))

    return image_data, shape, bboxes, labels, labels_text, difficult, truncated

# 轉(zhuǎn)化樣例
def _convert_to_example(image_data, labels, labels_text, bboxes, shape,
                        difficult, truncated):
    xmin = []
    ymin = []
    xmax = []
    ymax = []

    for b in bboxes:
        assert len(b) == 4
        [l.append(point) for l, point in zip([ymin, xmin, ymax, xmax], b)]

    image_format = b'JPEG'
    example = tf.train.Example(features=tf.train.Features(feature={
        'image/height': int64_feature(shape[0]),
        'image/width': int64_feature(shape[1]),
        'image/channels': int64_feature(shape[2]),
        'image/shape': int64_feature(shape),
        'image/object/bbox/xmin': float_feature(xmin),
        'image/object/bbox/xmax': float_feature(xmax),
        'image/object/bbox/ymin': float_feature(ymin),
        'image/object/bbox/ymax': float_feature(ymax),
        'image/object/bbox/label': int64_feature(labels),
        'image/object/bbox/label_text': bytes_feature(labels_text),
        'image/object/bbox/difficult': int64_feature(difficult),
        'image/object/bbox/truncated': int64_feature(truncated),
        'image/format': bytes_feature(image_format),
        'image/encoded': bytes_feature(image_data)}))

    return example


def _add_to_tfrecord(dataset_dir, name, tfrecord_writer):
    image_data, shape, bboxes, labels, labels_text, difficult, truncated = \
        _process_image(dataset_dir, name)
    example = _convert_to_example(image_data, labels, labels_text,
                                  bboxes, shape, difficult, truncated)
    tfrecord_writer.write(example.SerializeToString())

def _get_output_filename(output_dir, name, idx):
    return '%s/%s_%03d.tfrecord' % (output_dir, name, idx)

def run(dataset_dir, output_dir, name='voc_2007_train', shuffling=False):
    if not tf.gfile.Exists(dataset_dir):
        tf.gfile.MakeDirs(dataset_dir)

    path = os.path.join(dataset_dir, DIRECTORY_ANNOTATIONS)
    filenames = sorted(os.listdir(path))  # 排序

    if shuffling:
        random.seed(RANDOM_SEED)
        random.shuffle(filenames)

    i = 0
    fidx = 0
    while i < len(filenames):
        # Open new TFRecord file.
        tf_filename = _get_output_filename(output_dir, name, fidx)
        with tf.python_io.TFRecordWriter(tf_filename) as tfrecord_writer:
            j = 0
            while i < len(filenames) and j < SAMPLES_PER_FILES:
                sys.stdout.write(' Converting image %d/%d \n' % (i + 1, len(filenames)))  # 終端打印,類似print
                sys.stdout.flush()  # 緩沖
                filename = filenames[i]
                img_name = filename[:-4]
                _add_to_tfrecord(dataset_dir, img_name, tfrecord_writer)
                i += 1
                j += 1
            fidx += 1
    print('\nFinished converting the Pascal VOC dataset!')

# 原數(shù)據(jù)集路徑浩嫌,輸出路徑以及輸出文件名檐迟,要根據(jù)自己實際做改動
dataset_dir = "C:\\Users\\zhxing\\Desktop\\VOCtrainval_06-Nov-2007\\VOCdevkit\\MyDate\\"
output_dir = "./tfrecords_"
name = "voc_train"

def main(_):
    run(dataset_dir, output_dir, name)

if __name__ == '__main__':
    tf.app.run()

大概生成這樣的文件就可以了:



下面就是訓練了,不知道能有什么結(jié)果B肽汀追迟!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市骚腥,隨后出現(xiàn)的幾起案子敦间,更是在濱河造成了極大的恐慌,老刑警劉巖束铭,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件廓块,死亡現(xiàn)場離奇詭異,居然都是意外死亡契沫,警方通過查閱死者的電腦和手機带猴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來埠褪,“玉大人浓利,你說我怎么就攤上這事挤庇。” “怎么了贷掖?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵嫡秕,是天一觀的道長。 經(jīng)常有香客問我苹威,道長昆咽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任牙甫,我火速辦了婚禮掷酗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘窟哺。我一直安慰自己泻轰,他們只是感情好,可當我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布且轨。 她就那樣靜靜地躺著浮声,像睡著了一般。 火紅的嫁衣襯著肌膚如雪旋奢。 梳的紋絲不亂的頭發(fā)上泳挥,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機與錄音至朗,去河邊找鬼屉符。 笑死,一個胖子當著我的面吹牛锹引,可吹牛的內(nèi)容都是我干的矗钟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼粤蝎,長吁一口氣:“原來是場噩夢啊……” “哼真仲!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起初澎,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤秸应,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后碑宴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體软啼,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年延柠,在試婚紗的時候發(fā)現(xiàn)自己被綠了祸挪。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡贞间,死狀恐怖贿条,靈堂內(nèi)的尸體忽然破棺而出雹仿,到底是詐尸還是另有隱情,我是刑警寧澤整以,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布胧辽,位于F島的核電站,受9級特大地震影響公黑,放射性物質(zhì)發(fā)生泄漏邑商。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一凡蚜、第九天 我趴在偏房一處隱蔽的房頂上張望人断。 院中可真熱鬧,春花似錦朝蜘、人聲如沸恶迈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蝉绷。三九已至,卻和暖如春枣抱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背辆床。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工佳晶, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人讼载。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓轿秧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親咨堤。 傳聞我的和親對象是個殘疾皇子菇篡,可洞房花燭夜當晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容