简体   繁体   English

如何使用SurfaceView android处理来自相机的帧

[英]How can I process the frames from camera using SurfaceView android

I am working in project where I capture frames fps from Android camera. 我在项目中工作,我从Android相机捕获帧fps。 after each frame is converted in Bitmap to use a native library with opencv SDK and after this bitmap is showed in an ImageView. 在Bitmap中转换每个帧以使用带有opencv SDK的本机库之后,在ImageView中显示此位图。 this process to consume heap memory and to affect the performance the app. 这个过程消耗堆内存并影响app的性能。 I add the next tag in the manifest.xml to increase the heap memory: 我在manifest.xml中添加下一个标记以增加堆内存:

<application
    android:name="app"
    android:largeHeap="true" />

With this, the app work fine when to generate an apk version in debug mode, but when to generate an apk version in release mode, the app is very slow and doesn't work fine, there is issues in the performance. 有了这个,应用程序在调试模式下生成apk版本时工作正常,但是何时在发布模式下生成apk版本,应用程序非常慢并且无法正常工作,性能存在问题。

I worked with a logic using a SurfaceView component to get frames from camera, I use a SurfaceView because I need to use in background inside of the app, I want to ask you, how do I solve this problem, counting on your help. 我使用SurfaceView组件使用逻辑从相机获取帧,我使用SurfaceView,因为我需要在应用程序内部的背景中使用,我想问你,如何解决这个问题,依靠你的帮助。

I am using this logic to get frames: 我正在使用这个逻辑来获取帧:

public synchronized void onPreviewFrame(final byte[] data, final Camera camera) {
        executorService.execute(new Runnable() {
            public void run() {

      Camera.Parameters parameters = camera.getParameters();
      orientation = getOrientationDevice().getOrientation();
      orientation = normalize(orientation);

      //converter yuv to bitmap
      int width = parameters.getPreviewSize().width;
      int height = parameters.getPreviewSize().height;
      YuvImage yuv = new YuvImage(data,PreviewFormat,width, height, null);
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      yuv.compressToJpeg(new Rect(0, 0, width, height), 80, out);
      byte[] bytes = out.toByteArray();
      Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

               // rotate image 
             if (cameraId == Camera.CameraInfo.CAMERA_FACING_FRONT){
                    matrix.setScale(-1, 1);
                    matrix.postTranslate(bitmap.getWidth(), 0);
                    matrix.postRotate(rotation + 90);
                } else {
                    matrix.postRotate(rotation + 90);
                }                        

               // process bitmap from method jni
                ....

               // to pass bitmap a ImageView to show
               mCameraFrame.onFrame(bitmap.copy(bitmap.getConfig(), false));


            if (bitmap != null && !bitmap.isRecycled()) {
                bitmap.recycle();
                bitmap = null;
            }


            camera.addCallbackBuffer(data);

            return;

            });

        }

    };

in the UI the callback receive the bitmap to show in Imageview 在UI中,回调接收要在Imageview中显示的位图

@Override
    public void onFrame(final Bitmap mBitmap) {

        this.bitmapWeakReference = new WeakReference<Bitmap>(mBitmap);

        if (imageViewReference != null && bitmapWeakReference.get() != null) {
            final ImageView imageView = imageViewReference.get();
            if (imageView != null) {

                imageView.post(new Runnable() {
                    @Override
                    public void run() {
                        imageView.setImageBitmap(bitmapWeakReference.get());
                    }
                });

            }
        }

Working with camera API at high frame rate requires to push camera callbacks off the main UI thread, you will need a separate Handler thread for that. 以高帧速率使用相机API需要将相机回调推离主UI线程,您需要一个单独的Handler线程 Get rid of all unnecessary processing in your onPreviewFrame() callback. 摆脱onPreviewFrame()回调中的所有不必要的处理。 You can pre-calculate the camera parameters. 您可以预先计算相机参数。 Avoid new , even for Rect: garbage collection may be killing performance. 避免使用new ,即使对于Rect:垃圾收集可能会导致性能下降。

You can feed a YUV frame via JNI to native OpenCV-based JNI and all transformations and conversions may be performed much faster. 您可以通过JNI将YUV帧提供给基于OpenCV的本机JNI,并且可以更快地执行所有转换和转换。

If you don't use OpenCV for every bitmap, you can convert YUV to RGB without going through JPEG. 如果不对每个位图使用OpenCV,则可以将YUV转换为RGB而不通过JPEG。 Rotation by 90° can be performed in one step with such conversion. 通过这种转换可以一步完成90°的旋转。

If you are running on a multi-core device, you can start the executorService with newFixedThreadPool(), but then release of camera buffers (calls to camera.addCallbackBuffer() ) may require delicate management, especially if you want the frame rate to be uniform. 如果您在多核设备上运行,可以使用newFixedThreadPool()启动executorService,但是然后释放相机缓冲区(对camera.addCallbackBuffer()调用)可能需要精细管理,特别是如果您希望帧速率为制服。

If you simply want to show two copies of the preview stream, you can use OpenGL, and CPU will not be involved in rotation and YUV to RGB conversion at all. 如果您只想显示预览流的两个副本,则可以使用OpenGL,并且CPU根本不会涉及旋转和YUV到RGB转换。 You can even apply some advanced image processing to texture displayed via OpenGL. 您甚至可以对通过OpenGL显示的纹理应用一些高级图像处理。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM