2015-12-22 1 views
3

Я работаю в проекте, где я снимаю фреймы fps с камеры Android. после того, как каждый кадр преобразуется в Bitmap для использования родной библиотеки с SDK opencv и после того, как это растровое изображение отображается в ImageView. этот процесс потребляет кучу памяти и влияет на производительность приложения. Добавить следующий тег в Manifest.xml увеличить объем памяти кучи:Как я могу обработать кадры с камеры с помощью SurfaceView android

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

с этим, приложение отлично работает, когда для создания версии в режиме АПК отладки, но когда для создания версии в режиме АПК релиз , приложение работает очень медленно и не работает нормально, есть проблемы в производительности.

Я работал с логикой с использованием компонента SurfaceView для получения кадров с камеры, я использую SurfaceView, потому что мне нужно использовать в фоновом режиме внутри приложения, я хочу спросить вас, как решить эту проблему, рассчитывая на ваша помощь.

Я использую эту логику, чтобы получить кадры:

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; 

      }); 

     } 

    }; 

в пользовательском интерфейсе обратного вызова получить растровое изображение, чтобы показать в 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()); 
        } 
       }); 

      } 
     } 
+0

Вы посмотрели примеры, которые поставляются с SDK opencv android? Я считаю, что примеры имеют код для обработки всего этого для вас и предоставляют вам Mat для выполнения любых операций opencv, которые вы хотите на каждом фрейме. – medloh

+0

привет, я пытался использовать opencv для получения кадра, но с этим sdk возникли проблемы, чтобы показать изображение в другой ориентации устройства, потому что я пытаюсь использовать api-камеру Android. – fahoyos127

ответ

1

Работа с камерой API при высокой частоте кадров требует, чтобы подтолкнуть камера обращается к основному потоку пользовательского интерфейса, для этого вам понадобится separate Handler thread. Избавьтесь от ненужной обработки в обратном вызове onPreviewFrame(). Вы можете предварительно вычислить параметры камеры. Избегайте новых, даже для Rect: сбор мусора может привести к гибели.

Вы можете подавать YUV-фрейм через JNI на собственный JNI на базе OpenCV, и все преобразования и преобразования могут выполняться намного быстрее.

Если вы не используете OpenCV для каждого растрового изображения, вы можете конвертировать YUV в RGB без прохождения через JPEG. Вращение на 90 ° может быть выполнено за один шаг с таким преобразованием.

Если вы работаете на многоядерном устройстве, вы можете запустить службу-исполнитель с помощью newFixedThreadPool(), но тогда освобождение буферов камеры (вызовы camera.addCallbackBuffer()) может потребовать деликатного управления, особенно если вы хотите, чтобы частота кадров была равномерная.

Если вы просто хотите показать две копии потока предварительного просмотра, вы можете использовать OpenGL, а CPU не будет задействован в повороте и преобразовании YUV в RGB. Вы даже можете применить некоторую расширенную обработку изображений к текстуре, отображаемой через OpenGL.

+0

Спасибо за предложения, можете ли вы помочь повернуть и перенести операции Mat, где я могу найти примеры? Пожалуйста. – fahoyos127

+0

В чем проблема с операциями Mat? –

+0

Как я могу выполнить операцию поворота и перевести левую сторону в правую сторону изображения с помощью зеркального эффекта на изображении ?. эффективнее выполнять эти операции в Android Java или JNI Native? – fahoyos127