如何在Android面部检测器(facedetector)的跟踪事件中获取当前帧(作为位图)?

9
我已经成功在我的Android设备上运行了标准的com.google.android.gms.vision.Tracker example,现在我需要对图像进行后处理,以查找已在Tracker事件方法中通知的当前脸部的虹膜。
那么,我如何获取与Tracker事件中收到的com.google.android.gms.vision.face.Face完全匹配的位图帧?这也意味着最终的位图应该与网络摄像头分辨率匹配,而不是屏幕分辨率。
一个糟糕的替代方案是每隔几毫秒调用一次takePicture,在CameraSource上单独处理此图片使用FaceDetector。虽然这样可以工作,但我有一个问题,即在takepicture期间视频流会冻结,并且由于单个bmp facedetector内存浪费,我会收到大量GC_FOR_ALLOC消息。

1
你所需要的似乎可以在 FaceDetector.SparseArray<Face> detect(Frame var1) 中找到。一旦你获取了 Frame 对象,你就可以使用 getBitmap() 方法,这听起来非常有前途。不幸的是,该类是 final 类,这意味着使用反射拦截 Frame 应该是可能的。 - Fabio
我不确定我理解你的建议。你是不是假设我手头有一个Frame对象?因为这就是我面临的问题。我有一个检测到的Face对象,但没有当前的Frame,我需要与给定的Face对象对应的Frame。例如,我在问题中提供的链接底部有一个名为onUpdate()的方法。有了这个方法,我如何获取与该方法的Face参数对应的当前Frame? - John Doe
除非您将FaceDetector中的所有方法包装并拦截detect方法(反射显然无法帮助,因为它是final),否则我们无法访问框架。保存框架并创建getter,然后在正确的时刻在其他地方调用它。 - Fabio
我明白了 - 谢谢你的帮助。 - John Doe
如果您尝试并且它可以工作,请返回翻译后的文本。 - Fabio
1个回答

9

您需要创建自己的人脸追踪器版本,扩展谷歌视觉人脸检测器。在您的mainActivity或FaceTrackerActivity(在谷歌跟踪示例中)类中,按照以下方式创建您自己的FaceDetector类:

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

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

    public SparseArray<Face> detect(Frame frame) {
        YuvImage yuvImage = new YuvImage(frame.getGrayscaleImageData().array(), ImageFormat.NV21, frame.getMetadata().getWidth(), frame.getMetadata().getHeight(), null);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        yuvImage.compressToJpeg(new Rect(0, 0, frame.getMetadata().getWidth(), frame.getMetadata().getHeight()), 100, byteArrayOutputStream);
        byte[] jpegArray = byteArrayOutputStream.toByteArray();
        Bitmap TempBitmap = BitmapFactory.decodeByteArray(jpegArray, 0, jpegArray.length);

        //TempBitmap is a Bitmap version of a frame which is currently captured by your CameraSource in real-time
        //So you can process this TempBitmap in your own purposes adding extra code here

        return mDelegate.detect(frame);
    }

    public boolean isOperational() {
        return mDelegate.isOperational();
    }

    public boolean setFocus(int id) {
        return mDelegate.setFocus(id);
    }
}

接下来,您需要通过修改CreateCameraSource方法,将自己的FaceDetector与CameraSource连接起来:

private void createCameraSource() {

    Context context = getApplicationContext();

    // You can use your own settings for your detector
    FaceDetector detector = new FaceDetector.Builder(context)
            .setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)
            .setProminentFaceOnly(true)
            .build();

    // This is how you merge myFaceDetector and google.vision detector
    MyFaceDetector myFaceDetector = new MyFaceDetector(detector);

    // You can use your own processor
    myFaceDetector.setProcessor(
            new MultiProcessor.Builder<>(new GraphicFaceTrackerFactory())
                    .build());

    if (!myFaceDetector.isOperational()) {
        Log.w(TAG, "Face detector dependencies are not yet available.");
    }

    // You can use your own settings for CameraSource
    mCameraSource = new CameraSource.Builder(context, myFaceDetector)
            .setRequestedPreviewSize(640, 480)
            .setFacing(CameraSource.CAMERA_FACING_FRONT)
            .setRequestedFps(30.0f)
            .build();
}

1
谢谢,但是如何使用它?我怎样可以从FaceGraphicTracker类中获取帧位图?谢谢。 - jennie788

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接