??? 摘 要: 介紹了QR碼識別的基本原理,并設計了一個基于Symbian智能手機的QR碼識別系統" title="識別系統">識別系統,重點說明了系統在Symbian平臺上實現時,圖像采集、異常處理" title="異常處理">異常處理和代碼移植等方面的問題。測試表明,該系統可以快速、準確地識別QR碼,并有效地處理圖像傾斜和投影形變等問題。
??? 關鍵詞: QR碼? 智能手機? Symbian操作系統? Series 60平臺
?
??? 由于內置高分辨率攝像頭手機的逐漸普及,催生了一種新的二維碼應用模式——手機二維碼。手機二維碼是指將相關信息使用二維碼編碼,并以各類業務的形式在手機里存儲、閱讀和傳播[1]。手機既是二維碼信息的載體,也是二維碼的識讀設備。目前,手機二維碼在歐美、日韓等發達國家和地區已有較成熟的市場應用。2006年9月,中國移動也正式推出了手機二維碼業務,并表示手機二維碼將會成為移動增值服務的重要內容之一。
??? QR碼(Quick Response Code)是由日本Denso公司于1994年9月研制的一種矩陣式二維碼,它除具有其他二維碼所具有的信息容量大、可靠性高、可表示漢字及圖像有多種文字信息、保密防偽性強等優點外,還具有如下主要特點:超高速識讀,全方位識讀,能夠有效地表示中國漢字和日本漢字[2]。本文設計了一個基于Symbian智能手機的QR碼識別系統,重點介紹了系統在Symbian平臺上實現時需要注意的關鍵問題。測試表明,該系統可以快速、準確地識別QR碼,并能有效地處理圖像傾斜和投影形變等問題。
1 QR碼符號簡介
??? QR碼符號是由正方形模塊構成的正方形陣列,它由編碼區域和功能圖形構成。其中,編碼區域包含格式信息、版本信息、數據和糾錯碼字;功能圖形由尋像圖形、分隔符、定位圖形和校正圖形組成。QR碼符號共有40種規格。版本1的規格為21×21模塊,每一版本的符號比前一版本每邊增加4個模塊,直到版本40,規格為177×177模塊。QR碼符號的示例見圖1。
?
?
2 QR碼的識別
??? 這一過程的基本思路是將攝像頭采集到的彩色圖像I(x,y)進行灰度化;然后用適當的閾值T對灰度圖像進行二值化處理,從而得到二值圖像B(x,y);接著在二值圖像中掃描位置探測圖形,通過3個位置探測圖形,求出QR碼的4個頂點坐標和旋轉角度,然后將QR碼旋轉至水平位置,并把QR碼從圖像I(x,y)分割出來。
2.1 圖像的二值化
??? 圖像二值化的關鍵在于閾值的選取。二值化閾值計算方法主要有直方圖雙峰法、微分直方圖法和最大類間方差法。在基于手機的QR碼識別系統中,由于人在拍攝過程中會有意識地“瞄準”QR碼符號,并使其盡量充滿取景器的主要區域,因此采集到的QR碼圖像一般都比較簡單,淺色的背景與條碼基本模塊構成的正方形陣列形成了較大的反差,其直方圖經過平滑之后,呈現出明顯的“雙峰”特性。這樣,使用簡單的直方圖雙峰法就可以快速地確定圖像的二值化閾值。
2.2 QR碼的定位
??? QR碼符號的尋像圖形包括3個相同的位置探測圖形,分別位于左上角、右上角和左下角。每個位置探測圖形可以看作是由3個重疊的同心正方形組成,它們分別為7×7個深色模塊、5×5個淺色模塊和3×3個深色模塊。位置探測圖形的模塊寬度比為1:1:3:1:1。符號中其他地方遇到類似圖形的可能性極小,因此可通過識別這三個位置探測圖形來確定視場中符號的位置和方向,從而使迅速識讀QR碼符號成為可能。在圖2中,a、b、c為QR碼符號旋轉不同角度時穿過位置探測圖形中心的掃描線。可以看出,旋轉的角度不影響掃描線上的模塊寬度之比。實際中,由于噪聲、投影形變等因素的影響,應該允許這個比例有一定的偏差。
?
?
2.3 圖像的旋轉
檢測到3個位置探測圖形之后,就可以計算出QR碼的4個頂點坐標和旋轉角度。根據這些參數即可將QR碼旋轉至水平位置并從圖像中分割出來。在對圖像做旋轉時,變換之后的坐標不一定是整數,因此要對變換之后整數坐標的像素值進行估計。這里采用的是雙線形插值算法。假設輸出圖像某像素的位置坐標通過反向變換得到的浮點坐標為(i+u,j+v),其中i,j為非負整數,u,v為[0,1)區域的浮點數,則該像素的值f(i+u,j+v)可由原圖像中坐標為(i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)的4個像素的值決定,即[3]:
??? f(i+u,j+v)=(1-u)(1-v)f(i,j)+(1-u)vf(i,j+1)+u(1-v)f(i+1,j)+uvf(i+1,j+1)
??? 將QR碼從圖像中分割出來之后,建立采樣網格,對網格的每一交點上的圖像像素取樣,即可得出QR碼符號的位圖矩陣。
3 QR碼的解碼
??? 這一過程將QR碼符號數據按照QR碼標準進行解碼,從而得到存儲在其中的用戶信息。解碼的流程如下[2]:
??? (1)識讀格式信息,按需要去除掩模" title="掩模">掩模圖形并完成對格式信息模塊的糾錯,識別糾錯等級與掩模圖形參考。
??? (2)識讀版本信息,確定符號的版本。
??? (3)用掩模圖形(掩模圖形參考已從格式信息中得出)對編碼區域的位圖進行異或處理,消除掩模。
??? (4)根據模塊排列規則,識讀符號字符,恢復信息的數據與糾錯碼字。
??? (5)用與糾錯級別信息相對應的糾錯碼字檢測錯誤,如果發現錯誤,立即糾錯。
??? (6)根據模式指示符和字符計數指示符將數據碼字劃分成多個部分。
??? (7)按照使用的模式譯碼得出數據字符并輸出結果。
4 QR碼識別系統在Symbian平臺上的實現
4.1 Symbian操作系統
??? 智能手機是一種擁有開放型操作系統的手機,用戶可以在這個平臺上安裝各種各樣的應用程序" title="應用程序">應用程序,從而使手機的功能得到無限擴充。目前,主流的智能手機操作系統有三種" title="三種">三種:Symbian、Windows Mobile和Linux。其中Symbian以其平臺的開放性、較低的授權費用、眾多廠商的支持、對硬件要求低、第三方軟件豐富等優勢,成為智能手機市場上應用最為廣泛的產品。Symbian由Psion公司的EPOC(Electronic Piece of Cheese)操作系統發展而來,是一個32位的多任務操作系統,其內核由基礎組件(微核、設備驅動程序和用戶庫)、中間件(系統服務、安全和應用程序框架)和通信組件(電話、消息和個人區域網絡)構成[4]。由于不同的終端產品在屏幕尺寸、用戶輸入方式等方面的差異,Symbian給出了用戶界面風格的三種參考設計:Pearl、Crystal和Quartz,最終演變為Symbian上的三種主要平臺:Series 60、Series 80和UIQ。Series 60針對屏幕分辨率為176×208像素、單手操作的智能手機;Series 80針對屏幕分辨率為640×200像素、采用標準鍵盤輸入的高端智能手機;UIQ針對采用筆式輸入(觸摸屏)的智能手機。其中Series 60是應用最為廣泛的平臺。本系統就是在基于Symbian Series 60平臺的手機上實現的。
4.2 圖像采集
??? 系統在手機上實現時, 待識別圖像的采集是一個比較關鍵的問題。在Series 60平臺上,CCamera類包裝了攝像頭相關的API。為了使用這些API,應用程序必須實現一個MCameraObserver(或MCameraObserver2)的派生類。MCameraObserver類與CCamera類之間的關系是觀測者設計模式(Observer Design Pattern)在Symbian系統中的具體體現。圖像采集可通過以下三種方式實現:
??? (1)用CCamera∷CaptureImage()啟動靜態圖像的捕獲。當其調用完成之后,MCameraObserver∷ImageReady()會被異步調用。用戶可在該函數中訪問剛剛捕獲的圖像。此方式一般用來實現手機的照相功能。
??? (2)用CCamera∷StartVideoCapture()啟動視頻捕獲。當視頻緩沖區被預置數目的視頻幀填充之后,MCameraObserver∷FrameBufferReady()會被異步調用。用戶可在該函數中訪問視頻緩沖區。此方式一般用來實現手機的攝像功能。
??? (3)用CCamera∷StartViewFinderBitmapsL()啟動取景器(View Finder)數據的傳輸。當其調用完成之后,MCameraObserver∷ViewFinderFrameReady()會被周期性地調用。用戶可在該函數中訪問剛剛獲取的視景幀(View Finder Frame)。此方式一般用來實現手機照相或攝像過程中的取景器功能。
??? 第一種方式采用非連續模式采集圖像,效率較低且不利于人在識別過程中的主動參與。第二種方式雖是連續模式,但在視頻采集過程中,攝像頭的閃光燈會一直亮著,不符合低功耗原則。第三種方式采集圖像的分辨率高,有利于識別精度的提高,但會增加處理時間。最終采用第三種方式并折中處理,選擇400×300的分辨率。
??? ViewFinderFrameReady()函數的處理流程如圖3所示。視景幀是一個CFbsBitmap類型的位圖對象。可以通過CFbsBitmap::DataAddress()函數獲得位圖中第一個像素(位于位圖的左上角)的地址,從而實現對位圖數據的直接訪問。視景幀根據手機類型的不同,具有不同的顏色格式。所以需要首先通過CFbsBitmap∷DisplayMode()函數獲得圖像的顏色格式,然后采用相應的方式獲取各像素的R、G、B分量,以便將彩色圖像轉換為灰度圖像。
?
4.3 異常處理
??? 對手機而言,內存泄漏是十分嚴重的問題。因為手機的內存資源非常有限,而它又通常會連續運行很長時間不重啟,這樣,異常處理就顯得尤為重要。Symbian系統采用了一套不同于標準C++的異常處理機制。
??? Symbian對異常處理的基本支持包括:(1)TRAP和TRAPD宏,用作捕獲異常,類似于標準C++中的try和catch。(2)異常退出(Leave)機制,其作用類似于標準C++中的throw。
??? 清理棧(Cleanup Stack)是Symbian避免內存泄漏的主要手段之一。請看如下示例代碼:
void DoExampleL(){
CSomeObject*myObject=new(ELeave) CSomeObject;
CallLeavingMethodL();
delete myObject;}
??? 代碼使用重載的操作符new(ELeave)為CSomeObject類的新實例分配動態內存。在Symbian中,為簡單對象在堆內存上分配空間基本都采用這種方式。ELeave參數表明內存分配失敗時會發生異常退出。傳統的new操作符無法利用異常退出機制,只是在極少數情況下才被使用。CallLeavingMethodL()是一個調用時可能會發生異常退出的函數。當CallLeavingMethodL()發生異常退出時,DoExampleL()的函數棧會被釋放。這就意味著,局部指針變量myObject會被銷毀,但它指向的堆內存卻沒有被釋放,從而發生了內存泄漏。Symbian使用清理棧(CleanupStack類在e32base.h中定義)來解決這個問題。基本用法是:在調用可能會發生異常退出的代碼之前,使用PushL()方法將任何指向堆內存的局部指針壓入清理棧內。若發生異常退出,清理棧確保所有相關的資源都被釋放。如果沒有發生異常,則使用Pop()方法將那些指針彈出。這樣,DoExampleL()函數可以修改為:
void DoExampleL(){
CSomeObject*myObject=new(ELeave) CSomeObject;
CleanupStack∷PushL(myObject);
CallLeavingMethodL();
CleanupStack∷Pop(myObject);
delete myObject;}
??? 可以使用“CleanupStack∷PopAndDestroy(myObject);”代替上述代碼的最后兩句。有三種情況可能會使代碼發生異常退出:
??? (1)使用了退出函數:User∷Leave(),User∷LeaveIfError(),User∷LeaveNoMemory(),或User∷LeaveIfNull()。
??? (2)使用了重載的new(ELeave)操作符。
??? (3)調用了一個可能會異常退出的函數。
??? 構造過程中需要分配資源的對象被稱為復雜對象,其所屬類通常為CBase類的派生類。在堆內存上構造復雜對象時,若其構造函數發生異常退出,則會發生內存泄漏。所以復雜對象采用兩階段構造過程,這是Symbian避免內存泄漏的另一主要手段。例如,使用CText類表征解碼之后的文本,它的一個私有成員變量textBuf8為指向HBuf8類描述符(Symbian主要使用描述符來處理字符串)的指針。下面為兩階段構造過程的示例代碼:
//第一階段構造
CText∷CText(){}
//第二階段構造
void CText∷ConstructL(TUint aMaxTextLength)
{ textBuf8=HBufC8∷NewL(aMaxTextLength);}
??? 這樣,每次構造復雜對象都需要兩行代碼。為了避免這個麻煩,通常會提供兩個靜態成員函數:
//不將指向函數返回對象的指針留在清理棧內
CText*CText∷NewL(TUint aMaxTextLength){?
CText*self=CText∷NewLC(aMaxTextLength);
CleanupStack∷Pop(self);
return self;}
//將指向函數返回對象的指針留在清理棧內
CText*CText∷NewLC(TUint aMaxTextLength){
CText*self=new(ELeave) CText;
CleanupStack∷PushL(self);
self->ConstructL(aMaxTextLength);
return self;}
4.4 代碼移植
??? 系統開發并不需要從零開始編寫所有程序,有很多地方(例如直方圖雙峰法、雙線性插值和RS碼糾錯算法等)可將現成的Windows平臺的代碼移植到Symbian平臺上來。在移植過程中,除了異常處理方式需要改變之外,還需要注意以下幾點:
??? (1)將標準C++的內建數據類型替換為對應的或者合適的Symbian C++的基本數據類型,以保持平臺的獨立性。例如,用TInt類型替換int類型。
??? (2)在Symbian系統中,由于GUI應用程序(后綴為.app的程序)的棧的默認尺寸只有8KB,所以不要在這類程序中使用尺寸較大的局部變量。遇有需要的情況(例如大數組),將對象分配在堆內存上。
??? (3)在Symbian 8.1a及以前版本的操作系統中,DLL(Dynamic Link Library)程序不能使用可寫的靜態數據(例如全局變量);在Symbian 8.1b及以后版本的操作系統中,盡管DLL程序支持可寫的靜態數據,但不推薦使用。Symbian的GUI應用程序實際上是apprun.exe程序啟動的DLL程序,所以在這類程序中不可以使用全局變量。代碼移植時,應將這些變量封裝到類中。另一種解決方案是將原代碼移植為Symbian服務器程序(后綴為.exe的程序,支持可寫的靜態數據),并向客戶程序提供API接口。
??? (4)Symbian不支持標準模板庫(STL),但提供了一些集合類來支持數組、鏈表等數據結構。
??? 系統基于S60 2nd Edition SDK(FP3)開發,采用的開發環境為Metrowerks公司的CodeWarrior。系統在Nokia N70上做了性能測試,可以達到平均約0.6s的識別速度。在沒有微距模式支持的情況下,可以識別的QR碼符號的最高版本為10。測試還表明,系統可以有效地處理QR碼圖像傾斜和投影失真等問題。系統在Nokia 3230和Nokia 6680上做了兼容性測試,也取得了比較好的效果。
參考文獻
[1] 梁鵬.手機二維碼業務研究[J].電信科學,2006;(12):36-39.
[2] 張成海,郭衛華,羅秋科.QR Code二維碼——一種新型的矩陣符號[M].北京:中國標準出版社,2000.
[3] 劉宏偉,嚴妍.快速響應碼的識別和解碼[J].計算機工程與設計,2005;26(6):1560-1562.
[4] Digia Inc.Programming for the series 60 platform and?symbian OS[M].Chichester:John Wiley & Sons Ltd,2003.