如何使用 CameraX 拍摄多张图像?
Posted
技术标签:
【中文标题】如何使用 CameraX 拍摄多张图像?【英文标题】:How to take multiple images using CameraX? 【发布时间】:2020-08-08 14:29:58 【问题描述】:我的用例是一次拍摄两张图像。第一个为 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】:您不需要多个ImageCapture
实例来捕获具有2 个缩放比例的图像,您可以使用相同的实例,ImageCapture
处理拍照并保存/提供它,与诸如此类的参数无关作为缩放比例。
查看您的代码示例,您似乎在第二次尝试捕获图像(使用不同的缩放比例)时没有绑定Preview
用例。这可以解释为什么您的预览在第一次图像捕获后卡住了。请记住,ImageCapture
用例不能单独绑定,它必须与至少 1 个 Preview
或 ImageAnalysis
用例绑定。
以下是捕获 2 张图像的示例,每张图像具有不同的缩放比例。代码包含一些重复,并且都在 1 块中,所以它肯定可以改进。
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)
【讨论】:
以上是关于如何使用 CameraX 拍摄多张图像?的主要内容,如果未能解决你的问题,请参考以下文章