李殊哲 丁德紅
摘要:為實現多人臉目標的識別,使用FileWatcher監(jiān)測文件夾下新生成的圖片,從這些新的圖片中,利用改進后的虹軟算法實現人臉檢測,再提取其人臉特征值,最后與注冊過的人臉特征值進行對比。該系統采用.Net Frame框架,簡化了原demo中對識別沒有幫助的數據處理程序,糾正了代碼中導致內存泄漏的函數,實現了多線程并發(fā)的多目標識別。
關鍵詞:虹軟算法;多人臉目標;文件監(jiān)控
中圖分類號:TP311.1 ? ? ?文獻標識碼:A
文章編號:1009-3044(2020)31-0215-04
1 背景
人臉識別作為一種新興的生物特征識別技術,依據人的面部特征對身份進行自動鑒別技術[2]。隨著我國計算機技術的不斷發(fā)展,我國在這方面也取得了較好的成就,國家863項目“面像檢測與識別核心技術”通過成果鑒定并初步應用,就標志著我國在人臉識別這一當今熱點科研領域掌握了一定的核心技術。
文獻[4]在低像素人臉識別檢測的過程中,首次將單一圖像分辨率重建的SRCNN算法用于提高人臉檢測率,優(yōu)化改進了對異常值和噪聲的處理,并將MTCNN、S-LBPH以及SRCNN算法結合應用于考勤中取得了較高的考勤率。使用S-LBPH算法克服了傳統LBPH算法不能很好區(qū)分異類間特征的問題。文獻[5]中通過對視頻圖像多人臉并行檢測算法和PCA多人臉識別算法的改進大大提高了單幅人臉的檢測效率,充分利用了視頻圖像幀序列直接的間接信息,在一定條件下提高了人臉識別的正確率,通過新建ORL人臉庫進行檢驗正確率高達97.62%。但是,文中也提到該算法雖然在速度方面有明顯的優(yōu)勢,但在處理遠處人臉或遮擋人臉時識別率有待提高。文獻[6]中作者將多人臉識別應用到反恐維穩(wěn)、案件偵破、服務民生等公共安全領域。并提到在進行多人臉識別算法應用平臺建設過程中,我們不僅要注意技術的創(chuàng)新,也需要將技術于業(yè)務有機結合才能真正的服務于社會。
目前我國各大企業(yè)都給出了自己的免費人臉識別算法。雖然,各企業(yè)都盡可能地簡化了他們的算法接口,但由于其本身的復雜性,大多數人在使用時仍然會遇到大量的問題。而且他們的代碼在使用時也并不完全安全,例如:某些代碼在使用時會造成內存泄漏、某些對象不可以多線程調用。這些問題官方在文檔中并沒有標識,如果要開發(fā)者自行摸索通常需要很長時間。因此,我們撰寫了此文,總結一年以來我們使用虹軟算法開發(fā)的經驗,提醒后續(xù)研究者避免相同的錯誤。
2 系統整體設計
如下圖1,該程序的設計類圖如下:
Form類,這個類表示的是系統中的所有界面類,根據行業(yè)慣例簡化類圖,我們將他們統一放在一個類中表示。
DBOparetor負責提供數據庫操作有關的接口,避免類與數據庫直接接觸,也可以減少訪問數據庫所需編寫的代碼量。這個類與Loader的區(qū)別在于它包含的最底層的數據庫操作,而Loader則是將他的操作組合起來再封裝一次以簡化外部模塊調用時的復雜度。
Comparer類負責將照片與數據庫中的特征碼比對,其結果會傳回到調用模塊。這個類的技術難點在于識別所需的計算量巨大,該類必須大量采用多線程與異步的技術來提升識別速度與避免堵塞UI線程。
FileWatcher類負責調用FileSystemWatcher來控制Comparer對圖像的識別。FileSystemWatcher是微軟提供給開發(fā)者的文件監(jiān)測類,它可以監(jiān)控指定文件夾內一個甚至多個指定類型或指定名稱的文件的生成、修改和刪除。它通過Windows的消息機制來實現,我們只需要編寫回調函數并訂閱其相應事件設定好響應功能就可以。對于這個類的介紹在下面還會詳細描述。我們的程序使用這個類監(jiān)控文件夾內的照片類型文件的生成,這樣一旦有照片放入文件夾內就會調用執(zhí)行函數讓Comparer類對其進行掃描。此外我們還可以一些異常處理的方法來提高程序的可靠性。
Loader類負責從數據庫加載數據。由于在該程序中可能需要在多個表之間查詢,而且還需要有多種查詢模式,因此我們將加載單獨作為一個功能集成了起來。當外部模塊需要查詢數據時不會直接調用DBOparetor類,而是統一使用Loader來獲取數據。
Submiter類負責提交數據。在Comparer類完成數據比對之后,主控模塊通過該類來將數據傳至Web服務器或數據庫服務器。Submiter會直接與DBOparetor交互而不經過Loader,因為他所需要的數據庫操作并不是獲取信息而時提交信息,但是目前Submiter已經不會直接向數據庫提交信息了。這是早期程序提交考勤記錄的方法。那時我們的系統還沒有建立專門管理考勤數據Web服務器,現在有了Web服務之后比對程序的考勤記錄會提交給Web服務器由它來負責管理數據庫。本文僅討論對比算法的使用Web服務器的相關事項不再詳細介紹。
3 文件監(jiān)控模塊
要進行人臉識別就必須有輸入的圖片,本系統通過調用微軟提供的FileSystemWatcher類來監(jiān)控文件夾下的圖片文件。它的主要作用是Listens to the file system change notifications and raises events when a directory, or file in a directory, changes[1].該類可以監(jiān)聽指導文件夾內的五種操作,而我們通過監(jiān)控文件夾內圖片文件的生成操作,一旦有新的圖片文件進入文件夾就會啟動識別程序對其進行識別。
FileSystemWatcher有六個事件,其中五個是當指定文件發(fā)生某種操作時的響應事件,而Error則是FileSystemWatcher本身發(fā)生異常時的響應事件。通過這五個事件我們可以順利的完成對指定文件的所有活動進行處理,當然在本系統里只用到了Created事件。
上面我們講解了如何指定響應函數和要響應的文件操作,接下來讀者可以通過我們的監(jiān)測開始函數及其注釋來了解FileSystemWatcher的監(jiān)控目標的設置。如下FileWatch中的開始函數。
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public void WatcherStart(string StrWarcherPath, string FilterType, bool IsEnableRaising, bool IsInclude)
{
Task.Run(() =>
{
watcher = new FileSystemWatcher();
watcher.Filter = FilterType;
watcher.IncludeSubdirectories = IsInclude;
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.Path = StrWarcherPath;
watcher.Created += Watch_created;
watcher.Error += WatcherError;
watcher.EnableRaisingEvents = false;
watcher.EnableRaisingEvents = IsEnableRaising;
});
}
開始前我們需要一些系列的屬性設置,包括:指定文件夾、選定監(jiān)聽函數等。這里需要額外強調的是函數上方需要添加權限注解,否則監(jiān)控可能會無法開啟。
Watch_created就是Created事件觸發(fā)時對應的相應函數,它的代碼如下:
private void Watch_created(object sender, FileSystemEventArgs e)
{
List
Task> t = compare.GetIndex(image, MainWindow.pEngine);
FileInfo fileInfo = new FileInfo(e.FullPath);
indexes = t.Result;
foreach (int index in indexes) {
if (parent.stus[index].time == null || DateTime.Now - parent.stus[index].time >= parent.TimeSpan)
{
parent.stus[index].time = DateTime.Now;
_ = parent.ShowName(parent.stus[index].name);
parent.Log(parent.stus[index].name + "到勤");
});
}
else{
parent.Log(parent.stus[index].name + "五分鐘內多次出現");
}
}
在省略一部分用于處理異常的函數后可以看到在這個函數中,我們將調用對比模塊對其進行識別。由于C#的事件機制本身是多線程模式的,所以我們可以直接在函數中等待識別結果,而不用擔心阻塞主線程。獲取到照片的結果時,我們要對結果進行判斷,如果該結果五分鐘內未被識別到過判斷為有效考勤,如果五分鐘內出現過就判斷為無效考勤。
4 數據庫設計
在比對照片前首先需要提取作為標準的特征碼,這些特征碼我們將它們作為記錄保存在數據庫中。由于比對程序的數據庫十分簡單,因此在數據庫設計時做了說明但沒有設計具體設計,這里做一個補充說明。比對子系統所用到的數據只有臉部特征。其數據表的具體結構如下表。
程序開啟時,主控模塊會調用Load類將這些數據加載到內存中。在之后的比對過程中Comparer類直接訪問內存來獲取特征碼。
5 比對算法介紹
本系統采用的人臉識別算法為虹軟的免費算法,其具有離線、快速、識別率高等特點。在當時選擇算法時主要考慮到的就是離線或在線的問題。由于我們的系統要對密集人群進行考勤,所以在線方式的考勤勢必大大增加網絡壓力,而市面上免費又離線的人臉識別算法只有虹軟,因此我們選擇了他們的算法。
5.1 Entity
這個文件夾中包含了程序中將會使用到的實體類,目前這文件夾中只有一個類ImageInfo。這個類可以保存圖片的寬高等信息,其中還有一個IntPtr指針用于保存照片信息。因為該sdk是有C++編寫,因此在使用時參數常常要以非托管內存的形式傳入,將圖片轉化為這個類之后可以方便sdk對其進行識別
5.2 SDKModels
這個文件夾較為重要是一些sdk所用到數據結構。
這里面比較常用的有ASF_MultiFaceInfo類,用于保存多人臉識別后的函數返回值。ASF_SingleFaceInfo類,用于保存單人臉識別后的識別信息。值得一提的是,這里的函數返回值并不會直接是這里的類,因為虹軟的算法原本是由C++編寫的,實際上的返回值是一個C++的結構體。C++的結構體返回到C#中將會是一個IntPtr指針,虹軟還另給了函數將這些IntPtr指針轉化為這些實體類。
這個文件中的實體類與Entity十分相似,但這個文件夾中的實體類是對應著sdk算法中的實體類的。也就是動態(tài)庫里C++結構體的C#表達形式。
5.3 SDKUtils
這個文件夾中保存的是虹軟識別算法的函數入口。這個文件夾中只有一個ASFFunctions類,虹軟通過DllImport注解將dll中由C++編寫的函數的入口導出到這個類中。如圖5是一個函數導入的語法示范,是將名為ASFActivation的函數從dll中導入。
///
/// 激活人臉識別SDK引擎函數
///
/// SDK對應的AppID
/// SDK對應的SDKKey
///
[DllImport(Dll_PATH, CallingConvention = CallingConvention.Cdecl)]
public static extern int ASFActivation(string appId, string sdkKey);
這樣這些原本由C++編寫的算法就可以在這個類中被調用。這個文件夾中包含了所有虹軟sdk的識別函數。下面我們介紹三個特別重要的函數。這個三個函數在識別的過程中起到了非常重要的作用。
ASFDetectFaces函數,這個函數用于監(jiān)測是否由人臉。其會通過out參數的形式返回一個對應ASF_MultiFaceInfo的IntPtr指針,拿到這個返回值后我們就可以得到圖片中的人臉個數和具體位置、區(qū)域。
ASFFaceFeatureExtract函數用于提取某個區(qū)域的人臉特征。這個函數可以通過out參數來返回人臉特征碼以供后續(xù)的比對函數使用。
ASFFaceFeatureCompare比對函數,這個函數通過out參數返回一個float類型的值,這個值指示了兩個特征碼之間的相似度。
5.4 Utils
Utils文件夾中主要保存了處理照片信息的類和處理非托管內存的類。這些類可以將照片和IntPtr指針分別處理成易于操作的ImageInfo類或SDKModeles中的類。在識別中主要起到處理數據的作用。
Utils與SDKUtils的區(qū)別在于,SDKUtils中包含的是sdk中的函數,在C#中只是引入而沒有源碼,這些函數往往直接與識別相關。而Utils則是一些使用C#編寫的代碼,可以直接在文件中看到它們的實現方式,這些函數通常是做數據處理起到輔助識別的作用。
6 人臉檢測
在人臉檢測時需要有三個步驟,第一步處理照片,第二步提取人臉區(qū)域,第三步提取區(qū)域特征碼,第四步比對特征碼。
處理照片:程序通過FileSystemWatcher檢測到有文件生成時會得到文件的絕對路徑,然后程序會通過該路徑得到相應的圖片。由于比對算法不支持某些比例下的照片,得到照片之后程序會進行一個寬高比的調整將寬度統一改為4的整數倍。然后通過讀取圖片文件,將文件里的信息讀取到內存之中。由于該算法本來是由C++編寫,所以這里需要將圖片信息讀取到非托管內存中。到這里圖片數據的處理就結束了。
提取特征碼:對照片數據的處理完成后就可以調用ASFDetectFaces函數對照片進行照片中的人臉部分進行劃分,識別出人臉在照片中的具體位置,在官方給出的demo中沒有這一步驟,但是據我們的測試這樣做可以有效地降低非本人照片的識別率,一定程度上的增加總體識別率。
提取人臉區(qū)域特征碼:調用ASFFaceFeatureExtract函數對指定區(qū)域進行特征碼的提取。
比對特征碼:使用ASFFaceFeatureCompare將特征碼與所有數據庫中的已有特偵碼進行比對得到相似度最高的人臉。
7 結束語
本文詳細描述了如何使用微軟的FileSystemWatcher類對指定文件夾下的圖片文件進行監(jiān)控,并在新文件出現時使用虹軟的人臉識別算法識別對比。雖然由于其算法免費使用但不開源導致我們能施展的空間有限,但是我們還是在這種情況下,利用有限的條件對識別的速度和準確率進行改進。
1)在數據處理方面,我們精簡了Utils文件夾中的數據處理代碼,在不影響識別率的情況下將速度提升了5-6倍;此外在實際使用時,我們發(fā)現官方給出的CutImage函數會造成內存泄漏問題,請讀者在自己編程時務必自行編寫裁剪函數。
2)通過識別前的處理事先得到人臉的進一步位置,將出現人臉的位置圖片進一步裁剪下來,再提取特征值。這樣減少了特征值的提取范圍,經測試這一操作減少了誤判的概率在一定情況下有效提升了識別率,而且識別的速度也有一定的提升。
人臉識別技術已經成功應用到金融、軍工等多個領域, 行業(yè)發(fā)展優(yōu)勢明顯[3]。而本系統的代碼實現簡潔、高效,并且可以實現多線程識別(論文中沒有提及,但是實際上現有代碼中已經實現),讀者可以這些代碼和講解為基礎結合類名進一步理解SDK接口,將人臉識別廣泛地應用于各個領域。
參考文獻:
[1]微軟API參考文檔[EB/OL].[2020-05-14].https://docs.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=netcore-3.1.
[2] 李彬,曲寒,冰靳薇.淺談人臉識別技術在智能視頻監(jiān)控中的應用與發(fā)展趨勢[J].中國安防,2011(3):50-53.
[3] 耿艷萍.淺談人臉識別技術及其應用[J].科學之友,2011(7):131-133.
[4] 張玉云.基于MTCNN和S-LBPH算法的多人臉識別在課堂考勤中的應用[D].成都:西南交通大學,2019.
[5] 程戰(zhàn)員.面向智能視頻監(jiān)控的多人臉識別算法研究[D].武漢:武漢理工大學,2013.
[6] 李仁杰,曾鵬,張龍.多人臉識別算法和大數據融合技術在公共安全領域的應用研究[C].2019年全國公共安全通信學術研討會優(yōu)秀論文集,2019.
【通聯編輯:謝媛媛】