◆盛兆勇
(濟寧職業(yè)技術(shù)學院電子信息工程系 山東 272000)
云存儲網(wǎng)盤是一種基于 OpenStack Swift對象存儲技術(shù)的在線存儲服務(wù),能夠方便為用戶提供文件管理功能。OpenStack Swift是一個設(shè)計運行在通用硬件平臺上的分布式對象存儲服務(wù),具有彈性可伸縮、高可用等特點,它能夠在通用硬件上構(gòu)筑云存儲服務(wù),對很多應(yīng)用都能很好地支持,包括文件的上傳、下載、移動、拷貝、刪除、恢復等服務(wù),能夠提供PB級的數(shù)據(jù)存儲[1]。
云存儲網(wǎng)盤Android客戶端是一款可以兼容市面上大部分安卓手機的App軟件,已經(jīng)集成了用戶管理、快捷操作、分類視圖等功能模塊,網(wǎng)盤的常用操作包括用戶登錄、用戶注冊、修改用戶信息、獲取文件列表、分類、上傳文件、新建、拍照上傳、錄像上傳、錄音上傳、移動、復制、下載、刪除、還原、打開和查找文件或文件夾等[2]。本文是在已有功能的基礎(chǔ)上,將谷歌的開源的深度學習框架TensorFlow添加到Android手機客戶端中,使得用戶在上傳的圖片的時候可以自動識別出圖片中的物體,進而對上傳的圖片根據(jù)識別的結(jié)果進行自動命名,提高了易用性,增加了用戶友好度。增加了新模塊以后的Andorid手機客戶端系統(tǒng)框架如圖1所示。
圖1 云存儲網(wǎng)盤Android手機客戶端系統(tǒng)架構(gòu)
TensorFlow 是目前應(yīng)用最廣泛的深度學習框架[3],相對于其他的相對于其他主流的深度學習框架,如Caffe、Chainer、CNTK等,TensorFlow具有如下三點優(yōu)勢:
(1)可用性
TensorFlow用 Python 編寫,可讀性高,兼容性好,這使得大多數(shù)精通 Python 數(shù)據(jù)科學家很容易上手[4]。
(2)兼容性
TensorFlow可以在不同的計算機平臺上自由的運行代碼,從超級計算機到樹莓派等嵌入式系統(tǒng),還支持多CPU,多GPU或者兩者混合運行[5]。
(3)持續(xù)性
TensorFlow 是由谷歌開發(fā)、維護的,因此可以保障支持、開發(fā)的持續(xù)性,同時還在 TensorFlow 周圍形成了一個巨大、活躍的社區(qū)。并且谷歌為了讓開發(fā)者能夠更快的接受TensorFlow,已經(jīng)發(fā)布了很多訓練好的模型,開發(fā)者可以在自己的項目中自由、免費的使用。
本文是通過 TensorFlow已有模型構(gòu)建Android 應(yīng)用,這個已有的模型就是谷歌的 TensorFlow examples project 中叫作 TF Classify的demo,它能夠?qū)D片進行分類識別,并且將推斷的結(jié)果按照可信度進行排序[6]。
智能終端如果想使用TensorFlow,有兩種方式,第一種通過網(wǎng)絡(luò)連接到遠程服務(wù)器,但這樣會過分的依賴網(wǎng)絡(luò)環(huán)境,而且可能會很慢,另外一種方式就是可以把已經(jīng)訓練好的的模型遷移到智能終端上面[7]?;谏厦娴目紤],我們決定采取第二種方式實現(xiàn)在Android手機中使用TensorFlow。
由于TensorFlow版本增加了對Android、iOS和Raspberry Pi硬件平臺的支持,允許它在這些設(shè)備上執(zhí)行圖像分類等操作,使得這個工作變得更加容易。為了將 TensorFlow添加到 Android Studio項目中,我們只需要實現(xiàn)下面的步驟即可。
(1)因為在安卓系統(tǒng)中執(zhí)行TensorFlow Inference操作,需要調(diào)用 libandroid_tensorflow_inference_java.jar中的 JNI接口[8],所以需要將這個jar包集成到項目中去,跟在項目中集成其他第三庫一樣,只需要在build.gradle中添加如下的依賴:
compile files('libs/libandroid_tensorflow_inference_java.jar')
(2)另外,還需要一個libtensorflow_inference.so文件,可以通過下載TensorFlow源代碼后,采用bazel編譯出來,也可以從網(wǎng)上進行下載編譯好的so文件。同時為了解決ARM模擬器啟動過程慢的問題,Android項目依賴的 TensorFlow Lite的libtensorflow_inference.so文件增補了支持x86環(huán)境的so文件,增加后可以使用x86模擬器調(diào)用TensorFlow Lite APIs。將文件按照下圖放置到項目的相應(yīng)目錄下即可。
(3)將訓練好的數(shù)據(jù)模型,拷貝到指定的目錄下面,如圖2所示,其中后綴名為.pb的文件是已經(jīng)訓練好的模型,而后綴名為.txt的文件是訓練數(shù)據(jù)包含的所有標簽。這個模型可對一千多種物品進行識別分類,基本可以滿足我們的實驗要求。
圖2 項目結(jié)構(gòu)圖
這部分涉及的類有Classifier.java 和 TensorFlowImageClassi fier.java兩個,其中Classifier.java是一個接口類,定義了圖像分類用到的方法,TensorFlowImageClassifier.java類繼承至 Classifi er.java這個接口類,實現(xiàn)了接口類中定義的抽象方法。
這里我們重點關(guān)注 TensorFlowImageClassifier.java類的兩個方法,一個是 TensorFlowImageClassifier 類中的靜態(tài)方法 create方法:
/**
* Initializes a native TensorFlow session for classifying im ages.
* @param assetManager The asset manager to be used to load assets.
* @param modelFilename The filepath of the model Grap hDef protocol buffer.
* @param labelFilename The filepath of label file for clas-ses.
* @param inputSize The input size. A square image of i nputSize x inputSize is assumed.
* @param imageMean The assumed mean of the image va lues.
* @param imageStd The assumed std of the image values.
* @param inputName The label of the image input node.
* @param outputName The label of the output node.
* @throws IOException
*/
public static Classifier create(AssetManager assetManager,St ring modelFilename,String labelFilename,int inputSize,int image Mean,float imageStd,String inputName,String outputName)
該方法需要調(diào)用者傳進來8個與模型相關(guān)的參數(shù),并且有可能拋出一個IOException的異常,如果正確執(zhí)行就會返回一個Cl assifier實例。
另外一個recognizeImage方法,能夠通過 Classifier對象來識別我們傳入的 bitmap圖像數(shù)據(jù),并且將一個按照可信度從高到低排序的結(jié)果集返回給調(diào)用者。
/**
*圖片識別分類
*/
public List<Recognition> recognizeImage(final Bitmap bitm ap)
由于App客戶端原有的功能都是在MainFragment實現(xiàn)的,所以本文新增加的模塊也需要在MainFragment添加相應(yīng)的代碼。
這一部分功能的實現(xiàn),分為兩個步驟。第一個步驟的主要功能是:加載加載模型文件和標簽文件,獲得一個Classifier對象;將當前的圖片按一定比例創(chuàng)建一張新的圖,然后調(diào)用 recognizeI mage方法對這張新圖進行識別;讓用戶對識別出來的名字進行選擇確認。其核心實現(xiàn)如下:
private static final String MODEL_FILE=file:///android_asse t/tensorflow.pb;
private static final String LABEL_FILE=file:///android_asset/ label_strings.txt;
classifier = TensorFlowImageClassifier.create(context.getAsse ts(),MODEL_FILE,LABEL_FILE,INPUT_SIZE,IMAGE_MEAN,I MAGE_STD,INPUT_NAME,OUTPUT_NAME);
final File file=new File(imagePath);
Bitmap bm=BitmapFactory.decodeFile(imagePath);
bm = Bitmap.createScaledBitmap(bm,INPUT_SIZE,INPUT_S IZE,false);
//顯示識別的結(jié)果
List<Classifier.Recognition> results=classifier.recognizeImage(bm);
第二個步驟就是實現(xiàn)上傳,由于文件上傳是一個非常耗時的任務(wù),有可能會造成后面任務(wù)的阻塞,如果阻塞的時間太長,安卓系統(tǒng)就會拋出異常錯誤,所以我們需要利用AsyncTask類來進行異步處理。其核心代碼如下:
String filePath= null;
if (intent!=null){
Uri uri=intent.getData();
}
String containerName=getAppState().getSelectedContainer().g etName().toString();
String[]parts=filePath.split("/");
String directory=null;
if (getAppState().getSelectedDirectory()!=null){
directory=getAppState().getSelectedDirectory().getName().toSt ring();
}
String path=directory;
InputStream inputStream=new FileInputStream(filePath);getService().upload(containerName,inputStream,intent.getType(),path);
FileUtils.getSingleton(context).copyFile(filePath ,"/openstack/");
Return new TaskResult<String>(filePath);
識別結(jié)果如圖3所示,從截圖中可以看到結(jié)果是按照可信度從高到低進行排序的,點擊確定即可將該圖片按照識別出來的結(jié)果進行命名,并且上傳到Swift云存儲服務(wù)器。
圖3 圖片識別結(jié)果
隨著網(wǎng)絡(luò)帶寬的提高,網(wǎng)民習慣于將一些暫時用不到的資源存放到網(wǎng)盤中。企事業(yè)單位以及一些公司也出于高效性、可靠性和安全性的考慮,開始基于 OpenStack Swfit構(gòu)建自己的云存儲方案。本文驗證了將 TensorFlow框架添加到安卓手機客戶端中的可行性,使得用戶在使用云存儲網(wǎng)盤 App的時候更加方便快捷,增加了用戶粘合度。