Android camera2.params.face 矩形放置在画布上

Posted

技术标签:

【中文标题】Android camera2.params.face 矩形放置在画布上【英文标题】:Android camera2.params.face rectangle placement on canvas 【发布时间】:2015-08-25 02:57:15 【问题描述】:

我正在尝试在我的相机预览中实现人脸检测。我按照 android 参考页面在 TextureView 中实现了自定义相机预览,放置在 FrameLayout 中。在这个FrameLayout 中还有一个SurfaceView,具有清晰的背景(与相机预览重叠)。每次更新相机预览时(每帧一次),我的应用程序都会将第一个CaptureResult.STATISTICS_FACES 面部边界识别的Rect 动态绘制到SurfaceView 的画布上。我的应用假设只需要识别一张脸。

我在绘制矩形时出现了问题。如果我将脸保持在相机视图的中心,我会将矩形放在正确的位置,但是当我向上移动头部时,矩形会向右移动,而当我将头向右移动时,矩形会向下移动。好像画布需要旋转-90,但这对我不起作用(在下面的代码中解释)。

在我的活动onCreate():

//face recognition
rectangleView = (SurfaceView) findViewById(R.id.rectangleView);
rectangleView.setZOrderOnTop(true);
rectangleView.getHolder().setFormat(
    PixelFormat.TRANSPARENT); //remove black background from view
purplePaint = new Paint();
purplePaint.setColor(Color.rgb(175,0,255));
purplePaint.setStyle(Paint.Style.STROKE);

TextureView.SurfaceTextureListener.onSurfaceTextureAvailable()(在封装camera.open()try块中:

Rect cameraBounds = cameraCharacteristics.get(
    CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
cameraWidth = cameraBounds.right;
cameraHeight = cameraBounds.bottom;

onSurfaceTextureUpdated() 内的同一个监听器中:

if (detectedFace != null && rectangleFace.height() > 0) 
        Canvas currentCanvas = rectangleView.getHolder().lockCanvas();
        if (currentCanvas != null) 
            currentCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
            int canvasWidth = currentCanvas.getWidth();
            int canvasHeight = currentCanvas.getHeight();
            int l = rectangleFace.right;
            int t = rectangleFace.bottom;
            int r = rectangleFace.left;
            int b = rectangleFace.top;
            int left = (canvasWidth*l)/cameraWidth;
            int top  = (canvasHeight*t)/cameraHeight;
            int right = (canvasWidth*r)/cameraWidth;
            int bottom = (canvasHeight*b)/cameraHeight;

            currentCanvas.drawRect(left, top, right, bottom, purplePaint);
        
        rectangleView.getHolder().unlockCanvasAndPost(currentCanvas);
    

CameraCaptureSession.CameraCallback 中的方法onCaptureCompletedCameraCaptureSession.setRepeatingRequest() 循环器调用:

//May need better face recognition sdk or api
Face[] faces = result.get(CaptureResult.STATISTICS_FACES);

if (faces.length > 0)

    detectedFace = faces[0];
    rectangleFace = detectedFace.getBounds();

所有变量都在函数之外实例化。

如果您不能完全理解我的问题或需要更多信息,请在此处发布类似的问题:

How can i handle the rotation issue with Preview & FaceDetection

但是,与上面的海报不同,我什至无法让我的画布在旋转画布后显示矩形,所以这不是解决方案。

我尝试使用 x=-y, y=x (left=-top, top=left) 将我的点旋转 -90 度,但它也不起作用。我觉得需要对这些点应用某种功能,但我不知道该怎么做。

关于如何解决这个问题的任何想法?

【问题讨论】:

九你好!我看到了您的问题,据我了解,您已经完成了人脸检测(Camera 2 API)。我是Android的菜鸟,尝试在3周内进行人脸检测但没有成功...请您提示我在哪部分代码中实现了人脸检测...这对我很有帮助。谢谢 @Aleksey,看上面的“onCaptureCompleted”方法 这个 camera2 API 的 STATISTICS_FACES 是 Firebase 或 ML Kit 人脸检测的替代品吗?有谁知道他们如何比较?谢谢! 【参考方案1】:

为了将来参考,这是我最终得到的解决方案:

设置一个名为 orientation_offset 的类/活动变量:

orientation_offset = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);

这是相机传感器的视图(或用于人脸检测的矩形)需要旋转才能正确查看的角度。

然后,我换了onSurfaceTextureUpdated()

Canvas currentCanvas = rectangleView.getHolder().lockCanvas();
    if (currentCanvas != null) 

        currentCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);

        if (detectedFace != null && rectangleFace.height() > 0) 

            int canvasWidth = currentCanvas.getWidth();
            int canvasHeight = currentCanvas.getHeight();
            int faceWidthOffset = rectangleFace.width()/8;
            int faceHeightOffset = rectangleFace.height()/8;

            currentCanvas.save();
            currentCanvas.rotate(360 - orientation_offset, canvasWidth / 2, 
                canvasHeight / 2);

            int l = rectangleFace.right;
            int t = rectangleFace.bottom;
            int r = rectangleFace.left;
            int b = rectangleFace.top;
            int left = (canvasWidth - (canvasWidth*l)/cameraWidth)-(faceWidthOffset);
            int top  = (canvasHeight*t)/cameraHeight - (faceHeightOffset);
            int right = (canvasWidth - (canvasWidth*r)/cameraWidth) + (faceWidthOffset);
            int bottom = (canvasHeight*b)/cameraHeight + (faceHeightOffset);

            currentCanvas.drawRect(left, top, right, bottom, purplePaint);
            currentCanvas.restore();
        
    
    rectangleView.getHolder().unlockCanvasAndPost(currentCanvas);

如果其他人可以提供解决方案,我会保留这个问题。

【讨论】:

不错的解决方案!仍然不是很准确

以上是关于Android camera2.params.face 矩形放置在画布上的主要内容,如果未能解决你的问题,请参考以下文章

Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )

android 21 是啥版本

Android逆向-Android基础逆向(2-2)

【Android笔记】android Toast

图解Android - Android核心机制

Android游戏开发大全的目录