1. 程式人生 > 其它 >使用Tensorflow物件檢測在安卓手機上“尋找”皮卡丘

使用Tensorflow物件檢測在安卓手機上“尋找”皮卡丘

在TensorFlow的許多功能和工具中,隱藏著一個名為TensorFlow物件探測API(TensorFlow Object Detection API)的元件。正如它的名字所表達的,這個庫的目的是訓練一個神經網路,它能夠識別一個框架中的物體。這個庫的用例和可能性幾乎是無限的。它可以通過訓練來檢測一張影象上的貓、汽車、浣熊等等物件。本文將用它來實現皮卡丘的檢測。

  • TensorFlow物件檢測API:https://github.com/tensorflow/models/tree/master/research/object_detection

本文的目的是描述我在訓練自己的自定義物件檢測模型時所採取的步驟,並展示我的皮卡丘檢測技能,以便你可以自己嘗試。首先,我將從程式包的介紹開始。其次,我將繼續討論如何將我的皮卡丘影象轉換為正確的格式並建立資料集。然後,我將盡可能詳細地寫關於訓練的過程,以及如何評估它。最後,我將演示如何在Python notebook中使用該模型,以及將其匯出到安卓手機的過程。

  • 我在這個專案中使用的程式碼:https://github.com/juandes/pikachu-detection

在應用中的檢測的螢幕截圖

Tensorflow物件檢測API

這個程式包是TensorFlow對物件檢測問題的響應——也就是說,在一個框架中檢測實際物件(皮卡丘)的過程。它的獨特之處在於它能夠準確地記錄速度和記憶體使用情況(反之亦然),因此你可以根據你的需要和你的選擇平臺(手機)來調整模型。這個庫包含了許多不被發現的物件檢測架構,如SSD(Single Shot MultiBox Detector)、Faster R-CNN(Faster Region-based Convolutional Neural Network)和R-FCN(Region-based Fully Convolutional Networks),以及一些特徵提取器,如MobileNet、Inception和Resnet;這些提取器是非常重要的,因為它們在系統的速度/效能平衡中扮演了重要的角色。

此外,該庫還提供了一些已經準備好的用於檢測的模型,在Google Cloud中進行訓練的選項,再加上TensorBoard的支援來監控訓練。

既然我們已經瞭解了這個實驗所使用的系統,我將繼續解釋如何構建你自己的自定義模型。

構建自己的自定義模型

安裝 在我們開始之前,請確保你的計算機上安裝了TensorFlow。接下來,clone包含物件檢測API的repo,連結如下:

  • https://github.com/tensorflow/models

找到“research”目錄並執行:

# From tensorflow/models/research/
protoc object_detection/protos/*.proto --python_out=.

這個過程編譯了Protobuf庫。

Protobuf下載地址:https://developers.google.com/protocol-buffers/docs/downloads

最後,你需要將庫新增到PYTHONPATH中。可以通過執行下面的命令來完成:

# From tensorflow/models/research/
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

有關所需的所有依賴項的更多細節:https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/installation.md

現在來看看我是如何從許多皮卡丘影象到一個由TensorFlow讀取的資料集。

建立資料集並處理影象 建立資料集是成功訓練模型所需的眾多步驟中的第一步,在本節中,我將介紹完成此任務所需的所有步驟。對於這個專案,我將230箇中等大小的皮卡丘的圖片下載到一個名為“images”的目錄中。為了得到更好的結果,我試圖從影象中獲得不同角度和形狀的皮卡丘,但老實講,皮卡丘是一個不存在的黃色長耳的小老鼠,所以很難找到大量的合適的影象。

一些被使用的影象

一旦你獲得了所有的影象,下一步就是對它們進行標記。這是什麼意思? 因為我們在做物件檢測,所以我們需要一個關於物體到底是什麼的基本事實。為此,我們需要在物件周圍畫一個邊框,讓系統知道邊框裡面的“東西”是我們想要學習的實際物件。我用於這個任務的軟體是一個叫RectLabel的Mac應用。

  • RectLabel:https://rectlabel.com/

這就是一個帶有邊框的影象的樣子:

憤怒的皮卡丘。被一個邊框包圍著

在RectLabel中,你需要為你的影象的每個邊框設定一個標籤,在我的例子中,標籤是“Pikachu”。一旦你對所有影象進行了標記,你就會注意到你有一個名為“annotations”的目錄,其中有許多XML檔案用來描述每個影象的邊框。

分成訓練和測試資料集 一旦所有的影象都被貼上了標籤,我的下一步就是將資料集分解成一個訓練和測試資料集。在影象所在的同一個目錄中,我建立了一個名為“train”和“test”的目錄,並將大約70%的影象和它們各自的XML新增到“train”目錄,剩下的30%新增到“test”目錄。

生成TFRECORD 在資料集的分離之後,唯一缺少的是將我們的影象和它們的XML轉換成一個由TensorFlow可讀的格式。這種格式被稱為“tfrecord”,並且從我們的影象中生成它,需要兩個步驟。首先,為了簡單起見,兩組XML(訓練和測試)的資料都被轉換為兩個CSV檔案(再一次,訓練和測試),使用的是修改版本的xml_to_csv.py程式碼。

  • 程式碼地址:https://github.com/datitran/raccoon_dataset

然後,使用CSV檔案,tfrecord資料集是使用指令碼generate_tfrecord.py建立的(該指令碼也能從上面的程式碼地址中找到)。請記住,在執行指令碼之前,必須在函式class_text_to_int中指定物件的類。

建立標籤對映 需要一個“labels”對映,指示標籤及其索引。下面就是他們的樣子:

item {
  id: 1
  name: 'Pikachu'
}

將“Pikachu”標籤替換為你想用的標籤,並且重要的是,總是從index 1開始,因為index 0是預留的。我將這個檔案在一個名為“training”的新目錄下儲存為object-detection.pbtxt。

訓練模型

管道(The Pipeline) 完整的訓練過程由一個稱為“pipeline”的配置檔案來處理。管道被劃分為五個主要結構,負責定義模型、訓練和評估過程引數,以及訓練和評估資料集的輸入。這條管道的架構是這樣的:

model {
(... Add model config here...)
}

train_config : {
(... Add train_config here...)
}

train_input_reader: {
(... Add train_input configuration here...)
}

eval_config: {
}

eval_input_reader: {
(... Add eval_input configuration here...)
}

但是!你不必從頭開始編寫(write)整個管道。事實上,TensorFlow開發人員建議訓練應該使用他們自己的和已經訓練過的模型作為起點。這背後的原因是從頭開始訓練一個全新的模型可能需要相當長的時間。因此,TensorFlow提供了幾個配置檔案(下方),只需要很少的更改就可以使其在新的訓練環境中工作。我使用的模型是ssd_mobilenet_v1_coco_11_06_2017。

  • 配置檔案:https://github.com/tensorflow/models/tree/master/research/object_detection/samples/configs
  • ssd_mobilenet_v1_coco_11_06_2017模型:http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_coco_11_06_2017.tar.gz

在我的訓練中,我使用了配置檔案ssd_mobilenet_v1_pets.config作為一個起點。因為我的類的數量只有一個,所以我改變了變數num_classes。num_steps停止訓練前,fine_tune_checkpoint指向模型下載的位置,還有train_input_reader和eval_input_reader的變數input_path和label_map_path指向訓練和測試資料集與標籤對映。

  • ssd_mobilenet_v1_pets.config:https://github.com/tensorflow/models/blob/master/research/object_detection/samples/configs/ssd_mobilenet_v1_pets.config

我不會細講配置檔案的每一個細節,不過,我想解釋一下SSD和MobileNet是什麼意思。SSD是一種基於單一前饋神經網路的神經網路結構。它被稱為“single shot”,因為它可以預測影象的類和在同一步驟中表示檢測(稱為anchor)的邊框的位置。與此相反的是一個架構,它需要一個稱為“proposal generator”的第二個元件來預測該框的確切位置。

MobileNet是一個卷積特徵提取器,用於在移動裝置上工作,用於獲取影象的高階特徵。一旦準備好了管道,就把它新增到“training”目錄中。然後,繼續使用下面的命令開始訓練:

python object_detection/train.py --logtostderr 
--train_dir=path/to/training/ 
--pipeline_config_path=path/to/training/ssd_mobilenet_v1_pets.config

在訓練期間和之後評估模型 這個庫提供了在訓練期間和之後評估模型所需的程式碼。每次訓練產生一個新的檢查點時,評估工具將使用給定目錄中可用的影象進行預測(在我的例子中,我使用了來自測試集中的影象)。要執行評估工具,執行以下操作:

python object_detection/eval.py --logtostderr 
--train_dir=path/to/training/ 
--pipeline_config_path=path/to/training/ssd_mobilenet_v1_pets.config 
--checkpoint_dir=path/to/training/ --eval_dir=path/to/training/

TensorBoard 通過TensorFlow的視覺化平臺TensorBoard,可以看到訓練和評估階段的結果。在這裡,我們可以監控一些指標,如訓練時間、總損失、步驟數等等。很酷的一點是,當模型被訓練的時候,TensorBoard也可以工作,這是一個很好的工具,可以確保訓練的方向是正確的。

要執行TensorBoard,請執行以下命令:

tensorboard --logdir=path/to/training/

匯出模型

訓練完成後,下一步是匯出模型,以便可以使用它。為了執行這一步,該庫提供了名為export_inference_graph.py的指令碼。

在匯出之前,請確保你在訓練目錄中有以下檔案:

model.ckpt-${CHECKPOINT_NUMBER}.data-00000-of-00001,
model.ckpt-${CHECKPOINT_NUMBER}.index
model.ckpt-${CHECKPOINT_NUMBER}.meta

你可能有幾個具有相同格式的檔案,但是使用不同的檢查點數量。因此,只需選擇所需的檢查點,並執行以下命令:

python object_detection/export_inference_graph.py 
--input_type image_tensor 
--
pipeline_config_path=path/to/training/ssd_mobilenet_v1_pets.config 
--trained_checkpoint_prefix=path/to/training/model.ckpt-xxxxx 
--output_directory path/to/output/directory

輸出將是一個檔案,該檔案包含一個叫做frozen_inference_graph.pb模型的“凍結(frozen)”版本。

結果

在訓練階段結束時,該模型的精確度為87%,總損失為0.67。然而,在訓練過程中,模型的精確度最高達到了95%。儘管如此,精確度最高的模型並沒有達到我預期設想的結果。例如,它將許多黃色物體(甚至一些人)歸類為皮卡丘。另一方面,我注意到,精確度為87%的模型產生的假陽性結果較少,因而忽略了一些皮卡丘。下面的圖片是由TensorBoard製作的總損失和精確度圖表。

精確度指標

TensorBoard還會自動評估評估集的一些影象。它真正的好處是,通過使用一個滑塊(slider),你可以看到預測的置信(confidence)是如何根據模型的檢查點的變化而變化的。

更多的皮卡丘。這種檢測是在TensorBoard中進行的

影象檢測包包括一個notebook,用來測試TensorFlow提供的預先訓練過的模型。然而,這個notebook可以被修改為使用自定義訓練模型的frozen版本(我們匯出的版本),所以我就這樣做了。

  • notebook地址:https://github.com/tensorflow/models/blob/master/research/object_detection/object_detection_tutorial.ipynb

下面,你可以看到一些在notebook上的發現。

皮卡丘在鍛鍊

皮卡丘和lil bro

人類裝扮成皮卡丘。沒有被檢測到

在安卓手機上檢測皮卡丘

到目前為止,我們已經對模型進行了訓練,並對其進行了評估。現在是時候把它匯入安卓手機中了,這樣我們就可以用手機攝像頭來檢測皮卡丘了。然而,這個部分是非常複雜的,所以我會盡可能詳細地解釋主要步驟。但是,我確信你們中有些人在進行這個操作時會有一些問題,所以如果我的指導不能夠幫到你們,我想先道歉。

讓我們轉到TensorFlow的安卓部分。首先,你需要下載Android Studio。然後,clone上面的提到的TensorFlow的repo,並使用你剛剛clone的TensorFlow的repo中的目錄在Android Studio中匯入一個的新專案,叫做“Android”。

  • Android Studio下載地址: https://developer.android.com/studio/index.html
  • Android專案:https://github.com/tensorflow/tensorflow/tree/master/tensorflow/examples/android

作為補充說明,我還建議通過README對庫進行熟悉。README建議將構建變得最簡單,並建議將Gradle(一個基於Apache Ant和Apache Maven概念的專案自動化構建工具)構建的nativeBuildSystem變數改變為零,然而,我將其更改為cmake來構建它(沒有任何其他的替代方案)。

構建完成後,下一步是將frozen模型新增到“assets”目錄中。然後,在那裡的資料夾中,建立一個名為“labels”的檔案,在第一行中寫入???(還記得我說過第一個類是被預留的嗎?),在第二行中,寫上你的物件的標籤(在我的例子中,我的標籤為“Pikachu”)。

然後,開啟位於“java”目錄中的名為“DetectionActitivity.java”的檔案;這是應用程式用來執行探測的程式碼。查詢變數TF_OD_API_MODEL_FILE和TF_OD_API_LABELS_FILE,並且在第一個檔案中,將其值更改為位於“assets”資料夾中的frozen模型的路徑,然後在第二個檔案中寫入帶有標籤的檔案路徑。你應該知道的另一個有用的變數是MINIMUM_CONFIDENCE_TF_OD_API,它是跟蹤檢測所需的最低置信。

現在我們準備好了! 點選“run”按鈕,選擇你的安卓裝置,然後等待幾秒鐘,直到該應用安裝在手機上。需要注意的一個重要的細節:不是一個,而是四個應用將安裝在手機上,然而,我們所包含的檢測模型是TF Detect。如果一切順利的話,應用啟動,找到你的物件的一些圖片,看看這個模型是否能夠檢測到它們。以下是我在手機上做的一些檢測:

穿著和服的皮卡丘

幾個皮卡丘。其中大部分沒有被檢測到

總結和回顧

在本文中,我解釋了使用TensorFlow物件檢測庫來訓練自定義模型的所有必要步驟。在開始的時候,我提供了一些關於這個庫的背景資訊以及它是如何工作的,接下來是關於如何標記、處理和影象來生成資料集的指南。後來,我把注意力集中在如何進行訓練上。在這一節中,我談到了訓練管道,如何使用TensorBoard來評估模型。然後,一旦訓練完成,我就完成了匯出模型並匯入Python notebook和安卓手機的過程。