用虹軟Android SDK做人臉識別
人臉識別第三方sdk比較多,但是大多都是收費的或者限制次數什麼的,虹軟的效果還不錯,全免費也不需要聯網
V1.2版本使用和快速整合:Android整合虹軟人臉、人證對比,活體檢測
虹軟官網:http://www.arcsoft.com.cn/
官網下載sdk,還要引入一個依賴,用來轉換把bitmap以一定的格式轉為byte[]的
api 'com.guo.android_extend:android-extend:1.0.1'
官網的demo裡面其實就寫的比較清楚了,總共分為兩個部分,一個是人臉註冊,一個是人臉識別,先提取人臉特徵,再和之前提取的比較得出相似度,可以根據相似度來判斷是不是一個人
人臉註冊
就是提取人臉的特徵,一張圖片可以識別出多個人臉特徵(如果有多個人臉),特徵是一個byte陣列,其實不用圖片,獲取相機的預覽回撥獲取圖片資料這種方法也是很好的,反正傳入圖片資料就可以,分為以下幾步: 初始化要提取人臉識別的圖片資料
//初始化圖片資料 byte[] data = new byte[mBitmap.getWidth() * mBitmap.getHeight() * 3 / 2]; ImageConverter convert = new ImageConverter(); convert.initial(mBitmap.getWidth(), mBitmap.getHeight(), ImageConverter.CP_PAF_NV21); if (convert.convert(mBitmap, data)) { Log.d(TAG, "convert ok!"); } convert.destroy();
首先獲取了一個AFD_FSDKFace的集合,用來儲存傳入引擎檢測的人臉資訊,其中包括了人臉的角度和一個Rect物件,Rect物件就是人臉在圖片中的位置,可以根據這個Rect來把人臉部分標記出來什麼的
//初始化 AFD_FSDKEngine engine = new AFD_FSDKEngine(); AFD_FSDKVersion version = new AFD_FSDKVersion(); List<AFD_FSDKFace> result = new ArrayList<AFD_FSDKFace>(); //設定最多識別5張人臉 AFD_FSDKError err = engine.AFD_FSDK_InitialFaceEngine(FaceDB.appid, FaceDB.fd_key, AFD_FSDKEngine.AFD_OPF_0_HIGHER_EXT, 16, 5); //獲取人臉資訊 result err = engine.AFD_FSDK_GetVersion(version); err = engine.AFD_FSDK_StillImageFaceDetection(data, mBitmap.getWidth(), mBitmap.getHeight(), AFD_FSDKEngine.CP_PAF_NV21, result);
根據獲取到的AFD_FSDKFace集合和原影象獲取人臉的特徵,每個AFD_FSDKFace都可以獲取到一個AFR_FSDKFace對
象,包括就是一個byte[]型別的變數mFeatureData用來儲存人臉特徵,和一個引擎定義的特徵資訊資料長度int型別的變數
FEATURE_SIZE(不用管這個)
//初始化
AFR_FSDKVersion version1 = new AFR_FSDKVersion();
AFR_FSDKEngine engine1 = new AFR_FSDKEngine();
AFR_FSDKFace result1 = new AFR_FSDKFace();
AFR_FSDKError error1 = engine1.AFR_FSDK_InitialEngine(FaceDB.appid, FaceDB.fr_key);
error1 = engine1.AFR_FSDK_GetVersion(version1);
//獲取人臉特徵 mAFR_FSDKFace
error1 = engine1.AFR_FSDK_ExtractFRFeature(data, mBitmap.getWidth(), mBitmap.getHeight(), AFR_FSDKEngine.CP_PAF_NV21, new Rect(result.get(0).getRect()), result.get(0).getDegree(), result1);
if(error1.getCode() == error1.MOK) {
mAFR_FSDKFace = result1.clone();
}
//銷燬引擎,釋放記憶體資源
engine1.AFR_FSDK_UninitialEngine();
engine.AFD_FSDK_UninitialFaceEngine();
其實mAFR_FSDKFace裡面的byte[]型別的變數mFeatureData就是需要的人臉特徵,自己隨便儲存一下,人臉識別的時候再拿出來對比 人臉識別 人臉識別方式就是再獲取到人臉的特徵和之前儲存的人臉特徵對比,獲取的方式有很多,除了上面的圖片來獲取以外還可以通過呼叫相機的預覽回撥來獲取資料來獲取人臉的特徵再去對比,這樣體驗比較好和現在手機常用的人臉識別方法一樣,自定義相機就不寫出來了,步驟如下:
//初始化
public static List<AFT_FSDKFace> resultAtf;
AFT_FSDKEngine engine;
AFT_FSDKError err;
AFR_FSDKEngine engine2;
AFR_FSDKError error2;
AFR_FSDKFace result;
byte[] faceData;
resultAtf = new ArrayList<>();
engine = new AFT_FSDKEngine();
err = engine.AFT_FSDK_InitialFaceEngine(FaceDB.appid, FaceDB.ft_key, AFT_FSDKEngine.AFT_OPF_0_HIGHER_EXT, 16, 5);
err = engine.AFT_FSDK_GetVersion(new AFT_FSDKVersion());
engine2 = new AFR_FSDKEngine();
result = new AFR_FSDKFace();
error2 = engine2.AFR_FSDK_InitialEngine(FaceDB.appid, FaceDB.fr_key);
error2 = engine2.AFR_FSDK_GetVersion(new AFR_FSDKVersion());
//需要設定相機預覽圖片的格式
para.setPreviewFormat(ImageFormat.NV21);
//相機預覽回撥獲取資料
byte[] faceData;
private Camera.PreviewCallback mPreViewCallback = new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(final byte[] data, Camera camera) {
if (startFaceCheck) {
err = engine.AFT_FSDK_FaceFeatureDetect(data, mWidthPicture, mHeightPreview, AFT_FSDKEngine.CP_PAF_NV21, resultAtf);
faceData = data.clone();
}
}
};
獲取到資料後獲取人臉特徵然後開始對比,方法就是這樣,邏輯可以自己設計,也可以根據獲取到的人臉資料AFD_FSDKFace來實時的畫出人臉的位置
//獲取到人臉的資訊
resultAtf.clear();
startFaceCheck = true;
error2 = engine2.AFR_FSDK_ExtractFRFeature(faceData, mWidthPicture, mHeightPreview, AFR_FSDKEngine.CP_PAF_NV21, resultAtf.get(resultAtf.size() - 1).getRect(), resultAtf.get(resultAtf.size() - 1).getDegree(), result);
//初始化對比
AFR_FSDKMatching score = new AFR_FSDKMatching();
AFR_FSDKFace input = new AFR_FSDKFace();
//這是獲取我儲存的人臉資料,就是有個名字加一個人臉特徵
List<FaceDiscern> faceDiscernList = MLiteOrm.getInstance().query(FaceDiscern.class);
for (int i = 0; i < faceDiscernList.size(); i++) {
final String name = faceDiscernList.get(i).getUserName();
input.setFeatureData(faceDiscernList.get(i).getFaceId());
error2 = engine2.AFR_FSDK_FacePairMatching(result, input, score);
//獲取相似度
float max = 0.0f;
max = score.getScore();
if (max > 0.6) {
ToastUtils.showLong("驗證通過,操作人:" + name);
}
}
//銷燬引擎,釋放記憶體資源
engine2.AFR_FSDK_UninitialEngine();
engine.AFT_FSDK_UninitialFac