onPreviewCallback帧小于实际帧

时间:2016-09-23 19:00:53

标签: android opencv opencv4android

我正在尝试在imageview上显示从onPreviewCallback接收的帧。首先,帧的方向与实时预览不同,其次它似乎小于实际的实时预览,这里是我的代码。预览大小为1024 x 768:

cameraConfigUtil.cameraInstance.setOneShotPreviewCallback(new Camera.PreviewCallback() {
                        @Override
                        public void onPreviewFrame(byte[] originalData, Camera camera) {
                            Mat srcMat = new Mat(camera.getParameters().getPreviewSize().height, camera.getParameters().getPreviewSize().width, CvType.CV_8UC1);
                            srcMat.put(0, 0, originalData);
                            Bitmap bitmap = Bitmap.createBitmap(camera.getParameters().getPreviewSize().width, camera.getParameters().getPreviewSize().height, Bitmap.Config.ARGB_8888);
                            Utils.matToBitmap(srcMat, bitmap);
                            cameraPreviewImage.setVisibility(View.VISIBLE);
                            cameraPreviewImage.setImageBitmap(bitmap);
                        }
                    });

设置所有相机参数:

 if (!isCameraParametersSet) {
            MIN_FRAME_WIDTH = 1024;
            MIN_FRAME_HEIGHT = 768;
            if (android.os.Build.VERSION.SDK_INT >= 14) {
                setFocus(cameraParameters, false);
            } else {
                setFocus(cameraParameters, true);
            }
            WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
            Display display = manager.getDefaultDisplay();
            Point theScreenResolution = new Point();
            theScreenResolution.set(display.getHeight(), display.getWidth());
            SizePair picturePreviewSizePair = selectSizePair(cameraInstance, MIN_FRAME_WIDTH, MIN_FRAME_HEIGHT);
            cameraParameters.setPreviewSize(picturePreviewSizePair.mPreview.getWidth(), picturePreviewSizePair.mPreview.getHeight());
            cameraParameters.setPictureSize(picturePreviewSizePair.mPicture.getWidth(), picturePreviewSizePair.mPicture.getHeight());
            getTargetPictureSize();
            if (cameraParameters.getSupportedPictureFormats().contains(ImageFormat.JPEG)) {
                cameraParameters.setPictureFormat(ImageFormat.JPEG);
            }
            cameraParameters.setWhiteBalance(Camera.Parameters.WHITE_BALANCE_AUTO);
            isCameraParametersSet = true;
        }
        return cameraParameters;

这是我的解决方案代码:

private static SizePair selectSizePair(Camera camera, int desiredWidth, int desiredHeight) {
    List<SizePair> validPreviewSizes = generateValidPreviewSizeList(camera);
    SizePair selectedPair = null;
    int minDiff = Integer.MAX_VALUE;
    for (SizePair sizePair : validPreviewSizes) {
        Size size = sizePair.previewSize();
        int diff = Math.abs(size.getWidth() - desiredWidth) +
                Math.abs(size.getHeight() - desiredHeight);
        if (diff < minDiff) {
            selectedPair = sizePair;
            minDiff = diff;
        }
    }

    return selectedPair;
}


private static List<SizePair> generateValidPreviewSizeList(Camera camera) {
    Camera.Parameters parameters = camera.getParameters();
    List<android.hardware.Camera.Size> supportedPreviewSizes =
            parameters.getSupportedPreviewSizes();
    List<android.hardware.Camera.Size> supportedPictureSizes =
            parameters.getSupportedPictureSizes();
    List<SizePair> validPreviewSizes = new ArrayList<>();
    for (android.hardware.Camera.Size previewSize : supportedPreviewSizes) {
        float previewAspectRatio = (float) previewSize.width / (float) previewSize.height;
        for (android.hardware.Camera.Size pictureSize : supportedPictureSizes) {
            float pictureAspectRatio = (float) pictureSize.width / (float) pictureSize.height;
            if (Math.abs(previewAspectRatio - pictureAspectRatio) < ASPECT_RATIO_TOLERANCE) {
                validPreviewSizes.add(new SizePair(previewSize, pictureSize));
                break;
            }
        }
    }

enter image description here

2 个答案:

答案 0 :(得分:1)

你怎么知道这两个是不同的分辨率?

显示相机预览的标准UI元素(SurfaceView,TextureView)将按比例放大/缩小它们以适合View界限;因此,例如,如果SurfaceView覆盖1600x1200像素,并且它提供了640x480的相机预览帧,它将放大帧以填充1600x1200视图。

但是,您用来显示预览回调的ImageView不一定会这样做 - 它会进行上采样,但您需要确保其布局与SurfaceView的布局相匹配。看起来它看起来要小得多。

关于轮换 - setDisplayOrientation中记录的内容。仅旋转预览输出;你必须手动旋转预览回调中的任何内容。由于您已经将内容加载到OpenCV矩阵中,因此应用90度旋转应该很容易。您需要的旋转量与传递给setDisplayOrientation的旋转量相同。

答案 1 :(得分:0)

此代码适用于我:

Camera.Parameters cameraParam = mCamera.getParameters();
List<Size> sizes = cameraParam.getSupportedPreviewSizes();
            Camera.Size previewSize = cameraParam.getPreviewSize();
            previewFormat = cameraParam.getPreviewFormat();
            int[] sizesForCamera = new int[]{sizes.get(0).width,sizes.get(0).height};
            cameraParam.setPreviewSize(sizesForCamera[0], sizesForCamera[1]);
            mCamera.setParameters(cameraParam);

我的代码中没有找到setPreviewSize方法:)

但请使用CAMERA2 API

https://developer.android.com/reference/android/hardware/camera2/package-summary.html https://github.com/googlesamples/android-Camera2Basic