Android+Camera+SurfaceView自定义相机系列在这篇文章中已经介绍了如何使用camera+surfaceview
在此基础上我们介绍如何接入虹软的人脸识别功能。首先自己去注册虹软的开发者账号,并自行下载SDK,SDK的APP_ID和SDK_KEY是唯一的,可以激活一台设备,完成认证后,可以用于激活100台设备。
一、SDK接入配置
1、在官方文档中可以看到主要将几个jar包和几个so文件接入到你的项目目录下。完成这步就算完成了接入SDK。
2、激活引擎
我们在自定义的camera的项目中,将激活与初始化封装起来,重新写init()函数
private void init() { /* * 激活 * */ String APP_ID = "换成自己的ID"; String SDK_KEY = "换成自己的key"; int code = FaceEngine.activeOnline(MainActivity_l.this, APP_ID, SDK_KEY); if (code == ErrorInfo.MOK) { Log.i(TAG, "activeOnline success"); Toast.makeText(MainActivity_l.this, "激活成功", Toast.LENGTH_SHORT).show(); } else if (code == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED) { Log.i(TAG, "already activated"); Toast.makeText(MainActivity_l.this, "已经激活", Toast.LENGTH_SHORT).show(); } else { Log.i(TAG, "activeOnline failed, code is : " + code); } /* * 初始化 * */ faceEngine = new FaceEngine(); // int code_init = faceEngine.init(getApplicationContext(),DetectMode.ASF_DETECT_MODE_VIDEO, DetectFaceOrientPriority.ASF_OP_0_ONLY, scale,maxFaceNum, initMask); int code_init = faceEngine.init(getApplicationContext(), DetectMode.ASF_DETECT_MODE_VIDEO, DetectFaceOrientPriority.ASF_OP_ALL_OUT, scale, maxFaceNum, initMask); if (code_init != ErrorInfo.MOK) { Toast.makeText(this, "init failed, code is : " + code, Toast.LENGTH_SHORT).show(); } else { Log.i(TAG, "init success"); Toast.makeText(MainActivity_l.this, "初始化成功", Toast.LENGTH_SHORT).show(); } }
这样我们就完成了如何激活与初始化
3、属性检测
我们使用虹软SDK主要是使用他进行人脸追踪和人脸识别等功能,比如画人脸框,显示性别,年龄,人脸数,是否活体等功能,所以我们继续在init()添加功能
/* * 检测属性 * */ Camera camera = CameraUtils.getmCamera(); camera.setDisplayOrientation(90); DisplayMetrics metrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(metrics); final Camera.Parameters parameters = camera.getParameters(); parameters.setPreviewFormat(ImageFormat.NV21); camera.setParameters(parameters); camera.setPreviewCallback(new Camera.PreviewCallback() { @Override public void onPreviewFrame(byte[] nv21, Camera camera) { // 这里面的Bytes的数据就是NV21格式的数据 previewSize = camera.getParameters().getPreviewSize(); /* * 显示人脸个数 * */ faceInfoList = new ArrayList<>(); // long start = System.currentTimeMillis(); int code = faceEngine.detectFaces(nv21, previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, faceInfoList); if (code == ErrorInfo.MOK && faceInfoList.size() > 0) { Log.i(TAG, "detectFaces, face num is : " + faceInfoList.size()); // Toast.makeText(MainActivity.this,"检测成功",Toast.LENGTH_SHORT).show(); } else { Log.i(TAG, "no face detected, code is : " + code); // Toast.makeText(MainActivity.this,"检测失败",Toast.LENGTH_SHORT).show(); } face_num.setText("人脸数:" + faceInfoList.size()); /* * 显示年龄 * */ processMask = FaceEngine.ASF_AGE | FaceEngine.ASF_GENDER | FaceEngine.ASF_FACE3DANGLE | FaceEngine.ASF_LIVENESS; int faceProcessCode = faceEngine.process(nv21, previewSize.width, previewSize.height, FaceEngine.CP_PAF_NV21, faceInfoList, processMask); if (faceProcessCode == ErrorInfo.MOK) { Log.i(TAG, "process success"); // Toast.makeText(MainActivity.this,"属性成功",Toast.LENGTH_SHORT).show(); } else { Log.i(TAG, "process failed, code is : " + faceProcessCode); // Toast.makeText(MainActivity.this,"属性失败",Toast.LENGTH_SHORT).show(); } List<AgeInfo> ageInfoList = new ArrayList<>(); int ageCode = faceEngine.getAge(ageInfoList); // 获取第一个人脸的年龄信息,多人脸情况进行循环即可 if (ageCode == ErrorInfo.MOK && ageInfoList.size() > 0) { if (ageInfoList.size() > 0) { Log.i(TAG, "age of the first face is : " + ageInfoList.get(0).getAge()); // age.setText("年龄:"+ageInfoList.get(0).getAge()); } else { Log.i(TAG, "no face processed"); // age.setText("年龄:--"); } } else { Log.i(TAG, "get age failed, code is : " + ageCode); } if (ageInfoList.size() == 1) { age.setText("年龄:" + ageInfoList.get(0).getAge()); } if (ageInfoList.size() == 2){ age.setText("年龄:"+ageInfoList.get(0).getAge()+" ,"+ageInfoList.get(1).getAge()); } if (ageInfoList.size() == 0) { age.setText("年龄:--"); } /* * 显示性别 * */ List<GenderInfo> genderInfoList = new ArrayList<>(); int genderCode = faceEngine.getGender(genderInfoList); // 获取第一个人脸的性别信息,多人脸情况进行循环即可 if (genderCode == ErrorInfo.MOK) { if (genderInfoList.size() > 0) { Log.i(TAG, "gender of the first face is : " + genderInfoList.get(0).getGender()); } else { Log.i(TAG, "no face processed"); } } else { Log.i(TAG, "get gender failed, code is : " + genderCode); } if (genderInfoList.size() > 0 && genderInfoList.get(0).getGender() == 0) { gender.setText("年龄:M"); } if (genderInfoList.size() > 0 && genderInfoList.get(0).getGender() == 1) { gender.setText("年龄:F"); } if (genderInfoList.size() == 2 ){ gender.setText("年龄:"+gen(genderInfoList.get(0).getGender())+gen(genderInfoList.get(1).getGender())); } if (genderInfoList.size() == 0) { gender.setText("年龄:--"); } /* * 活体 * */ List<LivenessInfo> livenessInfoList = new ArrayList<>(); int livenessCode = faceEngine.getLiveness(livenessInfoList); // RGB活体不支持多人脸,因此只能拿第1个活体信息 if (livenessCode == ErrorInfo.MOK) { if (livenessInfoList.size() > 0) { Log.i(TAG, "liveness of the first face is : " + livenessInfoList.get(0).getLiveness()); } else { Log.i(TAG, "no face processed"); } } else { Log.i(TAG, "get liveness failed, code is : " + livenessCode); } if (livenessInfoList.size() > 0 && livenessInfoList.get(0).getLiveness() == 1) { liveness.setText("活体:Y"); } else { liveness.setText("活体:--"); } if (livenessInfoList.size() == 2 ){ liveness.setText("活体:"+Live(livenessInfoList.get(0).getLiveness())+Live(livenessInfoList.get(1).getLiveness())); }
所以写完这些就完成了检测人脸数,年龄等。在这里我们先是使用textView的方式将这些信息显示在屏幕上。后面我们在移植虹软的人脸识别框,就可以去掉这些代码;
4、布局文件
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity_l"> <FrameLayout android:id="@+id/layout_aspect" android:layout_width="match_parent" android:layout_height="wrap_content"> </FrameLayout> <com.example.camera.widget.FaceRectView android:id="@+id/face_rect_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_gravity="top" android:gravity="center"> <TextView android:id="@+id/face_num" android:layout_width="100dp" android:layout_height="50dp" android:text="人脸数:--" android:textColor="#000000" /> <TextView android:id="@+id/age" android:layout_width="100dp" android:layout_height="50dp" android:layout_toRightOf="@id/face_num" android:text="年龄:--" android:textColor="#000000" /> <TextView android:id="@+id/gender" android:layout_width="100dp" android:layout_height="50dp" android:layout_toRightOf="@id/age" android:text="性别:--" android:textColor="#000000" /> <TextView android:id="@+id/liveness" android:layout_width="100dp" android:layout_height="50dp" android:layout_toRightOf="@id/gender" android:text="活体:--" android:textColor="#000000" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_gravity="bottom" android:gravity="center"> <Button android:id="@+id/btn_init" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="初始化" /> <Button android:id="@+id/btn_switch" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="切换相机" /> <Button android:id="@+id/btn_focus" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="focus" android:text="聚焦" /> <Button android:id="@+id/btn_facerect" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="facerect" android:text="人脸框" /> </LinearLayout> </FrameLayout>
我们在点击初始化的按钮的时候调用init()函数。就可以了
这些就是我们需要的虹软的人脸识别SDK的基础功能。完整的代码下载链接:https://download.csdn.net/download/hequnwang10/14150596