我正在创建一个虚拟现实应用程序,摄像机应该检测到面部,找到它们并在摄像机预览中显示它们的位置.
我知道有3种方法可以做到这一点,我想尽可能快地使用GLSurfaceView(according to this post),但是目前我正在尝试使用相机用于预览的相同SurfaceView.我在其上绘制的回调将是onFaceDetection,如下所示:
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)
相机是否有问题试图在同一SurfaceView上绘制预览面部检测回调?如何在不分层SurfaceView的情况下执行此操作?
解决方法
你不能在具有Type.PUSH_BUFFERS(你要显示帧的那个)的SurfaceView上进行locK和绘图.您必须在Z方向上创建原始视图上方的另一个视图,并在该视图中的SurfaceView上绘制.
因此,在main.xml中,在FrameLayout中的原始视图下创建一个自定义视图.
在活动视图中创建和处理SurfaceView.将此视图添加到相机预览显示中.通过SurfaceHolder启动自定义视图.在此视图中可以在画布上锁定和绘制.