2012-09-25 5 views
1

openCV 응용 프로그램이 작동하지만 레이아웃에 버튼 등을 추가해야합니다. 그래서 기본적으로 SurfaceView에 opencv 카메라 뷰를 표시하고 나머지는 아래에 추가하려고합니다.사용자 정의 레이아웃 (SurfaceView)이있는 opencv 구현

인터넷 및 포럼을 잠시 동안 검색했지만 opencv 얼굴 인식 응용 프로그램을 사용하는 사람에게 맞춤 레이아웃을 추가하려는 경우에만 해결책을 찾지 못했습니다.

저는 솔루션에 대한 절박한 마음으로 도움을 크게 감사 할 것입니다. 이를 위해 OpenCV 샘플 3 응용 프로그램 (간단한 예제)을 사용하여 간단한 사용자 정의 레이아웃에서 표면보기에 바인딩하려고했습니다. 나는 정상적인 카메라 응용 프로그램에서 그것을 관리했지만 opencv 예제로 상당히 어려움을 겪고 있습니다.

그래서이 각각 I (예에서와 같이)를 Sample3Native.java, Sample3View.java 및 SampleViewBase.java에 대해 가지고있는 코드 파일은 다음과 같다 :

public class Sample3Native extends Activity { 
private Sample3View mView; 

private BaseLoaderCallback mOpenCVCallBack = new BaseLoaderCallback(this) { 
    @Override 
    public void onManagerConnected(int status) { 
     switch (status) { 
      case LoaderCallbackInterface.SUCCESS: 
      { 

       // Load native library after(!) OpenCV initialization 
       System.loadLibrary("native_sample"); 

       // Create and set View 
       mView = new Sample3View(mAppContext); 
       setContentView(R.layout.main); 
       //setContentView(mView); 

       // Check native OpenCV camera 
       mView.openCamera(); 
      } break; 
      default: 
      { 
       super.onManagerConnected(status); 
      } break; 
     } 
    } 
}; 

//constructor 
public Sample3Native() {} 

@Override 
protected void onPause() { 
    super.onPause(); 
    if (null != mView) 
     mView.releaseCamera(); 
} 

@Override 
protected void onResume() { 
    super.onResume(); 
    if((null != mView) && !mView.openCamera()) { 
     AlertDialog ad = new AlertDialog.Builder(this).create(); 
     ad.setCancelable(false); // This blocks the 'BACK' button 
     ad.setMessage("Fatal error: can't open camera!"); 
     ad.setButton("OK", new DialogInterface.OnClickListener() { 
      public void onClick(DialogInterface dialog, int which) { 
      dialog.dismiss(); 
      finish(); 
      } 
     }); 
     ad.show(); 
    } 
} 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    requestWindowFeature(Window.FEATURE_NO_TITLE); 

    OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_2, this, mOpenCVCallBack); 
} 

}

class Sample3View extends SampleViewBase { 

private int mFrameSize; 
private Bitmap mBitmap; 
private int[] mRGBA; 

public Sample3View(Context context) { 
    super(context); 
} 

@Override 
protected void onPreviewStarted(int previewWidtd, int previewHeight) { 
    mFrameSize = previewWidtd * previewHeight; 
    mRGBA = new int[mFrameSize]; 
    mBitmap = Bitmap.createBitmap(previewWidtd, previewHeight, Bitmap.Config.ARGB_8888); 
} 

@Override 
protected void onPreviewStopped() { 
    if(mBitmap != null) { 
     mBitmap.recycle(); 
     mBitmap = null; 
    } 
    mRGBA = null; 
} 

@Override 
protected Bitmap processFrame(byte[] data) { 
    int[] rgba = mRGBA; 

    FindFeatures(getFrameWidth(), getFrameHeight(), data, rgba); 

    Bitmap bmp = mBitmap; 
    bmp.setPixels(rgba, 0, getFrameWidth(), 0, 0, getFrameWidth(), getFrameHeight()); 
    return bmp; 
} 

public native void FindFeatures(int width, int height, byte yuv[], int[] rgba); 

}

public abstract class SampleViewBase extends SurfaceView implements SurfaceHolder.Callback, Runnable { 

private Camera    mCamera; 
private SurfaceHolder  mHolder; 
private SurfaceView   mViewer; 
private int     mFrameWidth; 
private int     mFrameHeight; 
private byte[]    mFrame; 
private boolean    mThreadRun; 
private byte[]    mBuffer; 


public SampleViewBase(Context context) { 
    super(context); 
    mViewer = (SurfaceView)this.findViewById(R.id.camera_view); 
    mHolder = mViewer.getHolder(); 
    mHolder.addCallback(this); 
} 

public int getFrameWidth() { 
    return mFrameWidth; 
} 

public int getFrameHeight() { 
    return mFrameHeight; 
} 

public boolean openCamera() { 
    releaseCamera(); 
    mCamera = Camera.open(); 
    if(mCamera == null) 
     return false; 

    mCamera.setPreviewCallbackWithBuffer(new PreviewCallback() { 
     public void onPreviewFrame(byte[] data, Camera camera) { 
      synchronized (SampleViewBase.this) { 
       System.arraycopy(data, 0, mFrame, 0, data.length); 
       SampleViewBase.this.notify(); 
      } 
      camera.addCallbackBuffer(mBuffer); 
     } 
    }); 
    return true; 
} 

public void releaseCamera() { 
    mThreadRun = false; 
    synchronized (this) { 
     if (mCamera != null) { 
      mCamera.stopPreview(); 
      mCamera.setPreviewCallback(null); 
      mCamera.release(); 
      mCamera = null; 
     } 
    } 
    onPreviewStopped(); 
} 

public void setupCamera(SurfaceHolder holder,int width, int height) { 
    synchronized (this) { 
     if (mCamera != null) { 
      Camera.Parameters params = mCamera.getParameters(); 
      List<Camera.Size> sizes = params.getSupportedPreviewSizes(); 
      mFrameWidth = width; 
      mFrameHeight = height; 

      // selecting optimal camera preview size 
      { 
       int minDiff = Integer.MAX_VALUE; 
       for (Camera.Size size : sizes) { 
        if (Math.abs(size.height - height) < minDiff) { 
         mFrameWidth = size.width; 
         mFrameHeight = size.height; 
         minDiff = Math.abs(size.height - height); 
        } 
       } 
      } 

      params.setPreviewSize(getFrameWidth(), getFrameHeight()); 

      List<String> FocusModes = params.getSupportedFocusModes(); 
      if (FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) 
      { 
       params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); 
      }    

      mCamera.setParameters(params); 

      /* Now allocate the buffer */ 
      params = mCamera.getParameters(); 
      int size = params.getPreviewSize().width * params.getPreviewSize().height; 
      size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat())/8; 
      mBuffer = new byte[size]; 
      /* The buffer where the current frame will be copied */ 
      mFrame = new byte [size]; 
      mCamera.addCallbackBuffer(mBuffer); 

      try { 
       mCamera.setPreviewDisplay(holder); 
       //mCamera.setPreviewDisplay(null); 
      } catch (IOException e) {} 

      /* Notify that the preview is about to be started and deliver preview size */ 
      onPreviewStarted(params.getPreviewSize().width, params.getPreviewSize().height); 

      /* Now we can start a preview */ 
      mCamera.startPreview(); 
     } 
    } 
} 

public void surfaceChanged(SurfaceHolder _holder, int format, int width, int height) { 
    setupCamera(_holder,width, height); 
} 

public void surfaceCreated(SurfaceHolder holder) { 
    (new Thread(this)).start(); 
} 

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


//abstract functions used by child class 
protected abstract Bitmap processFrame(byte[] data); 
protected abstract void onPreviewStarted(int previewWidtd, int previewHeight); 
protected abstract void onPreviewStopped(); 
//================================ 

public void run() { 
    mThreadRun = true; 
    while (mThreadRun) { 
     Bitmap bmp = null; 

     synchronized (this) { 
      try { 
       this.wait(); 
       bmp = processFrame(mFrame); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 

     if (bmp != null) { 
      Canvas canvas = mHolder.lockCanvas(); 
      if (canvas != null) { 
       canvas.drawBitmap(bmp, (canvas.getWidth() - getFrameWidth())/2, (canvas.getHeight() - getFrameHeight())/2, null); 
       mHolder.unlockCanvasAndPost(canvas); 
      } 
     } 
    } 
} 

}

,

필자는이 코드가 내 코드를 통과하는 데 중요한 역할을해야한다는 것을 알고 있지만 실제로 도움이 필요합니다. 또는이 구현 유형의 실제 예제에 대한 링크를 얻을 수 있더라도. 또한, 단지 (그것은 나에게 도움이되지 않습니다) 나에게이 링크를 보내하지 마십시오 :이 openCV in custom applications

+0

그것은 주요한 끌기이며, 제대로 포맷되지 않은 이처럼 긴 게시물을 읽는 것이 눈을 아프게합니다. 그걸로 일해라. 나는'}'문자를 사용하는 것을 본다. 그것들은 코드의 일부인가 아닌가? 그렇다면 코드 블록 안에 있어야합니다. – karlphillip

+0

그래, 나는 또한 내 문자가 코드 블록에서 제외되었다는 것을 성가신 것으로 발견했다. 처음으로 스택 오버플로를 사용하여 아이디어를 얻을 것이라고 생각했습니다. 이것이 바로 코드 블록과 코드 블록이 연결 한 것입니다. 코드를 수동으로 포함시키는 방법은 무엇입니까? 어쨌든 openCV 프로젝트를 이전에 사용자 정의 레이아웃과 결합했거나이를위한 예제 솔루션에 대한 링크가 있습니까? 나는 필사적으로 도움이 필요하다. – PwC

답변

1

내 acitivity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    xmlns:opencv="http://schemas.android.com/apk/res-auto" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <org.opencv.android.JavaCameraView 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:visibility="gone" 
     android:id="@+id/tutorial1_activity_java_surface_view" 
     opencv:show_fps="true" 
     opencv:camera_id="any" /> 

    <org.opencv.android.NativeCameraView 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:visibility="gone" 
     android:id="@+id/tutorial1_activity_native_surface_view" 
     opencv:show_fps="true" 
     opencv:camera_id="any" /> 

    <Button 
     android:id="@+id/btnOK" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentTop="true" 
     android:layout_marginLeft="105dp" 
     android:layout_marginTop="139dp" 
     android:onClick="OKClicked" 
     android:text="@string/OK" /> 

    <TextView 
     android:id="@+id/txtDisp" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignBaseline="@+id/btnOK" 
     android:layout_alignBottom="@+id/btnOK" 
     android:layout_marginLeft="25dp" 
     android:layout_toRightOf="@+id/btnOK" 
     android:text="@string/app_name" 
     android:textAppearance="?android:attr/textAppearanceLarge" /> 

</RelativeLayout> 

이다 그리고이 코드는 MainActivity.java 클래스

으로 편집해야합니다
@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    setContentView(R.layout.activity_main); 
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

    if (mIsJavaCamera){ 
     mOpenCvCameraView = (CameraBridgeViewBase)findViewById(R.id.tutorial1_activity_java_surface_view); 
    }else{ 
     mOpenCvCameraView = (CameraBridgeViewBase)findViewById(R.id.tutorial1_activity_native_surface_view); 
    } 
    mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE); 
    mOpenCvCameraView.setCvCameraViewListener(this); 

    ArrayList<View> views = new ArrayList<View>(); 
    views.add(findViewById(R.id.btnOK)); 
    views.add(findViewById(R.id.txtDisp)); 
    mOpenCvCameraView.addTouchables(views); 
} 

public void OKClicked(View view){ 
    TextView disp = (TextView)findViewById(R.id.txtDisp); 
    disp.setText("OK Clicked"); 
} 

이 코드는 사용자가 버튼과 서피스 뷰 SurfaceView를 통해 텍스트 뷰를 볼 수 OpenCV의 설명 1.

로 수정됩니다. OK 버튼을 클릭하면 TextView에 "OK Clicked"가 표시됩니다. 이것은 삼성 갤럭시에서 나를 위해 일하고있다.

+1

Nativecameraview 또는 Javacameraview를 배경으로 만들고 싶습니다. 그러나이 방법은 작동하지 않으며 여전히 버튼 위에 겹쳐 있습니다. 카메라보기를 제외하고 아무것도 표시되지 않습니다. –

관련 문제