[Android]CameraX

简介

CameraX 应用可以通过 CameraX Extensions API 使用扩展。CameraX Extensions API 可用于管理可用扩展的查询、配置扩展相机会话以及与相机扩展 OEM 库的通信。这样,您的应用就可以使用夜间、HDR、自动、焦外成像或脸部照片修复等功能。

相机任务

CameraX 中默认有以下四个 UseCase,您可以将其用于各种相机任务:PreviewImageCaptureVideoCapture 和 ImageAnalysis

Preview

在向应用添加预览时,请使用 PreviewView,这是一种可以剪裁、缩放和旋转以确保正确显示的 View。

当相机处于活动状态时,图片预览会流式传输到 PreviewView 中的 Surface。

1、实现预览

previewView = findViewById(R.id.pv_camera_x);
cameraProviderFuture = ProcessCameraProvider.getInstance(this);
cameraProviderFuture.addListener(new Runnable() {
    @Override
    public void run() {
        try {
            //将相机的生命周期和activity的生命周期绑定,camerax 会自己释放
            ProcessCameraProvider cameraProvider = cameraProviderFuture.get();
            Preview preview = new Preview.Builder().build();

            mImageCapture = new ImageCapture.Builder()
                    .setFlashMode(ImageCapture.FLASH_MODE_OFF)
                    .build();
            //选择后置摄像头
            CameraSelector cameraSelector = new CameraSelector.Builder()
                    .requireLensFacing(CameraSelector.LENS_FACING_BACK)
                    .build();

            camera = cameraProvider.bindToLifecycle(
                    ((LifecycleOwner) CameraXActivity.this),
                    cameraSelector,
                    preview,
                    mImageCapture);

            preview.setSurfaceProvider(
                    previewView.getSurfaceProvider());

        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
        }
    }
},ContextCompat.getMainExecutor(this));

2、用于渲染预览流的实现模式。

PERFORMANCE 是默认模式。PreviewView 会使用 SurfaceView 显示视频串流,但在某些情况下会回退为使用 TextureView。SurfaceView 具有专用的绘图界面,该对象更有可能通过内部硬件合成器实现硬件叠加层,尤其是当预览视频上面没有其他界面元素(如按钮)时。通过使用硬件叠加层进行渲染,视频帧会避开 GPU 路径,从而能降低平台功耗并缩短延迟时间。

COMPATIBLE 模式。在此模式下,PreviewView 会使用 TextureView;不同于 SurfaceView,该对象没有专用的绘图表面。因此,视频要通过混合渲染,才能显示。在这个额外的步骤中,应用可以执行额外的处理工作,例如不受限制地缩放和旋转视频。

3、缩放类型

当预览视频分辨率与目标 PreviewView 的尺寸不同时,视频内容需要通过剪裁操作或添加遮幅式黑边来适应视图(保持原始宽高比)。为此,PreviewView 提供了以下 ScaleTypes

  1. FIT_CENTERFIT_START 和 FIT_END,用于添加遮幅式黑边。整个视频内容会调整(放大或缩小)为可在目标 PreviewView 中显示的最大尺寸。不过,虽然整个视频帧会完整显示,但屏幕画面中可能会出现空白部分。视频帧会与目标视图的中心、起始或结束位置对齐,具体取决于您在上述三种缩放类型中选择了哪一种。
  2. FILL_CENTERFILL_START 和 FILL_END,用于进行剪裁。如果视频的宽高比与 PreviewView 不匹配,画面中只会显示部分内容,但视频仍会填满整个 PreviewView。

CameraX 使用的默认缩放类型是 FILL_CENTER。您可以使用 PreviewView.setScaleType() 设置最适合具体应用的缩放类型。下面的代码示例设置了 FIT_CENTER 缩放类型:

//用于设置缩放类型
previewView.setScaleType(PreviewView.ScaleType.FILL_CENTER);

ImageCapture

运行 ImageCapture 的可自定义执行程序有两种类型:回调执行程序和 IO 执行程序。

  1. 回调执行程序是 takePicture 方法的参数。它用于执行用户提供的 OnImageCapturedCallback()
  2. 如果调用方选择将图片保存到文件位置,您可以指定执行程序以执行 IO。如需设置 IO 执行程序,请调用 ImageCapture.Builder.setIoExecutor(Executor)。如果执行程序不存在,则默认 CameraX 为任务的内部 IO 执行程序。

设置闪光灯模式

默认闪光灯模式为 FLASH_MODE_OFF

如需设置闪光灯模式,请使用 ImageCapture.Builder.setFlashMode()

  1. FLASH_MODE_OFF :没有闪光灯。拍照时永远不会使用闪光灯。
  2. FLASH_MODE_ON :闪光灯始终处于开启状态。
  3. FLASH_MODE_AUTO :在弱光环境下拍摄时,自动开启闪光灯。
//设置闪光灯模式
mImageCapture.setFlashMode(ImageCapture.FLASH_MODE_AUTO);

设置拍摄模式

ImageCapture.Builder.setCaptureMode() 可用于配置拍摄照片时所采用的拍摄模式:

拍摄模式默认为 CAPTURE_MODE_MINIMIZE_LATENCY

  1. CAPTURE_MODE_MINIMIZE_LATENCY :缩短图片拍摄的延迟时间。
  2. CAPTURE_MODE_MAXIMIZE_QUALITY :提高图片拍摄的图片质量。
  3. CAPTURE_MODE_ZERO_SHOT_LAG : 与CAPTURE_MODE_MINIMIZE_LATENCY延迟时间会更加明显缩短,零快门延迟。
mImageCapture = new ImageCapture.Builder()
        //设置闪光灯模式
        .setFlashMode(ImageCapture.FLASH_MODE_OFF)
        //设置拍摄模式
        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
        .build();

拍照

private void takePic(){
    mImageCapture.takePicture(ContextCompat.getMainExecutor(this), new 			ImageCapture.OnImageCapturedCallback() {
        @Override
        public void onCaptureSuccess(@NonNull ImageProxy image) {
            super.onCaptureSuccess(image);
            Log.w(TAG , "onCaptureSuccess");
            //转bitmap
            Bitmap bitmap =  image.toBitmap();
            //使用完image关闭
            image.close();
        }

        @Override
        public void onError(@NonNull ImageCaptureException exception) {
            super.onError(exception);
        }
    });
}

ImageAnalysis

图像分析用例为您的应用提供可供 CPU 访问的图像,您可以对这些图像执行图像处理、计算机视觉或机器学习推断。应用会实现对每个帧运行的 analyze() 方法。

操作模式

当应用的分析流水线无法满足 CameraX 的帧速率要求时,您可以将 CameraX 配置为通过以下其中一种方式丢帧:

  1. 非阻塞(默认):在该模式下,执行器始终会将最新的图像缓存到图像缓冲区(与深度为 1 的队列相似),与此同时,应用会分析上一个图像。如果 CameraX 在应用完成处理之前收到新图像,则新图像会保存到同一缓冲区,并覆盖上一个图像。 请注意,在这种情况下,ImageAnalysis.Builder.setImageQueueDepth() 不起任何作用,缓冲区内容始终会被覆盖。您可以通过使用 STRATEGY_KEEP_ONLY_LATEST 调用 setBackpressureStrategy() 来启用该非阻塞模式。如需详细了解执行器的相关影响,请参阅 STRATEGY_KEEP_ONLY_LATEST 的参考文档。
  2. 阻塞:在该模式下,内部执行器可以向内部图像队列添加多个图像,并仅在队列已满时才开始丢帧。系统会在整个相机设备上进行屏蔽:如果相机设备具有多个绑定用例,那么在 CameraX 处理这些图像时,系统会屏蔽所有这些用例。例如,如果预览和图像分析都已绑定到某个相机设备,那么在 CameraX 处理图像时,系统也会屏蔽相应预览。您可以通过将 STRATEGY_BLOCK_PRODUCER 传递到 setBackpressureStrategy() 来启用阻塞模式。此外,您还可以通过使用 ImageAnalysis.Builder.setImageQueueDepth() 来配置图像队列深度。

如果分析器延迟低且性能高,在这种情况下用于分析图像的总时间低于 CameraX 帧的时长(例如,60fps 用时 16 毫秒),那么上述两种操作模式均可提供顺畅的总体体验。在某些情况下,阻塞模式仍非常有用,例如在处理非常短暂的系统抖动时。

如果分析器延迟高且性能高,则需要结合使用阻塞模式和较长的队列来抵补延迟。但请注意,在这种情况下,应用仍可以处理所有帧。

如果分析器延迟高且耗时长(分析器无法处理所有帧)非阻塞模式可能更为适用,因为在这种情况下,系统必须针对分析路径进行丢帧,但要让其他同时绑定的用例仍能看到所有帧。

图像输出参数

  1. 格式 : CameraX 可通过 setOutputImageFormat(int) 支持 YUV_420_888 和 RGBA_8888。默认格式为 YUV_420_888。
  2. Resolution 和 AspectRatio :您可以设置其中一个参数,但请注意,您不能同时设置这两个值。
  3. SetTargetRotation : 设置选择
  4. setTargetName : 设置正在配置的目标对象的名称,仅用于调试日志记录。
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder()
                //设置图像输出格式
                .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_YUV_420_888)
                //设置此配置中图像的预期目标的纵横比。
                .setTargetAspectRatio(AspectRatio.RATIO_4_3)
                //设置此配置中预期目标的分辨率。请注意Resolution和Ratio只能设置一个
//                .setTargetResolution(new Size(1200,900))
                //设置正在配置的目标对象的名称,仅用于调试日志记录。
                .setTargetName("LiangXy")
                //设置将用于后台任务的默认执行器。
//                .setBackgroundExecutor()
                //设置应用于图像生成器的背压策略,以处理图像生成速度可能快于分析速度的情况。
                .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
                .build();

VideoCapture

CameraX 视频捕获架构

捕获系统通常会录制视频流和音频流,对其进行压缩,对这两个流进行多路复用,然后将生成的流写入磁盘。

在 CameraX 中,用于视频捕获的解决方案是 VideoCapture 用例:

使用 VideoCapture API

如需将 CameraX VideoCapture 用例集成到您的应用中,请执行以下操作:

  1. 绑定 VideoCapture。
  2. 准备和配置录制。
  3. 开始和控制运行时录制
private void initVideoCapture(){
    try {
        ProcessCameraProvider  cameraProvider = cameraProviderFuture.get();
        List<CameraInfo> cameraInfo = cameraProvider.getAvailableCameraInfos();
        List<Quality> supportedQualities = QualitySelector.getSupportedQualities(cameraInfo.get(0));

        QualitySelector qualitySelector  = QualitySelector.from(supportedQualities.get(0));
        Recorder recorder  = new Recorder.Builder()
                .setQualitySelector(qualitySelector)
                .setExecutor(ContextCompat.getMainExecutor(this))
                .build();
        VideoCapture videoCapture = VideoCapture.withOutput(recorder);

        cameraProvider.bindToLifecycle((LifecycleOwner) this, CameraSelector.DEFAULT_BACK_CAMERA, videoCapture);
    } catch (ExecutionException | InterruptedException e) {
        e.printStackTrace();
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值