編者按:本文作者Sara Robinson在Medium上發(fā)布了一個(gè)有趣的項(xiàng)目,她自制了一款A(yù)PP,能自動(dòng)識別歌手Taylor Swift。這與我們之前介紹的尋找威利項(xiàng)目很像。該教程非常詳細(xì),有興趣的同學(xué)可以學(xué)習(xí)一下,動(dòng)手做一個(gè)自己的圖像識別工具哦~本文已獲作者授權(quán),以下是對原文的編譯。
注:由于寫作本文時(shí)TensorFlow沒有Swift庫,我用Swift構(gòu)建了針對我的模型的預(yù)測請求的APP。
以下就是我們創(chuàng)建的APP:
TensorFlow物體檢測API能讓你識別出一張圖片中特定物體的位置,這可以應(yīng)用到許多有趣的程序上。不過我平常拍人比較多,所以就想把這一技術(shù)應(yīng)用到人臉識別上。結(jié)果發(fā)現(xiàn)模型表現(xiàn)得非常好!也就是上圖我創(chuàng)建的Taylor Swift檢測器。
本文將列出模型的構(gòu)建步驟,從收集Taylor Swift的照片到模型的訓(xùn)練:
對圖像進(jìn)行預(yù)處理,改變大小、貼標(biāo)簽、將它們分成訓(xùn)練和測試兩部分,并修改成Pascal VOC格式;
將圖片轉(zhuǎn)化成TFRecords文件以符合物體檢測API;
利用MobileNet在谷歌Cloud ML Engine上訓(xùn)練模型;
導(dǎo)出訓(xùn)練好的模型并將其部署到ML Engine上進(jìn)行服務(wù);
構(gòu)建一個(gè)iOS前端,根據(jù)訓(xùn)練好的模型做出預(yù)測請求(使用Swift)。
下面是各部分如何結(jié)合在一起的架構(gòu)圖:
在開始之前,首先要解釋一下我們即將用到的技術(shù)和術(shù)語:TensorFlow物體檢測API是一個(gè)構(gòu)建在TensorFlow上的框架,用于識別圖像中特定的對象。例如,你可以用很多貓的照片訓(xùn)練它,一旦訓(xùn)練完畢,你可以輸入一張貓的圖像,它就會輸出一個(gè)方框列表,認(rèn)為圖像中有一只貓。雖然它的名字中含有API,但是你可以將它更多地想象成用于遷移學(xué)習(xí)的一套便利的工具。
但是,訓(xùn)練模型識別圖像中的對象是個(gè)費(fèi)時(shí)費(fèi)力的活。物體檢測最酷的地方就是它支持五個(gè)預(yù)訓(xùn)練模型的遷移學(xué)習(xí)(transfer learning),那么什么是遷移學(xué)習(xí)呢?比如,當(dāng)兒童學(xué)習(xí)第一門語言時(shí),他們會接觸大量的例子,如果有錯(cuò)就會立刻被糾正過來。例如當(dāng)孩子們學(xué)習(xí)識別貓時(shí),他們的父母會指著圖片上的貓,并說出“貓”這個(gè)詞,這種重復(fù)增強(qiáng)了他們的腦回路。當(dāng)它們學(xué)習(xí)如何識別一只狗時(shí),無需從頭開始,這一過程與貓的識別類似,只是學(xué)習(xí)對象不同。這就是遷移學(xué)習(xí)的工作原理。
但我沒有時(shí)間尋找并標(biāo)記數(shù)千個(gè)Taylor Swift的圖像,但是我可以通過修改最后幾個(gè)圖層、在數(shù)百萬張圖像上訓(xùn)練的模型中提取特征,應(yīng)用于TSwift的檢測。
第一步:預(yù)處理圖像
首先要感謝Dat Tran寫的關(guān)于浣熊檢測器的博客,地址: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)簽之前,我把圖片分為兩類:訓(xùn)練和測試。另外,我寫了一個(gè)調(diào)整圖片大小的腳本(https://github.com/sararob/tswift-detection/blob/master/resize.py),確保每張圖的寬度不超過600px。
由于檢測器會告訴我們圖中的對象位置,所以你不能直接把圖像和標(biāo)簽作為訓(xùn)練數(shù)據(jù)。你需要用邊框?qū)ο笕Τ鰜恚约皩⒈砜虼蛏蠘?biāo)簽(在我們的數(shù)據(jù)集中,只需要一個(gè)標(biāo)簽tswift)。
打邊框工具依然使用LabelImg,這是一個(gè)基于Python的程序,你只需輸入帶標(biāo)簽的圖像,它就會輸出一個(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ù),一次用于測試數(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)練檢測器
我可以在筆記本電腦上訓(xùn)練這個(gè)模型,但是時(shí)間會很長,而且占用大量的資源。并且一旦我需要用電腦做別的事,訓(xùn)練就會中斷。所以,我選擇了云!我們可以利用云來運(yùn)行多個(gè)跨核心的訓(xùn)練,幾個(gè)小時(shí)內(nèi)就能完成整個(gè)工作,并且用Cloud ML engine的速度比GPU還要快。
設(shè)置Cloud ML Engine
我準(zhǔn)備將所有TFRecord格式的數(shù)據(jù)上傳到云并開始訓(xùn)練。首先,我在谷歌云端控制臺中創(chuàng)建了一個(gè)項(xiàng)目,并啟用了Cloud ML Engine:
然后,我將創(chuàng)建一個(gè)云存儲bucket來打包模型的所有資源。確保在指定區(qū)域進(jìn)行存儲(不要選擇多個(gè)區(qū)域):
我將在這個(gè)bucket中/data子目錄來放置訓(xùn)練和測試TFRecord的文件:
目標(biāo)對象檢測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)槲也⒎菑牧汩_始訓(xùn)練這個(gè)模型,所以當(dāng)我運(yùn)行訓(xùn)練時(shí),我需要指向我將要建立的預(yù)訓(xùn)練模型。我選擇使用MobileNet模型——它是針對移動(dòng)設(shè)備優(yōu)化的一系列小模型。雖然我不會直接在移動(dòng)設(shè)備上訓(xùn)練模型,但MobileNet將會快速訓(xùn)練,并允許更快的預(yù)測請求。我下載了這個(gè)MobileNet檢查點(diǎn)用于訓(xùn)練,檢查點(diǎn)是一個(gè)二進(jìn)制文件,包含訓(xùn)練過程中特定點(diǎn)的TensorFlow模型的狀態(tài)。下載并解壓縮后,你可以看到它包含的三個(gè)文件:
以上所有都要用來訓(xùn)練模型,所以我將它們放在云存儲bucket中的同一個(gè)data/目錄中。
在開始訓(xùn)練之前,還需要添加一個(gè)文件。對象檢測腳本需要一種方法查找模型的檢查點(diǎn)、標(biāo)簽映射和訓(xùn)練數(shù)據(jù)。我們將用配置文件處理這一點(diǎn)。TF對象檢測為五個(gè)預(yù)訓(xùn)練模型采集了樣本配置文件。我們在這里為MobileNet使用一個(gè),并且在云存儲bucket的相應(yīng)路徑中更新了所有PATH_TO_BE_CONFIGURED占位符。除了將我的模型連接到云存儲中的數(shù)據(jù)外,此文件還為我的模型配置了幾個(gè)超參數(shù),如卷積大小、激活函數(shù)和步驟。
以下是開始訓(xùn)練之前云存儲bucket中我的/data中的所有文件:
我還會在bucket中創(chuàng)建train/和eval/子目錄——這是TensorFlow在訓(xùn)練和評估時(shí)書寫模型檢查點(diǎn)文件的地方。
現(xiàn)在已經(jīng)準(zhǔn)備好訓(xùn)練了,通過執(zhí)行g(shù)cloud命令開始。請注意,你需要在本地復(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í),我也開始了評估工作。我會使用之前從未見過的數(shù)據(jù)來評估模型的準(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
你可以通過在云端控制臺導(dǎo)航到ML Engine的“作業(yè)”部分來驗(yàn)證您的任務(wù)是否正確運(yùn)行,并檢查日志以查找特定作業(yè):
第三步:部署預(yù)測模型
為了將模型部署到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文件。將它們保存在本地目錄中后,我可以使用對象檢測的export_inference_graph腳本將它們轉(zhuǎn)換為ProtoBuf。要運(yùn)行以下腳本,你需要定義MobileNet配置文件的本地路徑、訓(xùn)練時(shí)下載的模型檢查點(diǎn)編號以及要導(dǎo)出的圖形目錄名稱:
# 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)行后,你將會在.pb輸出目錄中看到一個(gè)saved_model/目錄。將saved_model.pb文件上傳到你的云存儲/data目錄中(不要擔(dān)心生成其他文件)。
現(xiàn)在你已經(jīng)準(zhǔn)備好將模型部署到ML Engine上了。首先,用gcloud創(chuàng)建你的模型:
gcloud ml-engine models create tswift_detector
然后,通過將模型指向剛剛上傳到云存儲的已保存的ProtoBuf來創(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ù)測API生成新的預(yù)測圖像。
第四步:使用Firebase函數(shù)和Swift構(gòu)建預(yù)測客戶端
我在Swift中編寫了一個(gè)iOS客戶端來對我的模型進(jìn)行預(yù)測請求。Swift客戶端將圖像上傳到云存儲,云存儲觸發(fā)Firebase函數(shù),在Node.js中發(fā)起預(yù)測請求,并將生成的預(yù)測圖像和數(shù)據(jù)保存到云存儲和Firebase中。
首先,在我的Swift客戶端中,我添加了一個(gè)按鈕,供用戶訪問設(shè)備的圖片庫。用戶選擇照片后,會觸發(fā)將圖像上傳到云端存儲的操作:
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)
}
接下來,我編寫了在上傳到云存儲時(shí)觸發(fā)的Firebase函數(shù)(https://github.com/sararob/tswift-detection/blob/master/firebase/functions/index.js)。下面的代碼也包含了我向ML Engine預(yù)測API發(fā)出請求的函數(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:可以用來標(biāo)出Taylor Swift周圍的邊框;
detection_scores:為每個(gè)檢測框架返回一個(gè)置信度值,其中只包括分?jǐn)?shù)高于70%的檢測;
detection_classes:告訴我們與檢測相關(guān)的ID。在這種情況下,因?yàn)橹挥幸粋€(gè)標(biāo)簽所以該值總為1。
在函數(shù)中,如果檢測到Taylor,則用detection_boxes在圖像中繪制一個(gè)邊框以及生成置信度分?jǐn)?shù)。然后將新的帶有邊框的圖像保存到云中,將圖像的文件路徑寫入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)測圖像Firestore路徑的更新。如果檢測到目標(biāo),我會下載這張圖片并在應(yīng)用程序中顯示這張圖以及可信度分?jǐn)?shù)。這個(gè)函數(shù)將替換上一個(gè)代碼片段中的注釋:
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檢測器了!注意,由于模型只用了140張圖像進(jìn)行訓(xùn)練,所以準(zhǔn)確度不夠高,可能會把其他人誤認(rèn)為是Taylor。但是,如果有時(shí)間的話,我會收集更多貼有標(biāo)簽的圖片,并更新模型,發(fā)布到應(yīng)用商店里。
-
圖像識別
+關(guān)注
關(guān)注
9文章
526瀏覽量
39005 -
SWIFT
+關(guān)注
關(guān)注
0文章
116瀏覽量
24312 -
tensorflow
+關(guān)注
關(guān)注
13文章
330瀏覽量
61094
原文標(biāo)題:教程帖:用TensorFlow自制Taylor Swift識別器
文章出處:【微信號:jqr_AI,微信公眾號:論智】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
使用Python卷積神經(jīng)網(wǎng)絡(luò)(CNN)進(jìn)行圖像識別的基本步驟
【瑞芯微RK1808計(jì)算棒試用申請】圖像識別以及芯片評測
研發(fā)干貨丨基于OK3399-C平臺android系統(tǒng)下實(shí)現(xiàn)圖像識別
如何構(gòu)建基于圖像識別的印制線路板精密測試系統(tǒng)?
圖像識別技術(shù)原理 深度學(xué)習(xí)的圖像識別應(yīng)用研究
模擬矩陣在圖像識別中的應(yīng)用

評論