MLkitFaceDetectionを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」リスナーでは、faceの「BoundingBox」を持つ「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オブジェクトをビットマップに変換する方法を知りたいです。顔画像を抽出してImageViewに表示したい。誰か助けてくれませんか。前もって感謝します。
注:MLKitのサンプルソースコードをダウンロードしましたAndroid以下のURLから
https://github.com/firebase/quickstart-Android/tree/master/mlkit
ビットマップからFirebaseVisionImage
を作成しました。検出が戻った後、各FirebaseVisionFace
は、元のビットマップから検出された顔を抽出するために使用できるRect
として境界ボックスを記述します。 Bitmap.createBitmap() を使用します。
受け入れられた答えは十分に具体的ではなかったので、私は私がしたことを説明しようとします。
1.-次のようにLivePreviewActivityでImageViewを作成します。
private ImageView imageViewTest;
2.-アクティビティ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.-ビットマップとRectを使用して顔だけに焦点を合わせるcropメソッドを作成しました。だから先に進んで同じことをしてください。
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.-最後に、cropingメソッドを呼び出して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);
}
これは、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());
}
}
実際には、ByteBuffer
を読み取るだけで、OutputStream
を使用して必要なオブジェクトファイルに書き込むための配列を取得できます。もちろん、getBoundingBox()
からも取得できます。