【问题标题】:How to detect face by portrait mode?如何通过人像模式检测人脸?
【发布时间】:2013-10-18 09:30:19
【问题描述】:

我最近在学习 OpenCV。

OpenCV for Android 示例代码(2.4.6)已经过测试。

我有点奇怪。

我可以通过示例代码检测人脸(OpenCV 示例 - 人脸检测)。但是,在安卓设备上无法通过纵向模式(垂直模式)检测人脸。

首先,我尝试通过纵向模式设置前置摄像头。

//在onCameraFrame()方法中添加代码。

Core.flip(mRgba, mRgba, 1);

还是不认脸。

人像模式如何检测人脸?

谢谢。

【问题讨论】:

    标签: android opencv screen-orientation portrait


    【解决方案1】:

    先在android的manifest中设置竖屏模式。

     android:screenOrientation="portrait"
    

    顺时针翻转彩色和灰色图像(Mat),以在纵向模式下进行面部/特征检测。 在特征检测逻辑结束时,逆时针翻转彩色图像(mRgba Mat)。如图所示。

     public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    
        Core.flip(inputFrame.gray().t(),mGray,1); //rotate clockwise 
        Core.flip(inputFrame.rgba().t(),mRgba,1);
        mRgba=Feature_DetectionNATIVE(mRgba,mGray);
        Core.flip(mRgba.t(),mRgba,0);             //rotate counter clockwise
    //this is a solution for  allowing face detection in portrait view if it isn't working at all.
        return mRgba;
     }
    public Mat Feature_DetectionNATIVE(Mat mRgba2, final Mat Gray)
    {
    if (mAbsoluteFaceSize == 0) 
    {
        int height = Gray.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(Gray, faces, 1.1, 2, 2, 
      new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
     }
    else if (mDetectorType == NATIVE_DETECTOR)
    {
    if (mNativeDetector != null)
      mNativeDetector.detect(Gray, faces);
     }
    else 
    {
    Log.e(TAG, "Detection method is not selected!");
    }
    
    
    Rect[] facesArray = faces.toArray();
    for (int i = 0; i < facesArray.length; i++)
    {
      Core.rectangle(mRgba2, facesArray[i].tl(), facesArray[i].br(),     FACE_RECT_COLOR, 3);
    }
        return mRgba2;
    }
    

    之后,相机将在横向显示面部检测以解决此问题,您可以在 opencv 的 CameraBridgeViewBase 主类中将画布顺时针旋转 90 度或对其进行破解。(请注意,这会降低 FPS,但面部检测仍然存在快)

     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);
     Log.d(TAG, "mStretch value: " + mScale);
     canvas=rotateCanvas(canvas,mCacheBitmap);
     getHolder().unlockCanvasAndPost(canvas);
     }    } }
    
     protected Canvas rotateCanvas(final Canvas canvas, final Bitmap mCacheBitmap)
     { 
     final CountDownLatch latch =new CountDownLatch(1);
     final Mat[] mRgba=new Mat[1];
    
     new Thread(new Runnable() {
     @Override
     public void run() {
    
     try {
     Bitmap bitmap = Bitmap.createScaledBitmap(mCacheBitmap, canvas.getHeight(),  canvas.getWidth(), true);
    canvas.rotate(90,0,0);
    mScale = canvas.getWidth() / (float)bitmap.getHeight();
    float scale2 = canvas.getHeight() / (float)bitmap.getWidth();
    if(scale2 > mScale){
        mScale = scale2;
     }
    if (mScale != 0) {
     canvas.scale(mScale, mScale,0,0);
     }
    canvas.drawBitmap(bitmap, 0, -bitmap.getHeight(), null);
    
    }
    catch (CvException e) {           e.printStackTrace();}
    latch.countDown();//setting //release await() in this thread
    }
    
    }).start();
    
    try {  latch.await(); //waits for countDown in the Thread inorder to obtain a value from the thread
    
    } catch (InterruptedException e) {   e.printStackTrace();}
    
    return canvas;
    

    }

    (使用 OpenCV 2.4.9)

    【讨论】:

      【解决方案2】:

      你需要转置然后翻转:

                  int height = mGray.rows();
                  int faceSize = Math.round(height * 0.5F);
      
                  Mat temp = mGray.clone();
                  Core.transpose(mGray, temp);
                  Core.flip(temp, temp, -1);
      
                  MatOfRect rectFaces = new MatOfRect();
      
                  // java detector fast
                  mCascade.detectMultiScale(temp, rectFaces, 1.1, 1, 0, new Size(faceSize, faceSize), new Size());
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-08-09
        • 1970-01-01
        • 1970-01-01
        • 2019-12-03
        • 2019-11-18
        • 1970-01-01
        • 1970-01-01
        • 2013-09-24
        相关资源
        最近更新 更多