使用位图时,Android MLKit 人脸检测未检测到人脸

Posted

技术标签:

【中文标题】使用位图时,Android MLKit 人脸检测未检测到人脸【英文标题】:Android MLKit face detection not detecting faces when using Bitmap 【发布时间】:2021-08-27 19:46:52 【问题描述】:

我有一个 XR 应用程序,其中显示屏显示摄像头(后部)馈送。因此,捕获屏幕与捕获相机馈送几乎相同...... 因此,我截取屏幕截图(位图),然后尝试使用 Google MLKit 检测其中的人脸。

我正在关注official guide 来检测人脸。

为此,我首先启动我的面部检测器:

FaceDetector detector;

public MyFaceDetector()
    FaceDetectorOptions realTimeOpts =
            new FaceDetectorOptions.Builder()
                    .setContourMode(FaceDetectorOptions.CONTOUR_MODE_ALL)
                    .build();
    detector = FaceDetection.getClient(realTimeOpts);

然后我有一个传入位图的函数。我首先将位图转换为字节数组。我这样做是因为InputImage.fromBitmap 非常慢,而且 MLKit 实际上告诉我应该使用字节数组:

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 85, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream .toByteArray();

接下来,我制作 Bitmap 的可变副本(以便我可以在其上绘制),并设置一个 Canvas 对象,以及在 Bitmap 上绘制时将使用的颜色:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inMutable = true;
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length, options);
Canvas canvas = new Canvas(bmp);
Paint p = new Paint();
p.setColor(Color.RED);

所有设置完成后,我使用字节数组创建了一个InputImage(由 FaceDetector 使用):

InputImage image = InputImage.fromByteArray(byteArray, bmp.getWidth(), bmp.getHeight(),0, InputImage.IMAGE_FORMAT_NV21);

注意图像格式...有一个InputImage.IMAGE_FORMAT_BITMAP,但使用它会引发 IllegalArgumentException。无论如何,我接下来尝试处理 Bitmap,检测人脸,用之前定义的颜色填充每个检测到的人脸,然后将 Bitmap 保存到磁盘:

Task<List<Face>> result = detector.process(image).addOnSuccessListener(
            new OnSuccessListener<List<Face>>() 
                @Override
                public void onSuccess(List<Face> faces) 
                    Log.e("FACE DETECTION APP", "NUMBER OF FACES: " + faces.size());

                    Thread processor = new Thread(new Runnable() 
                        @Override
                        public void run() 
                            for (Face face : faces) 
                                Rect destinationRect = face.getBoundingBox();
                                canvas.drawRect(destinationRect, p);
                                canvas.save();
                                Log.e("FACE DETECTION APP", "WE GOT SOME FACCES!!!");

                            
                            File file = new File(someFilePath);
                            try 
                                FileOutputStream fOut = new FileOutputStream(file);
                                bmp.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
                                fOut.flush();
                                fOut.close();
                             catch (Exception e) 
                                e.printStackTrace();
                            
                        
                    );

                    processor.start();
                
            )
            .addOnFailureListener(
                    new OnFailureListener() 
                        @Override
                        public void onFailure(@NonNull Exception e) 
                            // Task failed with an exception
                            // ...
                        
                    );

虽然此代码运行(即没有异常)并且位图已正确写入磁盘,但从未检测到任何人脸 (faces.size() is always 0)。我试过旋转图像。我试过改变位图的质量。我已经尝试使用和不使用线程来处理任何检测到的面孔。我已经尝试了所有我能想到的。

有人有什么想法吗?

【问题讨论】:

ML 套件输入图像。 fromByteArray 仅支持 yv12 和 nv21 格式。您需要将位图转换为其中一种格式,以便 ML 套件管道进行处理。此外,如果您拥有的原始图像是位图,您可能只使用 InputImage.fromBitmap 来构造 InputImage。它不应该比您当前的方法慢。 【参考方案1】:

ML 套件输入图像。 fromByteArray 仅支持 yv12 和 nv21 格式。您需要将位图转换为其中一种格式,以便 ML 套件管道进行处理。此外,如果您拥有的原始图像是位图,您可能只使用 InputImage.fromBitmap 来构造 InputImage。它不应该比您当前的方法慢。

【讨论】:

【参考方案2】:

我在使用 ImageInput.fromMediaImage(..., ...) 时遇到了同样的问题

override fun analyze(image: ImageProxy) 

     val mediaImage: Image = image.image.takeIf  it != null  ?: run 
                image.close()
                return
            
     val inputImage = InputImage.fromMediaImage(mediaImage, image.imageInfo.rotationDegrees)
     // TODO: Your ML Code

点击此处了解更多详情 https://developers.google.com/ml-kit/vision/image-labeling/android

【讨论】:

以上是关于使用位图时,Android MLKit 人脸检测未检测到人脸的主要内容,如果未能解决你的问题,请参考以下文章

使用 CameraX 时,前置摄像头的 Facebase MLKit 人脸检测失败

MLKit 旋转面部图像使其笔直(iOS 和 Android)

android mobile vision api自定义检测器未检测到人脸

需要在使用 MLKit 和 Camera2 进行人脸检测期间捕获静止图像

人脸检测安卓

使用 CameraView 在 Android 上使用 ML Kit 检测人脸