Android整合虹軟人臉、人證對比,活體檢測

img.png
本文是基於人臉識別v1.2版本進行封裝;虹軟官網已更新為v2.0版本
最近虹軟新增了 人證識別 、 活體檢測 的功能,好像之前的人臉識別也更新過版本,之前一篇文章 ofollow,noindex">用虹軟Android SDK做人臉識別 ,寫過虹軟人臉識別的用法,最近把 人臉識別 、 人證識別 , 活體檢測 功能都簡單的封裝了一下,使用起來可以更簡單一點;但是由於appkey是和so庫繫結的,所以不能直接依賴,需要下載專案換成自己的so庫就能使用或者釋出了,還是挺方便的
虹軟人臉識別庫的介紹
so庫和appkey是繫結的
以人臉識別為例,它包括 人臉檢測、人臉追蹤、人臉識別、年齡識別、性別識別 這5種引擎,每個引擎都有一個 so庫和jar包 ,申請的5種 AppKey 和 APPID 是和自己下載的so庫是繫結的,不能混淆使用
人臉檢測(FD)
用於獲取靜態圖片的人臉的位置和角度,傳入格式為 NV21 的圖片資料(byte[]),返回一個 AFD_FSDKFace 物件的集合, AFD_FSDKFace 只儲存了一個位置和角度;如果用於視訊流裡面好像也不報錯
public class AFD_FSDKFace { Rect mRect; int mDegree; ...
人臉追蹤(FT)
和人臉檢測一樣,也是用來獲取人臉的位置和角度,不過只適用於獲取視訊流的人臉,也就是在相機的 onPreviewFrame 方法裡面使用,返回的是 AFT_FSDKFace 物件的集合,也只儲存了一個位置和角度;如果用於靜態圖片好像是會報錯的
public class AFT_FSDKFace { Rect mRect; int mDegree; ...
人臉識別(FR)
用於獲取人臉特徵和對比人臉特徵的
獲取人臉特徵,需要傳入格式為 NV21 的圖片資料(byte[])和人臉的位置、人臉的角度,所以需要先用前面的引擎獲取到人臉的資訊,返回一個 AFR_FSDKFace 物件,這個物件也只儲存了人臉特徵(byte[])
對比人臉,需要傳入兩個 AFR_FSDKFace 物件,返回一個 AFR_FSDKMatching 物件,只儲存了相似度
public class AFR_FSDKFace { public static final int FEATURE_SIZE = 22020; byte[] mFeatureData; ... public class AFR_FSDKMatching { float mScore = 0.0F; ...
活體檢測
活體檢測是檢測是不是活人的,也是傳入人臉的位置、人臉的角度,又是一個新的 FaceInfo 物件,傳入的是FaceInfo的集合,返回 LivenessInfo 集合,但是目前只支援單人臉我們只管第一個資料, LivenessInfo 裡面儲存的返回的結果,活體、非活體、人臉超過一個、未知錯誤(經常返回,問題不大)
人證對比
用來對比人臉和身份證的,傳入傳入格式為 NV21 的證件照片(byte[])和人臉的照片,還有各自的圖片大小和比對閾值;返回一個 CompareResult 物件,包括相似度、是否成功等資訊
public class CompareResult { private boolean isSuccess; private double result; ...
人證識別其實是人臉識別的那幾個引擎(FD,FT,FR)的集合,所以有同時整合肯定包衝突了,可以使用人臉識別的so庫,然後把人臉識別的jar包都刪了,使用人證的jar包,人證的啟用碼使用 FR 的啟用碼就行了

螢幕快照 2018-10-11 下午3.41.05.png-15.5kB
其他的年齡、性別的引擎應該都差不多
封裝後的部分功能的展示
初始化AppKey和APPID
new AcrFaceManagerBuilder().setContext(this) .setFreeSdkAppId(Constants.FREESDKAPPID) .setFdSdkKey(Constants.FDSDKKEY) .setFtSdkKey(Constants.FTSDKKEY) .setFrSdkKey(Constants.FRSDKKEY) .setLivenessAppId(Constants.LIVENESSAPPID) .setLivenessSdkKey(Constants.LIVENESSSDKKEY) .create(); }
相機預覽追蹤人臉位置
//初始化人臉追蹤引擎 FaceTrackService faceTrackService = new FaceTrackService(); //設定傳入的圖片的大小 faceTrackService.setSize(previewSize.width, previewSize.height); camera.setPreviewCallback(new Camera.PreviewCallback() { @Override public void onPreviewFrame(byte[] data, Camera camera) { //獲取人臉的位置資訊 List<AFT_FSDKFace> fsdkFaces = faceTrackService.getFtfaces(data); //畫出人臉的位置 drawFaceRect(fsdkFaces); //輸出資料進行其他處理 cameraPreviewListener.onPreviewData(data.clone(), fsdkFaces); ... } });
相機自己實現,獲取人臉位置的程式碼非常簡單,就一句程式碼,畫出人臉的位置實現是用了兩個surfaceView,一個用於相機畫面展示,另一個畫出人臉的位置
畫出人臉的位置
值得注意的是獲取的人臉的位置Rect是傳入的圖片的相對位置,圖片大小是相機預覽設定的大小,畫的時候是畫在了surfaceView上面,surfaceView一般和預覽大小是不一樣的,而且還要考慮畫面是否旋轉、相機的位置等,所以需要先進行轉換
Rect rect1=DrawUtils.adjustRect(rect, previewSizeX, previewSizeY,canvas.getWidth(), canvas.getHeight(), cameraOri, cameraId);
獲取人臉特徵進行註冊
//初始化人臉識別引擎 FaceRecognitionService faceRecognitionService = new FaceRecognitionService(); faceRecognitionService.setSize(width, height); //獲取人臉特徵 AFR_FSDKFace afr_fsdkFace =faceRecognitionService.faceData(data, aft_fsdkFace.getRect(), aft_fsdkFace.getDegree()); tv_status.setText("人臉特徵為:" + afr_fsdkFace.getFeatureData());
aft_fsdkFace為上一步獲取的人臉的位置資訊
相機獲取的人臉和已儲存的人臉進行對比
//獲取儲存的人臉特徵 byte[] faceData=faces.get(0).getData(); //對比人臉特徵 float socre=faceRecognitionService.faceRecognition(afr_fsdkFace.getFeatureData(),faceData); tv_status.setText("相似度為:" + sorce);
afr_fsdkFace為上一步獲取的人臉的特徵, faceData 為已儲存的人臉特徵,也有提供一個人臉和多個對比獲取相似度最高的一個的方法
活體檢測
//啟用活體檢測 LivenessService.activeEngine(new LivenessActiveListener() { @Override public void activeSucceed() { toast("啟用成功"); } @Override public void activeFail(String massage) { LogUtils.log(massage); toast("啟用失敗:" + massage); } }); LivenessService livenessService = new LivenessService(); // List<FaceInfo> faceInfos = new ArrayList<>(); faceInfos.add(new FaceInfo(aft_fsdkFace.getRect(), aft_fsdkFace.getDegree())); //判斷是否是活體 boolean isLive=livenessService.isLive(faceInfos,data);
aft_fsdkFace為上一步獲取的人臉的位置資訊,第一次啟用好像需要聯網
人證對比
//初始化 IdCardVerifyManager.getInstance().init(Constants.IDCARDAPPID, Constants.FRSDKKEY); //bitmap轉NV21資料 byte[] nv21Data = ImageUtils.getNV21(bitmap.getWidth(), bitmap.getHeight(), bitmap); //傳入證件照片 DetectFaceResult result = IdCardVerifyManager.getInstance().inputIdCardData(nv21Data, bitmap.getWidth(), bitmap.getHeight()); //傳入相機獲取的人臉資料 DetectFaceResult result = IdCardVerifyManager.getInstance().onPreviewData(data, mWidth, mHeight, true); //對比相似度 CompareResult compareResult = IdCardVerifyManager.getInstance().compareFeature(THRESHOLD); if (compareResult.isSuccess()) { tv_status.setText("相似度為:" + compareResult.getResult()); }
證件圖片是本地的,轉成了NV21的格式的byte陣列,方法也集成了
圖片獲取人臉特徵
//先把bitmap轉NV21格式 byte[] photoData = ImageUtils.getNV21(bitmap1.getWidth(), bitmap1.getHeight(), bitmap1); //獲取人臉位置資訊 List<AFD_FSDKFace> afd_fsdkFaces = faceFindService.findFace(photoData); for (AFD_FSDKFace afdFsdkFace : afd_fsdkFaces) { //獲取每一個人臉的特徵 AFR_FSDKFace afr_fsdkFace = faceRecognitionService.faceData(photoData, afdFsdkFace.getRect(), afdFsdkFace.getDegree()); }
引擎釋放
livenessService.destoryEngine(); faceTrackService.destoryEngine(); faceRecognitionService.destroyEngine(); IdCardVerifyManager.getInstance().unInit();
效果都還不錯,主要是全部免費,原始碼下載可以直接執行,可以檢視所有功能

螢幕快照 2018-10-11 下午4.50.30.png-32.4kB
demo下載地址: http://lc-fgtnb2h8.cn-n1.lcfile.com/1e5588481efc19352e52.apk