2013-04-17 1 views
4

Я борюсь с IllegalArgumentException при использовании lockCanvas() в onPreviewFrame.Могу ли я использовать lockCanvas() в обратном вызове onPreviewFrame?

В основном я хочу, чтобы захватить рамку, обработать ее и нарисовать непосредственно на поверхности SurfacePreview.

вот мой код onPreviewFrame

@Override 
public void onPreviewFrame(byte[] data, Camera camera) { 
    Canvas canvas = null; 

    if (mHolder == null) { 
     return; 
    } 

    int mImgFormat = mCamera.getParameters().getPreviewFormat(); 

    try { 
     canvas = mHolder.lockCanvas(); 
     canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR); 
     mHolder.unlockCanvasAndPost(canvas); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } finally { 
     if (canvas != null) 
     { 
      mHolder.unlockCanvasAndPost(canvas); 
     } 
    } 
} 

Я прочитал много документации и темы о камере в андроида, и я полагаю, что замок на поверхность, что кадры рисуются на это не представляется возможным, так как это за пределами контроля приложения. Это правда?

Одно из возможных решений заключается в том, чтобы нарисовать сверху вид сверху с другим видом, но я хочу сохранить свои обработанные кадры (будет обнаружено какое-то непонятное обнаружение края и цветовые исправления, которые могут занять много времени), выполненные синхронно с предварительным просмотром. Когда камера будет продолжать сплевывать кадры с хорошими fps, мои расчеты будут усложнять время, а в худшем случае - наложение, которое составляет десятки кадров.

Я изучал источник OpenCV и для меня это выглядит, как им удалось это сделать в CameraBridgeViewBase.java:

protected void deliverAndDrawFrame(CvCameraViewFrame frame) { 
    Mat modified; 

    if (mListener != null) { 
     modified = mListener.onCameraFrame(frame); 
    } else { 
     modified = frame.rgba(); 
    } 

    boolean bmpValid = true; 
    if (modified != null) { 
     try { 
      Utils.matToBitmap(modified, mCacheBitmap); 
     } catch(Exception e) { 
      Log.e(TAG, "Mat type: " + modified); 
      Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight()); 
      Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage()); 
      bmpValid = false; 
     } 
    } 

    if (bmpValid && mCacheBitmap != null) { 
     Canvas canvas = getHolder().lockCanvas(); 
     if (canvas != null) { 
      canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR); 
      canvas.drawBitmap(mCacheBitmap, (canvas.getWidth() - mCacheBitmap.getWidth())/2, (canvas.getHeight() - mCacheBitmap.getHeight())/2, null); 
      if (mFpsMeter != null) { 
       mFpsMeter.measure(); 
       mFpsMeter.draw(canvas, 20, 30); 
      } 
      getHolder().unlockCanvasAndPost(canvas); 
     } 
    } 
} 

Я либо отсутствующий что-то или я просто слишком стар для этого :)

Кроме того, это мой первый пост здесь, так что привет всем :)

ответ

1

на самом деле, камера OpenCV играет маленькую хитрость. В файле CameraBridgeViewBase.java и JavaCameraView.java. Я обнаружил, что класс SurfaceTexture (от api 11) используется для приема кадров с камеры. Преимущество SurfaceTexture заключается в том, что вам не нужно всегда рисовать его на экране (оно может содержаться в памяти). Затем класс SurfaceView отвечает за рисование обработанного фрейма из функции onPreviewFrame. Обратите внимание, что SurfaceView не привязан к камере. Надеюсь, это поможет.