如何集成
- 虹软开发者中心登录[虹软官网](https://ai.arcsoft.com.cn/ucenter/user/userlogin)
- 进入开发者中心,新建应用获取APPID 和 APPSDKKEY 后面要用到
- 下载所需要的SDK
- 查看集成文档,官方文档写的很详细地址(https://ai.arcsoft.com.cn/manual/arcface_windows_guideV2.html)
如何调用
-在你集成的应用内Activity或SplashActivity
编写如下方法,引擎初始化
/**
* 激活引擎
*
*/
public void activeEngine() {
Observable.create(new ObservableOnSubscribe<Integer>() {
@Override
public void subscribe(ObservableEmitter<Integer> emitter) throws Exception {
FaceEngine faceEngine = new FaceEngine();
int activeCode = faceEngine.active(SplashActivity.this, CommMacro.ARC_APPID, CommMacro.ARC_SDKKEY);
emitter.onNext(activeCode);
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<Integer>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(Integer activeCode) {
if (activeCode == ErrorInfo.MOK) {
Toast.makeText(getApplicationContext(),"激活成功",Toast.LENGTH_SHORT).show();
Log.d("Arc", "激活成功了: ");
} else if (activeCode == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED) {
//Toast.makeText(getApplicationContext(),"已激活,无需再次激活",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),"激活失败",Toast.LENGTH_SHORT).show();
}
}
@Override
public void onError(Throwable e) {
}
@Override
public void onComplete() {
}
});
}
- 代码中的APPID 和 SDKKEY就是你在开发者中心申请的
如何使用
- 人脸识别初始化
/**
* 人脸识别初始化
*/
private void initArcSetting() {
//本地人脸库初始化
FaceServer.getInstance().init(SignActivity.this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
WindowManager.LayoutParams attributes = getWindow().getAttributes();
attributes.systemUiVisibility = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
getWindow().setAttributes(attributes);
}
// Activity启动后就锁定为启动时的方向
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED);
previewView = findViewById(R.id.sign_texture_preview);
faceRectView = findViewById(R.id.sign_face_rect_view);
previewView.getViewTreeObserver().addOnGlobalLayoutListener(this);
compareResultList = new ArrayList<>();
}
-
其中的FaceServer是在demo中直接使用额
image.png - 声明代码
/**
* 相机预览显示的控件,可为SurfaceView或TextureView
*/
private View previewView;
private ArcCameraHelper cameraHelper;
private DrawHelper drawHelper;
private Camera.Size previewSize;
private FaceRectView faceRectView;
private Integer rgbCameraId = Camera.CameraInfo.CAMERA_FACING_FRONT;//前置摄像头
private FaceEngine faceEngine;
private FaceHelper faceHelper;
private int afCode = -1;
/**
* 活体检测的开关
*/
private boolean livenessDetect = true;
/**
* 当FR成功,活体未成功时,FR等待活体的时间
*/
private static final int WAIT_LIVENESS_INTERVAL = 10;
private static final int MAX_DETECT_NUM = 10;
private List<CompareResult> compareResultList;
private ConcurrentHashMap<Integer, Integer> requestFeatureStatusMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<Integer, Integer> livenessMap = new ConcurrentHashMap<>();
private CompositeDisposable getFeatureDelayedDisposables = new CompositeDisposable();
private static final int ACTION_REQUEST_PERMISSIONS = 0x001;
private static final float SIMILAR_THRESHOLD = 0.8F;
- 相机初始化代码部分
private void initCamera() {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
final FaceListener faceListener = new FaceListener() {
@Override
public void onFail(Exception e) {
Log.e(TAG, "onFail: " + e.getMessage());
}
//请求FR的回调
@Override
public void onFaceFeatureInfoGet(@Nullable final FaceFeature faceFeature, final Integer requestId) {
//FR成功
if (faceFeature != null) {
Log.i(TAG, "onPreview: fr end = " + System.currentTimeMillis() + " trackId = " + requestId);
//不做活体检测的情况,直接搜索
if (!livenessDetect) {
Log.d(TAG, "不做活体检测的情况,直接搜索: ");
searchFace(faceFeature, requestId);
}
//活体检测通过,搜索特征
else if (livenessMap.get(requestId) != null && livenessMap.get(requestId) == LivenessInfo.ALIVE) {
Log.d(TAG, "活体检测通过,搜索特征: ");
searchFace(faceFeature, requestId);
}
//活体检测未出结果,延迟100ms再执行该函数
else if (livenessMap.get(requestId) != null && livenessMap.get(requestId) == LivenessInfo.UNKNOWN) {
Log.d(TAG, "活体检测未出结果,延迟10ms再执行该函数: ");
getFeatureDelayedDisposables.add(Observable.timer(WAIT_LIVENESS_INTERVAL, TimeUnit.MILLISECONDS)
.subscribe(new Consumer<Long>() {
@Override
public void accept(Long aLong) {
onFaceFeatureInfoGet(faceFeature, requestId);
}
}));
}
//活体检测失败
else {
Log.d(TAG, "活体检测失败");
requestFeatureStatusMap.put(requestId, CompareResult.NOT_ALIVE);
}
}
//FR 失败
else {
requestFeatureStatusMap.put(requestId, CompareResult.FAILED);
}
}
};
ArcCameraListener arcCameraListener = new ArcCameraListener() {
@Override
public void onCameraOpened(Camera camera, int cameraId, int displayOrientation, boolean isMirror) {
Log.i(TAG, "onCameraOpened: " + cameraId + " " + displayOrientation + " " + isMirror);
previewSize = camera.getParameters().getPreviewSize();
drawHelper = new DrawHelper(previewSize.width, previewSize.height, previewView.getWidth(), previewView.getHeight(), displayOrientation
, cameraId, isMirror,false,false);
faceHelper = new FaceHelper.Builder()
.faceEngine(faceEngine)
.frThreadNum(MAX_DETECT_NUM)
.previewSize(previewSize)
.faceListener(faceListener)
.currentTrackId(ConfigUtil.getTrackId(SignActivity.this.getApplicationContext()))
.build();
}
@Override
public void onPreview(byte[] nv21, Camera camera) {
if (faceRectView != null) {
faceRectView.clearFaceInfo();
}
if (faceHelper == null) {
return;
}
final List<FacePreviewInfo> facePreviewInfoList = faceHelper.onPreviewFrame(nv21);
if (facePreviewInfoList != null && faceRectView != null && drawHelper != null) {
List<DrawInfo> drawInfoList = new ArrayList<>();
boolean isAlive = false;//活体判断
//识别有人脸后进入此处,facePreviewInfoList为已注册过的人脸数据
for (int i = 0; i < facePreviewInfoList.size(); i++)
{
String name = faceHelper.getName(facePreviewInfoList.get(i).getTrackId());
/*drawInfoList.add(new DrawInfo(facePreviewInfoList.get(i).getFaceInfo().getRect(), GenderInfo.UNKNOWN, AgeInfo.UNKNOWN_AGE, LivenessInfo.UNKNOWN,
name == null ? String.valueOf(facePreviewInfoList.get(i).getTrackId()) : name));*/
//name 置为空字符,为了人脸识别框上不显示文字
drawInfoList.add(new DrawInfo(drawHelper.adjustRect(facePreviewInfoList.get(i).getFaceInfo().getRect()), GenderInfo.UNKNOWN, AgeInfo.UNKNOWN_AGE, facePreviewInfoList.get(i).getLivenessInfo().getLiveness(),
""));
isAlive = facePreviewInfoList.get(i).getLivenessInfo().getLiveness() == 1 ? true : false;
}
drawHelper.draw(faceRectView, drawInfoList);
}
clearLeftFace(facePreviewInfoList);
if (facePreviewInfoList != null && facePreviewInfoList.size() > 0 && previewSize != null) {
for (int i = 0; i < facePreviewInfoList.size(); i++) {
if (livenessDetect) {
livenessMap.put(facePreviewInfoList.get(i).getTrackId(), facePreviewInfoList.get(i).getLivenessInfo().getLiveness());
}
/**
* 对于每个人脸,若状态为空或者为失败,则请求FR(可根据需要添加其他判断以限制FR次数),
* FR回传的人脸特征结果在{@link FaceListener#onFaceFeatureInfoGet(FaceFeature, Integer)}中回传
*/
if (requestFeatureStatusMap.get(facePreviewInfoList.get(i).getTrackId()) == null
|| requestFeatureStatusMap.get(facePreviewInfoList.get(i).getTrackId()) == CompareResult.FAILED) {
requestFeatureStatusMap.put(facePreviewInfoList.get(i).getTrackId(), CompareResult.SEARCHING);
faceHelper.requestFaceFeature(nv21, facePreviewInfoList.get(i).getFaceInfo(), previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, facePreviewInfoList.get(i).getTrackId());
Log.i(TAG, "onPreview: fr start = " + System.currentTimeMillis() + " trackId = " + facePreviewInfoList.get(i).getTrackId());
}
}
}
}
@Override
public void onCameraClosed() {
Log.i(TAG, "onCameraClosed: ");
}
@Override
public void onCameraError(Exception e) {
// Log.i(TAG, "onCameraError: " + e.getMessage());
}
@Override
public void onCameraConfigurationChanged(int cameraID, int displayOrientation) {
if (drawHelper != null) {
drawHelper.setCameraDisplayOrientation(displayOrientation);
}
// Log.i(TAG, "onCameraConfigurationChanged: " + cameraID + " " + displayOrientation);
}
};
cameraHelper = new ArcCameraHelper.Builder()
.previewViewSize(new Point(previewView.getMeasuredWidth(),previewView.getMeasuredHeight()))
.rotation(getWindowManager().getDefaultDisplay().getRotation())
.specificCameraId(rgbCameraId != null ? rgbCameraId : Camera.CameraInfo.CAMERA_FACING_FRONT)
.isMirror(false)
.previewOn(previewView)
.cameraListener(arcCameraListener)
.build();
cameraHelper.init();
cameraHelper.start();
}
- 匹配查找人脸
private void searchFace(final FaceFeature frFace, final Integer requestId) {
Observable
.create(new ObservableOnSubscribe<CompareResult>() {
@Override
public void subscribe(ObservableEmitter<CompareResult> emitter) {
Log.i(TAG, "subscribe: fr search start = " + System.currentTimeMillis() + " trackId = " + requestId);
Log.i(TAG, "frFace: " + frFace);
CompareResult compareResult = FaceServer.getInstance().getTopOfFaceLib(frFace);
Log.i(TAG, "searchFace: " + compareResult);
Log.i(TAG, "subscribe: fr search end = " + System.currentTimeMillis() + " trackId = " + requestId);
if (compareResult == null) {
emitter.onError(null);
} else {
emitter.onNext(compareResult);
}
}
})
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<CompareResult>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onNext(CompareResult compareResult) {//循环录过的所有人脸
if (compareResult == null || compareResult.getUserName() == null) {
requestFeatureStatusMap.put(requestId, CompareResult.FAILED);
faceHelper.addName(requestId, "VISITOR " + requestId);
return;
}
Log.i(TAG, "onNext: fr search get result = " + System.currentTimeMillis() + " trackId = " + requestId + " similar = " + compareResult.getSimilar());
if (compareResult.getSimilar() > SIMILAR_THRESHOLD) {//在录入过的人脸中对比找出当前人脸
boolean isAdded = false;
if (compareResultList == null) {
requestFeatureStatusMap.put(requestId, CompareResult.FAILED);
faceHelper.addName(requestId, "VISITOR " + requestId);
return;
}
for (CompareResult compareResult1 : compareResultList) {
if (compareResult1.getTrackId() == requestId) {
isAdded = true;
break;
}
}
if (!isAdded) {
//对于多人脸搜索,假如最大显示数量为 MAX_DETECT_NUM 且有新的人脸进入,则以队列的形式移除
if (compareResultList.size() >= MAX_DETECT_NUM) {
compareResultList.remove(0);
//adapter.notifyItemRemoved(0);
}
//添加显示人员时,保存其trackId
compareResult.setTrackId(requestId);
compareResultList.add(compareResult);
//adapter.notifyItemInserted(compareResultList.size() - 1);
}
requestFeatureStatusMap.put(requestId, CompareResult.SUCCEED);
faceHelper.addName(requestId, compareResult.getUserName());
sign(compareResult.getUserName(),"name");
} else {
requestFeatureStatusMap.put(requestId, CompareResult.FAILED);
faceHelper.addName(requestId, "VISITOR " + requestId);
}
}
@Override
public void onError(Throwable e) {
requestFeatureStatusMap.put(requestId, CompareResult.FAILED);
}
@Override
public void onComplete() {
}
});
}
- 以上就是人脸识别的核心代码了,我本人也是Android 小白一枚,这也算是我在集成过程中一点小心得而已,本人在集成过程中也遇到了很多的问题,也查找了很多的资料,当然还是觉得简书的文章最靠谱了,也希望简书越来越好
网友评论