如何使用CameraX拍摄多张图片?

3

我的用例是同时拍摄两张照片。第一张在2倍缩放级别下,第二张在1倍缩放级别下。此外,我想将图片保存到文件中。

我打算这么做:先在2倍缩放级别下拍摄第一张图片,当图像保存后将缩放级别设置为1倍,并在镜头缩放至1倍缩放级别时拍摄第二张图片。

然而,当我拍摄第一张照片时,预览画面停留在第一张照片上,并且从设置1倍缩放的回调函数永远不会发生。

以下是我创建捕获用例的方式。

private void createImageCaptureUseCases() {
    ImageCapture imageCapture1 = new ImageCapture.Builder()
        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
        .build();

    ImageCapture imageCapture2 = new ImageCapture.Builder()
        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
        .build();

    imageCaptureUseCases.clear();
    imageCaptureUseCases.add(imageCapture1);
    imageCaptureUseCases.add(imageCapture2);

这是我第一次启动相机会话的方式。

ListenableFuture<ProcessCameraProvider> cameraProviderFuture = ProcessCameraProvider.getInstance(getContext());

cameraProviderFuture.addListener(() -> {
    try {
        cameraProvider = cameraProviderFuture.get();
        preview = new Preview.Builder().build();

        cameraSelector = new CameraSelector.Builder()
            .requireLensFacing(CameraSelector.LENS_FACING_BACK)
            .build();

        Camera camera = cameraProvider.bindToLifecycle(
            ((LifecycleOwner) this),
            cameraSelector,
            preview,
            imageCapture);

        camera.getCameraControl().setZoomRatio(2f);

        preview.setSurfaceProvider(previewView.createSurfaceProvider(camera.getCameraInfo()));
    } catch (InterruptedException | ExecutionException e) {}
}, ContextCompat.getMainExecutor(getContext()));

这就是所谓的截图。

private void captureImage(ImageCapture imageCapture) {

    File pictureFile = ImageUtils.createImageFile(getActivity());
    ImageCapture.OutputFileOptions options = new 
        ImageCapture.OutputFileOptions.Builder(pictureFile).build();

    final Activity activity = getActivity();

    imageCapture.takePicture(options, ContextCompat.getMainExecutor(activity),
        new ImageCapture.OnImageSavedCallback() {

            @Override
            public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults){
                Log.i("my tag", "image Saved: " + pictureFile.getAbsolutePath());

                int index = imageCaptureUseCases.indexOf(imageCapture);
                cameraProvider.unbind(imageCapture);
                if (index < imageCaptureUseCases.size() - 1) {
                    Camera camera = cameraProvider.bindToLifecycle(
                    (LifecycleOwner) activity,
                    cameraSelector,
                    imageCaptureUseCases.get(index + 1));

                    ListenableFuture future = camera.getCameraControl().setZoomRatio(1f);
                    future.addListener(() -> captureImage(imageCaptureUseCases.get(index + 1)),
                                    ContextCompat.getMainExecutor(activity));
                } else {
                    createImageCaptureUseCases();
                    cameraProvider.unbindAll();
                    Camera camera = cameraProvider.bindToLifecycle(
                        (LifecycleOwner) activity,
                        cameraSelector,
                        preview,
                        imageCaptureUseCases.get(0));

                    camera.getCameraControl().setZoomRatio(2f);
                }
            }

            @Override
            public void onError(@NonNull ImageCaptureException exception) {
                Log.i("my tag", "image save error: " + pictureFile.getAbsolutePath());
            }
    });
}
1个回答

1
  • 你不需要多个ImageCapture实例来捕获两个缩放比率的图像,你可以使用同一个实例,ImageCapture处理拍照和保存/提供图像,与缩放比率等参数无关。

  • 从您的代码示例中看,似乎您第二次尝试捕获图像(具有不同的缩放比率)时没有绑定Preview用例。这就解释了为什么您的预览在第一次图像捕获后会卡住。请记住,ImageCapture用例不能单独绑定,它必须与至少1个PreviewImageAnalysis用例一起绑定。

以下是一个捕获2张图像的示例,每张图像都具有不同的缩放比率。代码包含一些重复,并且全部在一个块中,因此肯定可以改进。

    private fun setUpCamera() {
       val mainExecutor = ContextCompat.getMainExecutor(this)
       val cameraProviderFuture = ProcessCameraProvider.getInstance(this)
       cameraProviderFuture.addListener(Runnable {
          // Wait for the camera provider to be retrieved
          val cameraProvider = cameraProviderFuture.get()

          // Build your use cases
          val preview = Preview.Builder().build()
          val imageCapture = ImageCapture.Builder().build()

          // Get a camera selector to use
          val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

          // Bind the use cases to a lifecycle
          val camera = cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture)

          // Set the preview surface provider
preview.setSurfaceProvider(previewView.createSurfaceProvider(camera.cameraInfo))

          // Set the zoom ratio for the first photo
          val cameraControl = camera.cameraControl
          cameraControl.setZoomRatio(1F)

          // When the previewView is clicked, take the photos
          previewView.setOnClickListener {
             imageCapture.takePicture(createOutputFilesOptions(), mainExecutor, object : ImageCapture.OnImageSavedCallback {
                override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {

                   // First image captured and saved successfully
                   Log.d(TAG, "OnImageSavedCallback.onImageSaved: Image saved with zoom ratio 1F")

                   // Set a new zoom ratio for the second image capture
                   cameraControl.setZoomRatio(2F)

                   // Capture the second picture with a different zoom ratio
                   imageCapture.takePicture(createOutputFilesOptions(), mainExecutor, object : ImageCapture.OnImageSavedCallback {
                      override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) {

                         // Second image captured and saved successfully
                         Log.d(TAG, "OnImageSavedCallback.onImageSaved: Image saved with zoom ratio 2F")
                      }

                      override fun onError(exception: ImageCaptureException) {
                         Log.e(TAG, "OnImageSavedCallback.onError", exception)
                      }
                   })
                }

                override fun onError(exception: ImageCaptureException) {
                   Log.e(TAG, "OnImageSavedCallback.onError", exception)
                }
             })
          }
       }, mainExecutor)
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接