API Mobile Vision – объединить новый объект-детектор для продолжения обработки кадра

Я хочу использовать новую функцию обнаружения лица, которую API видения предоставляет вместе с дополнительной обработкой кадров в приложении. Для этого мне нужно иметь доступ к кадру камеры, который был обработан детектором лица, и объединить процессор, используя данные, обнаруженные лицом.

Как я вижу в примере, CameraSource абстрагирует обнаружение и доступ камеры, и я не могу получить доступ к обрабатываемому кадру. Есть ли примеры того, как получить кадр камеры в этом API или, может быть, создать и объединить детектор, который его получает? Это возможно хотя бы?

Спасибо, Лусио

Solutions Collecting From Web of "API Mobile Vision – объединить новый объект-детектор для продолжения обработки кадра"

Да, это возможно. Вам необходимо создать свой собственный подкласс Detector, который обертывает FaceDetector и выполняет ваш дополнительный код обработки кадра в методе обнаружения. Это будет выглядеть примерно так:

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 фрейма.

Одно слово предостережения: как только метод обнаружения вернется, вы не должны получить доступ к данным пикселя кадра. Поскольку источник камеры перерабатывает буферы изображений, содержимое объекта фрейма будет в конечном итоге переопределено после возвращения метода.

EDIT: (дополнительные примечания). Вы также можете избежать кода MyFaceDetector с помощью MultiDetector следующим образом:

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

Также обратите внимание на использование FaceTrackerFactory в FaceTrackerFactory с описанным здесь MultiProcessor .

Вот окончательное решение, на котором я остановился. Предполагается, что окно центрируется на экране.

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