2015-12-22 89 views
3

我的項目,我從Android攝像頭捕捉的FPS幀的工作我處理來自攝像機的幀。每幀在位圖中轉換後使用opencv SDK的本地庫,並在ImageView中顯示此位圖後。這個過程消耗堆內存並影響應用程序的性能。我添加下一個標籤在manifest.xml,增加堆內存:如何使用SurfaceView的Android

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

這樣,應用程序工作正常時生成在調試模式下的APK版本,但是當產生在釋放模式的APK版本,該應用程序非常緩慢,並且無法正常工作,因此存在性能問題。

我用一個使用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; 

      }); 

     } 

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

      } 
     } 
+0

你有沒有看着來與OpenCV的Android SDK中的例子嗎?我相信這些例子有代碼來處理所有這些,併爲您提供Mat,以便在每個框架上執行您希望的任何opencv操作。 – medloh

+0

嗨,我試圖用OpenCV的獲得框架,但與此SDK有問題,說明了在不同設備方向的圖像,因爲我試圖使用API​​相機的Android。 – fahoyos127

回答

1

顯示在高幀率攝像頭API工作需要推相機回調關閉主UI線程,您將需要一個separate Handler thread。擺脫onPreviewFrame()回調中的所有不必要的處理。您可以預先計算相機參數。避免新的,即使對於Rect:垃圾收集可能會造成性能下降。

您可以通過JNI喂YUV框架基於本地的OpenCV-JNI,所有的轉換和轉換可更快進行。

如果你不使用OpenCV的每一個位圖,您可以YUV轉換爲RGB格式,而無需通過JPEG去。這種轉換可以一步完成90°的旋轉。

如果您正在多核設備上運行,您可以使用newFixedThreadPool()啓動executorService,但隨後釋放相機緩衝區(調用camera.addCallbackBuffer())可能需要進行微妙的管理,尤其是如果您希望幀速率爲制服。

如果你只是想顯示預覽流的兩個副本,你可以使用OpenGL,而CPU也不會轉動和YUV到RGB轉換參與的。您甚至可以將一些高級圖像處理應用於通過OpenGL顯示的紋理。

+0

感謝您的建議,您可以幫助我們進行旋轉和轉置Mat操作,我可以在哪裏找到示例?請。 – fahoyos127

+0

Mat操作有什麼問題? –

+0

如何通過鏡像效果在圖像中執行旋轉操作並將左側翻譯爲圖像的右側? 在Android Java或JNI Native中執行這些操作更有效嗎? – fahoyos127