原作者: TensorFlow(Kunwoo Park, Moogung Kim, Eunsung Han)
鏈接: https://medium.com/tensorflow/how-vflat-used-the-tflite-gpu-delegate-for-real-time-inference-to-scan-books-df3bb86a4eb7
盡管有許多移動掃描應(yīng)用程序可供下載躬柬,但大多數(shù)都專注于將平面文檔數(shù)字化,在掃描書籍的彎曲頁面時會遇到困難。當(dāng)掃描帶有文本的曲面時,人們可以通過移除書本或出版物的裝訂來進(jìn)行破壞性掃描,或者簡單地按原樣接受輸入并處理讀取相機(jī)捕獲的曲面圖像油宜。
這就是為什么我們在旅行者開發(fā) vFlat, 一款使用深度學(xué)習(xí)來解決這個問題的Android應(yīng)用程序。vFlat應(yīng)用程序的目的是讓用戶輕松地瀏覽他們的書籍,而不必?fù)?dān)心彎曲的頁面宪睹。它還試圖通過自動確定書籍頁面的邊界來減少用戶的手動輸入。
左圖:普通移動相機(jī)拍攝的彎曲書頁圖像蚕钦。右:使用vFlat掃描同一圖像的版本
當(dāng)用戶試圖通過OCR(光學(xué)字符識別)從書頁的照片中提取文本時亭病,這一點(diǎn)非常有用。當(dāng)從上面的左圖像中提取文本時嘶居,OCR無法正確識別某些單詞和文本行罪帖,因?yàn)樗鼈兲珡澢恕H欢程瑢⑼瑯拥募夹g(shù)應(yīng)用到右邊的圖像會產(chǎn)生更高的成功率胸蛛,并且可以在幾乎沒有錯誤的情況下提取文本。
如何構(gòu)建vFlat應(yīng)用程序
我們開發(fā)了一個深度學(xué)習(xí)模型樱报,可以使彎曲的書頁變平葬项,并決定在移動設(shè)備上進(jìn)行,以提供最佳的最終用戶體驗(yàn)迹蛤。在vFlat應(yīng)用程序中民珍,有一個“實(shí)時預(yù)覽”功能,用戶可以在其中看到實(shí)時展平的書頁(超過20FPS)盗飒。如果用戶只需使用該應(yīng)用程序就可以將掃描的頁面實(shí)時預(yù)覽為扁平圖像嚷量,那么他們可以在拍照前調(diào)整角度和邊框。
為了在移動應(yīng)用程序中實(shí)現(xiàn)實(shí)時推理逆趣,我們優(yōu)化了訓(xùn)練模型蝶溶,并利用硬件加速的優(yōu)點(diǎn)。我們最初的想法是用OpenGL自己實(shí)現(xiàn)推理模塊宣渗,所以我們準(zhǔn)備用GLSL(OpenGL著色語言)實(shí)現(xiàn)模型的層抖所。
幸運(yùn)的是,我們遇到了TensorFlow Lite的GPU支持痕囱,并決定嘗試一下(在編寫本文時田轧,'TensorFlow-Lite-GPU' package版本已更新為“org.tensorflow:tensorflow-lite-gpu:0.0.0-nightly”). 我們減少了權(quán)重和復(fù)雜操作的數(shù)量,提出了一個輕量級版本的模型鞍恢,并利用TFLite GPU代理進(jìn)行硬件加速傻粘。深神經(jīng)網(wǎng)絡(luò)非常適合GPU每窖,因?yàn)樗鼈儽萩pu具有更多的計算能力,并且擅長處理大量并行工作負(fù)載弦悉。但是窒典,使用移動GPU并不是一件小事;這就是TFLite GPU代理的作用所在警绩。
TFLite GPU代理為移動GPU優(yōu)化神經(jīng)網(wǎng)絡(luò)圖崇败,并生成和編譯異步執(zhí)行的計算著色器。感謝TFLite GPU代理肩祥,我們不必實(shí)現(xiàn)自己的硬件加速推理模塊后室,從而節(jié)省了幾個月的開發(fā)時間。
盡管我們使用TFLite GPU代理節(jié)省了時間和精力混狠,但我們在將自己的模型轉(zhuǎn)換為TFLite模型并將其與TFLite GPU代理集成時遇到了問題岸霹。僅GPU代理的實(shí)驗(yàn)版本支持的操作 它主要用于MobileNet,不支持我們原始模型中的某些操作将饺。
為了在不犧牲模型性能的情況下利用GPU代理贡避,我們必須在保持整個網(wǎng)絡(luò)結(jié)構(gòu)不變的情況下替換一些操作。我們在轉(zhuǎn)換過程中遇到了問題予弧,由于此時源代碼尚未打開刮吧,因此很難確定我們看到的錯誤的原因。(TFLite GPU代理的代碼現(xiàn)在公開提供在 GitHub)
例如掖蛤,由于TFLite GPU代理不支持LeakyReLU操作杀捻,因此我們必須按以下方式使用受支持的PReLU操作:
通過改變
tf.keras.layers.LeakyReLU(alpha=0.3)
to
tf.keras.layers.PReLU(alpha_initializer=Constant(0.3), shared_axes=[1, 2], trainable=False)
然而,當(dāng)我們試圖通過共享所有軸(shared_axes=[1蚓庭,2致讥,3])將PReLU操作中的參數(shù)數(shù)量減少到1時,我們遇到了一個意外的行為器赞。雖然此代碼在CPU模式下運(yùn)行良好垢袱,但GPU代理失敗,錯誤為“線性alpha形狀與輸入通道數(shù)不匹配”港柜。這就是為什么我們最終只沿著軸1和軸2共享參數(shù)请契。
我們遇到的另一個問題是,當(dāng)我們試圖使用網(wǎng)絡(luò)中的Lambda層規(guī)范化-1和1之間的輸入數(shù)據(jù)時:
tf.keras.layers.Lambda(lambda x : (x / 127.5) — 1.0)用TFLite轉(zhuǎn)換器轉(zhuǎn)換Lambda層的可視化這似乎適用于GPU代理夏醉,但當(dāng)實(shí)際運(yùn)行時爽锥,它會在沒有警告的情況下返回到CPU。通常情況下授舟,當(dāng)這種情況發(fā)生時救恨,TFLite會以“未能應(yīng)用代理”之類的消息警告我們贸辈。只有第一個M操作將在GPU上運(yùn)行释树,其余的N操作將在CPU上運(yùn)行”肠槽。因此,在使用Lambda層時要小心奢啥,并在繼續(xù)之前始終嘗試測量實(shí)際的推斷時間
結(jié)論
盡管在這一過程中有幾個障礙,但是我們通過使用TFLite GPU代理將模型的推理時間減少了一半以上桩盲。我們終于能夠?yàn)橛脩籼峁┮粋€“實(shí)時預(yù)覽”功能寂纪,其中扁平的頁面實(shí)時顯示.
我們可以自信地說,使用TFLite GPU代理是一個很好的選擇赌结,強(qiáng)烈建議那些想在移動設(shè)備上部署他們的訓(xùn)練模型的人嘗試一下捞蛋。
要了解更多,并親自嘗試柬姚,請閱讀TensorFlow Lite GPU delegate.