问题描述
我正在尝试在相机预览中实施人脸检测。我按照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在画布上的矩形放置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!