如何在使用 Android 移动视觉库时处理单个相机帧

Posted

技术标签:

【中文标题】如何在使用 Android 移动视觉库时处理单个相机帧【英文标题】:How to process individual camera frames while using Android mobile vision library 【发布时间】:2017-07-02 16:25:03 【问题描述】:

我正在尝试制作一个相机应用程序,它使用带有自定义相机实例的 Google 移动视觉 API 来检测人脸,这与 Google API 中的“CameraSource”不同,因为我也在处理帧以检测颜色并使用 Camerasource我不允许获取相机帧。

搜索此问题后,我发现的唯一结果是关于将移动视觉与它的 CameraSource 结合使用,而不是与任何自定义 camera1 API 结合使用。 我试图覆盖帧处理,然后对输出的图片进行检测,如下所示:

camera.setPreviewCallback(new Camera.PreviewCallback() 
            @Override
            public void onPreviewFrame(byte[] data, Camera camera) 
                Log.d("onPreviewFrame", "" + data.length);
                Camera.Parameters parameters = camera.getParameters();
                int width = parameters.getPreviewSize().width;
                int height = parameters.getPreviewSize().height;
                ByteArrayOutputStream outstr = new ByteArrayOutputStream();
                Rect rect = new Rect(0, 0, width, height);
                YuvImage yuvimage = new YuvImage(data, ImageFormat.NV21, width, height, null);
                yuvimage.compressToJpeg(rect, 20, outstr);
                Bitmap bmp = BitmapFactory.decodeByteArray(outstr.toByteArray(), 0, outstr.size());
                detector = new FaceDetector.Builder(getApplicationContext())
                        .setTrackingEnabled(true)
                        .setClassificationType(FaceDetector.ALL_LANDMARKS)
                        .setMode(FaceDetector.FAST_MODE)
                        .build();

                detector.setProcessor(
                        new MultiProcessor.Builder<>(new GraphicFaceTrackerFactory())
                                .build());

                if (detector.isOperational()) 
                    frame = new Frame.Builder().setBitmap(bmp).build();
                    mFaces = detector.detect(frame);
//                    detector.release();
                
            
        );

那么有什么方法可以将移动视觉与我的相机实例关联起来,以便进行帧处理并用它来检测人脸? 你可以在这里看到我到目前为止所做的事情: https://github.com/etman55/FaceDetectionSampleApp

**新更新

在找到 CameraSource 类的开源文件后,我解决了大部分问题,但现在在尝试检测人脸时,检测器会正确接收帧但它无法检测到任何内容 >> 你可以在github 仓库。

【问题讨论】:

我认为很难支持 API 级别 21 的 Vision API 检查 android Vision API 的先决条件是 SDK 级别 26 或更高级别,并且从 API 级别 21 不推荐使用 camera1 github.com/googlesamples/android-vision developer.android.com/reference/android/hardware/Camera.html跨度> 实际上 android vision 正在使用他们自己的 camera1 Api 类,并且它被 proguard 锁定,所以很难弄清楚这就是我制作自定义 camera1 类的原因 【参考方案1】:

我可以为您提供一些非常有用的提示。

为相机提供的每一帧构建一个新的 FaceDetector 是非常个坏主意,而且也没有必要。您只需在相机帧接收器之外启动一次。

无需获取 YUV_420_SP(或 NV21)帧,然后将其转换为 YUV 实例,然后将其转换为 Bitmap,然后使用 Bitmap 创建 Frame.Builder()。如果您查看Frame.Builder Documentation,您会发现它允许直接从相机预览中使用 NV21。 像这样:

@override public void onPreviewFrame(byte[] data, Camera camera) detector.detect(new Frame.Builder().setImageData(ByteBuffer.wrap(data), previewW, previewH, ImageFormat.NV21));

【讨论】:

它应该调用 .build() 也像detector.detect(new Frame.Builder().setImageData(ByteBuffer.wrap(data), previewW, previewH, ImageFormat.NV21).build()) ;【参考方案2】:

还有 Kotin 版本:

    import com.google.android.gms.vision.Frame as GoogleVisionFrame
    import io.fotoapparat.preview.Frame as FotoapparatFrame

    fun recogniseFrame(frame: FotoapparatFrame) = detector.detect(buildDetectorFrame(frame))
        .asSequence()
        .firstOrNull  it.displayValue.isNotEmpty() 
        ?.displayValue

    private fun buildDetectorFrame(frame: FotoapparatFrame) =
        GoogleVisionFrame.Builder()
            .setRotation(frame.rotation.toGoogleVisionRotation())
            .setImageData(
                ByteBuffer.wrap(frame.image),
                frame.size.width,
                frame.size.height,
                ImageFormat.NV21
            ).build()

【讨论】:

以上是关于如何在使用 Android 移动视觉库时处理单个相机帧的主要内容,如果未能解决你的问题,请参考以下文章

如何在使用改造和 android jetpack 库时使用此动态 json 键创建数据类

Android - Things Raspberry Pi - Google 移动视觉支持

未找到 Android 移动视觉 API 库

Android(移动)视觉相机亮度非常低

OpenCV 在 Android 上的应用

Android - Things Raspberry Pi - Google移动视觉支持