现在,我们的应用程序正在成功运行 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();
}