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

Nin*_*erd 5 java camera android canvas face-detection

我正在尝试在相机预览中实现人脸检测。我按照Android参考页在中TextureView放置了,以实现自定义相机预览FrameLayout。此外,在此FrameLayout是一个SurfaceView带有明显的背景(重叠相机预览)。每当相机预览更新(每帧一次)时,我的应用程序都会将Rect第一个CaptureResult.STATISTICS_FACES面的边界所识别的绘制动态地绘制到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);
Run Code Online (Sandbox Code Playgroud)

in TextureView.SurfaceTextureListener.onSurfaceTextureAvailable()(在try{}封装的块中camera.open()

Rect cameraBounds = cameraCharacteristics.get(
    CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE);
cameraWidth = cameraBounds.right;
cameraHeight = cameraBounds.bottom;
Run Code Online (Sandbox Code Playgroud)

在同一听众中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);
    }
Run Code Online (Sandbox Code Playgroud)

方法onCaptureCompletedCameraCaptureSession.CameraCallback通过所谓的CameraCaptureSession.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();
}
Run Code Online (Sandbox Code Playgroud)

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

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

我如何使用Preview&FaceDetection处理旋转问题

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

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

有想法该怎么解决这个吗?

Nin*_*erd 3

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

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

orientation_offset = cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
Run Code Online (Sandbox Code Playgroud)

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

然后,我改变了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);
Run Code Online (Sandbox Code Playgroud)

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