Tensorflow object detection API 搭建物體識別模型(二)


二、數據准備

 1)下載圖片

  圖片來源於ImageNet中的鯉魚分類,下載地址:https://pan.baidu.com/s/1Ry0ywIXVInGxeHi3uu608g 提取碼: wib3

  在桌面新建文件夾目標檢測,把下載好的壓縮文件n01440764.tar放到其中,並解壓

 2)選擇圖片

  在此數據集中,大部分圖片都較為清晰,但是有極少數圖片像素點少,不清晰。像素點少的圖片不利於模型訓練或模型測試,選出部分圖片文件,在目標檢測路徑下輸入jupyter notebook,新建一個get_some_qualified_images的文件:

  代碼運行完成后,在桌面的目標檢測文件夾中,會有一個selected_images文件夾,如下圖所示:

import os
import random
from PIL import Image
import shutil

#獲取1000張圖片中隨機選出數量為sample_number*2的一部分圖片的路徑
def get_some_imagePath(dirPath, sample_number):
    fileName_list = os.listdir(dirPath)
    all_filePath_list = [ os.path.join(dirPath, fileName) for fileName in fileName_list ]
    all_imagePath_list = [ filePath for filePath in all_filePath_list if '.jpg' in filePath ]
    some_filePath_list = random.sample( all_filePath_list, k=sample_number * 2)
    return some_filePath_list

#獲取一部分像素足夠,即長,寬都大於300的圖片
def get_some_qualified_images(dirPath, sample_number, new_dirPath):
    some_imagePath_list = get_some_imagePath(dirPath, sample_number)
    if not os.path.isdir(new_dirPath):
        os.mkdir(new_dirPath)
        
    i = 0
    for imagePath in some_imagePath_list:
        image = Image.open(imagePath)
        width, height = image.size
        if width > 300 and height > 300:
            i += 1
            new_imagePath = 'selected_images/%03d.jpg' % i
            #在處理圖像的時候常常需要將一個圖像復制到另一個文件夾中,Python可以很方便的利用shutil.copy(src,dst)函數實現這個操作
            #返回復制圖像的文件路徑
            shutil.copy( imagePath, new_imagePath)
        if i == sample_number:
            break

#獲取數量為100的合格樣本存放到selected_images文件夾中
get_some_qualified_images('n01440764', 100, 'selected_images')

  

 3)縮小圖片

  前面我們選出了100張像素足夠的圖片存放在selected_images文件夾中,即淘汰了像素過小的圖片。接着我們實現將像素過大的圖片做縮小

import os
from PIL import Image

def get_small_images(dirPath, new_dirPath):
    fileName_list = os.listdir(dirPath)
    filePath_list = [os.path.join(dirPath, fileName) for fileName in fileName_list]
    imagePath_list = [filePath for filePath in filePath_list if '.jpg' in filePath]

    if not os.path.isdir(new_dirPath):
        os.mkdir(new_dirPath)
        
    for imagePath in imagePath_list:
        image = Image.open( imagePath )
        width, height = image.size
        imageName = imagePath.split('\\')[-1]
        save_path = os.path.join(new_dirPath, imageName)
        if width >= 600 and height >= 600:
            minification = min(width, height) // 300 #縮小倍數
            new_width = width // minification
            new_height = height // minification
            resized_image = image.resize( (new_width, new_height),Image.ANTIALIAS )
            print('圖片%s由原來的寬%d,高%d,縮小為寬%d,高%d' % (imageName, width, height, new_width, new_height))
            resized_image.save(save_path)
            
        else:
            image.save(save_path)
            
get_small_images('selected_images', 'smaller_images')

 

  

 

 4)給圖片打標簽

  使用打標簽工具LabelImg,下載頁面鏈接:https://tzutalin.github.io/labelImg/

  下載后解壓,打開:

  在輸入法為英文輸入的情況下,按鍵盤上的w鍵則可以開始繪制方框,方框會框住圖片中的物體。完成繪制方框后,還需要為方框標上類別,如下圖所示。

  注意:每完成一張圖的打標簽,一定要記得保存!!!,初次使用可以在edit選項中設置正方形和矩形框:

  在本文演示中,需要給圖片中的鯉魚人臉2個類別打標簽。鯉魚的標簽名叫做fish,人臉的標簽名叫human_face,打標簽的結果如上圖所示

  注意:用方框框住物體時,盡量框住物體的所有部位,例如本文中的魚,魚鰭是一個重要特征。保證框住物體所有部位的情況下,也不要使方框四周留出過多空白。用LabelImg軟件打標簽會給每張圖片產生對應的xml文件

  還有:打標簽很耗時間!!!

  每次打完標簽,會生成對應的xml數據,感興趣的可以查看一下某個xml文件,其中記錄了標簽及bounding box坐標:

 

 5)xml轉csv

  xml轉csv的意思是,將xml文件中的信息整合到csv文件中,其中利用的是xml模塊

import os
import pandas as pd
import xml.etree.ElementTree as ET
from sklearn.model_selection import train_test_split

def xmlPath_list_to_df(xmlPath_list):
    xmlContent_list = []
    for xmlPath in xmlPath_list:
        print(xmlPath)
        tree = ET.parse(xmlPath)
        root = tree.getroot()
    
        for member in root.findall('object'):
            value = ( root.find('filename').text,#文件名
                     int( root.find('size')[0].text),#width
                     int( root.find('size')[1].text),#height
                     member[0].text,#標簽
                     int( member[4][0].text),#xmin
                     int( member[4][1].text),#ymin
                     int( member[4][2].text),#xmax
                     int( member[4][3].text)#ymax
                    )
            xmlContent_list.append(value)
            
    column_name = ['filename', 'width', 'height', 'class', 'xmin', 'ymin', 'xmax', 'ymax']

    xmlContent_df = pd.DataFrame( xmlContent_list, columns = column_name )
    
    return xmlContent_df
    
def dirPath_to_csv(dirPath):
    fileName_list = os.listdir(dirPath)
    all_xmlPath_list = [os.path.join(dirPath, fileName) for fileName in fileName_list if '.xml' in fileName]
    train_xmlPath_list, test_xmlPath_list = train_test_split(all_xmlPath_list, test_size=0.1, random_state=1)
    train_df = xmlPath_list_to_df( train_xmlPath_list)
    train_df.to_csv('train.csv')
    print('成功產生文件train.csv,訓練集共有%d張圖片' % len(train_xmlPath_list) )
    
    test_df = xmlPath_list_to_df(test_xmlPath_list)
    test_df.to_csv('test.csv')
    print('成功產生文件test.csv,測試集共有%d張圖片' % len(test_xmlPath_list) )
    
dirPath_to_csv('smaller_images')

  將函數train_test_split的參數random_state的值設為1,這樣每次划分的訓練集和測試集總是相同。如果不設置此參數,則每次划分的訓練集和測試集不同。上面一段代碼的運行結果如下:

  我們以train.csv文件來看看xml轉換為csv后的信息:

 6)csv轉tfrecord

  由於下面的代碼我們需要模塊

from object_detection.utils import dataset_util

  該模塊是我們在Tensorflow object detection API 搭建物體識別模型(一)中下載的,要想使用該模塊,我們需要添加環境變量PATHPATH。方法如下:右鍵計算機->屬性

其中變量值包含下載的objec_detection路徑及slim路徑,如E:\ML\models-master\research;E:\ML\models-master\research\slim 

#csv轉tfrecords
import os
import pandas as pd
import tensorflow as tf
from object_detection.utils import dataset_util
import shutil

def csv2tfrecord( csv_path, imageDir_path, tfrecord_path):
    objectInfo_df = pd.read_csv(csv_path)
    tfrecord_writer = tf.python_io.TFRecordWriter(tfrecord_path)
    for filename, group in objectInfo_df.groupby('filename'):
        height = group.iloc[0]['height']
        width = group.iloc[0]['width']
        filename_bytes = filename.encode('utf-8')
        image_path = os.path.join( imageDir_path, filename)
        
        with open(image_path, 'rb') as file:
            encoded_jpg = file.read()
        
        image_format = b'jpg'
        xmin_list = list(group['xmin'] / width )
        xmax_list = list(group['xmax'] / width )
        ymin_list = list(group['ymin'] / height )
        ymax_list = list(group['ymax'] / height )
        
        classText_list = [ classText.encode('utf-8') for classText in group['class']]
        classLabel_list = [ classText_to_classLabel(classText) for classText in group['class']]
        
        tf_example = tf.train.Example( features=tf.train.Features(
                        feature = {
                            'image/height' : dataset_util.int64_feature(height),
                            'image/width'  : dataset_util.int64_feature(width),
                            'image/filename' : dataset_util.bytes_feature(filename_bytes),
                            'image/source_id' : dataset_util.bytes_feature(filename_bytes),
                            'image/encoded' : dataset_util.bytes_feature(encoded_jpg),
                            'image/format' : dataset_util.bytes_feature(image_format),
                            'image/object/bbox/xmin' : dataset_util.float_list_feature(xmin_list),
                            'image/object/bbox/xmax' : dataset_util.float_list_feature(xmax_list),
                            'image/object/bbox/ymin' : dataset_util.float_list_feature(ymin_list),
                            'image/object/bbox/ymax' : dataset_util.float_list_feature(ymax_list),
                            'image/object/class/text' : dataset_util.bytes_list_feature(classText_list),
                            'image/object/class/label' : dataset_util.int64_list_feature(classLabel_list),
                            
                        }))
        tfrecord_writer.write(tf_example.SerializeToString())
        
    tfrecord_writer.close()
    print('成功產生tfrecord文件,保存在路徑:%s' % tfrecord_path)
  
#如果訓練自己的模型,目標檢測類別不同,需要修改此處
def classText_to_classLabel(row_label):
    if row_label == 'fish':
        return 1
    elif row_label == 'human_face':
        return 2
    else:
        return None

dir_name = 'training'
if not os.path.isdir(dir_name):
    os.mkdir(dir_name)
    
csv2tfrecord('train.csv', 'smaller_images', 'training/train.tfrecord')
csv2tfrecord('test.csv', 'smaller_images', 'training/test.tfrecord')

  運行上面的代碼,目標檢測文件夾中會產生一個文件夾training,如下圖所示:

 7)編寫pbtxt文件

  目標檢測的文件夾training中,創建文本文件my_label_map.pbtxt復制下面一段內容到文本文件my_label_map.pbtxt中:

item {
    name : "fish"
    id : 1
}
item {
    name : "human_face"
    id : 2
}

 8)編寫配置文件

  可以在object_detection文件夾中的samples/config路徑下,找到原生配置文件ssdlite_mobilenet_v2_coco.config先復制1份到桌面文件目標檢測的文件夾training中,並做如下修改:

  1. 第9行的num_classes,對於本文來說,此數設置為2
  2. 第143行的batch_size,對於本文來說,此數設置為5,讀者根據自己的電腦配置,可以調高或者調低
  3. 第177行input_path設置成"training/train.tfrecord"
  4. 第179行label_map_path設置成"training/my_label_map.pbtxt"
  5. 第191行input_path設置成"training/test.tfrecord"
  6. 第193行label_map_path設置成"training/my_label_map.pbtxt"
  7. 第158、159這2行需要刪除

  修改配置文件ssdlite_mobilenet_v2_coco.config並保存后,此時文件夾training中有4個文件,如下圖所示:

 

 9)模型訓練

  接着請讀者參考:Tensorflow object detection API 搭建物體識別模型(三)


免責聲明!

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



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