人臉識別第三方sdk比較多,但是大多都是收費的或者限制次數(shù)什么的,虹軟的效果還不錯逼蒙,全免費也不需要聯(lián)網(wǎng)
V1.2版本使用和快速集成:Android集成虹軟人臉、人證對比秘蛇,活體檢測
虹軟官網(wǎng):http://www.arcsoft.com.cn/
官網(wǎng)下載sdk其做,還要引入一個依賴,用來轉換把bitmap以一定的格式轉為byte[]的
api 'com.guo.android_extend:android-extend:1.0.1'
官網(wǎng)的demo里面其實就寫的比較清楚了赁还,總共分為兩個部分妖泄,一個是人臉注冊,一個是人臉識別艘策,先提取人臉特征蹈胡,再和之前提取的比較得出相似度,可以根據(jù)相似度來判斷是不是一個人
人臉注冊
就是提取人臉的特征朋蔫,一張圖片可以識別出多個人臉特征(如果有多個人臉)罚渐,特征是一個byte數(shù)組,其實不用圖片驯妄,獲取相機的預覽回調獲取圖片數(shù)據(jù)這種方法也是很好的荷并,反正傳入圖片數(shù)據(jù)就可以,分為以下幾步:
初始化要提取人臉識別的圖片數(shù)據(jù)
//初始化圖片數(shù)據(jù)
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的集合青扔,用來保存?zhèn)魅胍鏅z測的人臉信息源织,其中包括了人臉的角度和一個Rect對象翩伪,Rect對象就是人臉在圖片中的位置,可以根據(jù)這個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);
根據(jù)獲取到的AFD_FSDKFace集合和原圖像獲取人臉的特征谈息,每個AFD_FSDKFace都可以獲取到一個AFR_FSDKFace對象缘屹,包括就是一個byte[]類型的變量mFeatureData用來保存人臉特征,和一個引擎定義的特征信息數(shù)據(jù)長度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就是需要的人臉特征轻姿,自己隨便保存一下,人臉識別的時候再拿出來對比
人臉識別
人臉識別方式就是再獲取到人臉的特征和之前保存的人臉特征對比逻炊,獲取的方式有很多互亮,除了上面的圖片來獲取以外還可以通過調用相機的預覽回調來獲取數(shù)據(jù)來獲取人臉的特征再去對比,這樣體驗比較好和現(xiàn)在手機常用的人臉識別方法一樣嗅骄,自定義相機就不寫出來了胳挎,步驟如下:
//初始化
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);
//相機預覽回調獲取數(shù)據(jù)
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();
}
}
};
獲取到數(shù)據(jù)后獲取人臉特征然后開始對比,方法就是這樣溺森,邏輯可以自己設計慕爬,也可以根據(jù)獲取到的人臉數(shù)據(jù)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();
//這是獲取我保存的人臉數(shù)據(jù),就是有個名字加一個人臉特征
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_UninitialFaceEngine();