2013-06-05 31 views
0

我開發了一個Android項目,我使用YUV420幀並使用opencv庫將它們轉換爲灰度。然後最終在相機表面上使用位圖創建灰度圖像。 經過一段時間的應用程序停止接收幀。我甚至將幀速率降低到15.相機卡在Android應用程序

package com.example; 

import org.opencv.android.Utils; 
import org.opencv.core.CvType; 
import org.opencv.core.Mat; 
import org.opencv.imgproc.Imgproc; 

import android.graphics.Bitmap; 
import android.graphics.Canvas; 
//import android.graphics.drawable.BitmapDrawable; 
import android.hardware.Camera; 
import android.hardware.Camera.Size; 
import android.util.Log; 
import android.view.SurfaceHolder; 
import android.hardware.Camera.Parameters; 

public class Preview extends CameraDemo implements SurfaceHolder.Callback,Camera.PreviewCallback 

{//Class Starts 
    public Camera mCamera; //Camera Object 
    private int PreviewSizeWidth; //Width of preview size 
    private int PreviewSizeHeight; //Height of Preview Size 
    private static final String TAG = "Preview"; 
    public boolean drawStatus = true; 
    SurfaceHolder mHolder; 

//Constructor to set preview size width and height 
public Preview(int width, int height) 
{ 
    PreviewSizeWidth = width; 
    PreviewSizeHeight = height; 
    Log.i(TAG, "Instantiated new Preview"); 
} 

//Override onpreviewFrame method of camera.previewcallback 
@Override 
public void onPreviewFrame(byte[] arg0, Camera arg1) 
{ 
    Log.i(TAG, "Frame is Received +++++"); 
    Bitmap bmp = processFrame(arg0); 
      if (bmp != null) { 
     draw(bmp); 
      } 
      bmp.recycle(); 
    Log.i(TAG, "Frame is Processed"); 

} 

//Called when surface is changed 
@Override 
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) 
{ 

    Log.i(TAG, "Surface Changed"); 
     Parameters parameters; 
    parameters = mCamera.getParameters(); 
    Size size = parameters.getPreviewSize(); 


    PreviewSizeWidth = size.width; 
    PreviewSizeHeight = size.height; 
    parameters.setPreviewSize(PreviewSizeWidth, PreviewSizeHeight); 
    parameters.setPreviewFrameRate(15); 
      mCamera.setParameters(parameters); 
    mCamera.startPreview(); 
} 

//Called when surface is created 
@Override 
public void surfaceCreated(SurfaceHolder arg0) { 
    mHolder = arg0; 
    Log.i(TAG, "Surface Created"); 
    mCamera = Camera.open(); 
      mCamera.setPreviewCallback(this); 
    Log.i(TAG, "Surface Created Successfully"); 
} 

//Called when surface is destroyed 
@Override 
public void surfaceDestroyed(SurfaceHolder arg0) { 
    //mHolder = arg0; 
    Log.i(TAG, "Surface Destroyed"); 
      mCamera.setPreviewCallback(null); 
    mCamera.stopPreview(); 
    mCamera.release(); 
    mCamera = null; 
    Log.i(TAG, "Surface Destroyed Exit"); 

} 


//Process Frame Data 
protected Bitmap processFrame(byte[] data) 
{ 
    Log.i(TAG, "Frame is Processing"); 
    Mat mYUV = new Mat(PreviewSizeHeight + PreviewSizeHeight/2, PreviewSizeWidth, CvType.CV_8UC1); 
    mYUV.put(0, 0, data); 

    Mat mRgba = new Mat(); 
    Mat mGray = new Mat(); 
    Imgproc.cvtColor(mYUV, mRgba, Imgproc.COLOR_YUV2GRAY_NV21, 3); 
    Imgproc.cvtColor(mGray, mRgba, Imgproc.COLOR_GRAY2RGB, 0); 
    Bitmap mBitmap = Bitmap.createBitmap(PreviewSizeWidth,PreviewSizeHeight, Bitmap.Config.ARGB_8888); 
    try { 
      Utils.matToBitmap(mRgba, mBitmap); 
     } catch(Exception e) { 
      Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage()); 
      mBitmap.recycle(); 
      mBitmap = null; 
     } 
    mRgba.release(); 
    mGray.release(); 
    mYUV.release(); 
    return mBitmap; 
} 

//For drawing bitmap 
public void draw(Bitmap bmp){ 

    Canvas canvas = mHolder.lockCanvas(); 
      if (canvas != null) { 
       Log.i(TAG, "Drawing Canvas"); 
        canvas.drawBitmap(bmp, (canvas.getWidth() - bmp.getWidth())/2, (canvas.getHeight() - bmp.getHeight())/2, null); 
           } 
      else{ 
       Log.i(TAG, "Canvas is null"); 
       } 
      mHolder.unlockCanvasAndPost(canvas); 
} 



}//CameraPreview Class ends 

注意:我能夠在屏幕上看到灰色圖像,但它在某些幀後不顯示。

回答

0

主線程無法處理圖像處理並在表面創建位圖。因此,我創建了另一個將在表面上處理和創建位圖的線程。輸入幀將被存儲在緩衝區中。 更改mCamera.setPreviewCallback(this)mCamera.setPreviewCallbackWithBuffer(this)