本文介绍了Android camera2.params.face在画布上的矩形放置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to implement face detection in my camera preview. I followed the Android reference pages to implement a custom camera preview in a TextureView, placed in a FrameLayout. Also in this FrameLayout is a SurfaceView with a clear background (overlapping the camera preview). My app draws the Rect that is recognized by the first CaptureResult.STATISTICS_FACES face's bounds dynamically to the SurfaceView's canvas, every time the camera preview is updated (once per frame). My app assumes only one face will need to be recognized.

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

My issue arises when I draw the rectangle. I get the rectangle in the correct place if I keep my face in the center of the camera view, but when I move my head upward the rectangle moves to the right, and when I move my head to the right, the rectangle moves down. It's as if the canvas needs to be rotated by -90, but this doesn't work for me (Explained below code).

在我的活动的 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);
    }

方法 onCaptureCompleted CameraCaptureSession.CameraCallback CameraCaptureSession.setRepeatingRequest() looper调用:

method onCaptureCompleted in CameraCaptureSession.CameraCallback called by CameraCaptureSession.setRepeatingRequest() looper:

//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();
}

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

All variables are instantiated outside of the functions.

如果您不太了解我的问题或需要其他信息,请在此处发布类似的问题:

In case you can't quite understand my question or need additional information, a similar question is posted here:

但是,与上面的海报不同,旋转画布后我什至无法让画布显示矩形,因此

However, unlike the above poster, I couldn't even get my canvas to show the rectangle after rotating my canvas, so that can't be the solution.

我尝试使用x = -y,y = x(left = -top,top = left)将点旋转-90度,并且也不行。我觉得有些功能需要应用到这些要点上,但是我不知道该怎么做。

I tried to rotate my points by -90 degrees using x=-y, y=x (left=-top, top=left), and it doesn't do the trick either. I feel like some kind of function needs to be applied to the points but I don't know how to go about it.

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

Any ideas on how to fix this?

推荐答案

供以后参考,这是我最终得到的解决方案:

For future reference, this is the solution I ended up with:

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

set a class/Activity variable called orientation_offset :

orientation_offset = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);

这是相机传感器的视图(或用于面部检测的矩形)需要旋转的角度

This is the angle that the camera sensor's view (or rectangle for face detection) needs to be rotated to be viewed correctly.

然后,我将 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);

如果其他人有解决方案,我将保留这个问题。

I'll leave the question open in case somebody else has a solution to offer.

这篇关于Android camera2.params.face在画布上的矩形放置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-15 10:30