减慢相机对象的 setPreviewCallback 方法

发布于 2024-11-05 14:07:12 字数 1602 浏览 1 评论 0原文

我在相机对象(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();

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

I have the following code running on a camera object (mCamera) to detect faces in whatever the camera is pointing at. The problem is while this process is very fast indeed it slows the rest of the app down, i.e. when I press a button to do something while this face detection is running it takes about half a second to register it. My thinking is that is I somehow slow down or reduce the number of call back it makes in a certain time then this button press will be much faster:

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();

It is already inside a Thread as I thought that may help but has not really. Is there anyway to change the call back frequency?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

污味仙女 2024-11-12 14:07:12

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

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

希望其中一些有所帮助。

I've done some work getting face detection to happen in real time and here's a few thing's I've learned along the way:

  • The biggest contributor to the speed of the APIs face detector is the size of the image being examined. You might consider using the smallest reasonable Camera.getSupportedPreviewSizes() that you can to help speed this up. Note that the preview size and the picture size are independent params so you arent necessarily sacrificing captured picture quality unless you going to save the preview frame as a capture.
  • Also, if there is any way to assume that faces should be within some bounding area of the frame, you can gain some performance by cropping the preview frame to those bounds and then handing that bitmap to the face detector.
  • Avoid doing any allocations of new objects inside your loop that handles preview frames. The allocations and the eventual garbage collection that will need to happen can cost a lot of time. Use singletons, statics or member vars to hold onto stuff you can re-use rather than allocate new stuff.
  • finally, once youve got it performing as best you can, consider throttling the thread to not try to process every frame, but maybe process one every couple of seconds. Add a member var called something like mLastFrameAnalzedTime to your thread class. Store the time of the last successful decode/detect int that, and then each time you get a new frame, check to see if enough time has passed to want to process the next.

Hope some of that helps.

原谅过去的我 2024-11-12 14:07:12

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

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

You may try to insert some Thread.sleep() calls in the onPreviewFrame method, so that other parts of the code also get some cpu time. The code above looks like it may use up almost all cpu time in the onPreview code.

You may need to play with the sleep time, as too much sleeping will turn the preview rate way down.

葮薆情 2024-11-12 14:07:12

您可以查看 setOneShotPreviewCallback

You could have a look at setOneShotPreviewCallback.

旧话新听 2024-11-12 14:07:12

以下方法的文档

请检查 Camera.Parameters getSupportedPreviewFpsRange
获取预览帧率范围
在我的 Nexus 上设置PreviewFpsRange

,我有 3 个可能的预览 FPS
最小 15 帧/秒,最大 15 帧/秒
最小 15 帧/秒,最大 30 帧/秒
最小 24 fps,最大 30 fps

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

我不确定这是否有效,因为我测量了两次调用 onPreviewFrame 之间的时间,并且我得到了 fps 1000....也许我的测量中有错误。

关于 Camera.Parameters 的 Android 官方文档

Please check documentation of following methods of Camera.Parameters

getSupportedPreviewFpsRange
getPreviewFpsRange
setPreviewFpsRange

on my Nexus, i have 3 possible FPS of preview
min 15fps, max 15fps
min 15fps, max 30fps
min 24fps, max 30fps

Attention :
getSupportedPreviewFpsRange's return values are scaled by 1000 -- I have no idea why.

I am not sure this works as I measured the time between two call of onPreviewFrame, and I got a fps 1000.... maybe there is a mistake in my measurement .

Android Offical Doc on Camera.Parameters

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文