編者按:本文作者Sara Robinson在Medium上發(fā)布了一個(gè)有趣的項(xiàng)目,她自制了一款A(yù)PP,能自動(dòng)識(shí)別歌手Taylor Swift。這與我們之前介紹的尋找威利項(xiàng)目很像。該教程非常詳細(xì),有興趣的同學(xué)可以學(xué)習(xí)一下,動(dòng)手做一個(gè)自己的圖像識(shí)別工具哦~本文已獲作者授權(quán),以下是對(duì)原文的編譯。
注:由于寫(xiě)作本文時(shí)TensorFlow沒(méi)有Swift庫(kù),我用Swift構(gòu)建了針對(duì)我的模型的預(yù)測(cè)請(qǐng)求的APP。
以下就是我們創(chuàng)建的APP:
TensorFlow物體檢測(cè)API能讓你識(shí)別出一張圖片中特定物體的位置,這可以應(yīng)用到許多有趣的程序上。不過(guò)我平常拍人比較多,所以就想把這一技術(shù)應(yīng)用到人臉識(shí)別上。結(jié)果發(fā)現(xiàn)模型表現(xiàn)得非常好!也就是上圖我創(chuàng)建的Taylor Swift檢測(cè)器。
本文將列出模型的構(gòu)建步驟,從收集Taylor Swift的照片到模型的訓(xùn)練:
對(duì)圖像進(jìn)行預(yù)處理,改變大小、貼標(biāo)簽、將它們分成訓(xùn)練和測(cè)試兩部分,并修改成Pascal VOC格式;
將圖片轉(zhuǎn)化成TFRecords文件以符合物體檢測(cè)API;
利用MobileNet在谷歌Cloud ML Engine上訓(xùn)練模型;
導(dǎo)出訓(xùn)練好的模型并將其部署到ML Engine上進(jìn)行服務(wù);
構(gòu)建一個(gè)iOS前端,根據(jù)訓(xùn)練好的模型做出預(yù)測(cè)請(qǐng)求(使用Swift)。
下面是各部分如何結(jié)合在一起的架構(gòu)圖:

在開(kāi)始之前,首先要解釋一下我們即將用到的技術(shù)和術(shù)語(yǔ):TensorFlow物體檢測(cè)API是一個(gè)構(gòu)建在TensorFlow上的框架,用于識(shí)別圖像中特定的對(duì)象。例如,你可以用很多貓的照片訓(xùn)練它,一旦訓(xùn)練完畢,你可以輸入一張貓的圖像,它就會(huì)輸出一個(gè)方框列表,認(rèn)為圖像中有一只貓。雖然它的名字中含有API,但是你可以將它更多地想象成用于遷移學(xué)習(xí)的一套便利的工具。
但是,訓(xùn)練模型識(shí)別圖像中的對(duì)象是個(gè)費(fèi)時(shí)費(fèi)力的活。物體檢測(cè)最酷的地方就是它支持五個(gè)預(yù)訓(xùn)練模型的遷移學(xué)習(xí)(transfer learning),那么什么是遷移學(xué)習(xí)呢?比如,當(dāng)兒童學(xué)習(xí)第一門(mén)語(yǔ)言時(shí),他們會(huì)接觸大量的例子,如果有錯(cuò)就會(huì)立刻被糾正過(guò)來(lái)。例如當(dāng)孩子們學(xué)習(xí)識(shí)別貓時(shí),他們的父母會(huì)指著圖片上的貓,并說(shuō)出“貓”這個(gè)詞,這種重復(fù)增強(qiáng)了他們的腦回路。當(dāng)它們學(xué)習(xí)如何識(shí)別一只狗時(shí),無(wú)需從頭開(kāi)始,這一過(guò)程與貓的識(shí)別類(lèi)似,只是學(xué)習(xí)對(duì)象不同。這就是遷移學(xué)習(xí)的工作原理。
但我沒(méi)有時(shí)間尋找并標(biāo)記數(shù)千個(gè)Taylor Swift的圖像,但是我可以通過(guò)修改最后幾個(gè)圖層、在數(shù)百萬(wàn)張圖像上訓(xùn)練的模型中提取特征,應(yīng)用于TSwift的檢測(cè)。
第一步:預(yù)處理圖像
首先要感謝Dat Tran寫(xiě)的關(guān)于浣熊檢測(cè)器的博客,地址:https://towardsdatascience.com/how-to-train-your-own-object-detector-with-tensorflows-object-detector-api-bec72ecfe1d9
首先,我從谷歌圖片上下載了200張Taylor Swift的照片,這里安利一個(gè)Chrome插件:Fatkun Batch Download Image,可以下載所有圖片搜索結(jié)果。在打標(biāo)簽之前,我把圖片分為兩類(lèi):訓(xùn)練和測(cè)試。另外,我寫(xiě)了一個(gè)調(diào)整圖片大小的腳本(https://github.com/sararob/tswift-detection/blob/master/resize.py),確保每張圖的寬度不超過(guò)600px。
由于檢測(cè)器會(huì)告訴我們圖中的對(duì)象位置,所以你不能直接把圖像和標(biāo)簽作為訓(xùn)練數(shù)據(jù)。你需要用邊框?qū)?duì)象圈出來(lái),以及將表框打上標(biāo)簽(在我們的數(shù)據(jù)集中,只需要一個(gè)標(biāo)簽tswift)。
打邊框工具依然使用LabelImg,這是一個(gè)基于Python的程序,你只需輸入帶標(biāo)簽的圖像,它就會(huì)輸出一個(gè)xml文件,將每張照片都打上邊框同時(shí)還有相關(guān)標(biāo)簽(不到一上午我就處理好200張圖片了)。下面是它如何工作的(標(biāo)簽輸入為tswift):
然后LabelImg生成一個(gè)xml文件:
現(xiàn)在我有了一張帶有邊框和標(biāo)簽的圖片了,但是我還要把它轉(zhuǎn)換成TensorFlow可接受的方式——一個(gè)數(shù)據(jù)的二進(jìn)制表示TFRecord。關(guān)于這一方法可以在GitHub上查看。要運(yùn)行我的腳本,你需要先下載一個(gè)tensorflow/models,從tensorflow/models/research本地直接運(yùn)行腳本,帶上以下參數(shù)(運(yùn)行兩次:一次用于訓(xùn)練數(shù)據(jù),一次用于測(cè)試數(shù)據(jù))
python convert_labels_to_tfrecords.py
--output_path=train.record
--images_dir=path/to/your/training/images/
--labels_dir=path/to/training/label/xml/
第二步:訓(xùn)練檢測(cè)器
我可以在筆記本電腦上訓(xùn)練這個(gè)模型,但是時(shí)間會(huì)很長(zhǎng),而且占用大量的資源。并且一旦我需要用電腦做別的事,訓(xùn)練就會(huì)中斷。所以,我選擇了云!我們可以利用云來(lái)運(yùn)行多個(gè)跨核心的訓(xùn)練,幾個(gè)小時(shí)內(nèi)就能完成整個(gè)工作,并且用Cloud ML engine的速度比GPU還要快。
設(shè)置Cloud ML Engine
我準(zhǔn)備將所有TFRecord格式的數(shù)據(jù)上傳到云并開(kāi)始訓(xùn)練。首先,我在谷歌云端控制臺(tái)中創(chuàng)建了一個(gè)項(xiàng)目,并啟用了Cloud ML Engine:

然后,我將創(chuàng)建一個(gè)云存儲(chǔ)bucket來(lái)打包模型的所有資源。確保在指定區(qū)域進(jìn)行存儲(chǔ)(不要選擇多個(gè)區(qū)域):

我將在這個(gè)bucket中/data子目錄來(lái)放置訓(xùn)練和測(cè)試TFRecord的文件:

目標(biāo)對(duì)象檢測(cè)API還需要一個(gè)將標(biāo)簽映射到整數(shù)ID的pbtxt文件。由于我們只有一個(gè)標(biāo)簽,這個(gè)是非常短的:
item {
id: 1
name: 'tswift'
}
添加MobileNet檢查點(diǎn)進(jìn)行遷移學(xué)習(xí)
因?yàn)槲也⒎菑牧汩_(kāi)始訓(xùn)練這個(gè)模型,所以當(dāng)我運(yùn)行訓(xùn)練時(shí),我需要指向我將要建立的預(yù)訓(xùn)練模型。我選擇使用MobileNet模型——它是針對(duì)移動(dòng)設(shè)備優(yōu)化的一系列小模型。雖然我不會(huì)直接在移動(dòng)設(shè)備上訓(xùn)練模型,但MobileNet將會(huì)快速訓(xùn)練,并允許更快的預(yù)測(cè)請(qǐng)求。我下載了這個(gè)MobileNet檢查點(diǎn)用于訓(xùn)練,檢查點(diǎn)是一個(gè)二進(jìn)制文件,包含訓(xùn)練過(guò)程中特定點(diǎn)的TensorFlow模型的狀態(tài)。下載并解壓縮后,你可以看到它包含的三個(gè)文件:

以上所有都要用來(lái)訓(xùn)練模型,所以我將它們放在云存儲(chǔ)bucket中的同一個(gè)data/目錄中。
在開(kāi)始訓(xùn)練之前,還需要添加一個(gè)文件。對(duì)象檢測(cè)腳本需要一種方法查找模型的檢查點(diǎn)、標(biāo)簽映射和訓(xùn)練數(shù)據(jù)。我們將用配置文件處理這一點(diǎn)。TF對(duì)象檢測(cè)為五個(gè)預(yù)訓(xùn)練模型采集了樣本配置文件。我們?cè)谶@里為MobileNet使用一個(gè),并且在云存儲(chǔ)bucket的相應(yīng)路徑中更新了所有PATH_TO_BE_CONFIGURED占位符。除了將我的模型連接到云存儲(chǔ)中的數(shù)據(jù)外,此文件還為我的模型配置了幾個(gè)超參數(shù),如卷積大小、激活函數(shù)和步驟。
以下是開(kāi)始訓(xùn)練之前云存儲(chǔ)bucket中我的/data中的所有文件:

我還會(huì)在bucket中創(chuàng)建train/和eval/子目錄——這是TensorFlow在訓(xùn)練和評(píng)估時(shí)書(shū)寫(xiě)模型檢查點(diǎn)文件的地方。
現(xiàn)在已經(jīng)準(zhǔn)備好訓(xùn)練了,通過(guò)執(zhí)行g(shù)cloud命令開(kāi)始。請(qǐng)注意,你需要在本地復(fù)制tensorflow/models/research并從該目錄運(yùn)行此訓(xùn)練腳本:
# Run this script from tensorflow/models/research:
gcloud ml-engine jobs submit training ${YOUR_TRAINING_JOB_NAME}
--job-dir=${YOUR_GCS_BUCKET}/train
--packages dist/object_detection-0.1.tar.gz,slim/dist/slim-0.1.tar.gz
--module-name object_detection.train
--region us-central1
--config object_detection/samples/cloud/cloud.yml
--runtime-version=1.4
--
--train_dir=${YOUR_GCS_BUCKET}/train
--pipeline_config_path=${YOUR_GCS_BUCKET}/data/ssd_mobilenet_v1_coco.config
訓(xùn)練的同時(shí),我也開(kāi)始了評(píng)估工作。我會(huì)使用之前從未見(jiàn)過(guò)的數(shù)據(jù)來(lái)評(píng)估模型的準(zhǔn)確性:
# Run this script from tensorflow/models/research:
gcloud ml-engine jobs submit training ${YOUR_EVAL_JOB_NAME}
--job-dir=${YOUR_GCS_BUCKET}/train
--packages dist/object_detection-0.1.tar.gz,slim/dist/slim-0.1.tar.gz
--module-name object_detection.eval
--region us-central1
--scale-tier BASIC_GPU
--runtime-version=1.4
--
--checkpoint_dir=${YOUR_GCS_BUCKET}/train
--eval_dir=${YOUR_GCS_BUCKET}/eval
--pipeline_config_path=${YOUR_GCS_BUCKET}/data/ssd_mobilenet_v1_coco.config
你可以通過(guò)在云端控制臺(tái)導(dǎo)航到ML Engine的“作業(yè)”部分來(lái)驗(yàn)證您的任務(wù)是否正確運(yùn)行,并檢查日志以查找特定作業(yè):

第三步:部署預(yù)測(cè)模型
為了將模型部署到ML Engine,我需要將模型檢查點(diǎn)轉(zhuǎn)換為ProtoBuf。在我的train/bucket中,可以看到從幾處保留的檢查點(diǎn)文件:

文件的第一行告訴我最新的檢查點(diǎn)路徑——我應(yīng)從該檢查點(diǎn)本地下載3個(gè)文件。每個(gè)檢查點(diǎn)應(yīng)該有一個(gè).index,.meta,和.data文件。將它們保存在本地目錄中后,我可以使用對(duì)象檢測(cè)的export_inference_graph腳本將它們轉(zhuǎn)換為ProtoBuf。要運(yùn)行以下腳本,你需要定義MobileNet配置文件的本地路徑、訓(xùn)練時(shí)下載的模型檢查點(diǎn)編號(hào)以及要導(dǎo)出的圖形目錄名稱(chēng):
# Run this script from tensorflow/models/research:
python object_detection/export_inference_graph.py
--input_type encoded_image_string_tensor
--pipeline_config_path ${LOCAL_PATH_TO_MOBILENET_CONFIG}
--trained_checkpoint_prefix model.ckpt-${CHECKPOINT_NUMBER}
--output_directory ${PATH_TO_YOUR_OUTPUT}.pb
這個(gè)腳本運(yùn)行后,你將會(huì)在.pb輸出目錄中看到一個(gè)saved_model/目錄。將saved_model.pb文件上傳到你的云存儲(chǔ)/data目錄中(不要擔(dān)心生成其他文件)。
現(xiàn)在你已經(jīng)準(zhǔn)備好將模型部署到ML Engine上了。首先,用gcloud創(chuàng)建你的模型:
gcloud ml-engine models create tswift_detector
然后,通過(guò)將模型指向剛剛上傳到云存儲(chǔ)的已保存的ProtoBuf來(lái)創(chuàng)建第一個(gè)模型版本:
gcloud ml-engine versions create v1 --model=tswift_detector --origin=gs://${YOUR_GCS_BUCKET}/data --runtime-version=1.4
模型部署好后,我將用ML Engine的線上預(yù)測(cè)API生成新的預(yù)測(cè)圖像。
第四步:使用Firebase函數(shù)和Swift構(gòu)建預(yù)測(cè)客戶(hù)端
我在Swift中編寫(xiě)了一個(gè)iOS客戶(hù)端來(lái)對(duì)我的模型進(jìn)行預(yù)測(cè)請(qǐng)求。Swift客戶(hù)端將圖像上傳到云存儲(chǔ),云存儲(chǔ)觸發(fā)Firebase函數(shù),在Node.js中發(fā)起預(yù)測(cè)請(qǐng)求,并將生成的預(yù)測(cè)圖像和數(shù)據(jù)保存到云存儲(chǔ)和Firebase中。
首先,在我的Swift客戶(hù)端中,我添加了一個(gè)按鈕,供用戶(hù)訪問(wèn)設(shè)備的圖片庫(kù)。用戶(hù)選擇照片后,會(huì)觸發(fā)將圖像上傳到云端存儲(chǔ)的操作:
let firestore = Firestore.firestore()
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let imageURL = info[UIImagePickerControllerImageURL] as? URL
let imageName = imageURL?.lastPathComponent
let storageRef = storage.reference().child("images").child(imageName!)
storageRef.putFile(from: imageURL!, metadata: nil) { metadata, error in
if let error = error {
print(error)
} else {
print("Photo uploaded successfully!")
// TODO: create a listener for the image's prediction data in Firestore
}
}
}
dismiss(animated: true, completion: nil)
}
接下來(lái),我編寫(xiě)了在上傳到云存儲(chǔ)時(shí)觸發(fā)的Firebase函數(shù)(https://github.com/sararob/tswift-detection/blob/master/firebase/functions/index.js)。下面的代碼也包含了我向ML Engine預(yù)測(cè)API發(fā)出請(qǐng)求的函數(shù)部分:
function cmlePredict(b64img, callback) {
return new Promise((resolve, reject) => {
google.auth.getApplicationDefault(function (err, authClient, projectId) {
if (err) {
reject(err);
}
if (authClient.createScopedRequired && authClient.createScopedRequired()) {
authClient = authClient.createScoped([
'https://www.googleapis.com/auth/cloud-platform'
]);
}
var ml = google.ml({
version: 'v1'
});
const params = {
auth: authClient,
name: 'projects/sara-cloud-ml/models/tswift_detector',
resource: {
instances: [
{
"inputs": {
"b64": b64img
}
}
]
}
};
ml.projects.predict(params, (err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
});
});
}
在ML Engine的反應(yīng)中,我們得到:
detection_boxes:可以用來(lái)標(biāo)出Taylor Swift周?chē)倪吙颍?/p>
detection_scores:為每個(gè)檢測(cè)框架返回一個(gè)置信度值,其中只包括分?jǐn)?shù)高于70%的檢測(cè);
detection_classes:告訴我們與檢測(cè)相關(guān)的ID。在這種情況下,因?yàn)橹挥幸粋€(gè)標(biāo)簽所以該值總為1。
在函數(shù)中,如果檢測(cè)到Taylor,則用detection_boxes在圖像中繪制一個(gè)邊框以及生成置信度分?jǐn)?shù)。然后將新的帶有邊框的圖像保存到云中,將圖像的文件路徑寫(xiě)入Cloud Firestore,一邊在iOS應(yīng)用程序中讀取路徑并下載新圖像:
const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);
const db = admin.firestore();
let outlinedImgPath = `outlined_img/${filePath.slice(7)}`;
let imageRef = db.collection('predicted_images').doc(filePath);
imageRef.set({
image_path: outlinedImgPath,
confidence: confidence
});
bucket.upload('/tmp/path/to/new/image', {destination: outlinedImgPath});
最后,在iOS應(yīng)用程序中,我們可以監(jiān)測(cè)圖像Firestore路徑的更新。如果檢測(cè)到目標(biāo),我會(huì)下載這張圖片并在應(yīng)用程序中顯示這張圖以及可信度分?jǐn)?shù)。這個(gè)函數(shù)將替換上一個(gè)代碼片段中的注釋?zhuān)?/p>
self.firestore.collection("predicted_images").document(imageName!)
.addSnapshotListener { documentSnapshot, error in
if let error = error {
print("error occurred(error)")
} else {
if (documentSnapshot?.exists)! {
let imageData = (documentSnapshot?.data())
self.visualizePrediction(imgData: imageData)
} else {
print("waiting for prediction data...")
}
}
}
好了!現(xiàn)在我們有一款Taylor Swift檢測(cè)器了!注意,由于模型只用了140張圖像進(jìn)行訓(xùn)練,所以準(zhǔn)確度不夠高,可能會(huì)把其他人誤認(rèn)為是Taylor。但是,如果有時(shí)間的話,我會(huì)收集更多貼有標(biāo)簽的圖片,并更新模型,發(fā)布到應(yīng)用商店里。
-
圖像識(shí)別
+關(guān)注
關(guān)注
9文章
532瀏覽量
40018 -
SWIFT
+關(guān)注
關(guān)注
0文章
125瀏覽量
24770 -
tensorflow
+關(guān)注
關(guān)注
13文章
334瀏覽量
62108
原文標(biāo)題:教程帖:用TensorFlow自制Taylor Swift識(shí)別器
文章出處:【微信號(hào):jqr_AI,微信公眾號(hào):論智】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
使用Python卷積神經(jīng)網(wǎng)絡(luò)(CNN)進(jìn)行圖像識(shí)別的基本步驟
【瑞芯微RK1808計(jì)算棒試用申請(qǐng)】圖像識(shí)別以及芯片評(píng)測(cè)
研發(fā)干貨丨基于OK3399-C平臺(tái)android系統(tǒng)下實(shí)現(xiàn)圖像識(shí)別
如何構(gòu)建基于圖像識(shí)別的印制線路板精密測(cè)試系統(tǒng)?
圖像識(shí)別模組(包括PCB圖、圖像識(shí)別模組源代碼)
圖像識(shí)別技術(shù)原理 深度學(xué)習(xí)的圖像識(shí)別應(yīng)用研究
模擬矩陣在圖像識(shí)別中的應(yīng)用
基于TensorFlow和Keras的圖像識(shí)別
用TensorFlow制作一個(gè)圖像識(shí)別工具的構(gòu)建步驟解析
評(píng)論