如何通过纵向模式检测脸部?

时间:2013-10-10 14:40:31

标签: android opencv screen-orientation portrait

我最近正在学习OpenCV。

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

我有些奇怪。

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

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

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

Core.flip(mRgba,mRgba,1);

仍然不认识脸。

如何通过纵向模式检测脸部?

谢谢。

2 个答案:

答案 0 :(得分:0)

你需要进行转置,然后翻转:

            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());

答案 1 :(得分:0)

首先在android的清单中设置肖像模式。

 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)