2012-09-03 37 views
8

私は、カメラが顔を検出してカメラのプレビューに位置を表示する仮想現実感のアプリケーションを作っています。Androidでカメラをプレビューする

私は(according to this post)できるだけ速くなるようにGLSurfaceViewを使用したいのですが、それを行うには3つの方法を知っているが、現在、私はカメラのために使用される同じ SurfaceViewに描画しようとしていますそのプレビュー。私はこのエラーを取得しておく。このコードで

public class MyActivity extends Activity implements SurfaceHolder.Callback, Camera.FaceDetectionListener { 
    Camera camera; 
    SurfaceView svPreview; 
    SurfaceHolder previewHolder; 
    TextView tvInfo; 
    Paint red; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     svPreview = (SurfaceView) findViewById(R.id.svPreview); 
     tvInfo = (TextView) findViewById(R.id.tvInfo); 

     red = new Paint(); 
     red.setStyle(Paint.Style.STROKE); 
     red.setStrokeWidth(3); 

     previewHolder = svPreview.getHolder(); 
     previewHolder.addCallback(this); 
     previewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public void surfaceCreated(SurfaceHolder arg0) { 
     camera = Camera.open(); 
     try { 
      camera.setDisplayOrientation(90); 
      camera.setFaceDetectionListener(this); 
      camera.setPreviewDisplay(previewHolder); 
     } 
     catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
     // . . . 
     camera.startPreview(); 
     camera.autoFocus(null); 
     camera.startFaceDetection(); 
    } 

    public void surfaceDestroyed(SurfaceHolder arg0) { 
     camera.stopFaceDetection(); 
     camera.cancelAutoFocus(); 
     camera.stopPreview(); 
     camera.release(); 
     camera = null; 
    } 

    public void onFaceDetection(Face[] faces, Camera camera) { 
     tvInfo.setText("Faces: " + String.valueOf(faces.length)); 

     Canvas canvas = previewHolder.lockCanvas(); 
     for(int i=0; i < faces.length; i++) { 
      Point leftEye = faces[i].leftEye; 
      Point rightEye = faces[i].rightEye; 
      // this is not working 
      canvas.drawPoint(leftEye.x, leftEye.y, red); 
     } 
     previewHolder.unlockCanvasAndPost(canvas); 
    } 
} 

09-03 19:35:42.743: E/SurfaceHolder(19394): Exception locking surface 
09-03 19:35:42.743: E/SurfaceHolder(19394): java.lang.IllegalArgumentException 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at android.view.Surface.lockCanvasNative(Native Method) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at android.view.Surface.lockCanvas(Surface.java:76) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:744) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at android.view.SurfaceView$4.lockCanvas(SurfaceView.java:720) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at com.bluetooth.activities.MyActivity.onFaceDetection(MyActivity.java:90) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at android.hardware.Camera$EventHandler.handleMessage(Camera.java:729) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at android.os.Handler.dispatchMessage(Handler.java:99) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at android.os.Looper.loop(Looper.java:137) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at android.app.ActivityThread.main(ActivityThread.java:4424) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at java.lang.reflect.Method.invokeNative(Native Method) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at java.lang.reflect.Method.invoke(Method.java:511) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
09-03 19:35:42.743: E/SurfaceHolder(19394):  at dalvik.system.NativeStart.main(Native Method) 
09-03 19:35:42.743: W/dalvikvm(19394): threadid=1: thread exiting with uncaught exception (group=0x40a561f8) 
09-03 19:35:42.766: E/AndroidRuntime(19394): FATAL EXCEPTION: main 
09-03 19:35:42.766: E/AndroidRuntime(19394): java.lang.IllegalArgumentException 
09-03 19:35:42.766: E/AndroidRuntime(19394): at android.view.Surface.unlockCanvasAndPost(Native Method) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at android.view.SurfaceView$4.unlockCanvasAndPost(SurfaceView.java:775) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at com.bluetooth.activities.MyActivity.onFaceDetection(MyActivity.java:99) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at android.hardware.Camera$EventHandler.handleMessage(Camera.java:729) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at android.os.Handler.dispatchMessage(Handler.java:99) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at android.os.Looper.loop(Looper.java:137) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at android.app.ActivityThread.main(ActivityThread.java:4424) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at java.lang.reflect.Method.invokeNative(Native Method) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at java.lang.reflect.Method.invoke(Method.java:511) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
09-03 19:35:42.766: E/AndroidRuntime(19394): at dalvik.system.NativeStart.main(Native Method) 

同じにそのプレビューを描画しようとしているカメラに問題があるようにようにそれに描画する私のコールバックはonFaceDetectionだろうSurfaceviewの顔検出コールバック? SurfaceViewsをレイヤー化しないでこれを行うにはどうすればいいですか?

+0

Androidソースを掘り下げてプレビューをアプリの残りの部分とは別のスレッドで実行しているように見えるので、私はあなたのアプリがCanvasオブジェクトを取得できないそれらは異なるスレッドであるため、Surface。つまり、私はこれを処理している誰かが応答することを望んでいます –

+0

これらのビューの上に透明な背景を持つFrameLayoutを使用する方法はありますか? – Shafi

答えて

6

Type.PUSH_BUFFERS(フレームを表示しているもの)を持つSurfaceViewでlocKと描画を行うことはできません。 Z方向に元のビューの上に別のビューを作成し、そのビューでSurfaceViewを描画する必要があります。

したがって、main.xmlでは、元のビューの下にFrameLayoutのカスタムビューを作成します。

アクティビティビューでSurfaceViewを作成して処理します。このビューをカメラプレビュー表示に追加します。 SurfaceHolderを通過するカスタムビューを開始します。このビューでは、キャンバスをロックして描画できます。

-1

私は言った、

スレッドについてはありません。

この行のためにエラーが発生するわけではありません。あなたが持っているかもしれないので、キャンバスの

canvas.drawPoint(leftEye.x, leftEye.y, red); 

それはまだ使用して、あなたは慎重にチェックした場合は、それを

をロックすることはできません、あなたはあなたが得るこのキャンバスが表示されます== nullの

canvas = canvasHolder.lockCanvas(); 
    if (canvas == null) Log.i("Error", "Canvas == null!"); 

どのように使用されているのですか?

あなたは何が起こっているのかを表示するために既に使用しています。それはあなたがあなたの目の上にポイントを描きたいのであれば、私はお勧め、あなたがプレビューカメラのためにあなたSurfaceViewの上に別のSurfaceView/SurfaceHolderを持っている必要があります

camera.setPreviewDisplay(previewHolder); 

です:]

5

ジェームズはあなたを指摘したようにSurfaceViewを(私は通常もSurfaceHolder.Callbackを実装)拡張するカスタム表面を作成する必要があります。

public class CameraSurfacePreview extends SurfaceView implements SurfaceHolder.Callback

コンストラクタのようなものになります。

public CameraSurfacePreview(Context context) { 
    super(context); 
    ... 
    mHolder = getHolder(); 
    mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    ... 

カメラを開いた後でサーフェスにカメラをバインドする必要があります(実装している場合はSurfaceHolder。コールバック)が上書きsurfaceCreated内部でこのどこかに置く:

mCamera = Camera.open(); 
mCamera.setPreviewDisplay(mHolder); 

は最後に、活動内容ビューにカスタム表面somehereのインスタンスを追加する必要があります。活動のための私のレイアウト例で

CameraSurfacePreview cameraSurfacePreview = new CameraSurfacePreview(this); 
//camera surface preview is first child! 
((ViewGroup)findViewById(R.id.cameraLayout)).addView(cameraSurfacePreview, 0); 

は次のようになります(私はOPEとしてOpenGLを使用する場合

0
<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
       android:layout_width="fill_parent"   
         android:layout_height="fill_parent" 
       android:layout_gravity="top|left" 
       android:id="@+id/cameraLayout"> 

lockcanvas/unlockcanvasandpostアプローチが適切でないメインフレームレイアウトのカメラプレビュー)を示していnGLコードは表面を制御してロックしています。標準の2d APIを使用する場合は、OpenGLを使用しないでください。