添加分辨率更高的ImageReader会使预览和ImageReader结果倾斜

时间:2019-06-26 11:19:46

标签: java android android-camera2

在Samsung J6设备上使用Camera2 API并将ImageReader添加到照相机输出时,预览会倾斜,并且在ImageReader.onImageAvailable中获取的图像也会倾斜。

例如,如果我使用960x720作为预览的分辨率(屏幕尺寸为1:1像素比例),对于ImageReader使用960x720,则没有问题,所有图像看起来都不错,并且人脸检测也可以。但是,如果将ImageReader分辨率设置为2048x1536(以获得更好的处理质量),则预览图像看起来像裁剪为16:9,然后扩展回4:3以匹配预览尺寸。与ImageReader.onImageAvailable中的图像相同。

https://i.ibb.co/zPbTGJ3/ss1.jpg https://i.ibb.co/McbL93k/ss2.jpg

人脸检测似乎也是错误的,因为它返回的最大坐标是人脸仅位于视图的中心(SENSOR_INFO_ACTIVE_ARRAY_SIZE为4144x3106)。

https://i.ibb.co/6wtP5qS/ss3.jpg

这在Galaxy S7,S8,S9,A8等更高规格的设备上正常运行,但我注意到它在Samsung J5或J6设备上无法正常工作。

这是我的SurfaceTextureListener代码:

    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        try {
            if(useCamera2API) {
                mCameraManager = (CameraManager) context.getSystemService(CAMERA_SERVICE);
                String[] cameraList = mCameraManager.getCameraIdList();

                if(cameraList.length == 0) {
                    return;
                }

                mCameraCharacteristics = mCameraManager.getCameraCharacteristics(cameraList[0]);

                mMaxCameraSize = new Rectangle(mCameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE)).size;
                nativeRatio = mMaxCameraSize.width / mMaxCameraSize.height;

                height = (int)(width * nativeRatio);

                VCamera.getLayoutParams().height = height;

                mScreenSize = new Size(height, width);

                StreamConfigurationMap map = mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);

                if (map != null) {
                    Size[] previewSizes = Size.castSizes(map.getOutputSizes(SurfaceTexture.class));
                    Size[] yuvSizes = Size.castSizes(map.getOutputSizes(ImageFormat.YUV_420_888));

                    // this gets the smallest size closest to maximum camera size ratio while keeping both dimensions above 1000 pixels
                    mCameraSize = Helper.getSmallestSize(yuvSizes, 1000, nativeRatio);
                    // this gets size that is closest to 1:1 pixel ratio to screen
                    mPreviewSize = Helper.getOptimalPreviewSize(previewSizes, height, width);

                    log(String.format("%d %d, %d %d", (int) mCameraSize.width, (int) mCameraSize.height, (int) mPreviewSize.width, (int) mPreviewSize.height));

                    supportsAEAreas = mCameraCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AE) > 0;
                    supportsAFAreas = mCameraCharacteristics.get(CameraCharacteristics.CONTROL_MAX_REGIONS_AF) > 0;

                    mPreviewImageReader = ImageReader.newInstance((int) mCameraSize.getWidth(), (int) mCameraSize.getHeight(), ImageFormat.YUV_420_888, 1);

和CameraDevice.StateCallback代码:

CameraDevice.StateCallback stateCallback = new CameraDevice.StateCallback() {

    @Override
    public void onOpened(@NonNull CameraDevice camera) {
        Log.d(LOG_TAG, "Camera opened.");

        mCameraDevice = camera;

        SurfaceTexture texture = VCamera.getSurfaceTexture();

        if (texture == null) {
            return;
        }

        texture.setDefaultBufferSize((int) mPreviewSize.getWidth(), (int) mPreviewSize.getHeight());

        Surface surface = new Surface(texture);

        try {
            mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

            List<Surface> surfaces = new ArrayList<>();

            mPreviewBuilder.addTarget(surface);
            surfaces.add(surface);

            mPreviewBuilder.addTarget(mPreviewImageReader.getSurface());
            surfaces.add(mPreviewImageReader.getSurface());

            backgroundThread = new HandlerThread("CameraPreview");
            backgroundThread.start();
            backgroundHandler = new Handler(backgroundThread.getLooper());

            mPreviewImageReader.setOnImageAvailableListener(mImageAvailableListener, backgroundHandler);

            mCameraDevice.createCaptureSession(surfaces, previewStateCallback, null);

            if(mode == CameraRequestMode.BARCODE_CONTINUOUS) {
                delegate.cameraContinuousStarted();
            }

我希望至少预览看起来正常。我缺少任何配置吗?我在某些设备上看到了Camera2 API刚刚损坏的信息。如果可以得到比预览更高分辨率的帧,我将退回到旧的Camera API(可能是,但不是那么容易实现)。我是否仅使用960x720作为处理图像的分辨率?

0 个答案:

没有答案