【发布时间】:2016-03-11 23:44:32
【问题描述】:
现在,我们的应用程序正在成功运行 Snapdragon SDK。我们正在尝试在我们的项目中实现 Vision 8.3.0 的 FaceDetector,以增加兼容设备的数量。我们不能使用 CameraSource,因为我们依靠自定义相机 + 表面来提供某些功能。我们希望尽可能多地重用代码,而 Snapdragon SDK 在我们当前的实现中表现出色。
工作流程如下:
1) 检索相机预览
2) 将传入的字节数组转换为位图(由于某种原因,我们还没有设法使用 ByteBuffers。提供并验证了图像大小、旋转和 NV21 图像格式,但没有找到人脸)。位图是已经在处理线程内部初始化的全局变量,以避免分配速度变慢。
3) 通过receiveFrame馈送检测器
目前的结果还不够好。即使我们禁用了地标和分类,检测速度也太慢(2-3 秒)且不准确。
问题是:是否可以在不使用前者的情况下复制 CameraSource + Detector 的性能?是否必须使用 CameraSource 才能使其与实时输入一起使用?
提前致谢!
编辑
按照下面的 pm0733464 建议,我尝试使用 ByteBuffer 而不是 Bitmap。这是我遵循的步骤:
// Initialize variables
// Mat is part of opencvSDK
Mat currentFrame = new Mat(cameraPreviewHeight + cameraPreviewHeight / 2, cameraPreviewWidth, CvType.CV_8UC1);
Mat yuvMat = new Mat(cameraPreviewHeight + cameraPreviewHeight / 2, cameraPreviewWidth, CvType.CV_8UC1);
// Load current frame
yuvMat.put(0, 0, data);
// Convert the frame to gray for better processing
Imgproc.cvtColor(yuvMat, currentFrame, Imgproc.COLOR_YUV420sp2RGB);
Imgproc.cvtColor(currentFrame, currentFrame, Imgproc.COLOR_BGR2GRAY);
从这里开始,字节数组的创建:
// Initialize grayscale byte array
byte[] grayscaleBytes = new byte[data.length];
// Extract grayscale data
currentFrame.get(0, 0, grayscaleBytes);
// Allocate ByteBuffer
ByteBuffer buffer = ByteBuffer.allocateDirect(grayscaleBytes.length);
// Wrap grayscale byte array
buffer.wrap(grayscaleBytes);
// Create frame
// rotation is calculated before
Frame currentGoogleFrame = new Frame.Builder().setImageData(buffer, currentFrame.cols(), currentFrame.rows(), ImageFormat.NV21).setRotation(rotation).build();
以这种方式构建框架会导致找不到人脸。但是,使用位图可以按预期工作:
if(bitmap == null) {
// Bitmap allocation
bitmap = Bitmap.createBitmap(currentFrame.cols(), currentFrame.rows(), Bitmap.Config.ARGB_8888);
}
// Copy grayscale contents
org.opencv.android.Utils.matToBitmap(currentFrame, bitmap);
// Scale down to improve performance
Matrix scaleMatrix = new Matrix();
scaleMatrix.postScale(scaleFactor, scaleFactor);
// Recycle before creating scaleBitmap
if(scaledBitmap != null) {
scaledBitmap.recycle();
}
// Generate scaled bitmap
scaledBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), rotationMatrix, true);
// Create frame
// The same rotation as before is still used
if(scaledBitmap != null) {
Frame currentGoogleFrame = new Frame.Builder().setBitmap(scaledBitmap).setRotation(rotation).build();
}
【问题讨论】:
-
几点建议: 1) 您可以直接使用 YUV 格式的图像数据,而不是执行两个 cvtColor 调用。人脸检测器将使用灰度的 Y 通道,而忽略其余部分。 2)像你一样使用 ByteBuffer.allocateDirect 并不完全正确,因为这会忽略 arrayOffset - 效果是你的图像会向左移动几个像素。
-
谢谢!不幸的是,我们需要该灰度图像进行其他处理。我会检查一下避免 allocateDirect,但我记得有一个与此相关的异常。
标签: java android face-detection android-vision