2016-12-27 1 views
1

이미 세로보기 모드와 완벽하게 작동하는 카메라보기를 만들었지 만 가로 모드에서는 작동하지만 세로 모드에서는 작동하지 않는 얼굴 감지 기능을 적용하려고합니다. 아래 오류.Android OpenCv Utils : nMatToBitmap catched cv :: 예외 :

public class PortraitCameraView extends CameraBridgeViewBase implements Camera.PreviewCallback { 
    private static final int MAGIC_TEXTURE_ID = 10; 
    private static final String TAG = "JavaCameraView"; 

    private byte mBuffer[]; 
    private Mat[] mFrameChain; 
    private int mChainIdx = 0; 
    private Thread mThread; 
    private boolean mStopThread; 

    protected Camera mCamera; 
    protected JavaCameraFrame[] mCameraFrame; 
    private SurfaceTexture mSurfaceTexture; 
    private int mCameraId; 

    public static class JavaCameraSizeAccessor implements ListItemAccessor { 

     public int getWidth(Object obj) { 
      Camera.Size size = (Camera.Size) obj; 
      return size.width; 
     } 

     public int getHeight(Object obj) { 
      Camera.Size size = (Camera.Size) obj; 
      return size.height; 
     } 
    } 
    public PortraitCameraView(Context context, int cameraId) { 
     super(context, cameraId); 
    } 

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

    protected boolean initializeCamera(int width, int height) { 
     Log.d(TAG, "Initialize java camera"); 
     boolean result = true; 
     synchronized (this) { 
      mCamera = null; 

      boolean connected = false; 
      int numberOfCameras = android.hardware.Camera.getNumberOfCameras(); 
      android.hardware.Camera.CameraInfo cameraInfo = new android.hardware.Camera.CameraInfo(); 
      for (int i = 0; i < numberOfCameras; i++) { 
       android.hardware.Camera.getCameraInfo(i, cameraInfo); 
       if (cameraInfo.facing == android.hardware.Camera.CameraInfo.CAMERA_FACING_BACK) { 
        try { 
         mCamera = Camera.open(i); 
         mCameraId = i; 
         connected = true; 
        } catch (RuntimeException e) { 
         Log.e(TAG, "Camera #" + i + "failed to open: " + e.getMessage()); 
        } 
        if (connected) break; 
       } 
      } 

      if (mCamera == null) return false; 

     /* Now set camera parameters */ 
      try { 
       Camera.Parameters params = mCamera.getParameters(); 
       Log.d(TAG, "getSupportedPreviewSizes()"); 
       List<Camera.Size> sizes = params.getSupportedPreviewSizes(); 

       if (sizes != null) { 
       /* Select the size that fits surface considering maximum size allowed */ 
        Size frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), height, width); //use turn around values here to get the correct prev size for portrait mode 

        params.setPreviewFormat(ImageFormat.NV21); 
        Log.d(TAG, "Set preview size to " + Integer.valueOf((int)frameSize.width) + "x" + Integer.valueOf((int)frameSize.height)); 
        params.setPreviewSize((int)frameSize.width, (int)frameSize.height); 

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) 
         params.setRecordingHint(true); 

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

        mCamera.setParameters(params); 
        params = mCamera.getParameters(); 

        mFrameWidth = params.getPreviewSize().height; //the frame width and height of the super class are used to generate the cached bitmap and they need to be the size of the resulting frame 
        mFrameHeight = params.getPreviewSize().width; 

        int realWidth = mFrameHeight; //the real width and height are the width and height of the frame received in onPreviewFrame 
        int realHeight = mFrameWidth; 

        if ((getLayoutParams().width == FrameLayout.LayoutParams.MATCH_PARENT) && (getLayoutParams().height == FrameLayout.LayoutParams.MATCH_PARENT)) 
         mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth); 
        else 
         mScale = 0; 

        if (mFpsMeter != null) { 
         mFpsMeter.setResolution(mFrameWidth, mFrameHeight); 
        } 

        int size = mFrameWidth * mFrameHeight; 
        size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat())/8; 
        mBuffer = new byte[size]; 

        mCamera.addCallbackBuffer(mBuffer); 
        mCamera.setPreviewCallbackWithBuffer(this); 

        mFrameChain = new Mat[2]; 
        mFrameChain[0] = new Mat(realHeight + (realHeight/2), realWidth, CvType.CV_8UC1); //the frame chane is still in landscape 
        mFrameChain[1] = new Mat(realHeight + (realHeight/2), realWidth, CvType.CV_8UC1); 

        AllocateCache(); 

        mCameraFrame = new JavaCameraFrame[2]; 
        mCameraFrame[0] = new JavaCameraFrame(mFrameChain[0], mFrameWidth, mFrameHeight); //the camera frame is in portrait 
        mCameraFrame[1] = new JavaCameraFrame(mFrameChain[1], mFrameWidth, mFrameHeight); 

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { 
         mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID); 
         mCamera.setPreviewTexture(mSurfaceTexture); 
        } else 
         mCamera.setPreviewDisplay(null); 

       /* Finally we are ready to start the preview */ 
        Log.d(TAG, "startPreview"); 
        mCamera.startPreview(); 
       } 
       else 
        result = false; 
      } catch (Exception e) { 
       result = false; 
       e.printStackTrace(); 
      } 
     } 

     return result; 
    } 

    protected void releaseCamera() { 
     synchronized (this) { 
      if (mCamera != null) { 
       mCamera.stopPreview(); 
       mCamera.setPreviewCallback(null); 

       mCamera.release(); 
      } 
      mCamera = null; 
      if (mFrameChain != null) { 
       mFrameChain[0].release(); 
       mFrameChain[1].release(); 
      } 
      if (mCameraFrame != null) { 
       mCameraFrame[0].release(); 
       mCameraFrame[1].release(); 
      } 
     } 
    } 

    @Override 
    protected boolean connectCamera(int width, int height) { 

    /* 1. We need to instantiate camera 
    * 2. We need to start thread which will be getting frames 
    */ 
    /* First step - initialize camera connection */ 
     Log.d(TAG, "Connecting to camera"); 
     if (!initializeCamera(width, height)) 
      return false; 

    /* now we can start update thread */ 
     Log.d(TAG, "Starting processing thread"); 
     mStopThread = false; 
     mThread = new Thread(new CameraWorker()); 
     mThread.start(); 

     return true; 
    } 

    protected void disconnectCamera() { 
    /* 1. We need to stop thread which updating the frames 
    * 2. Stop camera and release it 
    */ 
     Log.d(TAG, "Disconnecting from camera"); 
     try { 
      mStopThread = true; 
      Log.d(TAG, "Notify thread"); 
      synchronized (this) { 
       this.notify(); 
      } 
      Log.d(TAG, "Wating for thread"); 
      if (mThread != null) 
       mThread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } finally { 
      mThread = null; 
     } 

    /* Now release camera */ 
     releaseCamera(); 
    } 

    public void onPreviewFrame(byte[] frame, Camera arg1) { 
     Log.d(TAG, "Preview Frame received. Frame size: " + frame.length); 
     synchronized (this) { 
      mFrameChain[1 - mChainIdx].put(0, 0, frame); 
      this.notify(); 
     } 
     if (mCamera != null) 
      mCamera.addCallbackBuffer(mBuffer); 
    } 
    private class JavaCameraFrame implements CvCameraViewFrame { 
     private Mat mYuvFrameData; 
     private Mat mRgba; 
     private int mWidth; 
     private int mHeight; 
     private Mat mRotated; 

     public Mat gray() { 
      if (mRotated != null) mRotated.release(); 
      mRotated = mYuvFrameData.submat(0, mWidth, 0, mHeight); //submat with reversed width and height because its done on the landscape frame 
      mRotated = mRotated.t(); 
      Core.flip(mRotated, mRotated, 1); 
      return mRotated; 
     } 

     public Mat rgba() { 
      Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2BGR_NV12, 4); 
      if (mRotated != null) mRotated.release(); 
      mRotated = mRgba.t(); 
      Core.flip(mRotated, mRotated, 1); 
      return mRotated; 
     } 

     public JavaCameraFrame(Mat Yuv420sp, int width, int height) { 
      super(); 
      mWidth = width; 
      mHeight = height; 
      mYuvFrameData = Yuv420sp; 
      mRgba = new Mat(); 
     } 

     public void release() { 
      mRgba.release(); 
      if (mRotated != null) mRotated.release(); 
     } 


    }; 

    private class CameraWorker implements Runnable { 

     public void run() { 
      do { 
       synchronized (PortraitCameraView.this) { 
        try { 
         PortraitCameraView.this.wait(); 
        } catch (InterruptedException e) { 
         Log.e(TAG, "CameraWorker interrupted", e); 
        } 
       } 

       if (!mStopThread) { 
        if (!mFrameChain[mChainIdx].empty()) 
         deliverAndDrawFrame(mCameraFrame[mChainIdx]); 
        mChainIdx = 1 - mChainIdx; 
       } 
      } while (!mStopThread); 
      Log.d(TAG, "Finish processing thread"); 
     } 
    } 
} 

OnCameraFrame 방법은 다음과 같은 설정이다 세로보기로 카메라 프레임을 보여주기 위해 다음과 같이

E/OpenCV/StaticHelper: OpenCV error: Cannot load info library for OpenCV 
    E/cv::error(): OpenCV Error: Assertion failed (src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols) in void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean), file /Volumes/Linux/builds/master_pack-android/opencv/modules/java/generator/src/cpp/utils.cpp, line 97 
    E/org.opencv.android.Utils: nMatToBitmap catched cv::Exception: /Volumes/Linux/builds/master_pack-android/opencv/modules/java/generator/src/cpp/utils.cpp:97: error: (-215) src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols in function void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean) 
    E/CameraBridge: Mat type: Mat [ 0*0*CV_8UC4, isCont=true, isSubmat=false, nativeObj=0xffffffffb80ebf00, dataAddr=0x0 ]E/CameraBridge: Bitmap type: 480*720 
    E/CameraBridge: Utils.matToBitmap() throws an exception: /Volumes/Linux/builds/master_pack-android/opencv/modules/java/generator/src/cpp/utils.cpp:97: error: (-215) src.dims == 2 && info.height == (uint32_t)src.rows && info.width == (uint32_t)src.cols in function void Java_org_opencv_android_Utils_nMatToBitmap2(JNIEnv*, jclass, jlong, jobject, jboolean) 

내 카메라 클래스입니다.

@Override 
public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) { 
    mRgba = inputFrame.rgba(); 
    mGray = inputFrame.gray(); 

    if (mAbsoluteFaceSize == 0) { 
     int height = mGray.rows(); 

     if (Math.round(height * mRelativeFaceSize) > 0) { 
      mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize); 
     } 

     mNativeDetector.setMinFaceSize(mAbsoluteFaceSize); 
    } 

    MatOfRect faces = new MatOfRect(); 

    if (mDetectorType == JAVA_DETECTOR) { 
     if (mJavaDetector != null) 
      mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2, 2, // TODO: objdetect.CV_HAAR_SCALE_IMAGE 
        new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size()); 
    } 
    else if (mDetectorType == NATIVE_DETECTOR) { 
     if (mNativeDetector != null) 
      mNativeDetector.detect(mGray, faces); 
    } 
    else { 
     Log.e(TAG, "Detection method is not selected!"); 
    } 

    Rect[] facesArray = faces.toArray(); 
    for (int i = 0; i < facesArray.length; i++) 
     Imgproc.rectangle(mRgba, facesArray[i].tl(), facesArray[i].br(), FACE_RECT_COLOR, 3); 

    return mRgba; 
} 

답변

0

나는이 질문이 개월의 주어진, 너무 늦기 확신하지만 대답은 (놀랍게도)에서 OpenCV/JavaCameraView은 세로 모드 만 풍경을 지원하지 않는다는 것입니다.

이상한가? 며칠 동안 나 자신과 함께 노력했지만 JavaCameraView가 초상화를 사용할 수 없다는 것을 알아 냈습니다. 거기에 사실상 초상화 모드 (이미지 매트를 뒤집음 포함)를 만드는 몇 가지 구부러진 - 뒤로 - 거트 해킹이 있지만, 그 결과는 노력 가치가 있다고 생각하지 않았다. AndroidManifest.xml 파일의 지시문을 사용하여 항상 가로로 표시하도록보기를 강요합니다.

 android:screenOrientation="landscape" 
     android:theme="@style/Theme.AppCompat.NoActionBar" 

http://answers.opencv.org/question/95248/changing-opencv-camera-view-orientation-on-androi/

관련 문제