Search code examples
androidgoogle-play-servicesface-detectiongoogle-vision

Google Mobile Vision: Face Detection stops after 3 seconds


Face Detection finds my face, then after 3 seconds the circle disappears. Only happens on some phones, so I am unsure why it is happening. My code is pretty boilerplate:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_detect);

    detector = new FaceDetector.Builder(getApplicationContext())
            .setTrackingEnabled(false)
            .setProminentFaceOnly(true)
            .setMode(FaceDetector.FAST_MODE)
            .setMinFaceSize((float) 0.60)
            .setLandmarkType(FaceDetector.ALL_CLASSIFICATIONS)
            .setClassificationType(FaceDetector.ALL_CLASSIFICATIONS)

            .build();


    initViews();

}

private void initViews() {
    imgTakePicture = (ImageView) findViewById(R.id.imgTakePic);
    btnTakePicture = (Button) findViewById(R.id.btnTakePicture);
    txtSampleDesc = (TextView) findViewById(R.id.txtSampleDescription);
    txtTakenPicDesc = (TextView) findViewById(R.id.textView);

    btnTakePicture.setOnClickListener(this);
    imgTakePicture.setOnClickListener(this);


}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    Log.d(TAG, "onActivityResult: this is resyult");
    if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {
        launchMediaScanIntent();
        try {
            processCameraPicture();
        } catch (Exception e) {
            Toast.makeText(getApplicationContext(), "Failed to load Image", Toast.LENGTH_SHORT).show();
        }
    }
}

private void launchMediaScanIntent() {
    Log.d(TAG, "launchMediaScanIntent: ");
    Intent mediaScanIntent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
    mediaScanIntent.setData(imageUri);
    this.sendBroadcast(mediaScanIntent);
}

private void startCamera() {
    Log.d(TAG, "startCamera: ");
    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    Log.d(TAG, "startCamera: 2");
    File photo = new File(Environment.getExternalStorageDirectory(), "/videoDIARY/ReferencePic/photo.jpg");

    imageUri = Uri.fromFile(photo);

    intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

    startActivityForResult(intent, CAMERA_REQUEST);

}

EDIT: Ok, I have worked out this is all about the device orientation. Works fine on all devices in landscape mode, only on some devices in portrait mode. Still trying to work out why, will update when i fix!


Solution

  • Ok, so it turned out to have nothing to do with facial detection, and everything to do with how Android saves Camera Intent Images. Basically it gets the orientation confused, so you need to check the width vs the height, to make sure it is doing it right, and rotate it if not. Here is how I checked:

    private Bitmap decodeBitmapUri(Context ctx, Uri uri) throws FileNotFoundException {
        Log.d(TAG, "decodeBitmapUri: ");
        //Toast.makeText(this, "1o" , Toast.LENGTH_LONG).show();
        Log.d(TAG, "initViews1: face detector is ============================ " + detector.isOperational());
        int targetW = 300;
        int targetH = 300;
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inJustDecodeBounds = true;
        bmOptions.inPreferredConfig=Bitmap.Config.RGB_565;
        BitmapFactory.decodeStream(ctx.getContentResolver().openInputStream(uri), null, bmOptions);
        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);
        int rotation = this.getWindowManager().getDefaultDisplay().getRotation();
        int orientation = this.getResources().getConfiguration().orientation;
        Log.d(TAG, "decodeBitmapUri: OREINTATION is ==================== " + orientation);
    
        Log.d(TAG, "decodeBitmapUri: CAMERA ROTATION ========================= " + rotation);
        //Camera.Size size = android.hardware.Camera.get
    
    
        int photoW = bmOptions.outWidth;
        Log.d(TAG, "decodeBitmapUri: width: " + photoW );
        int photoH = bmOptions.outHeight;
        Log.d(TAG, "decodeBitmapUri:  height: " + photoH);
        Log.d(TAG, "decodeBitmapUri: 4");
        //Toast.makeText(this, "11" , Toast.LENGTH_LONG).show();
    
        int scaleFactor = Math.min(photoW / targetW, photoH / targetH);
        bmOptions.inJustDecodeBounds = false;
        bmOptions.inSampleSize = scaleFactor;
    
        /*this is because some phones default a camera Intent to landscape no matter how the phone is held
        * so we check for camera orienatation, then check to see if width is greater than height
        * */
    
        if(orientation == 1 && (photoW > photoH)){
            return rotate(BitmapFactory.decodeStream(ctx.getContentResolver()
                    .openInputStream(uri), null, bmOptions));
        }
    
    
        return BitmapFactory.decodeStream(ctx.getContentResolver()
                .openInputStream(uri), null, bmOptions);
    }
    
    public static Bitmap rotate(Bitmap bitmap){
        int w = bitmap.getWidth();
        int h = bitmap.getHeight();
    
        Matrix mtx = new Matrix();
        mtx.postRotate(270);
    
        return Bitmap.createBitmap(bitmap, 0, 0, w, h, mtx, true);
    }