Android camera2.params.face 矩形放置在 canvas
Android camera2.params.face rectangle placement on canvas
我正在尝试在我的相机预览中实施人脸检测。我按照 Android 参考页面在 TextureView
中实现自定义相机预览,放置在 FrameLayout
中。此 FrameLayout
中还有一个具有清晰背景(与相机预览重叠)的 SurfaceView
。每次更新相机预览时(每帧一次),我的应用程序都会将第一个 CaptureResult.STATISTICS_FACES
面部边界识别的 Rect
动态绘制到 SurfaceView
的 canvas .我的应用假定只需要识别一张脸。
我在绘制矩形时出现问题。如果我将脸保持在相机视图的中央,我会在正确的位置得到矩形,但是当我向上移动头部时,矩形会向右移动,而当我向右移动头部时,矩形会向下移动。好像 canvas 需要旋转 -90,但这对我不起作用(在下面的代码中解释)。
在我的 activity 的 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);
in 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
中的方法 onCaptureCompleted
由 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();
}
所有变量都在函数外实例化。
如果您不能完全理解我的问题或需要更多信息,请在此处发布类似的问题:
How can i handle the rotation issue with Preview & FaceDetection
然而,与上面的海报不同,我什至无法让 canvas 在旋转 canvas 后显示矩形,所以这不是解决方案。
我尝试使用 x=-y, y=x (left=-top, top=left) 将我的点旋转 -90 度,但它也不起作用。我觉得需要对这些点应用某种功能,但我不知道该怎么做。
关于如何解决这个问题有什么想法吗?
为了将来参考,这是我最终得到的解决方案:
设置一个名为 orientation_offset
的 class/Activity 变量:
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 参考页面在 TextureView
中实现自定义相机预览,放置在 FrameLayout
中。此 FrameLayout
中还有一个具有清晰背景(与相机预览重叠)的 SurfaceView
。每次更新相机预览时(每帧一次),我的应用程序都会将第一个 CaptureResult.STATISTICS_FACES
面部边界识别的 Rect
动态绘制到 SurfaceView
的 canvas .我的应用假定只需要识别一张脸。
我在绘制矩形时出现问题。如果我将脸保持在相机视图的中央,我会在正确的位置得到矩形,但是当我向上移动头部时,矩形会向右移动,而当我向右移动头部时,矩形会向下移动。好像 canvas 需要旋转 -90,但这对我不起作用(在下面的代码中解释)。
在我的 activity 的 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);
in 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
中的方法 onCaptureCompleted
由 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();
}
所有变量都在函数外实例化。
如果您不能完全理解我的问题或需要更多信息,请在此处发布类似的问题:
How can i handle the rotation issue with Preview & FaceDetection
然而,与上面的海报不同,我什至无法让 canvas 在旋转 canvas 后显示矩形,所以这不是解决方案。
我尝试使用 x=-y, y=x (left=-top, top=left) 将我的点旋转 -90 度,但它也不起作用。我觉得需要对这些点应用某种功能,但我不知道该怎么做。
关于如何解决这个问题有什么想法吗?
为了将来参考,这是我最终得到的解决方案:
设置一个名为 orientation_offset
的 class/Activity 变量:
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);
我会留下这个问题,以防其他人有解决方案。