【问题标题】:Passing Mat from OpenCV to Facedetector from MLkit将 Mat 从 OpenCV 传递到 MLkit 的 Facedetector
【发布时间】:2019-12-30 14:50:54
【问题描述】:

对于 NVIDIA 盾牌上的个人应用程序,我正在使用 Firebase 的 MLKit 和面部检测功能,但从 OpenCV 传递 Mat 并不能真正起作用。

在我的 android 应用程序中,我使用了一个使用 OpenCV 制作的自定义相机视图,它在它处理的每一帧上创建返回一个 Mat。在这个过程中,我正在检查每一帧的脸。

我尝试的第一件事是使用以下代码将 Mat 转换为 Bitmap:

public static Bitmap bitmapFromMat(Mat mRgba) {
        Bitmap bitmap = Bitmap.createBitmap(mRgba.cols(), mRgba.rows(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(mRgba, bitmap);

        return bitmap;
    }

之后,我将位图传递给使用以下代码的 firebase:

FirebaseVisionImage fbImage = FirebaseVisionImage.fromBitmap(bitmap);
fbDetector.detectInImage(fbImage) ....

这在运行应用程序的前 1 分钟内运行良好。之后,应用程序开始严重滞后并停止工作,没有任何错误消息。在运行日志中,我看到了一条没有使用相机位图的消息。

之后,我一直在寻找将 Mat 转换为 bytearray 和 bytebuffer 的解决方案,但我尝试过的所有解决方案都失败了。 创建元数据的代码:

metadata = new FirebaseVisionImageMetadata.Builder()
                .setWidth(mFrame.width())
                .setHeight(mFrame.height())
                .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
                .setRotation(FirebaseVisionImageMetadata.ROTATION_0)
                .build();

(为了确保我将轮换更改为每种可能性并进行了测试)

我用来从 Mat 转换为 bytearray 的代码:

byte[] bytes = new byte[(int) (mFrame.total() * mFrame.channels())];
        mFrame.get(0,0, bytes);

        FirebaseVisionImage fbImage = FirebaseVisionImage.fromByteArray(bytes, metadata);

(发生的情况是人脸检测返回 0 个人脸)

我用来将位图转换为字节缓冲区的代码:

        int size = bitmap.getRowBytes() * bitmap.getHeight();
        ByteBuffer byteBuffer = ByteBuffer.allocate(size);
        bitmap.copyPixelsToBuffer(byteBuffer);

        FirebaseVisionImage fbImage = FirebaseVisionImage.fromByteBuffer(byteBuffer, metadata);

(发生的情况是人脸检测返回 0 个人脸)

我期望的是每帧都会检测到一张脸,但遗憾的是事实并非如此。当前的结果要么是巨大的延迟导致崩溃,要么是检测到 0 个面孔。

希望有人能帮我解决这个问题!

提前非常感谢!

【问题讨论】:

    标签: android firebase opencv firebase-mlkit


    【解决方案1】:

    在 JavaCameraView 类中,您需要有这样的 Mat 函数

     @Override
        public Mat rgba() {
           // Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4);
    
            if (previewFormat == ImageFormat.NV21) {
                Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGB_NV21, 4);
            }
            else if (previewFormat == ImageFormat.YV12) {
                Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGB_I420, 4);  // COLOR_YUV2RGBA_YV12 produces inverted colors
            }
            return mRgba;
        }
    

    您会注意到函数 initializeCamera 有 ImageFormat YV12 和 NV21...这是 MLkit 需要的 Image Format。

    然后,在您的面部检测器上,您需要像这样将您的 Mat 从 RGBA2YUV 转换:

        Imgproc.cvtColor(mRgba,mRgba,Imgproc.COLOR_RGBA2YUV_YV12);
    
    byte[] return_buff = new byte[(int) (mRgba.total() *
            mRgba.channels())];
    mRgba.get(0, 0, return_buff);
    

    您的 FirebaseVision 构建器需要像这样

    FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
            .setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_YV12)
            .setWidth(1920)   // 480x360 is typically sufficient for
            .setHeight(1080)  // image recognition
            .setRotation(0)
            .build();
    
    
    image = FirebaseVisionImage.fromByteArray(return_buff,metadata);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-23
      • 2019-02-24
      • 1970-01-01
      • 1970-01-01
      • 2014-02-16
      • 2015-10-04
      • 1970-01-01
      相关资源
      最近更新 更多