MLKit Firebase android - Как преобразовать FirebaseVisionFace в объект изображения (например, растровое изображение)?

Я интегрировал MLkit FaceDetection в свое приложение для Android. Я сослался на URL ниже

https://firebase.google.com/docs/ml-kit/android/detect-faces

Код для класса процессора распознавания лиц:

import java.io.IOException;
import java.util.List;

/** Face Detector Demo. */
public class FaceDetectionProcessor extends VisionProcessorBase<List<FirebaseVisionFace>> {

  private static final String TAG = "FaceDetectionProcessor";

  private final FirebaseVisionFaceDetector detector;

  public FaceDetectionProcessor() {

    FirebaseVisionFaceDetectorOptions options =
        new FirebaseVisionFaceDetectorOptions.Builder()
            .setClassificationType(FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS)
            .setLandmarkType(FirebaseVisionFaceDetectorOptions.ALL_LANDMARKS)
            .setTrackingEnabled(true)
            .build();

    detector = FirebaseVision.getInstance().getVisionFaceDetector(options);
  }

  @Override
  public void stop() {
    try {
      detector.close();
    } catch (IOException e) {
      Log.e(TAG, "Exception thrown while trying to close Face Detector: " + e);
    }
  }

  @Override
  protected Task<List<FirebaseVisionFace>> detectInImage(FirebaseVisionImage image) {
    return detector.detectInImage(image);
  }

  @Override
  protected void onSuccess(
      @NonNull List<FirebaseVisionFace> faces,
      @NonNull FrameMetadata frameMetadata,
      @NonNull GraphicOverlay graphicOverlay) {
      graphicOverlay.clear();

    for (int i = 0; i < faces.size(); ++i) {
      FirebaseVisionFace face = faces.get(i);
      FaceGraphic faceGraphic = new FaceGraphic(graphicOverlay);
      graphicOverlay.add(faceGraphic);
      faceGraphic.updateFace(face, frameMetadata.getCameraFacing());
    }




  }

  @Override
  protected void onFailure(@NonNull Exception e) {
    Log.e(TAG, "Face detection failed " + e);
  }
}

Здесь, в слушателе onSuccess, мы получим массив объектов класса FirebaseVisionFace, у которых будет граница грани.

@Override
      protected void onSuccess(
          @NonNull List<FirebaseVisionFace> faces,
          @NonNull FrameMetadata frameMetadata,
          @NonNull GraphicOverlay graphicOverlay) {
          graphicOverlay.clear();

        for (int i = 0; i < faces.size(); ++i) {
          FirebaseVisionFace face = faces.get(i);
          FaceGraphic faceGraphic = new FaceGraphic(graphicOverlay);
          graphicOverlay.add(faceGraphic);
          faceGraphic.updateFace(face, frameMetadata.getCameraFacing());
        }
      }

Я хочу знать, как преобразовать эти объекты FirebaseVisionFace в Bitmap. Я хочу извлечь изображение лица и показать его в ImageView. Кто-нибудь может мне помочь, пожалуйста . Заранее спасибо.

Примечание. Я загрузил образец исходного кода MLKit android по адресу ниже.

https://github.com/firebase/quickstart-android/tree/master/mlkit


person Mani murugan    schedule 14.07.2018    source источник


Ответы (4)


Вы создали FirebaseVisionImage из растрового изображения. После возврата обнаружения каждый FirebaseVisionFace описывает ограничивающий прямоугольник как Rect, который можно использовать для извлечения обнаруженного лица из исходного растрового изображения, например используя Bitmap.createBitmap ().

person gnuf    schedule 14.07.2018
comment
не могли бы вы опубликовать свой код решения для справки? - person JúlioCézar; 27.07.2018
comment
Привет, @Manimurugan. Ребята, можете ли вы рассказать здесь с помощью кода, как он будет createBitmap (). Для меня это не работает. Пожалуйста помоги. - person Tapan Kumar Patro; 03.09.2018
comment
@Manimurugan, ребята, не могли бы вы опубликовать решение? Пожалуйста - person as diu; 31.05.2019

Поскольку принятый ответ не был достаточно конкретным, я постараюсь объяснить, что я сделал.

1.- Создайте ImageView на LivePreviewActivity следующим образом:

private ImageView imageViewTest;

2.- Создайте его в Activity xml и свяжите с файлом java. Я поместил его прямо перед образцом кода, чтобы его можно было увидеть поверх изображения с камеры.

3.-Когда они создают FaceDetectionProcessor, передают экземпляр imageView, чтобы иметь возможность установить исходное изображение внутри объекта.

FaceDetectionProcessor processor = new FaceDetectionProcessor(imageViewTest);

4.-Измените конструктор FaceDetectionProcessor, чтобы он мог принимать ImageView в качестве параметра и создать глобальную переменную, которая сохраняет этот экземпляр.

public FaceDetectionProcessor(ImageView imageView) {
    FirebaseVisionFaceDetectorOptions options =
            new FirebaseVisionFaceDetectorOptions.Builder()
                    .setClassificationType(FirebaseVisionFaceDetectorOptions.ALL_CLASSIFICATIONS)
                    .setTrackingEnabled(true)
                    .build();

    detector = FirebaseVision.getInstance().getVisionFaceDetector(options);
    this.imageView  = imageView;
}

5.- Я создал метод кадрирования, который использует растровое изображение и прямоугольник для фокусировки только на лице. Так что продолжайте и делайте то же самое.

    public static Bitmap cropBitmap(Bitmap bitmap, Rect rect) {
    int w = rect.right - rect.left;
    int h = rect.bottom - rect.top;
    Bitmap ret = Bitmap.createBitmap(w, h, bitmap.getConfig());
    Canvas canvas = new Canvas(ret);
    canvas.drawBitmap(bitmap, -rect.left, -rect.top, null);
    return ret;
}

6.- Измените метод detectInImage, чтобы сохранить экземпляр обнаруженного растрового изображения и сохранить его в глобальной переменной.

    @Override
protected Task<List<FirebaseVisionFace>> detectInImage(FirebaseVisionImage image) {
    imageBitmap = image.getBitmapForDebugging();
    return detector.detectInImage(image);
}

7.- Наконец, измените метод OnSuccess, вызвав метод обрезки и назначив результат для imageView.

    @Override
protected void onSuccess(
        @NonNull List<FirebaseVisionFace> faces,
        @NonNull FrameMetadata frameMetadata,
        @NonNull GraphicOverlay graphicOverlay) {
    graphicOverlay.clear();
    for (int i = 0; i < faces.size(); ++i) {
        FirebaseVisionFace face = faces.get(i);
        FaceGraphic faceGraphic = new FaceGraphic(graphicOverlay);
        graphicOverlay.add(faceGraphic);
        faceGraphic.updateFace(face, frameMetadata.getCameraFacing());
        croppedImage = cropBitmap(imageBitmap, face.getBoundingBox());
    }
    imageView.setImageBitmap(croppedImage);
}
person Jmz    schedule 31.05.2019

Это может помочь вам, если вы пытаетесь использовать ML Kit для обнаружения лиц и OpenCV для обработки изображений на обнаруженном лице. Обратите внимание, что в этом конкретном примере вам понадобится исходное растровое изображение камеры внутри onSuccess.

Я не нашел способа сделать это без растрового изображения и, честно говоря, все еще ищу.

@Override
protected void onSuccess(@NonNull List<FirebaseVisionFace> faces, @NonNull FrameMetadata frameMetadata, @NonNull GraphicOverlay graphicOverlay) {
  graphicOverlay.clear();

  for (int i = 0; i < faces.size(); ++i) {
    FirebaseVisionFace face = faces.get(i);

    /* Original implementation has original image. Original Image represents the camera preview from the live camera */

    // Create Mat representing the live camera itself
    Mat rgba = new Mat(originalCameraImage.getHeight(), originalCameraImage.getWidth(), CvType.CV_8UC4);

    // The box with a Imgproc affect made by OpenCV
    Mat rgbaInnerWindow;
    Mat mIntermediateMat = new Mat();

    // Make box for Imgproc the size of the detected face
    int rows = (int) face.getBoundingBox().height();
    int cols = (int) face.getBoundingBox().width();

    int left = cols / 8;
    int top = rows / 8;

    int width = cols * 3 / 4;
    int height = rows * 3 / 4;

    // Create a new bitmap based on live preview
    // which will show the actual image processing
    Bitmap newBitmap = Bitmap.createBitmap(originalCameraImage);

    // Bit map to Mat
    Utils.bitmapToMat(newBitmap, rgba);

    // Imgproc stuff. In this examply I'm doing edge detection.
    rgbaInnerWindow = rgba.submat(top, top + height, left, left + width);
    Imgproc.Canny(rgbaInnerWindow, mIntermediateMat, 80, 90);
    Imgproc.cvtColor(mIntermediateMat, rgbaInnerWindow, Imgproc.COLOR_GRAY2BGRA, 4);
    rgbaInnerWindow.release();

    // After processing image, back to bitmap
    Utils.matToBitmap(rgba, newBitmap);

    // Load the bitmap
    CameraImageGraphic imageGraphic = new CameraImageGraphic(graphicOverlay, newBitmap);
    graphicOverlay.add(imageGraphic);

    FaceGraphic faceGraphic;
    faceGraphic = new FaceGraphic(graphicOverlay, face, null);
    graphicOverlay.add(faceGraphic);


    FaceGraphic faceGraphic = new FaceGraphic(graphicOverlay);
    graphicOverlay.add(faceGraphic);


    // I can't speak for this
    faceGraphic.updateFace(face, frameMetadata.getCameraFacing());
  }

}
person cookiemonster    schedule 07.05.2019

На самом деле вы можете просто прочитать ByteBuffer, а затем получить массив для записи в объектные файлы, которые хотите, с помощью OutputStream. Конечно, вы можете получить его и от getBoundingBox().

person AnsorKazama    schedule 05.09.2018