Jeroen Ritmeester
Jeroen Ritmeester

Reputation: 43

Google Vision: setRequestPreviewSize no effect

I am working on an Android application with an embedded QR code scanner using the Google Vision API. The scanner functions, but the SurfaceView that acts as camera preview is stretched vertically. The degree of distortion is different for different emulated devices.

As I understand it, you would use mCameraSource.setRequestedPreviewSize(w,h) to set the correct size. w and h I have set as Resources.getSystem().getDisplayMetrics().widthPixels and Resources.getSystem().getDisplayMetrics().heightPixels, respectively. However, I have noticed that regardless of what numbers I parse as width and height, there are no changes in the way it displays.

However, resizing the SurfaceView on which it is displayed does have an effect on the distortion. For one particular emulated Android device I can statically set the right width and height. For different devices, however, with a slightly different pixel w:h ratio, the distortion can become quite large.

I have read various solutions on StackOverflow, but most use the CameraPreview instead of the CameraSource.Builder.

My code thus far is (part of ScannerActivity.java):

private SurfaceView svCamera;
private BarcodeDetector barcodeDetector;
private CameraSource cameraSource;

@Override

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_scanner);
    initViews();
    initListeners();

    barcodeDetector = new BarcodeDetector.Builder(this)
                .setBarcodeFormats(Barcode.QR_CODE)
                .build();


    cameraSource = new CameraSource.Builder(this, barcodeDetector)
                .setRequestedPreviewSize(Resources.getSystem().getDisplayMetrics().widthPixels,     Resources.getSystem().getDisplayMetrics().heightPixels)
                .setAutoFocusEnabled(true)
                .build();

    svCamera.getHolder().addCallback(new SurfaceHolder.Callback() {
        @Override
        public void surfaceCreated(SurfaceHolder surfaceHolder) {
        requestPermission();
        try {
                if (ActivityCompat.checkSelfPermission(ScannerActivity.this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                   return;
                }
                cameraSource.start(svCamera.getHolder());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
         @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

        }
         @Override
        public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
            cameraSource.stop();
        }
    });

   barcodeDetector.setProcessor(new Detector.Processor<Barcode>() {
       @Override
        public void release() {
            scanned = true;
        }
         @Override
        public void receiveDetections(Detector.Detections<Barcode> detections) {
              ...
        }
    });
} }   

Can someone help me with setting preview size?


The way I fixed it with help of Alex Cohn's answer:

DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width = displayMetrics.widthPixels;    
int height = displayMetrics.heightPixels;
...
cameraSource.setRequestedPreviewSize(1280, 720); // Hardcoded, for now.

And I set the size of the SurfaceView with:

svCamera.setLayoutParams(new RelativeLayout.LayoutParams(width, width/9*16));

If I remember I will update this to a non-hardcoded version.

Upvotes: 4

Views: 2002

Answers (1)

Alex Cohn
Alex Cohn

Reputation: 57203

Quite contrary. You cannot choose arbitrary resolution for setRequestedPreviewSize(). This CameraSource API wraps the ordinary Camera API, which exposes only some, "supported" pairs of width and height.

If you want to display the live view undistorted, you must setup your SurfaceView to match the aspect ratio of chosen camera preview. This means, it's OK to use surface of 320x240 pixel for camera 640x480. It's even OK to use surface of 1280x720 for camera 1920x1080.

But if you have surface of 800x480 for camera of 1280x720 (and if your devices supports such camera resolution), the picture will be slightly stretched.

Upvotes: 3

Related Questions