Swift 兼容性說(shuō)明
本項(xiàng)目目前使用 Swift 3.1 或者 Swift 4.0 工具鏈編譯,可以在macOS / Ubuntu上使用。
編譯運(yùn)行
運(yùn)行以下命令可以運(yùn)行本示例程序并在8080端口創(chuàng)建服務(wù)器:
git clone https://github.com/PerfectExamples/Perfect-TensorFlow-Demo-Vision.git cd Perfect-TensorFlow-Demo-Vision
./install.sh ./.build/debug/PerfectTensorFlowDemo
應(yīng)該能夠看到以下輸出:
[INFO] Starting HTTP server localhost on 0.0.0.0:8080
意味著服務(wù)器已經(jīng)準(zhǔn)備好,請(qǐng)?jiān)L問(wèn) http://localhost:8080/ 查看演示主頁(yè),您可以如下圖所示上載一個(gè)本地圖片考驗(yàn)計(jì)算機(jī)是否能夠識(shí)別,或者甚至可以用鼠標(biāo)手繪一個(gè)草圖來(lái)測(cè)試計(jì)算機(jī)視覺(jué)識(shí)別能力。下面的例子是上載了一個(gè)信封??的照片,然后服務(wù)器識(shí)別返回給客戶端,用英語(yǔ)問(wèn)這是不是一個(gè)信封,并列出了可能是信封的概率::
組合鍵control-c可以停止服務(wù)器運(yùn)行。
服務(wù)器API
本項(xiàng)目的目標(biāo)是制作這樣的一個(gè)服務(wù)器,在調(diào)用根目錄/recog函數(shù)API之后,客戶端可以給服務(wù)器用POST表單發(fā)送一張圖片,然后服務(wù)器對(duì)圖像內(nèi)容進(jìn)行識(shí)別,識(shí)別完成之后返回給客戶端一個(gè)json字符串,其中內(nèi)容就是識(shí)別圖像內(nèi)容的結(jié)果;即如果圖像內(nèi)容是一個(gè)鬧鐘?,則回復(fù)字符串{“value”:”clock”}。
簡(jiǎn)介
本樣例代碼使用了一個(gè)預(yù)先訓(xùn)練好的機(jī)器視覺(jué)模型(數(shù)學(xué)家萬(wàn)歲,搞人工神經(jīng)網(wǎng)絡(luò)的數(shù)學(xué)家萬(wàn)歲萬(wàn)歲萬(wàn)萬(wàn)歲!):
(http://arxiv.org/abs/1512.00567).
您可以將人工神經(jīng)網(wǎng)絡(luò)模型文件加載到一個(gè)Perfect TensorFlow Session對(duì)象,像這樣:
let g = try TF.Graph()
let def = try TF.GraphDef(serializedData: model) try g.import(definition: def)
連同模型一起下載的還有一個(gè)已知物體的名單(英文)文件:
try fTag.open(.read)
let lines = try fTag.readString()
tags = lines.utf8.split(separator: 10).map { String(describing: $0) }
// 字符串?dāng)?shù)組變量應(yīng)該看起來(lái)像這樣:
// tags = ["dummy", "kit fox", "English setter", "Siberian husky" ...]
一旦從客戶端收到圖片后,服務(wù)器會(huì)將圖片內(nèi)容正規(guī)化:
public func constructAndExecuteGraphToNormalizeImage(_ g: TF.Graph, imageBytes: Data) throws -> TF.Tensor { let H:Int32 = 224 let W:Int32 = 224 let mean:Float = 117 let scale:Float = 1 let input = try g.constant(name: "input2", value: imageBytes) let batch = try g.constant( name: "make_batch", value: Int32(0)) let scale_v = try g.constant(name: "scale", value: scale) let mean_v = try g.constant(name: "mean", value: mean) let size = try g.constantArray(name: "size", value: [H,W]) let jpeg = try g.decodeJpeg(content: input, channels: 3) let cast = try g.cast(value: jpeg, dtype: TF.DataType.dtFloat) let images = try g.expandDims(input: cast, dim: batch) let resizes = try g.resizeBilinear(images: images, size: size) let subbed = try g.sub(x: resizes, y: mean_v) let output = try g.div(x: subbed, y: scale_v) let s = try g.runner().fetch(TF.Operation(output)).run()
guard s.count > 0 else { throw TF.Panic.INVALID } return s[0]
}
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
然后就可以跑一下TensorFlow的會(huì)話輸出:
let result = try g.runner().feed("input", tensor: image).fetch("output").run()
結(jié)果是一個(gè)概率數(shù)組,其長(zhǎng)度與名單吻合,用于預(yù)測(cè)名單中每一個(gè)對(duì)象可能的概率。因此只要找出數(shù)組中大概率就可以獲得圖像被“識(shí)別”的結(jié)果:
public func match(_ g: TF.Graph, image: Data) throws -> (Int, Int) { let normalized = try constructAndExecuteGraphToNormalizeImage(imageBytes: image) let possibilities = try executeInceptionGraph(image: normalized)
guard let m = possibilities.max(), let i = possibilities.index(of: m) else { throw TF.Panic.INVALID
} return (i, Int(m * 100))
}
后一步就是把概率索引轉(zhuǎn)換為對(duì)象名稱,然后發(fā)給客戶端:
let tag = tags[result.0] let p = result.1 response.setHeader(.contentType, value: "text/json")
.appendBody(string: "{\"value\": \"Is it a \(tag)? (Possibility: \(p)%)\"}")
.completed()
大功告成!就是這樣簡(jiǎn)單!
當(dāng)然,如果您仍然覺(jué)得服務(wù)器配置和部署比較麻煩,那么請(qǐng)?jiān)L問(wèn)Perfect官網(wǎng)perfect.org,下載Perfect Assistant 2.0 ,即軟件助手2.0版本,即可實(shí)現(xiàn)Swift函數(shù)庫(kù)和預(yù)裝人工智能服務(wù)器整體打包管理、編譯、部署一條龍,目前支持亞馬遜彈性計(jì)算和谷歌應(yīng)用引擎,還將陸續(xù)增加更多服務(wù)器部署方案選擇,這樣您就可以隨時(shí)改進(jìn)自己的程序應(yīng)用,逐步增加人工智能和神經(jīng)網(wǎng)絡(luò)、以及機(jī)器深度學(xué)習(xí)的新功能啦!
本站文章版權(quán)歸原作者及原出處所有 。內(nèi)容為作者個(gè)人觀點(diǎn), 并不代表本站贊同其觀點(diǎn)和對(duì)其真實(shí)性負(fù)責(zé),本站只提供參考并不構(gòu)成任何投資及應(yīng)用建議。本站是一個(gè)個(gè)人學(xué)習(xí)交流的平臺(tái),網(wǎng)站上部分文章為轉(zhuǎn)載,并不用于任何商業(yè)目的,我們已經(jīng)盡可能的對(duì)作者和來(lái)源進(jìn)行了通告,但是能力有限或疏忽,造成漏登,請(qǐng)及時(shí)聯(lián)系我們,我們將根據(jù)著作權(quán)人的要求,立即更正或者刪除有關(guān)內(nèi)容。本站擁有對(duì)此聲明的最終解釋權(quán)。