web-dev-qa-db-fra.com

API Mobile Vision - concaténer un nouvel objet détecteur pour continuer le traitement de la trame

Je souhaite utiliser la nouvelle fonctionnalité de détection de visages fournie par l'API Vision ainsi que le traitement de trame supplémentaire dans une application. Pour cela, je dois avoir accès au cadre de la caméra qui a été traité par le détecteur de visage et concaténer un processeur en utilisant les données détectées par le visage.

Comme je le vois dans l'exemple, CameraSource résume la détection et l'accès à la caméra, et je ne peux pas avoir accès à l'image en cours de traitement. Y a-t-il des exemples de comment obtenir le cadre de la caméra dans cette API, ou, peut-être, créer et concaténer un détecteur qui le reçoit? Est-ce possible au moins?

Merci, Lucio

18
Lxu

Oui c'est possible. Vous devez créer votre propre sous-classe de Detector qui enveloppe FaceDetector et exécute votre code de traitement de trame supplémentaire dans la méthode de détection. Cela ressemblerait à quelque chose comme ceci:

class MyFaceDetector extends Detector<Face> {
  private Detector<Face> mDelegate;

  MyFaceDetector(Detector<Face> delegate) {
    mDelegate = delegate;
  }

  public SparseArray<Face> 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);
  }
}

Vous emballez le détecteur de visage avec votre classe et passez votre classe dans la source de la caméra. Cela ressemblerait à quelque chose comme ceci:

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

Votre détecteur sera appelé en premier avec les données de trame brutes.

Notez que l'image peut ne pas être droite si l'appareil est tourné. Vous pouvez obtenir l'orientation grâce à la méthode metadata.getRotation du cadre.

Un mot d'avertissement: une fois que la méthode de détection revient, vous ne devez pas accéder aux données de pixel de trame. Étant donné que la source de la caméra recycle les tampons d'image, le contenu de l'objet cadre sera éventuellement remplacé une fois la méthode revenue.

EDIT: (notes supplémentaires) Vous pouvez également éviter le code passe-partout de MyFaceDetector en utilisant un MultiDetector comme ceci:

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

Notez également l'utilisation de FaceTrackerFactory en conjonction avec MultiProcessor qui y est décrite.

23
pm0733464

Voici la solution finale sur laquelle j'ai opté. Cela suppose que la boîte est centrée sur l'écran.

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

Enveloppez cette classe dans votre détecteur comme ceci

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

Selon la demande de l'utilisateur (nouveau développeur), comment configurer le détecteur de boîte. Vous pouvez utiliser comme ça

utilisation @MCR Classe BoxDetector, puis suivez ces étapes.

Je donne juste un exemple sur la reconnaissance de texte pour que vous puissiez définir comme ceci

TextRecognizer mTextRecognizer = new TextRecognizer.Builder(getApplicationContext()).build();
BoxDetector boxDetector = new BoxDetector(mTextRecognizer, heightPx, widthPx);

set boxDetecotr ici

boxDetector.setProcessor(new Detector.Processor<TextBlock>() {
                @Override
                public void release() {

                }

                @Override
                public void receiveDetections(Detector.Detections<TextBlock> detections) {
                    SparseArray<TextBlock> items = detections.getDetectedItems();
                    StringBuilder stringBuilder = new StringBuilder();
                    for (int i = 0; i < items.size(); ++i) {
                        TextBlock item = items.valueAt(i);
                        if (item != null && item.getValue() != null) {
                            stringBuilder.append(item.getValue() + " ");
                        }
                    }

                    final String fullText = stringBuilder.toString();
                    Handler handler = new Handler(Looper.getMainLooper());
                    handler.post(new Runnable() {
                        public void run() {
                            // here full string(fullText) you can get whatever is it scanned.
                        }
                    });

                }
            });
1
Dharmbir Singh