Mobile Vision API: concatenar el nuevo objeto detector para continuar el procesamiento del marco

Quiero utilizar la nueva característica de detección de rostros que ofrece la API de visión junto con el procesamiento de cuadros adicionales en una aplicación. Para esto, necesito tener acceso al marco de la cámara que fue procesado por el detector de rostros, y concatenar un procesador usando los datos de cara detectada.

Como veo en la muestra, CameraSource abstrae la detección y el acceso a la cámara, y no puedo tener acceso al marco que se está procesando. ¿Hay ejemplos de cómo obtener el marco de la cámara en esta API, o, tal vez, crear y concatenar un detector que lo recibe? ¿Es eso posible al menos?

Gracias, Lucio

Sí, es posible. Debería crear su propia subclase de Detector que envuelva FaceDetector y ejecute su código de procesamiento de ttwig adicional en el método de detección. Se vería algo como esto:

class MyFaceDetector extends Detector { private Detector mDelegate; MyFaceDetector(Detector delegate) { mDelegate = delegate; } public SparseArray detect(Frame frame) { // *** add your custom frame processing code here return mDelegate.detect(frame); } public boolean isOperational() { return mDelegate.isOperational(); } public boolean setFocus(int id) { return mDelegate.setFocus(id); } } 

Envolverías el detector facial con tu clase y pasarías tu clase a la fuente de la cámara. Se vería algo como esto:

  FaceDetector faceDetector = new FaceDetector.Builder(context) .build(); MyFaceDetector myFaceDetector = new MyFaceDetector(faceDetector); myFaceDetector.setProcessor(/* include your processor here */); mCameraSource = new CameraSource.Builder(context, myFaceDetector) .build(); 

Su detector se llamará primero con los datos del marco sin procesar.

Tenga en cuenta que la imagen puede no estar en posición vertical si se gira el dispositivo. Puede obtener la orientación a través del método metadata.getRotation del marco.

Una palabra de advertencia: una vez que el método de detección regresa, no debe acceder a los datos de píxeles del cuadro. Como la fuente de la cámara recicla los almacenamientos intermedios de imagen, el contenido del objeto de marco se anulará una vez que regrese el método.

EDITAR: (notas adicionales) También puede evitar el código MyFaceDetector de MyFaceDetector usando un MultiDetector como este:

 MultiDetector multiDetector = new MultiDetector.Builder() .add(new FaceDetector.Builder(context) .build()) .add(new YourReallyOwnDetector()) .build(); 

También tenga en cuenta el uso de FaceTrackerFactory en FaceTrackerFactory con MultiProcessor descrito allí.

Aquí está la solución final en la que me decidí. Asume que la caja está centrada en la pantalla.

 public class BoxDetector extends Detector { private Detector mDelegate; private int mBoxWidth, mBoxHeight; public BoxDetector(Detector delegate, int boxWidth, int boxHeight) { mDelegate = delegate; mBoxWidth = boxWidth; mBoxHeight = boxHeight; } public SparseArray detect(Frame frame) { int width = frame.getMetadata().getWidth(); int height = frame.getMetadata().getHeight(); int right = (width / 2) + (mBoxHeight / 2); int left = (width / 2) - (mBoxHeight / 2); int bottom = (height / 2) + (mBoxWidth / 2); int top = (height / 2) - (mBoxWidth / 2); YuvImage yuvImage = new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, width, height, null); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); yuvImage.compressToJpeg(new Rect(left, top, right, bottom), 100, byteArrayOutputStream); byte[] jpegArray = byteArrayOutputStream.toByteArray(); Bitmap bitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length); Frame croppedFrame = new Frame.Builder() .setBitmap(bitmap) .setRotation(frame.getMetadata().getRotation()) .build(); return mDelegate.detect(croppedFrame); } public boolean isOperational() { return mDelegate.isOperational(); } public boolean setFocus(int id) { return mDelegate.setFocus(id); } } 

Envuelva esta clase en su detector como este

 BarcodeDetector barcodeDetector = new BarcodeDetector.Builder(context).build(); BoxDetector boxDetector = new BoxDetector(barcodeDetector, heightPx, widthPx);