楊波 陶浩 朱劍林 李航高
(中南民族大學(xué)計算機(jī)科學(xué)學(xué)院 湖北省武漢市 430074)
深度學(xué)習(xí)中的圖像識別技術(shù)一直是現(xiàn)代技術(shù)研發(fā)的前沿技術(shù)[1],現(xiàn)代社會生活的方方面面幾乎都有它的身影,有著良好的應(yīng)用前景。將深度學(xué)習(xí)應(yīng)用在圖像識別領(lǐng)域,最早可以追溯到1989年,加拿大教授 Yann Le Cun與其小組成員提出卷積神經(jīng)網(wǎng)絡(luò)并將其應(yīng)用于圖像識別領(lǐng)域。當(dāng)時,卷積神經(jīng)網(wǎng)絡(luò)在小規(guī)模的圖像數(shù)據(jù)集上擁有著最好的成績,但受限于當(dāng)時的技術(shù)水平,之后很長一段時間卷積神經(jīng)網(wǎng)絡(luò)都沒有得到進(jìn)一步發(fā)展[2]。直到2012年10月,加拿大教授 Hinton與自己的小組成員在Image Net競賽中應(yīng)用了卷積神經(jīng)網(wǎng)絡(luò)技術(shù),使卷積神經(jīng)網(wǎng)絡(luò)在圖像識別領(lǐng)域有了實(shí)質(zhì)性的突破,這次之后,卷積神經(jīng)網(wǎng)絡(luò)模型能夠識別和理解一般的自然圖片的內(nèi)容[3]。
在國內(nèi),也有許多將深度學(xué)習(xí)應(yīng)用于圖像識別方面的研究。如,中國水產(chǎn)科學(xué)研究院東海水產(chǎn)研究所的崔雪森與其小組成員將深度學(xué)習(xí)應(yīng)用于微藻種類圖像的識別,成功證實(shí)了深度學(xué)習(xí)方法可以有效鑒定微藻種類[4];西安石油大學(xué)的碩士研究生張文樂研究深度學(xué)習(xí)應(yīng)用于交通路標(biāo)的識別,并成功優(yōu)化深度學(xué)習(xí)模型,提高了識別準(zhǔn)確率[5]。
本研究針對名畫識別,設(shè)計與建立基于卷積神經(jīng)網(wǎng)絡(luò)模型,設(shè)計與實(shí)現(xiàn)了基于Android的應(yīng)用系統(tǒng)。
圖像預(yù)處理主要是使用每張原圖生成其隨機(jī)樣本,其中翻轉(zhuǎn)樣本3張、隨機(jī)仿射透視變換樣本5張、隨機(jī)旋轉(zhuǎn)樣本5張、隨機(jī)仿射透視變換加旋轉(zhuǎn)樣本5張,對原圖進(jìn)行形變的樣本數(shù)(加上原圖)總計19;然后以形變樣本與25張背景圖進(jìn)行位置和alpha通道都隨機(jī)的疊加合成,疊加合成的樣本數(shù)總計有475;每張原圖的樣本數(shù)總計有494。而原圖數(shù)總計有135,所有原圖樣本數(shù)合計有570076。
為了方便讀取圖片以及保存生成的樣本,需要架構(gòu)一個合適的文件目錄結(jié)構(gòu)來存放圖片。本文所選擇的文件目錄結(jié)構(gòu)為“[圖片文件總文件夾]/[每張原圖文件夾(與原圖文件同名)]/[原圖文件]”。本文是通過自動腳本實(shí)現(xiàn)對1000張原圖移入文件目錄結(jié)構(gòu)下。
在Python中通過調(diào)用OpenCV中的flip()實(shí)現(xiàn)圖像鏡像翻轉(zhuǎn),使用函數(shù)將原圖依次變換并保存后,其效果圖如圖1所示。
圖1:鏡像翻轉(zhuǎn)圖樣
本文中使用仿射變換主要是應(yīng)用在圖像的錯切操作。首先需要在圖像的二維坐標(biāo)(以左上角的頂點(diǎn)為原點(diǎn),橫向向左為橫坐標(biāo)的正方向,豎直向下為縱坐標(biāo)的正方向)上取三個不在一條直線上的坐標(biāo)點(diǎn),將其存放在二維數(shù)組中;然后確定三個坐標(biāo)點(diǎn)變換后的位置,一一對應(yīng)存放在二維數(shù)組中。本文通過調(diào)用OpenCV的getAffineTransform函數(shù)獲取整個圖像的變換矩陣M;最后通過OpenCV的warpAffine函數(shù)獲取到變換后的圖像數(shù)據(jù)。最終效果圖如圖2。
圖2:仿射變換圖樣
本文中,使用透視變換主要是為了調(diào)整原圖的立體傾斜角度,為了使生成的樣本更貼近生活中拍出的照片(并不是完全與相機(jī)面平行)。通過OpenCV的getPerspectiveTransform函數(shù)獲取變換矩陣M,然后通過OpenCV的warpPerspective函數(shù)獲取變換之后的圖像數(shù)據(jù),其結(jié)果如圖3。
圖3:透視變換圖樣
由于圖片數(shù)量大,故需要預(yù)先將圖像數(shù)據(jù)進(jìn)行分割處理成計算機(jī)能讀取的大小,經(jīng)過測試,先將圖片數(shù)據(jù)進(jìn)行壓縮為128×128的大小,然后分割為5份,每份中有100張每張原圖的樣本數(shù)據(jù)(除了最后一份,494%100=94,最后一份只有94張每張原圖的樣本數(shù)據(jù)),總計每份中有樣本數(shù)13500。采用HDF5格式,不僅能降低存儲空間,讀取和操作也比較迅速,故本使用HDF5格式保存圖像數(shù)據(jù)。本文在每個原圖文件夾中讀取100個樣本,使用OpenCV中的imdecode方法,將讀取的數(shù)據(jù)保存到HDF5格式文件中。
由于生成HDF5文件也是互不干涉,通過多線程技術(shù)實(shí)現(xiàn)每個線程讀取每個原圖文件夾中的不同的100個樣本。故本文在此處使用線程池,需要傳入每個線程讀取的樣本位置,以保證不會重復(fù)讀取數(shù)據(jù)。
由于分類結(jié)果并不是連續(xù)的數(shù)值特征,在模型訓(xùn)練時其并不方便計算,所以需要將分類結(jié)果轉(zhuǎn)換為獨(dú)熱編碼,使其變?yōu)檫B續(xù)的數(shù)值特征,這樣可以更貼合機(jī)器學(xué)習(xí)算法,方便在模型訓(xùn)練時進(jìn)行計算[6]。獨(dú)熱編碼主要是通過0和1來表示分類狀態(tài)。在本文中,先通過numpy庫的eye函數(shù),生成135×135(原圖數(shù)量)的單位矩陣數(shù)組,然后通過字典生成式,將名稱列表與單位矩陣數(shù)組每行一一對應(yīng)綁定,這樣即可完成分類結(jié)果與獨(dú)熱編碼的綁定。
VGG網(wǎng)絡(luò)模型是卷積神經(jīng)網(wǎng)絡(luò)經(jīng)典模型中的一種,其最主要的特征便是VGG塊:將復(fù)數(shù)個卷積核窗口大小為3×3、向右和向下步長為1的卷積層與單個池化窗口為2×2、向右和向下步長為2的池化層組合。其中卷積層要保證輸入的特征圖的大小不變,池化層使輸入的特征圖大小減半。
本文結(jié)合實(shí)際應(yīng)用需求,將VGG模型進(jìn)行簡化,其VGG塊主要由一個卷積層和一個池化層組成,然后使用了三個VGG塊、一個全連接層塊組成整個網(wǎng)絡(luò)模型,其中在卷積輸出使用的ReLU激活函數(shù);每個VGG塊和全連接層塊之后會增加一個dropout層來抑制部分神經(jīng)元(即權(quán)值)參與運(yùn)算(本文設(shè)置50%的神經(jīng)元不參與運(yùn)算,這樣可以減少運(yùn)算量),防止模型過擬合。其網(wǎng)絡(luò)結(jié)構(gòu)如圖4和圖5所示。
圖4:本文所用卷積神經(jīng)網(wǎng)絡(luò)模型結(jié)構(gòu)圖
圖5:本文所用卷積神經(jīng)網(wǎng)絡(luò)模型的TensorFlow計算圖結(jié)構(gòu)圖
本文的數(shù)據(jù)集有兩種,一種是原始圖像樣本66690份,另一種是將圖像數(shù)據(jù)提取為數(shù)組形式并壓縮保存的純數(shù)字?jǐn)?shù)據(jù)樣本5份。實(shí)際操作中,由于硬件方面的限制,主要使用的是后一種數(shù)據(jù)集,選取前4份作為訓(xùn)練集,后1份作為樣本測試集,如圖6所示。
圖6:訓(xùn)練集文件和具有復(fù)雜生活背景圖的樣本測試集文件
將VGG塊數(shù)分別設(shè)為2、3、4,然后都進(jìn)行100輪(4份數(shù)據(jù)全部訓(xùn)練一遍記為1輪)訓(xùn)練后,然后以剩下的1份作為測試集,來測試對比模型優(yōu)劣。因為VGG塊為4時,特征圖大小就已經(jīng)為8×8,如果再加一個VGG塊并不能取得更好的效果,故只選取VGG塊為2、3、4的樣例進(jìn)行對比。而由于硬件和時間限制,本文暫時只能取訓(xùn)練100輪對比。
經(jīng)過對比,選取了最合適的網(wǎng)絡(luò)模型后,將這個網(wǎng)絡(luò)模型進(jìn)行重復(fù)訓(xùn)練,在訓(xùn)練過程中,模型訓(xùn)練3000輪之后,模型識別精確度約55%。
在Python中開發(fā)基于Android的APP比較便捷,需要調(diào)用Python的APP開發(fā)庫kivy。
使用kivy庫開發(fā)APP時,還可使用kv描述文檔設(shè)置各模塊的參數(shù)和動作來進(jìn)行更簡潔的APP開發(fā)。
獲取圖片主要有兩種方式,一種可以通過文件選擇器直接在設(shè)備內(nèi)存中獲取,另一種就是通過調(diào)用攝像頭拍照獲取。通過文件選擇器直接在設(shè)備內(nèi)存中獲取圖片,主要用到了kivy庫中的FileChooser模塊。使用該模塊的FileChooserIconView子模塊,可以以小視圖的方式瀏覽文件夾。然后當(dāng)用戶選擇文件時,可以獲取改文件的完整路徑,后臺就可根據(jù)該路徑讀取圖片數(shù)據(jù)。
調(diào)用攝像頭拍照獲取,主要是用到了kivy庫中的核心模塊Camera,使用該模塊即可直接調(diào)用攝像頭,然后通過截圖攝像頭內(nèi)的畫面,達(dá)到拍照的效果。
該功能訪問本地文件,將數(shù)據(jù)輸入已訓(xùn)練好的模型然后獲取輸出結(jié)果。這一步的實(shí)現(xiàn),需要用到TensorFlow庫中的train模塊的import_meta_graph函數(shù),通過meta文件加載已訓(xùn)練好的模型結(jié)構(gòu)與參數(shù)。然后使用TensorFlow中的get_default_graph獲取已加載的模型。獲取到模型后,要獲取輸入節(jié)點(diǎn)和輸出節(jié)點(diǎn),就需要通過get_tensor_by_name來獲取節(jié)點(diǎn),獲取到對應(yīng)的節(jié)點(diǎn)后,就可以傳入數(shù)據(jù)并進(jìn)行預(yù)測輸出。結(jié)果如圖7所示。
圖7:識別圖片結(jié)果對比
改主要是將預(yù)測的結(jié)果處理后展示在信息顯示界面。識別圖片功能預(yù)測輸出的是獨(dú)熱編碼,而信息展示功能首先讀取num_name.npy文件獲取保存的字典格式信息(字典中,獨(dú)熱編碼作為鍵,與獨(dú)熱編碼對應(yīng)的圖像名稱作為值),再通過預(yù)測的獨(dú)熱編碼在字典中獲取其對應(yīng)的圖像名稱,然后讀取info.npy文件獲取鍵值分別為圖像名稱與圖像介紹信息的字典格式信息,最后在字典中通過圖像名稱獲取對應(yīng)的圖像介紹信息。結(jié)果如圖8所示。
圖8:信息展示界面
實(shí)際應(yīng)用時,為了保證結(jié)果能更好的滿足用戶需求,需要在實(shí)際應(yīng)用時做一些額外的處理以擴(kuò)大預(yù)測的結(jié)果集。首先將用戶需要識別的圖片復(fù)制為100份,再將100份數(shù)據(jù)使用已訓(xùn)練好的模型進(jìn)行識別預(yù)測,然后統(tǒng)計其識別結(jié)果中每種結(jié)果出現(xiàn)的頻率,取其頻率出現(xiàn)最高的五種結(jié)果,最后將結(jié)果與其對應(yīng)的圖像展示在信息顯示界面,其流程如圖9所示,實(shí)驗結(jié)果如圖10。
圖9:用戶輸入到結(jié)果展示處理過程
圖10:實(shí)際應(yīng)用識別結(jié)果
本文設(shè)計了一套基于卷積神經(jīng)網(wǎng)絡(luò)VGG模型的名畫識別系統(tǒng),實(shí)現(xiàn)了圖像獲取、圖像識別、信息展示等功能。在實(shí)際應(yīng)用中,對識別結(jié)果進(jìn)行對比,發(fā)現(xiàn)要提高識別結(jié)果的準(zhǔn)確度,對拍照要求比較高,例如不能傾斜太嚴(yán)重、目標(biāo)圖像不能占整幅圖像的比重太小等。分析其原因:
(1)模型訓(xùn)練還不夠完美,還需要更多更廣泛的樣本來訓(xùn)練模型;
(2)抽象畫的特征十分復(fù)雜,生活背景圖對其識別的干擾很大。這還需要之后進(jìn)一步的探索。