开发者

Slow down the setPreviewCallback method of a camera object

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);
开发者_Go百科                    // 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?


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.


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.


You could have a look at setOneShotPreviewCallback.


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜