Google Mobile Vision: Schlechte FaceDetector-Leistung ohne CameraSource

Im Moment führt unsere Anwendung das Snapdragon SDK erfolgreich aus. Wir versuchen FaceDetector von Vision 8.3.0 in unserem Projekt zu implementieren, um die Anzahl der kompatiblen Geräte zu erhöhen. Wir können CameraSource nicht verwenden, da wir uns auf eine benutzerdefinierte Kamera + Oberfläche verlassen, um bestimmte Funktionen bereitzustellen. Wir möchten so viel Code wie möglich wiederverwenden, und das Snapdragon SDK leistet mit unserer aktuellen Implementierung erstaunliche Arbeit.

Workflow lautet wie folgt:

1) Kameravorschau abrufen

2) Eingehendes Byte-Array in Bitmap umwandeln (aus irgendeinem Grund haben wir es nicht geschafft, mit ByteBuffers zu arbeiten. Bildgröße, Drehung und NV21-Bildformat werden bereitgestellt und überprüft, aber es werden keine Gesichter gefunden). Bitmap ist eine globale Variable, die bereits innerhalb des Verarbeitungsthreads initialisiert wurde, um Verzögerungen durch Zuweisungen zu vermeiden.

3) Fütterungsdetektor über receiveFrame

Ergebnisse sind bisher nicht gut genug. Die Erkennung ist viel zu langsam (2-3 Sekunden) und ungenau, obwohl wir Orientierungspunkte und Klassifizierungen deaktiviert haben.

Die Frage ist: Ist es möglich, die Leistung von CameraSource + Detector zu replizieren, ohne die erstere zu verwenden? Ist es obligatorisch, CameraSource zu verwenden, damit es mit Live-Eingaben funktioniert?

Danke im Voraus

BEARBEITE

Den nachstehenden Empfehlungen von pm0733464 folgend, versuche ich, ByteBuffer anstelle von Bitmap zu verwenden. Dies sind die Schritte, denen ich folge:

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

Ab hier die Erstellung des Bytearrays:

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

Wenn Sie Frames auf diese Weise konstruieren, werden keine Gesichter gefunden. Bei Verwendung von Bitmaps funktioniert dies jedoch wie erwartet:

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

Antworten auf die Frage(2)

Ihre Antwort auf die Frage