Android中的视频帧捕获

时间:2013-12-25 10:35:22

标签: android video-capture

我正在尝试实现一个每秒捕获大约1张图片的Android应用,对每张图片执行一些处理并将输出发送到文件进行存储。我的第一次尝试尝试类似以下内容:

public class MainActivity extends Activity {

    ...
    Handler loopHandler = new Handler();
    Runnable loopRunnable = new Runnable() {

        @Override
        public void run() {
            Thread pictureThread = new Thread(pictureRunnable);
            pictureThread.start();
            loopHandler.postDelayed(this, 1000);
        }
    };

    Runnable pictureRunnable = new Runnable() {
        @Override
        public void run() {
            mCamera.takePicture(null, null, mPicture);
        }    
    };

    private PictureCallback mPicture = new PictureCallback() {
        @Override
        public void onPictureTaken(byte[] data, Camera camera) {
        ... My processing code ...
        }
    }

以这种方式拍摄约4张照片后该应用程序会冻结。所以,我猜这可能是一种过于天真的方法,但我希望能够更深入地理解为什么这种方法不起作用。

有没有办法在不直接使用视频的情况下执行此操作,或者我最终是否必须创建从视频流中提取帧的内容?

2 个答案:

答案 0 :(得分:0)

您可以使用OpenCV。它允许您对从相机接收的每个帧执行操作。 http://opencv.org/

答案 1 :(得分:0)

最好的办法是更深入地研究您的代码并准确了解导致应用冻结的原因。也许它与您发布的代码无关,而与图像的实际处理无关。

过去似乎对我有用的另一种方法是完全跳过PictureCallback。相反,您可以使用PreviewCallbackhttp://developer.android.com/reference/android/hardware/Camera.PreviewCallback.html)。每个帧都会触发此回调,因此您可以在此框架内查看自上次处理图像以来是否超过1秒,如果是,请在另一个线程上进行图像处理。

我没有测试过这个,但是这样:

myCamera.setPreviewCallback(new PreviewCallback() {

    @Override
    public void onPreviewFrame(byte[] data, Camera camera) {

        // previousTime is defined as a member variable
        long timeElapsed = System.currentTimeMillis() - previousTime;

        if(timeElapsed > 1000) {

            // reset values for the next run
            previousTime = System.currentTimeMillis();

            // process the image (just an example, you should do this inside an AsyncTask)
            Size previewSize = myCamera.getParameters().getPreviewSize();
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            YuvImage yuvImage = new YuvImage(data, myCamera.getParameters().getPreviewFormat(), previewSize.width,previewSize.height, null);
            yuvImage.compressToJpeg(new Rect(0, 0, previewSize.width, previewSize.height), 100, out);
            byte[] imageBytes = out.toByteArray();

            Options options = new Options();
            options.inSampleSize = 1;
            Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, options);

            // you now have the image bitmap which you can use to apply your processing ...
        }

    }
});