Google Mobile Vision: bajo rendimiento de FaceDetector sin CameraSource

En este momento, nuestra aplicación ejecuta Snapdragon SDK con éxito. Estamos tratando de implementar FaceDetector de Vision 8.3.0 en nuestro proyecto, para aumentar la cantidad de dispositivos compatibles. No podemos usar CameraSource, ya que confiamos en una cámara personalizada + superficie para proporcionar cierta funcionalidad. Queremos reutilizar la mayor cantidad de código posible, y Snapdragon SDK está funcionando increíblemente con nuestra implementación actual.

El flujo de trabajo es el siguiente:

1) Recuperar vista previa de la cámara

2) Transforme la matriz de bytes entrante en mapa de bits (por alguna razón, no hemos logrado trabajar con ByteBuffers. El tamaño de la imagen, la rotación y el formato de imagen NV21 se proporcionan y verifican, pero no se encuentran caras). El mapa de bits es una variable global ya inicializada dentro del subproceso de procesamiento, para evitar retrasos en las asignaciones.

3) Detector de alimentación a través de recibirFrame

Los resultados hasta ahora no son lo suficientemente buenos. La detección es demasiado lenta (2-3 segundos) e inexacta, a pesar de que hemos desactivado los puntos de referencia y las clasificaciones.

La pregunta es: ¿es posible replicar el rendimiento del detector CameraSource + sin usar el primero? ¿Es obligatorio usar CameraSource para que funcione con entrada en vivo?

¡Gracias por adelantado!

EDITAR

Siguiendo las recomendaciones de pm0733464 a continuación, estoy tratando de usar ByteBuffer en lugar de Bitmap. Estos son los pasos que sigo:

// 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); 

A partir de aquí, la creación de la matriz de bytes:

// 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();

La construcción de marcos de esta manera no permite encontrar caras. Sin embargo, el uso de mapas de bits funciona como se esperaba:

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();
}

Respuestas a la pregunta(1)

Su respuesta a la pregunta