Face Demo坑
在介绍完AID.Face 之后我们现来展现一下Face在Android方便的表现,我是使用的是firefly Face_RK3399平台。先来一张截图爽一下
预览角度
我们现来看一下角度问题,Camera默认角度可能会出现四种可能,0度、90度、180度、270度,预览角度我们可以通过Android Camera API来进行设置
public final void setDisplayOrientation (int degrees)Set the clockwise rotation of preview display in degrees. This affects the preview frames and the picture displayed after snapshot. This method is useful for portrait mode applications. Note that preview display of front-facing cameras is flipped horizontally before the rotation, that is, the image is reflected along the central vertical axis of the camera sensor. So the users can see themselves as looking into a mirror.
This does not affect the order of byte array passed in PreviewCallback#onPreviewFrame, JPEG pictures, or recorded videos. This method is not allowed to be called during preview.
If you want to make the camera image show in the same orientation as the display, you can use the following code.
public static void setCameraDisplayOrientation(Activity activity,
int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
调整好预览角度之后你会发现还是不能识别人脸,或者偶尔出现有识别的情况,这是为什么呢?
我们理一下demo的工作流程,第一步是从摄像头获取数据,数据流向有两个,第一个是给SurfaceView
显示,我们上面提到的设置角度问题就是设置SurfaceView的显示角度;第二个是Camera 设置的回调接口setOneShotPreviewCallback
,接口回调方法void onPreviewFrame(byte[] data, Camera camera)
,demo中在这个接口方法中获取Camera YUV格式的数据,
Mat角度问题
在demo中我们会发现SDK图片数据输入是Mat格式,我们先来看几个重要的api
- 获取特征值
public int GetFeature(FaceAPP.Image image, float[] feature, int[] res)
- 检测人脸
public int GetFeature(FaceAPP.Image image, FaceInfo detectInfo, float[] feature, int[] res)
这是比较重要的两个API,从接口的参数来看第一个都需要一个long image
的地址数据,SDK中并没有source Java doc文档的说明,我们在demo中查找看看是怎么调用的
- public int GetFeature(FaceAPP.Image image, FaceInfo detectInfo, float[] feature, int[] res)
private Mat mRgbaFrame, registFrame;
image.matAddrframe = mRgbaFrame.getNativeObjAddr();
j = face.Detect(image, FaceInfos, i);//检测人脸
if (j == face.SUCCESS) { //检测到人脸,进入下面处理流程
FaceAttribute faceAttr = new FaceAttribute();
face.GetFaceAttr(image, FaceInfos.get(0), faceAttr, this.i);//获取人脸属性
face.GetFeature(image, FaceInfos.get(0), feature, this.i);//获取特征值,存在feature里
- public int Detect(FaceAPP.Image image, List<FaceInfo> faceInfos, int[] res)
private Mat mRgbaFrame, registFrame;
Mat img = FileOperator.FileToMat(mUrl).clone();
image.matAddrframe = mRgbaFrame.getNativeObjAddr();
j = face.Detect(image, FaceInfos, i);//检测人脸
根据上面两段代码可以发现这个long image
参数就是Mat的地址,Mat是OpenCV包下的core,OpenCV旋转角度使用的是Core类,该类中我们旋转角度使用的一共有两个方法,我们分比来看看
- public static void transpose(Mat src, Mat dst)
这个方法是旋转九十度角,src->dst转角的输入和输出
- public static void flip(Mat src, Mat dst, int flipCode)
这个方法和上面一样,只是这个方法是一百八十度角;重点是int flipCode
参数的使用,当flipCode
等一1
则以y轴翻转,当flipCode
等一-1
则以y轴翻转
了解完上面的Mat接下来demo中的旋转角度代码就好解释了,我整理了一下旋转角度对应的方法
case ROTATION_0:
break;
case ROTATION_90:
Core.transpose(srcMat, tagMat);//顺时针90
break;
case ROTATION_180:
Core.flip(srcMat, tagMat, -1);//顺时针180
break;
case ROTATION_270:
Core.flip(srcMat, tagMat, -1);////顺时针270
Core.transpose(srcMat, tagMat);
break;
}
在调试的过成功我们可以将旋转之后的Mat生成本地图片文件,这样方便查看旋转之后的效果。
public static boolean imwrite(String filename, Mat img)