Google Jetpack新组件CameraX介绍与实践

简介: 近期,Google的Jetpack组件又出了新的库:CameraX。顾名思义:CameraX就是用来进行Camera开发的官方库了,而且后续会有Google进行维护和升级。这对于广大Camera开发工程师和即将成为Camera的程序员来说,真是个好消息~~~

作者:星陨

来源:音视频开发进阶

CameraX介绍

官方有提供一个示例的工程,我fork了之后,加入使用OpenGL黑白滤镜渲染的操作,具体地址如下:

https://github.com/glumes/camera

官方并没有提到CameraX库具体如何进行OpenGL线程渲染的,继续往下看,你会找到答案的~~~

关于CameraX更多的介绍,建议看看Google I / O大会上的视频记录,比看文档能了解更多内容~~~

https://www.youtube.com/watch?v=kuv8uK-5CLY

在视频中提到,目前有很多应用都开始加入了CameraX,例如Camera360,Tik Tok等。

image.png

简述Camera开发

关于Camera的开发,之前也有写过相关的文章🤔

Android相机开发中的尺寸和方向问题

https://glumes.com/post/android/android-camera-aspect-ratio-and-orientation/ 

Android相机模型及API接口演变

https://glumes.com/post/android/android-camrea-api-evolution/ 

对于一个简单能用的Camera应用(演示等级)来说,关注两个方面就好了:预览和拍摄。

相机最基本的功能就是能针对预览和拍摄提供两套分辨率,因此就得区分场景去设置。

对于拍摄还好说一点,要获得最好的图像质量,就选择同比例中分辨率最大的吧。

而预览的图像最终要呈现到Android的Surface上,因此选择分辨率的时候要考虑Surface的宽高比例,不要出现比例不匹配导致图像拉伸的现象。

另外,如果要做美颜,滤镜类的应用,就要把Camera预览的图像放到OpenGL渲染的线程上去,然后由OpenGL去做图像相关的操作,也就没Camera什么事了。等到拍摄图片时,可以由OpenGL去获取图像内容,也可以由Camera获得图像内容,然后通过OpenGL做离屏处理~~~

以Camera开发的其他功能,缩小对焦,曝光,白平衡,HDR等操作,不一定所有的Camera都能够支持,而且也可以在上面的基础上当做Camera的一个功能去拓展开发,而不是算难事,这也是一个Camera开发工程师进阶所要掌握的内容~~

CameraX开发实践

CameraX目前的版本是1.0.0-alpha01,在使用时要添加以下的依赖:

1    // CameraX
2    def camerax_version = "1.0.0-alpha01"
3    implementation "androidx.camera:camera-core:${camerax_version}"
4    implementation "androidx.camera:camera-camera2:${camerax_version}"

CameraX向后兼容到Android 5.0(API级别21),并且它是基于Camera 2.0的API进行封装的,解决了城市表面绝大部分手机的兼容性问题~~~

概述Camera 2.0复杂的调用流程,CameraX就简化了很多,只关心我们需要的内容就好了,不像前者得自己维护CameraSession会话等状态,并且CameraX和Jetpack主打的生命周期绑定在一起了,什么时候该打开相机,什么时候该释放相机,都交给Lifecycle生命周期去管理吧

上手CameraX主要关注三个方面:

  • 图像预览(Image Preview)
  • 图像分析(Image analysis)
  • 图像拍摄(Image capture)

预览

不论是预览还是图像分析,图像拍摄,CameraX都是通过一个构造器模式来构造参数。配置类,再由配置类创建预览,分析器,拍摄的类,并在绑定生命周期时将其传递过去。

1// // Apply declared configs to CameraX using the same lifecycle owner
2CameraX.bindToLifecycle(
3               lifecycleOwner: this, preview, imageCapture, imageAnalyzer)

既可以绑定Activity的生命周期,也可以绑定Fragment的。

当需要解除绑定时:

1// Unbinds all use cases from the lifecycle and removes them from CameraX.
2 CameraX.unbindAll()

关于预览的参数配置,如果你有看过之前的文章:Android相机开发中的尺寸和方向问题想必就会很了解了。

提供我们的目标参数,由CameraX去判断当前Camera是否支持,并选择最符合的。

1fun buildPreviewUseCase(): Preview {
 2    val previewConfig = PreviewConfig.Builder()
 3        // 宽高比
 4        .setTargetAspectRatio(aspectRatio)
 5        // 旋转
 6        .setTargetRotation(rotation)
 7        // 分辨率
 8        .setTargetResolution(resolution)
 9        // 前后摄像头
10        .setLensFacing(lensFacing)
11        .build()
12
13    // 创建 Preview 对象
14    val preview = Preview(previewConfig)
15    // 设置监听
16    preview.setOnPreviewOutputUpdateListener { previewOutput ->
17        // PreviewOutput 会返回一个 SurfaceTexture
18        cameraTextureView.surfaceTexture = previewOutput.surfaceTexture
19    }
20
21    return preview
22}

通过建造者模式创建Preview对象,并且一定要给Preview对象设置OnPreviewOutputUpdateListener接口替代。

相机预览的图像流是通过SurfaceTexture来返回的,而在项目示例中,是通过把TextureView的SurfaceTexture替换成CameraX返回的SurfaceTexture,从而实现了TextureView控件的显示。

另外,还需要考虑到设备的选择方向,当设备横屏变成竖屏了,TextureView也要相应的做旋转。

1preview.setOnPreviewOutputUpdateListener { previewOutput ->
 2    cameraTextureView.surfaceTexture = previewOutput.surfaceTexture
 3
 4    // Compute the center of preview (TextureView)
 5    val centerX = cameraTextureView.width.toFloat() / 2
 6    val centerY = cameraTextureView.height.toFloat() / 2
 7
 8    // Correct preview output to account for display rotation
 9    val rotationDegrees = when (cameraTextureView.display.rotation) {
10        Surface.ROTATION_0 -> 0
11        Surface.ROTATION_90 -> 90
12        Surface.ROTATION_180 -> 180
13        Surface.ROTATION_270 -> 270
14        else -> return@setOnPreviewOutputUpdateListener
15    }
16
17    val matrix = Matrix()
18    matrix.postRotate(-rotationDegrees.toFloat(), centerX, centerY)
19
20    // Finally, apply transformations to TextureView
21    cameraTextureView.setTransform(matrix)
22}

TextureView旋转的设置同样在OnPreviewOutputUpdateListener接口中去完成。

图像分析

bindToLifecycle方法中,imageAnalyzer参数并不是必需的。

ImageAnalysis可以帮助我们做一些图像质量的分析,需要我们去实现ImageAnalysis.Analyzer接口的analyze方法。

1fun buildImageAnalysisUseCase(): ImageAnalysis {
 2    // 分析器配置 Config 的建造者
 3    val analysisConfig = ImageAnalysisConfig.Builder()
 4        // 宽高比例
 5        .setTargetAspectRatio(aspectRatio)
 6        // 旋转
 7        .setTargetRotation(rotation)
 8        // 分辨率
 9        .setTargetResolution(resolution)
10        // 图像渲染模式
11        .setImageReaderMode(readerMode)
12        // 图像队列深度
13        .setImageQueueDepth(queueDepth)
14        // 设置回调的线程
15        .setCallbackHandler(handler)
16        .build()
17
18    // 创建分析器 ImageAnalysis 对象
19    val analysis = ImageAnalysis(analysisConfig)
20
21    // setAnalyzer 传入实现了 analyze 接口的类
22    analysis.setAnalyzer { image, rotationDegrees ->
23        // 可以得到的一些图像信息,参见 ImageProxy 类相关方法
24        val rect = image.cropRect
25        val format = image.format
26        val width = image.width
27        val height = image.height
28        val planes = image.planes
29    }
30
31    return analysis
32}

在图像分析器的相关配置中,有个ImageReaderModeImageQueueDepth的设置。

ImageQueueDepth会指定相机管线中图像的个数,提高ImageQueueDepth的数量相机的性能和内存的使用造成影响

其中,ImageReaderMode有两种模式:

  • ACQUIRE_LATEST_IMAGE
  • 该模式下,获得图像像素中最新的图片,并且会清空副本已有的旧的图像。
  • ACQUIRE_NEXT_IMAGE
  • 该模式下,获得下一张图像。

在图像分析的analyze方法中,能通过ImageProxy类拿到一些图像信息,并基于这些信息做分析。

拍摄

拍摄同样有一个Config参数内置者类,而且设置的参数和预览相差不大,也是图像宽高比例,旋转方向,分辨率,还有闪光灯等配置项。

1fun buildImageCaptureUseCase(): ImageCapture {
 2    val captureConfig = ImageCaptureConfig.Builder()
 3        .setTargetAspectRatio(aspectRatio)
 4        .setTargetRotation(rotation)
 5        .setTargetResolution(resolution)
 6        .setFlashMode(flashMode)
 7        // 拍摄模式
 8        .setCaptureMode(captureMode)
 9        .build()
10
11    // 创建 ImageCapture 对象
12    val capture = ImageCapture(captureConfig)
13    cameraCaptureImageButton.setOnClickListener {
14        // Create temporary file
15        val fileName = System.currentTimeMillis().toString()
16        val fileFormat = ".jpg"
17        val imageFile = createTempFile(fileName, fileFormat)
18
19        // Store captured image in the temporary file
20        capture.takePicture(imageFile, object : ImageCapture.OnImageSavedListener {
21            override fun onImageSaved(file: File) {
22                // You may display the image for example using its path file.absolutePath
23            }
24
25            override fun onError(useCaseError: ImageCapture.UseCaseError, message: String, cause: Throwable?) {
26                // Display error message
27            }
28        })
29    }
30
31    return capture
32}

在图像拍摄的相关配置中,也有个CaptureMode的设置。

它有两种选择:

  • MIN_LATENCY
  • 该模式下,拍摄速度会相对快一点,但图像质量会打折扣
  • MAX_QUALITY
  • 该模式下,拍摄速度会慢一点,但图像质量好

OpenGL渲染

以上是关于CameraX的简单应用方面的内容,更关心的是如何用CameraX去做OpenGL渲染实现美颜。滤镜等效果。

还记得在图像预览Preview的setOnPreviewOutputUpdateListener方法中,会返回一个SurfaceTexture,相机的图像流就是通过它返回的。

那么要实现OpenGL线程的渲染,首先就要基于EGL去创建OpenGL布局环境,然后利用SurfaceTexture的attachToGLContext方法,将SurfaceTexture添加到OpenGL线程去。

attachToGLContext的参数是一个纹理ID,这个纹理就必须是OES类型的纹理。

然后再把这一个纹理ID移到OpenGL对应的Surface上,这可以看成是两个不同的线程在允许,一个Camera预览线程,一个OpenGL布局线程。

如果你不是很理解的话,建议还是看看上面提供的代码地址:

https://github.com/glumes/camera

也可以关注我的微信公众号【纸上浅谈】,里面有一些关于OpenGL学习和实践的文章~~~

CameraX的拓展

如果您看了Google I / O大会的视频,那肯定了解CameraX的扩展属性。

在视频中提到Google也正在和华为,三星,LG,摩托摩拉等厂商进行合作,以便获得厂商系统相机的一些能力,例如HDR等。

不过考虑到目前的预期,可能和华为的合作难以继续下去了吧...

但还是期待CameraX能给带来更多的新特性吧~~~

参考

  1. https://www.youtube.com/watch?v=kuv8uK-5CLY
  2. https://proandroiddev.com/android-camerax-preview-analyze-capture-1b3f403a9395


安卓以及音视频杂谈

「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。  

阿里云社区.png

相关文章
|
5月前
|
存储 设计模式 数据库
构建高效的安卓应用:探究Android Jetpack架构组件
【4月更文挑战第20天】 在移动开发的世界中,构建一个既高效又可维护的安卓应用是每个开发者追求的目标。随着Android Jetpack的推出,Google为开发者提供了一套高质量的库、工具和指南,以简化应用程序开发流程。本文将深入探讨Jetpack的核心组件之一——架构组件,并展示如何将其应用于实际项目中,以提升应用的响应性和稳定性。我们将通过分析这些组件的设计原则,以及它们如何协同工作,来揭示它们对于构建现代化安卓应用的重要性。
|
3天前
|
测试技术 数据库 Android开发
深入解析Android架构组件——Jetpack的使用与实践
本文旨在探讨谷歌推出的Android架构组件——Jetpack,在现代Android开发中的应用。Jetpack作为一系列库和工具的集合,旨在帮助开发者更轻松地编写出健壮、可维护且性能优异的应用。通过详细解析各个组件如Lifecycle、ViewModel、LiveData等,我们将了解其原理和使用场景,并结合实例展示如何在实际项目中应用这些组件,提升开发效率和应用质量。
|
2月前
|
SQL 监控 大数据
"解锁实时大数据处理新境界:Google Dataflow——构建高效、可扩展的实时数据管道实践"
【8月更文挑战第10天】随着大数据时代的发展,企业急需高效处理数据以实现即时响应。Google Dataflow作为Google Cloud Platform的强大服务,提供了一个完全托管的流处理与批处理方案。它采用Apache Beam编程模型,支持自动扩展、高可用性,并能与GCP服务无缝集成。例如,电商平台可通过Dataflow实时分析用户行为日志:首先利用Pub/Sub收集数据;接着构建管道处理并分析这些日志;最后将结果输出至BigQuery。Dataflow因此成为构建实时数据处理系统的理想选择,助力企业快速响应业务需求。
119 6
|
2月前
|
人工智能 JSON 自然语言处理
我的Google Vertex AI实践经验分享
忙碌的开发者分享了使用Google Vertex AI的实践经验。从复杂的初始设置到微调模型时的手动资源分配,作者经历了种种挑战,包括高昂的成本与不足的文档支持。尽管如此,Vertex AI在图像识别和自然语言处理方面展现出强大能力。作者希望反馈能帮助Google改进服务,使之更加用户友好。
52 2
|
4月前
|
JavaScript Java Android开发
kotlin安卓在Jetpack Compose 框架下跨组件通讯EventBus
**EventBus** 是一个Android事件总线库,简化组件间通信。要使用它,首先在Gradle中添加依赖`implementation 'org.greenrobot:eventbus:3.3.1'`。然后,可选地定义事件类如`MessageEvent`。在活动或Fragment的`onCreate`中注册订阅者,在`onDestroy`中反注册。通过`@Subscribe`注解方法处理事件,如`onMessageEvent`。发送事件使用`EventBus.getDefault().post()`。
|
5月前
|
前端开发 Android开发
Android架构组件JetPack之DataBinding玩转MVVM开发实战(四)
Android架构组件JetPack之DataBinding玩转MVVM开发实战(四)
Android架构组件JetPack之DataBinding玩转MVVM开发实战(四)
|
5月前
|
物联网 区块链 Android开发
构建高效Android应用:Kotlin与Jetpack的实践之路未来技术的融合潮流:区块链、物联网与虚拟现实的交汇点
【5月更文挑战第30天】 在移动开发领域,效率和性能始终是开发者追求的核心。随着技术的不断进步,Kotlin语言以其简洁性和现代化特性成为Android开发的新宠。与此同时,Jetpack组件为应用开发提供了一套经过实践检验的库、工具和指南,旨在简化复杂任务并帮助提高应用质量。本文将深入探索如何通过Kotlin结合Jetpack组件来构建一个既高效又稳定的Android应用,并分享在此过程中的最佳实践和常见陷阱。
|
5月前
|
存储 数据库 Android开发
构建高效安卓应用:采用Jetpack架构组件优化用户体验
【4月更文挑战第12天】 在当今快速发展的数字时代,Android 应用程序的流畅性与响应速度对用户满意度至关重要。为提高应用性能并降低维护成本,开发者需寻求先进的技术解决方案。本文将探讨如何利用 Android Jetpack 中的架构组件 — 如 LiveData、ViewModel 和 Room — 来构建高质量的安卓应用。通过具体实施案例分析,我们将展示这些组件如何协同工作以实现数据持久化、界面与逻辑分离,以及确保数据的即时更新,从而优化用户体验并提升应用的可维护性和可测试性。
|
5月前
|
存储 数据库 Android开发
使用Android Jetpack组件加速开发流程
【4月更文挑战第14天】Android Jetpack是为提升开发速度和代码质量而生的组件集合,包括`ViewModel`、`LiveData`、`RecyclerView`、`Room`、`WorkManager`等,它们遵循最新设计原则和最佳实践。例如,`RecyclerView`优化列表显示,`Room`简化数据库操作,`WorkManager`处理后台任务,`ViewModel`和`LiveData`分离业务和UI逻辑。此外,`Navigation`和`Paging`分别优化用户导航和数据加载。通过这些组件,开发者能更高效地构建高性能应用,值得学习和使用。
36 2
|
5月前
|
设计模式 前端开发 数据库
构建高效Android应用:使用Jetpack架构组件实现MVVM模式
【4月更文挑战第21天】 在移动开发领域,构建一个既健壮又易于维护的Android应用是每个开发者的目标。随着项目复杂度的增加,传统的MVP或MVC架构往往难以应对快速变化的市场需求和复杂的业务逻辑。本文将探讨如何利用Android Jetpack中的架构组件来实施MVVM(Model-View-ViewModel)设计模式,旨在提供一个更加模块化、可测试且易于管理的代码结构。通过具体案例分析,我们将展示如何使用LiveData, ViewModel, 和Repository来实现界面与业务逻辑的分离,以及如何利用Room数据库进行持久化存储。最终,你将获得一个响应迅速、可扩展且符合现代软件工
70 0