0

Today I've added my custom view(face detection) for my android camera app. Everything looked fine, no errors and all. However, I realized that my custom face detection appears only when the camera is in landscape mode. What I want to do is to show face detection view in portrait mode. I searched around the web for some hints but I couldn't find a useful information that can guide me to solve this problem. It would be great if there are some tips or solutions. I would love to hear from you!

I've added the sample code from my app.

(1. I'm adding my Custom view(CameraOverlayView) to the typical xml layout(Relative layout).

 mCameraOverlayView = new CameraOverlayView(this, mSurfaceView);
        this.addContentView(mCameraOverlayView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));

(2. I use CameraOverLayView to show a rectangle in the preview

public class CameraOverlayView extends View {

    private Paint mPaint;
    private Face[] mFaces;
    private SurfaceView mSurfaceView;

    public CameraOverlayView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initialize();
    }

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

    public CameraOverlayView(Context context, SurfaceView surafaceView) {
        super(context);
        mSurfaceView = surafaceView;
        initialize();
    }


    private void initialize() {

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setColor(Color.WHITE);
        mPaint.setAlpha(128);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    }

    public void setFaces(Face[] faces) {
        mFaces = faces;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mFaces == null) {
            return;
        }
        for (Face face : mFaces) {
            if (face == null) {
                continue;
            }

            Matrix matrix = new Matrix();
            matrix.postScale(mSurfaceView.getWidth() / 2000f, mSurfaceView.getHeight() / 2000f);
            matrix.postTranslate(mSurfaceView.getWidth() / 2f, mSurfaceView.getHeight() / 2f);
            int saveCount = canvas.save();
            canvas.concat(matrix);
            canvas.drawRect(face.rect, mPaint);
            canvas.restoreToCount(saveCount);
        }
    }
}

(3. Just running the face detection in the surfaceCreated and in SurfaceChanged.

 @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = Camera.open(currentCamera);
        if (currentCamera != Camera.CameraInfo.CAMERA_FACING_FRONT) {
            mCamera.setFaceDetectionListener(faceDetectionListener);
            mCamera.startFaceDetection();
        }
    }

[Edited]

code for setting the camera orientation

/**
 * Camera orientation
 */
public void setCameraDisplayOrientation() {
        Camera.CameraInfo info = new Camera.CameraInfo();
        mCamera.getCameraInfo(currentCamera, info);
        int rotation = this.getWindowManager().getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }
        int resultA = 0, resultB = 0;
        if(currentCamera == Camera.CameraInfo.CAMERA_FACING_BACK) {
            resultA = (info.orientation - degrees + 360) % 360;
            resultB = (info.orientation - degrees + 360) % 360;
            mCamera.setDisplayOrientation(resultA);
        } else {
            resultA = (360 + 360 - info.orientation - degrees) % 360;
            resultB = (info.orientation + degrees) % 360;
            mCamera.setDisplayOrientation(resultA);
        }
        Camera.Parameters params = mCamera.getParameters();
        params.setRotation(resultB);
        mCamera.setParameters(params);
        mCameraOrientation = resultB;
}

setCameraDisplayOrientation() is used in the following location

   @Override
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {

        if (mPreviewRunning) {
            mCamera.stopPreview();
        }
        if (mSurfaceHolder.getSurface() == null){
            return;
        }
        Camera.Parameters p = mCamera.getParameters();
        List<String> focusModes = p.getSupportedFocusModes();
        if (focusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE)) {
            p.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
        }
        p.setFlashMode(currentFlashMode);
        mCamera.setParameters(p);
        try {
            if (mCamera != null) {
                mCamera.setPreviewDisplay(arg0);
                setCameraDisplayOrientation(); ← Here

The following layout is the main layout for displaying the camera preview

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

    <SurfaceView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/surfaceView"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentBottom="true"
         />

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="false"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="false"
        android:visibility="invisible" />

</RelativeLayout>
Jennifer
  • 1,822
  • 2
  • 20
  • 45
  • This is related to orientation... Could you please share your code where you set the camera orientation? – guipivoto Oct 06 '17 at 13:18
  • I've added the extra code for the camera orientation. – Jennifer Oct 06 '17 at 13:44
  • I tested your code and it seems to work fine... Your custom view is drawing a rect. above the faces... in both orientations... I'm trying to figure out what is different between your code and mine... since I created a simple activity to test – guipivoto Oct 06 '17 at 16:34
  • I still can't find the problem, maybe it's the xml layout I'm using for the camera preview ? I've added the xml layout sample I'm currently using. – Jennifer Oct 07 '17 at 03:58
  • Note that `CAMERA_FACING_BACK` is not an index; it should be compared to **info.[facing](https://developer.android.com/reference/android/hardware/Camera.CameraInfo.html#facing)**. – Alex Cohn Oct 09 '17 at 20:46
  • In AndroidManifest.xml, do you [handle screen rotation](https://developer.android.com/guide/topics/resources/runtime-changes.html), or the Activity is recreated by the system? – Alex Cohn Oct 09 '17 at 20:53

0 Answers0