新世界后半段 · 2019年10月17日

AID.Face Demo,调整预览角度和旋转Mat角度

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格式的数据,
1571275594(1).png

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)
推荐阅读
关注数
15
内容数
10
专注AI视觉,分享人脸及各视觉AI算法和解决方案。
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息