【问题标题】:Android canvas draw line on cameraAndroid画布在相机上画线
【发布时间】:2016-02-11 13:44:10
【问题描述】:

我正在使用增强现实应用程序,我想画一条线来连接相机顶部的两个可移动对象。但是我得到了这个异常

Process: test.job.reality.augument.job.com.augumentrealitytest, PID: 15056
    java.lang.IllegalArgumentException
    at android.view.Surface.nativeLockCanvas(Native Method)
    at android.view.Surface.lockCanvas(Surface.java:266)
    at custom.MyCameraView$MyThread.run(MyCameraView.java:447)

这是我的代码,你可以看到我在surfaceCreted 方法中开始我的线程。我在想我不能锁定Canvas,因为它已经被相机锁定了,对吗?但是我画线是可能的(我正在使用beyondAR 增强现实库)

public class MyCameraView extends SurfaceView implements SurfaceHolder.Callback, Camera.PictureCallback {
private MyThread thread;

public MyCameraView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

@SuppressWarnings("deprecation")
private void init(Context context) {
    mIsPreviewing = false;
    mHolder = getHolder();
    mHolder.addCallback(this);

    configureCamera();

    if (Build.VERSION.SDK_INT <= 10) {// Android 2.3.x or lower
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    thread=new MyThread(getHolder(),this);
    getHolder().addCallback(this);
    setFocusable(true);
}

 @Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);


}

public void surfaceCreated(SurfaceHolder holder) {
    // The Surface has been created, acquire the camera and tell it where
    // to draw.

    thread.startrun(true);
    thread.start();
    try {

        if (mCamera == null) {
            init(getContext());
            if (mCamera == null) {
                return;
            }
        }

        mCamera.setPreviewDisplay(holder);
    } catch (IOException exception) {
        if (mCamera != null) {
            mCamera.release();
        }
        mCamera = null;
        Logger.e(TAG, "CameraView -- ERROR en SurfaceCreated", exception);
    }
}

public void surfaceDestroyed(SurfaceHolder holder) {
    releaseCamera();

    thread.startrun(false);
    thread.stop();
}

public class MyThread extends Thread{

    private SurfaceHolder msurfaceHolder;
    private MyCameraView mSurfaceView;
    private boolean mrun =false;

    public MyThread(SurfaceHolder holder, MyCameraView mSurfaceView) {

        this.msurfaceHolder = holder;
        this.mSurfaceView=mSurfaceView;
    }

    public void startrun(boolean run) {

        mrun=run;
    }

    @SuppressLint("WrongCall")
    @Override
    public void run() {

        super.run();
        Canvas canvas;
        while (mrun) {
            canvas=null;
            try {
                canvas = msurfaceHolder.lockCanvas();
                synchronized (msurfaceHolder) {
                    mSurfaceView.onDraw(canvas);
                }
            } finally {
                if (canvas != null) {
                    msurfaceHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }
}

【问题讨论】:

    标签: android canvas android-camera


    【解决方案1】:

    当表面用于显示相机预览时,您不能再在其上绘图。原则上,您可以在预览表面上打开一个单独的透明画布,然后在该画布上绘图。切换到 OpenGL 预览(使用 SurfaceTexture)可能会容易得多;然后您可以为您的绘图使用相同的 OpenGL 上下文(但它们也必须在 OpenGL 中表示)。您可以找到一个简单的演示项目at GitHub 开始。

    但即使在这种情况下,您的任务也存在另一个问题:即使您的 CV 非常快,您的增强功能与直接从传感器到屏幕的相机框架之间也没有同步。在 OpenGL 的情况下,一些简单的事情可以在 0 时间内完成(例如,对接收到的纹理进行简单的卷积)。但更有趣的事情需要不同的东西。

    我们通常对用户隐藏实时预览,在onPreviewFrame() 回调中获取帧,处理它们并手动绘制帧和任何其他线条或对象。这会引入一些延迟,但如果您的算法真的很有效,那么这种延迟可能可以忽略不计。

    再次强调,OpenGL 通常在这方面有很大帮助。

    【讨论】:

      【解决方案2】:

      不要 lockCanvas 并停止线程调用,只需将以下代码放在 Draw 方法中。我希望它会起作用。

      protected void onDraw(Canvas canvas) {
          // TODO Auto-generated method stub
          super.onDraw(canvas);
      
          Paint paint = new Paint();
      
          DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
      
          int screenWidth = metrics.widthPixels;
          int screenHeight = metrics.heightPixels;
      
          screenHeight = (int) (metrics.heightPixels * 0.6290);
          paint.setAntiAlias(true);
          paint.setStrokeWidth(1);
          paint.setStyle(Paint.Style.STROKE);
      
          paint.setColor(Color.argb(255, 255, 255, 255));
      
          canvas.drawLine((screenWidth / 4), 0,
                  (screenWidth / 4), screenHeight + 500, paint);
      
      
          if(screenWidth == 1280 && screenHeight == 473)  // this condition for 10" tab only
          canvas.drawLine((screenWidth / 2f), 0,
                      (screenWidth / 2f), screenHeight + 500, paint);
      
          else
          canvas.drawLine((screenWidth / 2.20f), 0,
                  (screenWidth / 2.20f), screenHeight + 500, paint);
      
          canvas.drawLine(0, (screenHeight / 2.15f) * 2, screenWidth,
                  (screenHeight / 2.15f) * 2, paint);
      
          canvas.drawLine(0, (screenHeight / 2.15f) , screenWidth,
                  (screenHeight / 2.15f), paint);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-05-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-18
        相关资源
        最近更新 更多