【问题标题】:Slow down the setPreviewCallback method of a camera object减慢相机对象的 setPreviewCallback 方法
【发布时间】:2011-08-20 00:45:44
【问题描述】:

我在相机对象 (mCamera) 上运行以下代码,以检测相机指向的任何人脸。问题是虽然这个过程非常快,但它确实减慢了应用程序的其余部分,即当我在这个面部检测运行时按下按钮做某事时,注册它大约需要半秒钟。我的想法是,我会以某种方式减慢或减少它在特定时间内的回调次数,然后按此按钮会快得多:

Thread thread = new Thread(new Runnable() {
    public void run() {
        // TODO Auto-generated method stub
        mCamera.setPreviewCallback(new PreviewCallback() {
            public void onPreviewFrame(final byte[] _data, Camera _camera) {
                Camera.Parameters parameters = mCamera.getParameters();
                int format = parameters.getPreviewFormat();
                // YUV formats require more conversion
                if (format == ImageFormat.NV21) {
                    int w = parameters.getPreviewSize().width;
                    int h = parameters.getPreviewSize().height;
                    // Get the YuV image
                    YuvImage yuv_image = new YuvImage(_data, format, w, h, null);
                    // Convert YuV to Jpeg
                    Rect rect = new Rect(5 * w / 10, 1 * h / 5, 8 * w / 10, 4 * h / 5);
                    final ByteArrayOutputStream output_stream = new ByteArrayOutputStream();
                    yuv_image.compressToJpeg(rect, 10, output_stream);
                    // Convert from Jpeg to Bitmap
                    Bitmap bmp = Bitmap.createScaledBitmap(BitmapFactory.decodeByteArray(output_stream.toByteArray(), 0, output_stream.size()), 3 * w / 10, 3 * h / 5, true);
                    detectFaces(bmp, w, h);
                }
            }
        });
    }
});
thread.start();

它已经在一个线程中,因为我认为这可能会有所帮助,但实际上并没有。有没有办法改变回叫频率?

【问题讨论】:

    标签: java android callback camera


    【解决方案1】:

    我已经做了一些工作来实时进行人脸检测,以下是我在此过程中学到的一些东西:

    • API 人脸检测器速度的最大贡献者是被检查图像的大小。您可以考虑使用最小的、合理的 Camera.getSupportedPreviewSizes() 来帮助加快速度。请注意,预览大小和图片大小是独立的参数,因此您不必牺牲捕获的图片质量,除非您将预览帧保存为捕获。
    • 此外,如果有任何方法可以假设人脸应该在帧的某个边界区域内,您可以通过将预览帧裁剪到这些边界然后将该位图交给人脸检测器来获得一些性能。
    • 避免在处理预览帧的循环内分配任何新对象。需要进行的分配和最终的垃圾收集可能会花费大量时间。使用单例、静态或成员变量来保留可以重复使用的东西,而不是分配新的东西。
    • 最后,一旦你尽可能地发挥它的性能,考虑限制线程不要尝试处理每一帧,而是可能每隔几秒处理一个。将一个名为 mLastFrameAnalzedTime 的成员变量添加到您的线程类中。存储最后一次成功解码/检测 int 的时间,然后每次获得新帧时,检查是否已经过了足够的时间来处理下一帧。

    希望对你有所帮助。

    【讨论】:

      【解决方案2】:

      您可以尝试在onPreviewFrame 方法中插入一些Thread.sleep() 调用,以便代码的其他部分也获得一些cpu 时间。上面的代码看起来可能会耗尽 onPreview 代码中几乎所有的 cpu 时间。

      您可能需要调整睡眠时间,因为睡眠过多会降低预览率。

      【讨论】:

        【解决方案3】:

        你可以看看setOneShotPreviewCallback

        【讨论】:

          【解决方案4】:

          请查看以下Camera.Parameters方法的文档

          getSupportedPreviewFpsRange getPreviewFpsRange setPreviewFpsRange

          在我的 Nexus 上,我有 3 种可能的 FPS 预览 最低 15fps,最高 15fps 最低 15fps,最高 30fps 最低 24fps,最高 30fps

          注意: getSupportedPreviewFpsRange 的返回值按 1000 缩放——我不知道为什么。

          我不确定这是否有效,因为我测量了两次调用 onPreviewFrame 之间的时间,我得到了 fps 1000.... 可能我的测量有误。

          Android Offical Doc on Camera.Parameters

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-10-18
            • 2011-06-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-04
            相关资源
            最近更新 更多