web-dev-qa-db-ja.com

Mobile Vision API-新しい検出器オブジェクトを連結してフレーム処理を続行します

アプリケーションで追加のフレーム処理とともにビジョンAPIが提供する新しい顔検出機能を使用したいと思います。そのためには、顔検出器で処理されたカメラフレームにアクセスし、顔検出データを使用してプロセッサを連結する必要があります。

サンプルで見たように、CameraSourceは検出とカメラアクセスを抽象化しており、処理中のフレームにアクセスできません。このAPIでカメラフレームを取得する方法の例はありますか、またはそれを受信する検出器を作成して連結する方法はありますか?少なくともそれは可能ですか?

ありがとう、ルシオ

18
Lxu

はい、可能です。 FaceDetectorをラップし、detectメソッドで追加のフレーム処理コードを実行するDetectorの独自のサブクラスを作成する必要があります。次のようになります。

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

顔検出器をクラスでラップし、クラスをカメラソースに渡します。次のようになります。

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

検出器は、生のフレームデータで最初に呼び出されます。

デバイスを回転させると、画像が直立しない場合があることに注意してください。フレームのmetadata.getRotationメソッドを使用して方向を取得できます。

注意事項:いったんdetectメソッドが戻ったら、フレームピクセルデータにアクセスしないでください。カメラのソースは画像バッファーをリサイクルするため、メソッドが戻ると、フレームオブジェクトの内容は最終的にオーバーライドされます。

編集:(追加メモ) MultiDetector を使用して、MyFaceDetectorの定型コードを次のように回避することもできます。

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

また、ここで説明されているFaceTrackerFactoryと組み合わせたMultiProcessorの使用にも注意してください。

23
pm0733464

これが私が解決した最終的な解決策です。ボックスが画面の中央に配置されていると想定しています。

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

このクラスをこのように検出器でラップします

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

ユーザー(新規開発者)の要求に従って、ボックス検出器を設定する方法。このように使えます

使用する @MCR BoxDetectorクラスを作成し、次の手順に従います。

このように設定できるように、テキストレコグナイザの例を示しています

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

セットボックスDetecotrはこちら

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