【Android】增強現實應用——AR畫報
Ø 【作品名稱】:《AR畫報》
Ø 【實驗目的】
在Android系統上,開發基於增強現實技術的應用。可以通過手機攝像頭掃描的方式,獲取與紙質媒體(如雜誌)內容相關的視訊資訊,並能夠讓使用者方便快捷地跳轉到對應的網站。除了Target圖片的識別,還支援二維碼的識別。
希望通過這項應用,豐富紙質媒體的內容,同時將紙媒讀者導向網際網路入口,為內容生產者、廣告主提供更好的展示平臺,並且對圖片的掃描可以一定程度上代替較為“醜陋”的二維碼。
Ø 【實驗器材】
Android Studio 1.5.1
Xiaomi Pad (7.9’’): Android 4.4.4 , 1536*2048 xhdpi
Ø 【實驗原理】
一、 應用框架
上圖所示即為本工程的應用框架。
Android裝置首先會從攝像頭和預存的圖片檔案和配置檔案Json中獲取RGB彩色影象以及(圖片檔案和配置檔案Json中的)ImageTarget資訊,然後通過處理單元。處理單元包括兩個部分:
1、 ImageTracker:通過影象匹配的演算法從Camera獲取的Frame中找到與json配置的ImageTarget中最相關的影象,並進行精確的定位和追蹤。
2、 BarCodeScanner:從Camera獲取的Frame中發現是否存在二維碼,並進行解碼獲取其中的文字資訊。
通過處理單元處理後的資訊,傳送給Augmenter模組,它根據檢測到的影象位置和攝像機的位姿,對增強現實的內容(視訊)進行投影變換,並將結果用OpenGL繪製出來,顯示在螢幕上。
以上部分概括了本作品的工作內容和流程。
二、 EasyAR引擎簡介
本作品的增強現實技術主要依靠EasyAR提供的SDK編寫,在此對EasyAR做一個簡要的介紹。
EasyAR是Easy AugmentedReality的縮寫,是視辰資訊科技的增強現實解決方案系列的子品牌。它具有強大的跨平臺能力,支援Windows/Mac OS/Android/IOS等主流的作業系統,並且能夠完整的支援Unity3D。作為一個SDK,它的API設計也非常簡潔,對新手比較友好。因此,我選擇了EasyAR進行專案的編寫。
三、 AndroidNDK的配置
由於EasyAR SDK目前不支援純Java的API,所以我們需要同時編寫Java和C++程式碼來使用EasyAR。為了能夠在Android程式中同時執行C++和Java的程式碼,Google提供了Android NDK(Native Development Kit),它可以允許使用者使用C/C++之類的原聲程式碼在Dalvik虛擬機器中執行部分程式。
本次專案也需要配置AndroidNDK,其過程非常繁瑣,不過為了能夠正常執行程式以及備忘,所以也記錄在此:(我使用的IDE是Android Studio 1.5.1,NDK版本為Android NDK r10e)
容易遇到的問題:
如果你在修改了build.gradle之後,遇到了報錯java.lang.UnsatisfiedLinkError: Couldn't load EasyAR from loader dalvik.system.PathClassLoader…… :findLibrary returned null.
這時候需要先CleanProject之後,再Rebuild Project,即可解決這個問題(這個錯誤研究了我一晚上才搞定……心好累)。
四、 介面說明
如上圖所示:左圖是APP的啟動介面,右圖是APP的操作介面。這是我第一次嘗試為APP增加啟動介面的設定。
主要步驟是:
1、 新建名為GuideActivity的Class和guide.xml的佈局檔案,繪製啟動介面和過渡動畫,並且在最後呼叫MainActivity,釋放自己。
2、 在AndroidManifest.xml中增加GuideActivity的屬性資訊,並將其設定為預設啟動的Activity。具體增加的配置資訊如下:
<activity
android:name=".GuideActivity"
android:configChanges="orientation…">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN"/>
<categoryandroid:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
在操作介面上有3個按鈕,從左到右分別是“重播”、“開啟網頁”和“掃描二維碼”。點選它們可以完成相應的功能。
五、 功能實現
首先,在MainActivity的開始處,需要先呼叫EasyAR的初始函式,並且建立GLView用於OpenGL繪圖。
EasyAR.initialize(this, key); // 使用key初始化EasyAR引擎
nativeInit(); //設定匹配圖片namecard和目標配置檔案target.json
GLView glView =new GLView(this);
// 繼承至SurfaceView,它內嵌的surface專門負責OpenGL渲染。
glView.setRenderer(new Render());
// glView 置於檢視的頂部(覆蓋顯示)
glView.setZOrderMediaOverlay(true);
接下來設定3個按鈕的監聽函式,它們的OnClickListener都會呼叫相應的其他函式完成按鈕對應的功能,而OnTouchListener則用於顯示按鈕不同狀態下的圖片,以達到點選按鈕時的動畫效果。
為了建立完整的AR場景,一個CameraDevice需要attached到ImageTracker,然後Augmenter需要週期性地從ImageTracker獲取新的Frame。attach和newFrame操作讓整個AR鏈條開始工作,而資料則在這個鏈條上流動。
從CameraDevice產生的Image會在每幀進入ImageTracker並推動tracker執行。這些Image將跟隨Frame進入Augmenter。
Target從影象和json檔案中構造出來,可以被載入進ImageTracker。當它被tracker檢測或跟蹤到,將會跟隨Frame進入Augmenter。最終移動到AugmentedTarget。
下面介紹AR功能的實現:
在jni資料夾中有5個.cc/.hpp檔案。他們是實現AR效果的核心程式碼。其中ar.hpp和ar.cc中定義了Class AR,實現了包括相機初始化、載入json、圖片檔案、視訊的播放、停止、記憶體釋放、OpenGL的重新整理和Resize。
class AR
{
public:
AR();
virtual~AR();
virtualbool initCamera();
virtualvoid loadFromImage(const std::string& path);
virtualvoid loadAllFromJsonFile(const std::string& path);
virtualbool start();
virtualbool stop();
virtualbool clear();
virtualvoid initGL();
virtualvoid resizeGL(int width,int height);
virtualvoid render();
void setPortrait(bool portrait);
};
在helloarvideo.cc中實現了繼承自Class AR的Class HelloARVideo,它在Class AR的基礎上實現了從攝像頭獲取影象,並從中得到對應的ImageTargetID、二維碼文字。Helloarvideo.cc中實現的若干JNI函式也是C++與Java程式碼的介面。
Renderer.hpp/.cc實現了通過相機的位姿和圖片的位置,將視訊流進行投影變換至合適的尺寸。它主要是為了helloarvideo.cc中的功能服務的。
Java檔案中還有Render和GLView兩個Class。其中Render負責呼叫MainActivity中在helloarvideo.cc裡實現的函式。GLView負責增強後視訊的繪製。詳細資訊可以參照程式碼中的註釋進行了解。
六、 截圖
下圖藍框所示部分即為實時播放的視訊。
下圖為掃描發現二維碼的效果。
Ø 【小結】
通過本次專案,我進一步熟悉了安卓程式設計。在之前實驗的基礎上,又掌握了多了個Activity的使用、Android NDK的使用等新的技能。與此同時,自己編寫程式碼也讓我對增強現實技術有了更深層次的瞭解,看起來十分酷炫的功能能夠被自己實現出來,還是有滿滿的成就感的。
一學期的課程即將結束,我感覺還是收穫頗豐的。雖然剛開始從未接觸過Android程式設計,做起實驗來非常吃力,但是在老師和助教師兄的指導和包容下,我還是一步一步走了下來。總而言之,這門課程非常值得一選,也希望課程能夠越辦越好!